Skip to content

fix(spanner, sqlalchemy-spanner): fix reflection crashes, add native UUID support, and improve JsonObject#17822

Open
sakthivelmanii wants to merge 1 commit into
mainfrom
fix-sqlalchemy-spanner-reflection-uuid-batch-storing
Open

fix(spanner, sqlalchemy-spanner): fix reflection crashes, add native UUID support, and improve JsonObject#17822
sakthivelmanii wants to merge 1 commit into
mainfrom
fix-sqlalchemy-spanner-reflection-uuid-batch-storing

Conversation

@sakthivelmanii

Copy link
Copy Markdown
Contributor
  • Exclude SEARCH indexes and guard None column_sorting in SpannerDialect.get_multi_indexes to prevent reflection AttributeError crashes.
  • Register TOKENLIST in _type_map to enable table reflection for TOKENLIST columns without KeyError.
  • Add native UUID support in SpannerDialect (_type_map, _type_map_inv, SpannerDDLCompiler.visit_UUID, SpannerTypeCompiler.visit_UUID/visit_uuid) while preserving STRING(36) backward compatibility.
  • Fix spanner_storing column resolution in SpannerDDLCompiler.visit_create_index for unbound columns in Alembic batch mode.
  • Add to_python() method and public properties (is_null, is_array, is_scalar) to JsonObject in google-cloud-spanner.
  • Add unit tests in test_dialect.py and mockserver integration tests in test_dialect_integration.py.

Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:

  • Make sure to open an issue as a bug/issue before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea
  • Ensure the tests and linter pass
  • Code coverage does not decrease (if any source code was changed)
  • Appropriate docs were updated (if necessary)

Fixes #<issue_number_goes_here> 🦕

…UUID support, and improve JsonObject

- Exclude SEARCH indexes and guard None column_sorting in SpannerDialect.get_multi_indexes to prevent reflection AttributeError crashes.
- Register TOKENLIST in _type_map to enable table reflection for TOKENLIST columns without KeyError.
- Add native UUID support in SpannerDialect (_type_map, _type_map_inv, SpannerDDLCompiler.visit_UUID, SpannerTypeCompiler.visit_UUID/visit_uuid) while preserving STRING(36) backward compatibility.
- Fix spanner_storing column resolution in SpannerDDLCompiler.visit_create_index for unbound columns in Alembic batch mode.
- Add to_python() method and public properties (is_null, is_array, is_scalar) to JsonObject in google-cloud-spanner.
- Add unit tests in test_dialect.py and mockserver integration tests in test_dialect_integration.py.
@sakthivelmanii
sakthivelmanii requested a review from olavloite July 22, 2026 10:06
@sakthivelmanii
sakthivelmanii requested a review from a team as a code owner July 22, 2026 10:06

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

Copy link
Copy Markdown
Contributor

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 several enhancements across google-cloud-spanner and sqlalchemy-spanner. Specifically, it adds helper properties and a to_python() method to JsonObject for easier unwrapping of native Python objects. In sqlalchemy-spanner, it adds support for native UUID and TOKENLIST types, improves the handling of STORING clauses in index creation, and excludes SEARCH indexes from get_multi_indexes. Feedback is provided to guard against a potential TypeError in get_multi_indexes if the column orderings array (row[5]) is None.

Comment on lines 1340 to 1343
"column_sorting": {
col: order.lower() for col, order in zip(row[3], row[5])
col: (order.lower() if order else None)
for col, order in zip(row[3], row[5])
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

If row[5] (the column orderings array) is None (which can happen if the database returns a null array for certain index types or configurations), attempting to zip it with row[3] will raise a TypeError: zip argument #2 must support iteration. Guarding row[5] with a fallback to an empty list row[5] or [] prevents this potential crash.

Suggested change
"column_sorting": {
col: order.lower() for col, order in zip(row[3], row[5])
col: (order.lower() if order else None)
for col, order in zip(row[3], row[5])
},
"column_sorting": {
col: (order.lower() if order else None)
for col, order in zip(row[3], row[5] or [])
},

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.

1 participant