in src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java [1318:1394]
private void prepareExecuteDdl(BufferedStatement<?> bufferedStatement) {
DdlTransactionMode ddlTransactionMode = sessionState.getDdlTransactionMode();
try {
// Single statements are simpler to check, so we do that in a separate check.
if (bufferedStatements.size() == 1) {
switch (ddlTransactionMode) {
case Single:
case Batch:
case AutocommitImplicitTransaction:
// Single DDL statements outside explicit transactions are always allowed. For a single
// statement, there can also not be an implicit transaction that needs to be committed.
if (transactionMode == TransactionMode.EXPLICIT) {
throw PGExceptionFactory.newPGException(
"DDL statements are only allowed outside explicit transactions.",
SQLState.InvalidTransactionState);
}
// Fall-through to commit the transaction if necessary.
case AutocommitExplicitTransaction:
// DDL statements are allowed even in explicit transactions. Commit any transaction that
// might be active.
if (spannerConnection.isInTransaction()) {
spannerConnection.commit();
sessionState.commit();
if (transactionMode == TransactionMode.EXPLICIT) {
// Convert the explicit transaction to a DDL batch.
transactionMode = TransactionMode.DDL_BATCH;
spannerConnection.startBatchDdl();
} else {
transactionMode = TransactionMode.IMPLICIT;
}
}
}
return;
}
// We are in a batch of statements.
switch (ddlTransactionMode) {
case Single:
throw PGExceptionFactory.newPGException(
"DDL statements are only allowed outside batches and transactions.",
SQLState.InvalidTransactionState);
case Batch:
if (spannerConnection.isInTransaction()
|| bufferedStatements.stream()
.anyMatch(
statement -> !isStatementAllowedInDdlBatch(statement.parsedStatement))) {
throw PGExceptionFactory.newPGException(
"DDL statements are not allowed in mixed batches or transactions.",
SQLState.InvalidTransactionState);
}
break;
case AutocommitImplicitTransaction:
if (spannerConnection.isInTransaction() && transactionMode != TransactionMode.IMPLICIT) {
throw PGExceptionFactory.newPGException(
"DDL statements are only allowed outside explicit transactions.",
SQLState.InvalidTransactionState);
}
// Fallthrough to commit the transaction if necessary.
case AutocommitExplicitTransaction:
// Commit any transaction that might be active and allow executing the statement.
// Switch the execution state to implicit transaction.
if (spannerConnection.isInTransaction()) {
spannerConnection.commit();
sessionState.commit();
if (transactionMode == TransactionMode.EXPLICIT) {
// Convert the explicit transaction to a DDL batch.
transactionMode = TransactionMode.DDL_BATCH;
spannerConnection.startBatchDdl();
} else {
transactionMode = TransactionMode.IMPLICIT;
}
}
}
} catch (Throwable throwable) {
throw setAndReturn(bufferedStatement.result, throwable);
}
}