Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make Spanner SQL DDL parsing public #169

Merged
merged 1 commit into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,13 @@
*/
@AutoValue
public abstract class DatabaseDefinition {
static DatabaseDefinition create(List<ASTddl_statement> statements) {
/**
* Create a database definition from the list of parsed DDL statements.
*
* @param statements List of parsed DDL statements
* @return DatabaseDefinition instance
*/
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