Skip to content

fix(spanner): harden identifier escaping in dbapi driver - #19054

Open
olavloite wants to merge 1 commit into
mainfrom
spanner-dbapi-harden-identifier-quoting
Open

olavloite wants to merge 1 commit into
mainfrom
spanner-dbapi-harden-identifier-quoting

Conversation

@olavloite

Copy link
Copy Markdown
Contributor

Previously, the DB-API identifier escaping helper attempted selective quoting based on a hardcoded list of reserved SQL keywords and simple alphanumeric rules. This required continuous maintenance as new Spanner keywords were introduced, left unlisted keywords unquoted, and could misparse multipart names that contained dots inside already-quoted parts.

This change:

  • Unconditionally quotes identifiers using GoogleSQL backticks and properly escapes embedded backticks and backslashes, eliminating the need to maintain keyword lists for quoting.
  • Properly handles multipart qualified identifiers (such as schema.table) without corrupting dots that appear inside already-quoted segments.
  • Rejects ASCII control characters (such as newlines and null bytes) to prevent SQL injection.
  • Validates that identifiers are strings and non-empty.
  • Retains and updates the reserved keywords list for backwards compatibility with downstream libraries that import it.

@olavloite
olavloite requested a review from a team as a code owner November 12, 2026 12:42

@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 updates the escape_name function in parse_utils.py to unconditionally quote identifiers with backticks, while adding strict type checking and validation against ASCII control characters and invalid qualified identifiers. It also adds new reserved keywords (GRAPH_TABLE and QUALIFY) to maintain backwards compatibility. The review feedback suggests a performance-conscious improvement to use re.search instead of a generator expression for detecting control characters, which should be benchmarked before merging.

Previously, the DB-API identifier escaping helper attempted selective quoting based on a hardcoded list of reserved SQL keywords and simple alphanumeric rules. This required continuous maintenance as new Spanner keywords were introduced, left unlisted keywords unquoted, and could misparse multipart names that contained dots inside already-quoted parts.

This change:
- Unconditionally quotes identifiers using GoogleSQL backticks and properly escapes embedded backticks and backslashes, eliminating the need to maintain keyword lists for quoting.
- Properly handles multipart qualified identifiers (such as schema.table) without corrupting dots that appear inside already-quoted segments.
- Rejects ASCII control characters (such as newlines and null bytes) to prevent SQL injection.
- Validates that identifiers are strings and non-empty.
- Retains and updates the reserved keywords list for backwards compatibility with downstream libraries that import it.
@olavloite
olavloite force-pushed the spanner-dbapi-harden-identifier-quoting branch from 9431cc5 to 4caac46 Compare November 12, 2026 12:56
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@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 updates the Spanner DB-API driver's identifier escaping logic in parse_utils.py. The escape_name function has been refactored to unconditionally quote identifiers with backticks (unless already quoted) and escape embedded delimiters, rather than only quoting reserved keywords or invalid identifiers. Additionally, the function now includes type annotations and strict validation, raising a TypeError for non-string inputs and a ValueError for identifiers containing ASCII control characters or invalid qualified formats. The SPANNER_RESERVED_KEYWORDS set has been updated with GRAPH_TABLE and QUALIFY for backwards compatibility with downstream packages. Corresponding unit tests have been updated and expanded to cover these changes, including new tests for invalid inputs and keyword compatibility. There are no review comments, and I have no feedback to provide.

This branch has not been deployed

No deployments
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