fix: resolve pre-release dependency failures and sqlparse recursion (… · googleapis/python-spanner@9ec95b7

This repository was archived by the owner on Mar 31, 2026. It is now read-only.

File tree

3 files changed

lines changed

  • google/cloud/spanner_dbapi

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -233,6 +233,11 @@ def classify_statement(query, args=None):

233233

:rtype: ParsedStatement

234234

:returns: parsed statement attributes.

235235

"""

236+

# Check for RUN PARTITION command to avoid sqlparse processing it.

237+

# sqlparse fails with "Maximum grouping depth exceeded" on long partition IDs.

238+

if re.match(r"^\s*RUN\s+PARTITION\s+.+", query, re.IGNORECASE):

239+

return client_side_statement_parser.parse_stmt(query.strip())

240+
236241

# sqlparse will strip Cloud Spanner comments,

237242

# still, special commenting styles, like

238243

# PostgreSQL dollar quoted comments are not

Original file line numberDiff line numberDiff line change

@@ -555,6 +555,9 @@ def prerelease_deps(session, protobuf_implementation, database_dialect):

555555

"google-cloud-testutils",

556556

# dependencies of google-cloud-testutils"

557557

"click",

558+

# dependency of google-auth

559+

"cffi",

560+

"cryptography",

558561

]

559562
560563

for dep in prerel_deps:

Original file line numberDiff line numberDiff line change

@@ -200,6 +200,29 @@ def test_run_partition_classify_stmt(self):

200200

),

201201

)

202202
203+

def test_run_partition_classify_stmt_long_id(self):

204+

# Regression test for "Maximum grouping depth exceeded" with sqlparse

205+

long_id = "a" * 5000

206+

query = f"RUN PARTITION {long_id}"

207+

parsed_statement = classify_statement(query)

208+

self.assertEqual(

209+

parsed_statement,

210+

ParsedStatement(

211+

StatementType.CLIENT_SIDE,

212+

Statement(query),

213+

ClientSideStatementType.RUN_PARTITION,

214+

[long_id],

215+

),

216+

)

217+
218+

def test_run_partition_classify_stmt_incomplete(self):

219+

# "RUN PARTITION" without ID should be classified as UNKNOWN (not None)

220+

# because it falls through the specific check and sqlparse handles it.

221+

query = "RUN PARTITION"

222+

parsed_statement = classify_statement(query)

223+

self.assertEqual(parsed_statement.statement_type, StatementType.UNKNOWN)

224+

self.assertEqual(parsed_statement.statement.sql, query)

225+
203226

def test_run_partitioned_query_classify_stmt(self):

204227

parsed_statement = classify_statement(

205228

" RUN PARTITIONED QUERY SELECT s.SongName FROM Songs AS s "