private void prepareExecuteDdl()

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);
    }
  }