From 1d3a941612085d7e53cc9adae61f36115f19898d Mon Sep 17 00:00:00 2001 From: Gurminder Singh Date: Sun, 22 Sep 2024 10:49:35 -0700 Subject: [PATCH] Make DDL prasing public so that parsed SQL statements can be used by other Java programs --- .../spannerddl/diff/AstTreeUtils.java | 37 +++++++++++++++++++ .../spannerddl/diff/DatabaseDefinition.java | 2 +- .../solutions/spannerddl/diff/DdlDiff.java | 10 ++++- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/google/cloud/solutions/spannerddl/diff/AstTreeUtils.java b/src/main/java/com/google/cloud/solutions/spannerddl/diff/AstTreeUtils.java index aeed51e..290eee0 100644 --- a/src/main/java/com/google/cloud/solutions/spannerddl/diff/AstTreeUtils.java +++ b/src/main/java/com/google/cloud/solutions/spannerddl/diff/AstTreeUtils.java @@ -20,6 +20,7 @@ import com.google.cloud.solutions.spannerddl.parser.Node; import com.google.cloud.solutions.spannerddl.parser.SimpleNode; import com.google.cloud.solutions.spannerddl.parser.Token; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -30,6 +31,17 @@ /** Utility functions for getting and casting Nodes in the parsed AST. */ public class AstTreeUtils { + /** Gets (and casts) the first found child of a specific node type. */ + public static T getOptionalChildByType(Node node, Class type) { + for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { + Node child = node.jjtGetChild(i); + if (type.isInstance(child)) { + return type.cast(child); + } + } + return null; + } + /** Gets (and casts) the first found child of a specific node type. */ public static T getOptionalChildByType(Node[] children, Class type) { for (Node child : children) { @@ -40,6 +52,18 @@ public static T getOptionalChildByType(Node[] children, Class type) { return null; } + /** + * Gets (and casts) the first found child of a specific node type, throwing an exception if it + * does not exist. + */ + public static T getChildByType(Node node, Class type) { + T child = getOptionalChildByType(node, type); + if (child == null) { + throw new IllegalArgumentException("Cannot find child of type " + type.getName()); + } + return child; + } + /** * Gets (and casts) the first found child of a specific node type, throwing an exception if it * does not exist. @@ -64,6 +88,19 @@ public static boolean isReservedWord(String word) { return reservedWords.contains(word); } + /** + * Ensures that the passed Node children are of a specific node type, and returns a List with the + * specific type. + */ + public static List getChildrenAssertType(Node node, Class type) { + List list = new ArrayList<>(); + for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { + Node child = node.jjtGetChild(i); + list.add(type.cast(child)); + } + return list; + } + /** * Ensures that the passed array of Nodes is of a specific node type, and returns a List with the * specific type. diff --git a/src/main/java/com/google/cloud/solutions/spannerddl/diff/DatabaseDefinition.java b/src/main/java/com/google/cloud/solutions/spannerddl/diff/DatabaseDefinition.java index 60bc04c..577b4de 100644 --- a/src/main/java/com/google/cloud/solutions/spannerddl/diff/DatabaseDefinition.java +++ b/src/main/java/com/google/cloud/solutions/spannerddl/diff/DatabaseDefinition.java @@ -46,7 +46,7 @@ */ @AutoValue public abstract class DatabaseDefinition { - static DatabaseDefinition create(List statements) { + public static DatabaseDefinition create(List statements) { // Use LinkedHashMap to preserve creation order in original DDL. LinkedHashMap tablesInCreationOrder = new LinkedHashMap<>(); LinkedHashMap indexes = new LinkedHashMap<>(); 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 ede3aee..d112900 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 @@ -699,8 +699,14 @@ private static String getDatabaseNameFromAlterDatabase(List st } } - @VisibleForTesting - static List parseDdl(String original) throws DdlDiffException { + /** + * Parses the Cloud Spanner Schema (DDL) string to a list of AST DDL statements + * + * @param original DDL to parse + * @return List of parsed DDL statements + * @throws DdlDiffException if there is an error in parsing the DDL + */ + public static List parseDdl(String original) throws DdlDiffException { // Remove "--" comments and split by ";" List statements = Splitter.on(';').splitToList(original.replaceAll("--.*(\n|$)", "")); ArrayList ddlStatements = new ArrayList<>(statements.size());