Skip to content

Commit ca3a67d

Browse files
authored
fix: remove trailing semicolons in DDL (#3879)
The Connection API should automatically remove any trailing semicolons in DDL statements. Spanner accepts trailing semicolons in queries and DML statements, but not in DDL statements. Previously, the Connection API would remove all comments and trailing semicolons from DDL statements. Comments are now supported in DDL statements, and are therefore no longer removed by the Conneciton API, but that change also unintentionally kept any trailing semicolons in the SQL string that is sent to Spanner. Fixes https://togithub.com/cloudspannerecosystem/liquibase-spanner/issues/481
1 parent 6317402 commit ca3a67d

File tree

2 files changed

+59
-1
lines changed
  • google-cloud-spanner/src

2 files changed

+59
-1
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.concurrent.atomic.AtomicReference;
3636
import java.util.function.Consumer;
3737
import java.util.function.Supplier;
38+
import java.util.stream.Collectors;
3839

3940
/**
4041
* Convenience class for executing Data Definition Language statements on transactions that support
@@ -137,7 +138,21 @@ OperationFuture<Void, UpdateDatabaseDdlMetadata> executeDdl(
137138
dbBuilder.setProtoDescriptors(protoDescriptors);
138139
}
139140
Database db = dbBuilder.build();
140-
return dbAdminClient.updateDatabaseDdl(db, statements, null);
141+
return dbAdminClient.updateDatabaseDdl(
142+
db,
143+
statements.stream().map(DdlClient::stripTrailingSemicolon).collect(Collectors.toList()),
144+
null);
145+
}
146+
147+
static String stripTrailingSemicolon(String input) {
148+
if (!input.contains(";")) {
149+
return input;
150+
}
151+
String trimmed = input.trim();
152+
if (trimmed.endsWith(";")) {
153+
return trimmed.substring(0, trimmed.length() - 1);
154+
}
155+
return input;
141156
}
142157

143158
/** Returns true if the statement is a `CREATE DATABASE ...` statement. */

google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,47 @@ public void testSetsDefaultSequenceKindAndRetriesBatch() {
364364
"create table bar (id2 int64 auto_increment primary key",
365365
((UpdateDatabaseDdlRequest) requests.get(0)).getStatements(1));
366366
}
367+
368+
@Test
369+
public void testStripTrailingSemicolon() {
370+
addUpdateDdlResponse();
371+
addUpdateDdlResponse();
372+
addUpdateDdlResponse();
373+
addUpdateDdlResponse();
374+
try (Connection connection = createConnection()) {
375+
connection.execute(Statement.of("drop table foo;"));
376+
connection.execute(Statement.of("drop table foo \n\t;\n\t "));
377+
connection.execute(Statement.of("drop table foo"));
378+
379+
connection.startBatchDdl();
380+
connection.execute(Statement.of("create table foo (id1 int64 auto_increment primary key;"));
381+
connection.execute(
382+
Statement.of("create table foo (id1 int64 auto_increment primary key \n\t;\n\t "));
383+
connection.execute(Statement.of("create table foo (id2 int64 auto_increment primary key"));
384+
connection.runBatch();
385+
}
386+
assertEquals(4, mockDatabaseAdmin.getRequests().size());
387+
assertEquals(
388+
"drop table foo",
389+
((UpdateDatabaseDdlRequest) mockDatabaseAdmin.getRequests().get(0)).getStatements(0));
390+
assertEquals(
391+
"drop table foo \n\t",
392+
((UpdateDatabaseDdlRequest) mockDatabaseAdmin.getRequests().get(1)).getStatements(0));
393+
assertEquals(
394+
"drop table foo",
395+
((UpdateDatabaseDdlRequest) mockDatabaseAdmin.getRequests().get(2)).getStatements(0));
396+
397+
assertEquals(
398+
3,
399+
((UpdateDatabaseDdlRequest) mockDatabaseAdmin.getRequests().get(3)).getStatementsCount());
400+
assertEquals(
401+
"create table foo (id1 int64 auto_increment primary key",
402+
((UpdateDatabaseDdlRequest) mockDatabaseAdmin.getRequests().get(3)).getStatements(0));
403+
assertEquals(
404+
"create table foo (id1 int64 auto_increment primary key \n\t",
405+
((UpdateDatabaseDdlRequest) mockDatabaseAdmin.getRequests().get(3)).getStatements(1));
406+
assertEquals(
407+
"create table foo (id2 int64 auto_increment primary key",
408+
((UpdateDatabaseDdlRequest) mockDatabaseAdmin.getRequests().get(3)).getStatements(2));
409+
}
367410
}

0 commit comments

Comments
 (0)