Fix tuple parameter handling for SQLAlchemy 2.0 pooled queries

Fixes 'List of argument must consist only of dictionaries' error when
running parallel queries with ODBC-style ? placeholders.

The issue occurs because SQLAlchemy 2.0's text() expects named
parameters (dict) but the code was passing positional parameters (tuples).

Solution:
- Detect tuple parameters in _execute_query_pooled
- Convert tuples to dict with keys p1, p2, p3...
- Replace ? placeholders with :p1, :p2... in the query string
- Pass converted dict to conn.execute()

This maintains backward compatibility with single-connection mode
which uses pyodbc and handles tuple parameters natively.

Affected queries:
- table_exists (2 params: schema, table)
- get_columns (2 params: schema, table)
- get_primary_keys (2 params: schema, table)
This commit is contained in:
DevOps Team
2026-02-11 22:00:07 +07:00
parent 40bc615bf7
commit 2d6e8e6182

View File

@@ -75,6 +75,24 @@ class QueryExecutor:
raise ValueError("Only SELECT queries are allowed (READ ONLY)")
try:
# Convert tuple params to dict for SQLAlchemy 2.0 compatibility
if isinstance(params, tuple):
# Map positional params to p1, p2, p3...
params_dict = {f"p{i}": val for i, val in enumerate(params, 1)}
# Replace ? placeholders with :p1, :p2... by iterating
query_parts = []
last_pos = 0
param_index = 1
for char_pos, char in enumerate(query):
if char == '?':
query_parts.append(query[last_pos:char_pos])
query_parts.append(f':p{param_index}')
last_pos = char_pos + 1
param_index += 1
query_parts.append(query[last_pos:])
query = ''.join(query_parts)
params = params_dict
with self._engine.connect() as conn:
result = conn.execute(text(query), params or {})
df = pd.DataFrame(result.all(), columns=result.keys())