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:
@@ -75,6 +75,24 @@ class QueryExecutor:
|
|||||||
raise ValueError("Only SELECT queries are allowed (READ ONLY)")
|
raise ValueError("Only SELECT queries are allowed (READ ONLY)")
|
||||||
|
|
||||||
try:
|
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:
|
with self._engine.connect() as conn:
|
||||||
result = conn.execute(text(query), params or {})
|
result = conn.execute(text(query), params or {})
|
||||||
df = pd.DataFrame(result.all(), columns=result.keys())
|
df = pd.DataFrame(result.all(), columns=result.keys())
|
||||||
|
|||||||
Reference in New Issue
Block a user