21
21
22
22
from typing import Any , Dict , List , MutableMapping , Optional , Tuple , Union
23
23
24
+ import sqlalchemy as sa
24
25
from sqlalchemy import ColumnClause , ValuesBase , cast , exc
25
- from sqlalchemy .sql import crud , dml
26
+ from sqlalchemy .sql import dml
26
27
from sqlalchemy .sql .base import _from_objects
27
28
from sqlalchemy .sql .compiler import SQLCompiler
28
29
from sqlalchemy .sql .crud import (REQUIRED , _as_dml_column , _create_bind_param ,
@@ -47,6 +48,11 @@ def visit_update(self, update_stmt, **kw):
47
48
)
48
49
update_stmt = compile_state .statement
49
50
51
+ # [20] CrateDB patch.
52
+ if not compile_state ._dict_parameters and \
53
+ not hasattr (update_stmt , '_crate_specific' ):
54
+ return super ().visit_update (update_stmt , ** kw )
55
+
50
56
toplevel = not self .stack
51
57
if toplevel :
52
58
self .isupdate = True
@@ -87,7 +93,8 @@ def visit_update(self, update_stmt, **kw):
87
93
table_text = self .update_tables_clause (
88
94
update_stmt , update_stmt .table , render_extra_froms , ** kw
89
95
)
90
- crud_params_struct = crud ._get_crud_params (
96
+ # [20] CrateDB patch.
97
+ crud_params_struct = _get_crud_params (
91
98
self , update_stmt , compile_state , toplevel , ** kw
92
99
)
93
100
crud_params = crud_params_struct .single_params
@@ -105,12 +112,38 @@ def visit_update(self, update_stmt, **kw):
105
112
text += table_text
106
113
107
114
text += " SET "
115
+
116
+ # [20] CrateDB patch begin.
117
+ include_table = extra_froms and \
118
+ self .render_table_with_column_in_update_from
119
+
120
+ set_clauses = []
121
+
122
+ for c , expr , value , _ in crud_params :
123
+ key = c ._compiler_dispatch (self , include_table = include_table )
124
+ clause = key + ' = ' + value
125
+ set_clauses .append (clause )
126
+
127
+ for k , v in compile_state ._dict_parameters .items ():
128
+ if isinstance (k , str ) and '[' in k :
129
+ bindparam = sa .sql .bindparam (k , v )
130
+ clause = k + ' = ' + self .process (bindparam )
131
+ set_clauses .append (clause )
132
+
133
+ text += ', ' .join (set_clauses )
134
+ # [20] CrateDB patch end.
135
+
136
+ """
137
+ # TODO: Complete SA20 migration.
138
+ # This is the column name/value joining code from SA20.
139
+ # It may be sensible to use this procedure instead of the old one.
108
140
text += ", ".join(
109
141
expr + "=" + value
110
142
for _, expr, value, _ in cast(
111
143
"List[Tuple[Any, str, str, Any]]", crud_params
112
144
)
113
145
)
146
+ """
114
147
115
148
if self .implicit_returning or update_stmt ._returning :
116
149
if self .returning_precedes_values :
@@ -356,6 +389,24 @@ def _get_crud_params(
356
389
kw ,
357
390
)
358
391
392
+ # [20] CrateDB patch.
393
+ #
394
+ # This sanity check performed by SQLAlchemy currently needs to be
395
+ # deactivated in order to satisfy the rewriting logic of the CrateDB
396
+ # dialect in `rewrite_update` and `visit_update`.
397
+ #
398
+ # It can be quickly reproduced by activating this section and running the
399
+ # test cases::
400
+ #
401
+ # ./bin/test -vvvv -t dict_test
402
+ #
403
+ # That croaks like::
404
+ #
405
+ # sqlalchemy.exc.CompileError: Unconsumed column names: characters_name
406
+ #
407
+ # TODO: Investigate why this is actually happening and eventually mitigate
408
+ # the root cause.
409
+ """
359
410
if parameters and stmt_parameter_tuples:
360
411
check = (
361
412
set(parameters)
@@ -367,6 +418,7 @@ def _get_crud_params(
367
418
"Unconsumed column names: %s"
368
419
% (", ".join("%s" % (c,) for c in check))
369
420
)
421
+ """
370
422
371
423
if (
372
424
_compile_state_isinsert (compile_state )
0 commit comments