2727import com .google .cloud .solutions .spannerddl .parser .ASTcolumn_type ;
2828import com .google .cloud .solutions .spannerddl .parser .ASTcreate_change_stream_statement ;
2929import com .google .cloud .solutions .spannerddl .parser .ASTcreate_index_statement ;
30+ import com .google .cloud .solutions .spannerddl .parser .ASTcreate_or_replace_statement ;
31+ import com .google .cloud .solutions .spannerddl .parser .ASTcreate_schema_statement ;
3032import com .google .cloud .solutions .spannerddl .parser .ASTcreate_search_index_statement ;
3133import com .google .cloud .solutions .spannerddl .parser .ASTcreate_table_statement ;
3234import com .google .cloud .solutions .spannerddl .parser .ASTddl_statement ;
@@ -100,6 +102,7 @@ public class DdlDiff {
100102 private final MapDifference <String , ASTcreate_change_stream_statement > changeStreamDifferences ;
101103 private final MapDifference <String , ASTcreate_search_index_statement > searchIndexDifferences ;
102104 private final String databaseName ; // for alter Database
105+ private final MapDifference <String , ASTcreate_schema_statement > schemaDifferences ;
103106
104107 private DdlDiff (DatabaseDefinition originalDb , DatabaseDefinition newDb , String databaseName )
105108 throws DdlDiffException {
@@ -118,6 +121,7 @@ private DdlDiff(DatabaseDefinition originalDb, DatabaseDefinition newDb, String
118121 Maps .difference (originalDb .changeStreams (), newDb .changeStreams ());
119122 this .searchIndexDifferences =
120123 Maps .difference (originalDb .searchIndexes (), newDb .searchIndexes ());
124+ this .schemaDifferences = Maps .difference (originalDb .schemas (), newDb .schemas ());
121125
122126 if (!alterDatabaseOptionsDifferences .areEqual () && Strings .isNullOrEmpty (databaseName )) {
123127 // should never happen, but...
@@ -160,6 +164,12 @@ public List<String> generateDifferenceStatements(Map<String, Boolean> options)
160164 + Joiner .on (", " ).join (constraintDifferences .entriesDiffering ().keySet ()));
161165 }
162166
167+ if (!schemaDifferences .entriesDiffering ().isEmpty ()) {
168+ throw new DdlDiffException (
169+ "At least one schema differs but ALTER SCHEMA is not supported"
170+ + Joiner .on (", " ).join (schemaDifferences .entriesDiffering ().keySet ()));
171+ }
172+
163173 // check for modified Alter Database statements
164174 if (!alterDatabaseOptionsDifferences .areEqual ()) {
165175 String optionsUpdates = generateOptionsUpdates (alterDatabaseOptionsDifferences );
@@ -247,6 +257,14 @@ public List<String> generateDifferenceStatements(Map<String, Boolean> options)
247257 }
248258 }
249259
260+ // Drop schemas
261+ if (options .get (ALLOW_DROP_STATEMENTS_OPT )) {
262+ for (ASTcreate_schema_statement schema : schemaDifferences .entriesOnlyOnLeft ().values ()) {
263+ LOG .info ("Dropping schema: {}" , schema .getName ());
264+ output .add ("DROP SCHEMA " + schema .getName ());
265+ }
266+ }
267+
250268 // Alter existing tables, or error if not possible.
251269 for (ValueDifference <ASTcreate_table_statement > difference :
252270 tableDifferences .entriesDiffering ().values ()) {
@@ -255,6 +273,12 @@ public List<String> generateDifferenceStatements(Map<String, Boolean> options)
255273 generateAlterTableStatements (difference .leftValue (), difference .rightValue (), options ));
256274 }
257275
276+ // create schemas
277+ for (ASTcreate_schema_statement schema : schemaDifferences .entriesOnlyOnRight ().values ()) {
278+ LOG .info ("creating schema: {}" , schema .getName ());
279+ output .add (schema .toString ());
280+ }
281+
258282 // Create new tables. Must be done in the order of creation in the new DDL.
259283 for (Map .Entry <String , ASTcreate_table_statement > newTableEntry :
260284 newDb .tablesInCreationOrder ().entrySet ()) {
@@ -755,8 +779,8 @@ public static List<ASTddl_statement> parseDdl(String original, boolean parseAnno
755779 "Unsupported statement:\n "
756780 + statement
757781 + "\n "
758- + "Can only create diffs from 'CREATE TABLE, CREATE INDEX and 'ALTER TABLE "
759- + " table_name ADD [constraint|row deletion policy]' DDL statements " );
782+ + "ALTER TABLE statements only support 'ADD [constraint|row deletion "
783+ + " policy]'" );
760784 }
761785 if (alterTableStatement .jjtGetChild (1 ) instanceof ASTforeign_key
762786 && ((ASTforeign_key ) alterTableStatement .jjtGetChild (1 ))
@@ -791,14 +815,24 @@ public static List<ASTddl_statement> parseDdl(String original, boolean parseAnno
791815 case DdlParserTreeConstants .JJTALTER_DATABASE_STATEMENT :
792816 case DdlParserTreeConstants .JJTCREATE_CHANGE_STREAM_STATEMENT :
793817 case DdlParserTreeConstants .JJTCREATE_SEARCH_INDEX_STATEMENT :
794- // no-op
818+ // no-op - allowed
819+ break ;
820+ case DdlParserTreeConstants .JJTCREATE_OR_REPLACE_STATEMENT :
821+ // can be one of several types.
822+ switch (((ASTcreate_or_replace_statement ) ddlStatement .jjtGetChild (0 ))
823+ .getSchemaObject ()
824+ .getId ()) {
825+ case DdlParserTreeConstants .JJTCREATE_SCHEMA_STATEMENT :
826+ // no-op - allowed
827+ break ;
828+ default :
829+ throw new IllegalArgumentException (
830+ "Unsupported statement for creating diffs:\n " + statement );
831+ }
795832 break ;
796833 default :
797834 throw new IllegalArgumentException (
798- "Unsupported statement:\n "
799- + statement
800- + "\n Can only create diffs from 'CREATE TABLE, CREATE INDEX, and "
801- + "'ALTER TABLE table_name ADD CONSTRAINT' DDL statements" );
835+ "Unsupported statement for creating diffs:\n " + statement );
802836 }
803837 ddlStatements .add (ddlStatement );
804838 } catch (ParseException e ) {
0 commit comments