Skip to content

fix: safely handle schema expansion on prepared statements with results - #4929

Open
olavloite wants to merge 2 commits into
postgresql-dialectfrom
handle-changed-result-set-for-prepared-statement
Open

olavloite wants to merge 2 commits into
postgresql-dialectfrom
handle-changed-result-set-for-prepared-statement

Conversation

@olavloite

Copy link
Copy Markdown
Collaborator

When a table schema expands (e.g., adding a column) between executions of a prepared statement that returns rows (such as SELECT * or a write with RETURNING *), client drivers re-execute the statement using the number of result format codes negotiated during the initial parse/describe phase.

When Spanner returned more columns than the client provided format codes for, IntermediatePortalStatement.getResultFormatCode(index) threw an ArrayIndexOutOfBoundsException. Because Spanner had already executed and committed the statement, the client received a fatal error despite the write succeeding on the database.

This change:

  • Bounds-checks index in getResultFormatCode(int) and defaults out-of-bounds columns to text format (0).
  • Updates getParameterFormatCode(int) to check single-code mode before bounds checking, safely defaulting out-of-bounds parameter indices to 0.

Fixes b/562754971

When a table schema expands (e.g., adding a column) between executions of a
prepared statement that returns rows (such as `SELECT *` or a write with
`RETURNING *`), client drivers re-execute the statement using the number of
result format codes negotiated during the initial parse/describe phase.

When Spanner returned more columns than the client provided format codes for,
`IntermediatePortalStatement.getResultFormatCode(index)` threw an
`ArrayIndexOutOfBoundsException`. Because Spanner had already executed and
committed the statement, the client received a fatal error despite the write
succeeding on the database.

This change:
- Bounds-checks `index` in `getResultFormatCode(int)` and defaults out-of-bounds
  columns to text format (0).
- Updates `getParameterFormatCode(int)` to check single-code mode before bounds
  checking, safely defaulting out-of-bounds parameter indices to 0.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves the robustness of PGAdapter when handling concurrent schema changes. Specifically, it updates IntermediatePortalStatement to safely handle out-of-bounds indices for parameter and result format codes, preventing potential ArrayIndexOutOfBoundsException errors when columns are added or dropped. Additionally, it refactors DescribeResult to use a static factory method and introduces comprehensive unit and integration tests to verify these scenarios. I have no feedback to provide as there are no review comments to evaluate.

@rayudu3745

Copy link
Copy Markdown
Collaborator

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves the robustness of PGAdapter when handling concurrent schema changes by safely managing out-of-bounds parameter and result format codes in IntermediatePortalStatement. It also introduces a static factory method and a new constructor in DescribeResult to simplify instantiation, along with comprehensive unit and integration tests verifying these changes. The review feedback suggests renaming the parameters argument to givenParameterTypes in the new DescribeResult factory method and constructor to avoid confusion with the class field of the same name and to improve code clarity.

Comment thread src/main/java/com/google/cloud/spanner/pgadapter/metadata/DescribeResult.java Outdated
Comment thread src/main/java/com/google/cloud/spanner/pgadapter/metadata/DescribeResult.java Outdated
@olavloite
olavloite force-pushed the handle-changed-result-set-for-prepared-statement branch from 17a84c4 to df68d48 Compare September 29, 2026 08:35
@olavloite

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces safety checks and robust handling for out-of-bounds parameter and result format codes in IntermediatePortalStatement. It also adds a static factory method 'of' to DescribeResult with null preconditions, and updates IntermediatePreparedStatement to use it. Additionally, comprehensive unit and integration tests are added to verify behavior during concurrent schema changes (expansion and contraction) and with mixed or out-of-bounds format codes. I have no feedback to provide as there are no review comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants