Search in sources :

Example 1 with DescribeStatementMetadata

use of com.google.cloud.spanner.pgadapter.metadata.DescribeStatementMetadata in project pgadapter by GoogleCloudPlatform.

the class IntermediatePreparedStatement method describe.

@Override
public DescribeMetadata describe() {
    Set<String> parameters = ImmutableSortedSet.<String>orderedBy(Comparator.comparing(o -> o.substring(1))).addAll(PARSER.getQueryParameters(this.parsedStatement.getSqlWithoutComments())).build();
    ResultSet columnsResultSet = null;
    try {
        if (this.parsedStatement.isQuery()) {
            Statement statement = Statement.of(this.parsedStatement.getSqlWithoutComments());
            columnsResultSet = connection.analyzeQuery(statement, QueryAnalyzeMode.PLAN);
        }
        boolean describeFailed = false;
        if (parameters.isEmpty()) {
            ensureParameterLength(0);
        } else if (parameters.size() != this.parameterDataTypes.length || Arrays.stream(this.parameterDataTypes).anyMatch(p -> p == 0)) {
            // Note: We are only asking the backend to parse the types if there is at least one
            // parameter
            // with unspecified type. Otherwise, we will rely on the types given in PARSE.
            // Transform the statement into a select statement that selects the parameters, and then
            // extract the types from the result set metadata.
            Statement selectParamsStatement = transformToSelectParams(parameters);
            if (selectParamsStatement == null) {
                // The transformation failed. Just rely on the types given in the PARSE message. If the
                // transformation failed because the statement was malformed, the backend will catch that
                // at
                // a later stage.
                describeFailed = true;
                ensureParameterLength(parameters.size());
            } else {
                try (ResultSet paramsResultSet = connection.analyzeQuery(selectParamsStatement, QueryAnalyzeMode.PLAN)) {
                    extractParameterTypes(paramsResultSet);
                } catch (SpannerException exception) {
                    // Ignore here and rely on the types given in PARSE.
                    describeFailed = true;
                    ensureParameterLength(parameters.size());
                }
            }
        }
        if (columnsResultSet != null) {
            return new DescribeStatementMetadata(this.parameterDataTypes, columnsResultSet);
        }
        if (this.parsedStatement.isUpdate() && (describeFailed || !Strings.isNullOrEmpty(this.name))) {
            // Let the backend analyze the statement if it is a named prepared statement or if the query
            // that was used to determine the parameter types failed, so we can return a reasonable
            // error
            // message if the statement is invalid. If it is the unnamed statement or getting the param
            // types succeeded, we will let the following EXECUTE message handle that, instead of
            // sending
            // the statement twice to the backend.
            connection.analyzeUpdate(Statement.of(this.parsedStatement.getSqlWithoutComments()), QueryAnalyzeMode.PLAN);
        }
        return new DescribeStatementMetadata(this.parameterDataTypes, null);
    } finally {
        if (columnsResultSet != null) {
            columnsResultSet.close();
        }
    }
}
Also used : OptionsMetadata(com.google.cloud.spanner.pgadapter.metadata.OptionsMetadata) Arrays(java.util.Arrays) QueryAnalyzeMode(com.google.cloud.spanner.ReadContext.QueryAnalyzeMode) SpannerExceptionFactory(com.google.cloud.spanner.SpannerExceptionFactory) StatementType(com.google.cloud.spanner.connection.AbstractStatementParser.StatementType) ConnectionHandler(com.google.cloud.spanner.pgadapter.ConnectionHandler) Connection(com.google.cloud.spanner.connection.Connection) ArrayList(java.util.ArrayList) Oid(org.postgresql.core.Oid) ResultSet(com.google.cloud.spanner.ResultSet) Strings(com.google.common.base.Strings) ConnectionStatus(com.google.cloud.spanner.pgadapter.ConnectionHandler.ConnectionStatus) Nullable(javax.annotation.Nullable) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) Parser(com.google.cloud.spanner.pgadapter.parsers.Parser) ParsedStatement(com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement) Set(java.util.Set) DescribeStatementMetadata(com.google.cloud.spanner.pgadapter.metadata.DescribeStatementMetadata) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) DescribeMetadata(com.google.cloud.spanner.pgadapter.metadata.DescribeMetadata) ErrorCode(com.google.cloud.spanner.ErrorCode) SpannerException(com.google.cloud.spanner.SpannerException) Statement(com.google.cloud.spanner.Statement) List(java.util.List) FormatCode(com.google.cloud.spanner.pgadapter.parsers.Parser.FormatCode) StatementResult(com.google.cloud.spanner.connection.StatementResult) StructField(com.google.cloud.spanner.Type.StructField) VisibleForTesting(com.google.common.annotations.VisibleForTesting) InternalApi(com.google.api.core.InternalApi) Comparator(java.util.Comparator) ParsedStatement(com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement) Statement(com.google.cloud.spanner.Statement) ResultSet(com.google.cloud.spanner.ResultSet) SpannerException(com.google.cloud.spanner.SpannerException) DescribeStatementMetadata(com.google.cloud.spanner.pgadapter.metadata.DescribeStatementMetadata)

