void doExecute()

in src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java [300:408]


    void doExecute() {
      Statement updatedStatement = statement;
      try {
        checkConnectionState();
        // TODO(b/235719478): If the statement is a BEGIN statement and there is a COMMIT statement
        //  at a later point in the batch, and all the statements in the transaction block are
        //  SELECT statements, then we should create a read-only transaction. Also, if a transaction
        //  block always ends with a ROLLBACK, PGAdapter should skip the entire execution of that
        //  block.
        SessionStatement sessionStatement =
            getSessionManagementStatement(updatedStatement, parsedStatement);
        if (!localStatements.get().isEmpty()
            && localStatements.get().containsKey(statement.getSql())
            && localStatements.get().get(statement.getSql()) != null
            && !Objects.requireNonNull(localStatements.get().get(statement.getSql()))
                .hasReplacementStatement()) {
          LocalStatement localStatement =
              Objects.requireNonNull(localStatements.get().get(statement.getSql()));
          result.set(localStatement.execute(BackendConnection.this, statement));
        } else if (sessionStatement != null) {
          result.set(sessionStatement.execute(sessionState, spannerConnection));
        } else if (connectionState == ConnectionState.ABORTED
            && !spannerConnection.isInTransaction()
            && (isRollback(parsedStatement) || isCommit(parsedStatement))) {
          result.set(ROLLBACK_RESULT);
        } else if (isTransactionStatement(parsedStatement) && sessionState.isForceAutocommit()) {
          result.set(NO_RESULT);
        } else if (isBegin(parsedStatement) && spannerConnection.isInTransaction()) {
          // Ignore the statement as it is a no-op to execute BEGIN when we are already in a
          // transaction. TODO: Return a warning.
          result.set(NO_RESULT);
        } else if ((isCommit(parsedStatement) || isRollback(parsedStatement))
            && !spannerConnection.isInTransaction()) {
          // Check if we are in a DDL batch that was created from an explicit transaction.
          if (transactionMode == TransactionMode.DDL_BATCH) {
            try {
              if (isCommit(parsedStatement)) {
                spannerConnection.runBatch();
              } else {
                spannerConnection.abortBatch();
              }
            } finally {
              transactionMode = TransactionMode.IMPLICIT;
            }
          }
          // Ignore the statement as it is a no-op to execute COMMIT/ROLLBACK when we are not in a
          // transaction. TODO: Return a warning.
          result.set(NO_RESULT);
        } else if (SimpleParser.isEmpty(statement.getSql())) {
          result.set(NO_RESULT);
        } else if (parsedStatement.isDdl()) {
          if (analyze) {
            result.set(NO_RESULT);
          } else {
            result.set(ddlExecutor.execute(parsedStatement, statement));
          }
        } else {
          String sqlLowerCase = updatedStatement.getSql().toLowerCase(Locale.ENGLISH);
          // Potentially replace pg_catalog table references with common table expressions.
          updatedStatement =
              parsedStatement.getType() != StatementType.CLIENT_SIDE
                      && sessionState.isReplacePgCatalogTables()
                  ? pgCatalog.get().replacePgCatalogTables(updatedStatement, sqlLowerCase)
                  : updatedStatement;
          // TODO: Remove the check for isDelayBeginTransactionStartUntilFirstWrite when that
          //       feature is able to detect FOR UPDATE clauses as a write.
          if (sessionState.isReplaceForUpdateClause()
              && !spannerConnection.isDelayTransactionStartUntilFirstWrite()) {
            updatedStatement =
                replaceForUpdate(updatedStatement, sqlLowerCase, /* replaceWithHint= */ true);
          } else {
            updatedStatement =
                replaceForUpdate(updatedStatement, sqlLowerCase, /* replaceWithHint= */ false);
          }
          RemoveEscapeClauseEnum removeEscapeClauseEnum = sessionState.getRemoveEscapeClause();
          if (removeEscapeClauseEnum != RemoveEscapeClauseEnum.NONE) {
            updatedStatement =
                EscapeClauseParser.removeEscapeClauses(
                    updatedStatement, sqlLowerCase, removeEscapeClauseEnum);
          }
          updatedStatement = bindStatement(updatedStatement, sqlLowerCase);
          result.set(analyzeOrExecute(updatedStatement));
        }
      } catch (SpannerException spannerException) {
        // Executing queries against the information schema in a transaction is unsupported.
        // This ensures that those queries are retried using a separate single-use transaction.
        if (isUnsupportedConcurrencyModeException(spannerException)) {
          try {
            result.set(
                new QueryResult(
                    PGAdapterResultSetHelper.toDirectExecuteResultSet(
                        spannerConnection
                            .getDatabaseClient()
                            .singleUse()
                            .executeQuery(updatedStatement))));
            return;
          } catch (Exception exception) {
            throw setAndReturn(result, exception);
          }
        }
        if (spannerException.getErrorCode() == ErrorCode.CANCELLED || Thread.interrupted()) {
          throw setAndReturn(result, PGExceptionFactory.newQueryCancelledException());
        } else {
          throw setAndReturn(result, spannerException);
        }
      } catch (Throwable exception) {
        throw setAndReturn(result, exception);
      }
    }