From 336b9f2d6192d0a2bf1aa5782eb6db4a74154a97 Mon Sep 17 00:00:00 2001 From: Gurminder Singh Date: Thu, 26 Sep 2024 21:07:21 -0700 Subject: [PATCH] added option in parserDdl to parse or skip the annotations that are comments in the DDL file --- .../solutions/spannerddl/diff/DdlDiff.java | 19 +++++++- .../spannerddl/parser/DDLAnnotationTest.java | 43 +++++++++++++------ src/test/resources/annotations.txt | 10 ++--- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/google/cloud/solutions/spannerddl/diff/DdlDiff.java b/src/main/java/com/google/cloud/solutions/spannerddl/diff/DdlDiff.java index b291f66..426f5d3 100644 --- a/src/main/java/com/google/cloud/solutions/spannerddl/diff/DdlDiff.java +++ b/src/main/java/com/google/cloud/solutions/spannerddl/diff/DdlDiff.java @@ -55,6 +55,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.function.Function; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -707,10 +708,26 @@ private static String getDatabaseNameFromAlterDatabase(List st * @throws DdlDiffException if there is an error in parsing the DDL */ public static List parseDdl(String original) throws DdlDiffException { + return parseDdl(original, false); + } + + /** + * Parses the Cloud Spanner Schema (DDL) string to a list of AST DDL statements. + * + * @param original DDL to parse + * @param parseAnnotationInComments If true then the annotations that appear as comments + * "-- @ANNOTATION " will be parsed + * @return List of parsed DDL statements + */ + public static List parseDdl(String original, boolean parseAnnotationInComments) + throws DdlDiffException { // the annotations are prefixed with "--" so that SQL file remains valid. // strip the comment prefix before so that annotations can be parsed. // otherwise they will be ignored as comment lines - original = original.replaceAll("-- *@", "@"); + if (parseAnnotationInComments) { + original = + Pattern.compile("^\\s*--\\s+@", Pattern.MULTILINE).matcher(original).replaceAll("@"); + } // Remove "--" comments and split by ";" List statements = Splitter.on(';').splitToList(original.replaceAll("--.*(\n|$)", "")); diff --git a/src/test/java/com/google/cloud/solutions/spannerddl/parser/DDLAnnotationTest.java b/src/test/java/com/google/cloud/solutions/spannerddl/parser/DDLAnnotationTest.java index 556005c..d30a7ce 100644 --- a/src/test/java/com/google/cloud/solutions/spannerddl/parser/DDLAnnotationTest.java +++ b/src/test/java/com/google/cloud/solutions/spannerddl/parser/DDLAnnotationTest.java @@ -1,11 +1,13 @@ package com.google.cloud.solutions.spannerddl.parser; +import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; +import com.google.cloud.solutions.spannerddl.diff.DdlDiff; +import com.google.cloud.solutions.spannerddl.diff.DdlDiffException; import com.google.cloud.solutions.spannerddl.testUtils.ReadTestDatafile; import java.io.IOException; -import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -32,18 +34,14 @@ public void validateAnnotations() throws IOException { String segmentName = test.getKey(); try { - DdlParser parser = new DdlParser(new StringReader(test.getValue())); - parser.ddl_statement(); - Node tableStatement = parser.jjtree.rootNode().jjtGetChild(0); + // first get all the annotations without removing the comment prefix + List annotations = getTableAnnotations(test.getValue(), false); - // get all annotations - List annotations = new ArrayList<>(); - for (int i = 0, count = tableStatement.jjtGetNumChildren(); i < count; i++) { - Node child = tableStatement.jjtGetChild(i); - if (child instanceof ASTannotation) { - annotations.add(((ASTannotation) child).getAnnotation()); - } - } + // annotations should be empty + assertThat(annotations).isEmpty(); + + // now get all the annotations after removing the comment prefix + annotations = getTableAnnotations(test.getValue(), true); List expectedList = expected != null ? Arrays.asList(expected.split("\n")) : Collections.emptyList(); @@ -51,9 +49,28 @@ public void validateAnnotations() throws IOException { assertWithMessage("Mismatch for section " + segmentName) .that(annotations) .isEqualTo(expectedList); - } catch (ParseException e) { + } catch (DdlDiffException e) { fail("Failed to parse section: '" + segmentName + "': " + e); } } } + + private List getTableAnnotations(String ddl, boolean parseAnnotations) + throws DdlDiffException { + List annotations = new ArrayList<>(); + + List statements = DdlDiff.parseDdl(ddl, parseAnnotations); + for (ASTddl_statement statement : statements) { + if (statement.jjtGetChild(0).getId() == DdlParserTreeConstants.JJTCREATE_TABLE_STATEMENT) { + Node tableStatement = statement.jjtGetChild(0); + for (int i = 0, count = tableStatement.jjtGetNumChildren(); i < count; i++) { + Node child = tableStatement.jjtGetChild(i); + if (child instanceof ASTannotation) { + annotations.add(((ASTannotation) child).getAnnotation()); + } + } + } + } + return annotations; + } } diff --git a/src/test/resources/annotations.txt b/src/test/resources/annotations.txt index b874d4d..de7c7bd 100644 --- a/src/test/resources/annotations.txt +++ b/src/test/resources/annotations.txt @@ -1,11 +1,11 @@ == Test 1 all column annotations CREATE TABLE test1 ( - @ANNOTATION DEPRECATED, - @ANNOTATION PII, - @ANNOTATION TAG.business(internal), - @ANNOTATION TAG.business(key1,key2), - @ANNOTATION TAG.business(key1=val1,key2=value), + -- @ANNOTATION DEPRECATED, + -- @ANNOTATION PII, + -- @ANNOTATION TAG.business(internal), + -- @ANNOTATION TAG.business(key1,key2), + -- @ANNOTATION TAG.business(key1=val1,key2=value), id STRING(36), ) PRIMARY KEY (id)