Example 2 with DescribeStatementMetadata

use of com.google.cloud.spanner.pgadapter.metadata.DescribeStatementMetadata in project pgadapter by GoogleCloudPlatform.

the class DescribeMessage method handleDescribeStatement.

/**
 * Called when a describe message of type 'S' is received.
 *
 * @throws Exception if sending the message back to the client causes an error.
 */
public void handleDescribeStatement() throws Exception {
    try {
        DescribeStatementMetadata metadata = (DescribeStatementMetadata) this.statement.describe();
        new ParameterDescriptionResponse(this.outputStream, metadata.getParameters()).send();
        if (metadata.getResultSet() != null) {
            new RowDescriptionResponse(this.outputStream, this.statement, metadata.getResultSet(), this.connection.getServer().getOptions(), QueryMode.EXTENDED).send();
        } else {
            new NoDataResponse(this.outputStream).send();
        }
    } catch (SpannerException exception) {
        this.handleError(exception);
    }
}
Also used : RowDescriptionResponse(com.google.cloud.spanner.pgadapter.wireoutput.RowDescriptionResponse) ParameterDescriptionResponse(com.google.cloud.spanner.pgadapter.wireoutput.ParameterDescriptionResponse) SpannerException(com.google.cloud.spanner.SpannerException) NoDataResponse(com.google.cloud.spanner.pgadapter.wireoutput.NoDataResponse) DescribeStatementMetadata(com.google.cloud.spanner.pgadapter.metadata.DescribeStatementMetadata)

Aggregations

SpannerException (com.google.cloud.spanner.SpannerException)2 DescribeStatementMetadata (com.google.cloud.spanner.pgadapter.metadata.DescribeStatementMetadata)2 InternalApi (com.google.api.core.InternalApi)1 ErrorCode (com.google.cloud.spanner.ErrorCode)1 QueryAnalyzeMode (com.google.cloud.spanner.ReadContext.QueryAnalyzeMode)1 ResultSet (com.google.cloud.spanner.ResultSet)1 SpannerExceptionFactory (com.google.cloud.spanner.SpannerExceptionFactory)1 Statement (com.google.cloud.spanner.Statement)1 StructField (com.google.cloud.spanner.Type.StructField)1 ParsedStatement (com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement)1 StatementType (com.google.cloud.spanner.connection.AbstractStatementParser.StatementType)1 Connection (com.google.cloud.spanner.connection.Connection)1 StatementResult (com.google.cloud.spanner.connection.StatementResult)1 ConnectionHandler (com.google.cloud.spanner.pgadapter.ConnectionHandler)1 ConnectionStatus (com.google.cloud.spanner.pgadapter.ConnectionHandler.ConnectionStatus)1 DescribeMetadata (com.google.cloud.spanner.pgadapter.metadata.DescribeMetadata)1 OptionsMetadata (com.google.cloud.spanner.pgadapter.metadata.OptionsMetadata)1 Parser (com.google.cloud.spanner.pgadapter.parsers.Parser)1 FormatCode (com.google.cloud.spanner.pgadapter.parsers.Parser.FormatCode)1 NoDataResponse (com.google.cloud.spanner.pgadapter.wireoutput.NoDataResponse)1