2828import com .google .cloud .solutions .spannerddl .parser .ASTcolumns ;
2929import com .google .cloud .solutions .spannerddl .parser .ASTcreate_change_stream_statement ;
3030import com .google .cloud .solutions .spannerddl .parser .ASTcreate_index_statement ;
31+ import com .google .cloud .solutions .spannerddl .parser .ASTcreate_locality_group_statement ;
3132import com .google .cloud .solutions .spannerddl .parser .ASTcreate_or_replace_statement ;
3233import com .google .cloud .solutions .spannerddl .parser .ASTcreate_schema_statement ;
3334import com .google .cloud .solutions .spannerddl .parser .ASTcreate_search_index_statement ;
@@ -107,6 +108,7 @@ public class DdlDiff {
107108 private final MapDifference <String , ASTcreate_search_index_statement > searchIndexDifferences ;
108109 private final String databaseName ; // for alter Database
109110 private final MapDifference <String , ASTcreate_schema_statement > schemaDifferences ;
111+ private final MapDifference <String , ASTcreate_locality_group_statement > localityGroupDifferences ;
110112
111113 private DdlDiff (DatabaseDefinition originalDb , DatabaseDefinition newDb , String databaseName )
112114 throws DdlDiffException {
@@ -126,6 +128,8 @@ private DdlDiff(DatabaseDefinition originalDb, DatabaseDefinition newDb, String
126128 this .searchIndexDifferences =
127129 Maps .difference (originalDb .searchIndexes (), newDb .searchIndexes ());
128130 this .schemaDifferences = Maps .difference (originalDb .schemas (), newDb .schemas ());
131+ this .localityGroupDifferences =
132+ Maps .difference (originalDb .localityGroups (), newDb .localityGroups ());
129133
130134 if (!alterDatabaseOptionsDifferences .areEqual () && Strings .isNullOrEmpty (databaseName )) {
131135 // should never happen, but...
@@ -269,6 +273,13 @@ public List<String> generateDifferenceStatements(Map<String, Boolean> options)
269273 }
270274 }
271275
276+ // Create new locality groups
277+ for (ASTcreate_locality_group_statement lg :
278+ localityGroupDifferences .entriesOnlyOnRight ().values ()) {
279+ LOG .info ("Creating new locality group: {}" , lg .getNameOrDefault ());
280+ output .add (lg .toString ());
281+ }
282+
272283 // Alter existing tables, or error if not possible.
273284 for (ValueDifference <ASTcreate_table_statement > difference :
274285 tableDifferences .entriesDiffering ().values ()) {
@@ -277,6 +288,34 @@ public List<String> generateDifferenceStatements(Map<String, Boolean> options)
277288 generateAlterTableStatements (difference .leftValue (), difference .rightValue (), options ));
278289 }
279290
291+ // Drop deleted locality groups.
292+ if (options .get (ALLOW_DROP_STATEMENTS_OPT )) {
293+ for (ASTcreate_locality_group_statement lg :
294+ localityGroupDifferences .entriesOnlyOnLeft ().values ()) {
295+ LOG .info ("Dropping deleted locality group: {}" , lg .getNameOrDefault ());
296+ output .add ("DROP LOCALITY GROUP " + lg .getNameOrDefault ());
297+ }
298+ }
299+
300+ // update existing locality groups (options only)
301+ for (ValueDifference <ASTcreate_locality_group_statement > lgDiff :
302+ localityGroupDifferences .entriesDiffering ().values ()) {
303+ ASTcreate_locality_group_statement left = lgDiff .leftValue ();
304+ ASTcreate_locality_group_statement right = lgDiff .rightValue ();
305+
306+ // Only OPTIONS diffs are supported
307+ String updateText =
308+ generateOptionsClauseUpdates (left .getOptionsClause (), right .getOptionsClause ());
309+ if (!Strings .isNullOrEmpty (updateText )) {
310+ output .add (
311+ "ALTER LOCALITY GROUP "
312+ + right .getNameOrDefault ()
313+ + " SET OPTIONS ("
314+ + updateText
315+ + ")" );
316+ }
317+ }
318+
280319 // create schemas
281320 for (ASTcreate_schema_statement schema : schemaDifferences .entriesOnlyOnRight ().values ()) {
282321 LOG .info ("creating schema: {}" , schema .getName ());
@@ -395,19 +434,10 @@ public List<String> generateDifferenceStatements(Map<String, Boolean> options)
395434 if (!oldOptions .equals (newOptions )) {
396435
397436 // need to look at old and new options values individually
398-
399- Map <String , String > oldOptionsKv =
400- changedChangeStream .leftValue ().getOptionsClause () == null
401- ? Map .of ()
402- : changedChangeStream .leftValue ().getOptionsClause ().getKeyValueMap ();
403-
404- Map <String , String > newOptionsKv =
405- changedChangeStream .rightValue ().getOptionsClause () == null
406- ? Map .of ()
407- : changedChangeStream .rightValue ().getOptionsClause ().getKeyValueMap ();
408-
409- String optionsDiff = generateOptionsUpdates (Maps .difference (oldOptionsKv , newOptionsKv ));
410-
437+ String optionsDiff =
438+ generateOptionsClauseUpdates (
439+ changedChangeStream .leftValue ().getOptionsClause (),
440+ changedChangeStream .rightValue ().getOptionsClause ());
411441 if (optionsDiff != null ) {
412442 output .add (
413443 "ALTER CHANGE STREAM "
@@ -455,6 +485,7 @@ static List<String> generateAlterTableStatements(
455485 // - Add cols
456486 // - drop cols (if enabled)
457487 // - change on-delete action for interleaved
488+ // - update options
458489 // ALTER TABLE ALTER COLUMN can:
459490 // - change options on column
460491 // - change not null on column.
@@ -512,6 +543,13 @@ static List<String> generateAlterTableStatements(
512543 addColumnDiffs (left .getTableName (), alterStatements , columnDiff );
513544 }
514545
546+ // Table Options clause changes
547+ String updateText = generateOptionsClauseUpdates (left .getOptions (), right .getOptions ());
548+ if (!Strings .isNullOrEmpty (updateText )) {
549+ alterStatements .add (
550+ "ALTER TABLE " + left .getTableName () + " SET OPTIONS (" + updateText + ")" );
551+ }
552+
515553 return alterStatements ;
516554 }
517555
@@ -591,16 +629,9 @@ private static void addColumnDiffs(
591629 }
592630
593631 // Update options.
594- ASToptions_clause leftOptionsClause = columnDiff .leftValue ().getOptionsClause ();
595- ASToptions_clause rightOptionsClause = columnDiff .rightValue ().getOptionsClause ();
596- Map <String , String > leftOptions =
597- leftOptionsClause == null ? Collections .emptyMap () : leftOptionsClause .getKeyValueMap ();
598- Map <String , String > rightOptions =
599- rightOptionsClause == null ? Collections .emptyMap () : rightOptionsClause .getKeyValueMap ();
600- MapDifference <String , String > optionsDiff = Maps .difference (leftOptions , rightOptions );
601-
602- String updateText = generateOptionsUpdates (optionsDiff );
603-
632+ String updateText =
633+ generateOptionsClauseUpdates (
634+ columnDiff .leftValue ().getOptionsClause (), columnDiff .rightValue ().getOptionsClause ());
604635 if (!Strings .isNullOrEmpty (updateText )) {
605636 alterStatements .add (
606637 "ALTER TABLE "
@@ -639,6 +670,16 @@ private static void addColumnDiffs(
639670 }
640671 }
641672
673+ private static String generateOptionsClauseUpdates (
674+ ASToptions_clause leftOptionsClause , ASToptions_clause rightOptionsClause ) {
675+ Map <String , String > leftOptions =
676+ leftOptionsClause == null ? Collections .emptyMap () : leftOptionsClause .getKeyValueMap ();
677+ Map <String , String > rightOptions =
678+ rightOptionsClause == null ? Collections .emptyMap () : rightOptionsClause .getKeyValueMap ();
679+ MapDifference <String , String > optionsDiff = Maps .difference (leftOptions , rightOptions );
680+ return generateOptionsUpdates (optionsDiff );
681+ }
682+
642683 private static String generateOptionsUpdates (MapDifference <String , String > optionsDiff ) {
643684
644685 if (optionsDiff .areEqual ()) {
@@ -820,6 +861,7 @@ public static List<ASTddl_statement> parseDdl(String original, boolean parseAnno
820861 case DdlParserTreeConstants .JJTALTER_DATABASE_STATEMENT :
821862 case DdlParserTreeConstants .JJTCREATE_CHANGE_STREAM_STATEMENT :
822863 case DdlParserTreeConstants .JJTCREATE_SEARCH_INDEX_STATEMENT :
864+ case DdlParserTreeConstants .JJTCREATE_LOCALITY_GROUP_STATEMENT :
823865 case DdlParserTreeConstants .JJTCREATE_PROTO_BUNDLE_STATEMENT :
824866 case DdlParserTreeConstants .JJTALTER_PROTO_BUNDLE_STATEMENT :
825867 // no-op - allowed
0 commit comments