Skip to content

Commit

Permalink
feat: make Spanner SQL DDL parsing public
Browse files Browse the repository at this point in the history
  • Loading branch information
gurminder71 committed Sep 22, 2024
1 parent 1bb206a commit 8de1109
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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> T getOptionalChildByType(Node node, Class<T> 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> T getOptionalChildByType(Node[] children, Class<T> type) {
for (Node child : children) {
Expand All @@ -40,6 +52,18 @@ public static <T> T getOptionalChildByType(Node[] children, Class<T> 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> T getChildByType(Node node, Class<T> 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.
Expand All @@ -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 <T> List<T> getChildrenAssertType(Node node, Class<T> type) {
List<T> 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
*/
@AutoValue
public abstract class DatabaseDefinition {
static DatabaseDefinition create(List<ASTddl_statement> statements) {
public static DatabaseDefinition create(List<ASTddl_statement> statements) {
// Use LinkedHashMap to preserve creation order in original DDL.
LinkedHashMap<String, ASTcreate_table_statement> tablesInCreationOrder = new LinkedHashMap<>();
LinkedHashMap<String, ASTcreate_index_statement> indexes = new LinkedHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,14 @@ private static String getDatabaseNameFromAlterDatabase(List<ASTddl_statement> st
}
}

@VisibleForTesting
static List<ASTddl_statement> 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<ASTddl_statement> parseDdl(String original) throws DdlDiffException {
// Remove "--" comments and split by ";"
List<String> statements = Splitter.on(';').splitToList(original.replaceAll("--.*(\n|$)", ""));
ArrayList<ASTddl_statement> ddlStatements = new ArrayList<>(statements.size());
Expand Down

0 comments on commit 8de1109

Please sign in to comment.