Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ec20f34

Browse files
committed
anonymize CRUD params if visiting_cte is present
Fixed issue in :class:`.CTE` constructs involving multiple DDL :class:`.Insert` statements with multiple VALUES parameter sets where the bound parameter names generated for these parameter sets would conflict, generating a compile time error. Fixes: sqlalchemy#12363 Change-Id: If8344ff725d4e0ec58d3ff61f38a0edcfc5bdebd
1 parent bceff0e commit ec20f34

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. change::
2+
:tags: bug, sql
3+
:tickets: 12363
4+
5+
Fixed issue in :class:`.CTE` constructs involving multiple DDL
6+
:class:`.Insert` statements with multiple VALUES parameter sets where the
7+
bound parameter names generated for these parameter sets would conflict,
8+
generating a compile time error.
9+

lib/sqlalchemy/sql/crud.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ def _create_bind_param(
393393
process: Literal[True] = ...,
394394
required: bool = False,
395395
name: Optional[str] = None,
396+
force_anonymous: bool = False,
396397
**kw: Any,
397398
) -> str: ...
398399

@@ -413,10 +414,14 @@ def _create_bind_param(
413414
process: bool = True,
414415
required: bool = False,
415416
name: Optional[str] = None,
417+
force_anonymous: bool = False,
416418
**kw: Any,
417419
) -> Union[str, elements.BindParameter[Any]]:
418-
if name is None:
420+
if force_anonymous:
421+
name = None
422+
elif name is None:
419423
name = col.key
424+
420425
bindparam = elements.BindParameter(
421426
name, value, type_=col.type, required=required
422427
)
@@ -486,7 +491,7 @@ def _key_getters_for_crud_column(
486491
)
487492

488493
def _column_as_key(
489-
key: Union[ColumnClause[Any], str]
494+
key: Union[ColumnClause[Any], str],
490495
) -> Union[str, Tuple[str, str]]:
491496
str_key = c_key_role(key)
492497
if hasattr(key, "table") and key.table in _et:
@@ -832,6 +837,7 @@ def _append_param_parameter(
832837
):
833838
value = parameters.pop(col_key)
834839

840+
has_visiting_cte = kw.get("visiting_cte") is not None
835841
col_value = compiler.preparer.format_column(
836842
c, use_table=compile_state.include_table_with_column_exprs
837843
)
@@ -864,6 +870,7 @@ def _append_param_parameter(
864870
else "%s_m0" % _col_bind_name(c)
865871
),
866872
accumulate_bind_names=accumulated_bind_names,
873+
force_anonymous=has_visiting_cte,
867874
**kw,
868875
)
869876
elif value._is_bind_parameter:
@@ -1435,6 +1442,7 @@ def _extend_values_for_multiparams(
14351442
values_0 = initial_values
14361443
values = [initial_values]
14371444

1445+
has_visiting_cte = kw.get("visiting_cte") is not None
14381446
mp = compile_state._multi_parameters
14391447
assert mp is not None
14401448
for i, row in enumerate(mp[1:]):
@@ -1451,7 +1459,8 @@ def _extend_values_for_multiparams(
14511459
compiler,
14521460
col,
14531461
row[key],
1454-
name="%s_m%d" % (col.key, i + 1),
1462+
name=("%s_m%d" % (col.key, i + 1)),
1463+
force_anonymous=has_visiting_cte,
14551464
**kw,
14561465
)
14571466
else:

test/sql/test_cte.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,37 @@ def test_insert_uses_independent_cte(self):
19001900
checkparams={"id": 1, "price": 20, "param_1": 10, "price_1": 50},
19011901
)
19021902

1903+
@testing.variation("num_ctes", ["one", "two"])
1904+
def test_multiple_multivalues_inserts(self, num_ctes):
1905+
"""test #12363"""
1906+
1907+
t1 = table("table1", column("id"), column("a"), column("b"))
1908+
1909+
t2 = table("table2", column("id"), column("a"), column("b"))
1910+
1911+
if num_ctes.one:
1912+
self.assert_compile(
1913+
insert(t1)
1914+
.values([{"a": 1}, {"a": 2}])
1915+
.add_cte(insert(t2).values([{"a": 5}, {"a": 6}]).cte()),
1916+
"WITH anon_1 AS "
1917+
"(INSERT INTO table2 (a) VALUES (:param_1), (:param_2)) "
1918+
"INSERT INTO table1 (a) VALUES (:a_m0), (:a_m1)",
1919+
)
1920+
1921+
elif num_ctes.two:
1922+
self.assert_compile(
1923+
insert(t1)
1924+
.values([{"a": 1}, {"a": 2}])
1925+
.add_cte(insert(t1).values([{"b": 5}, {"b": 6}]).cte())
1926+
.add_cte(insert(t2).values([{"a": 5}, {"a": 6}]).cte()),
1927+
"WITH anon_1 AS "
1928+
"(INSERT INTO table1 (b) VALUES (:param_1), (:param_2)), "
1929+
"anon_2 AS "
1930+
"(INSERT INTO table2 (a) VALUES (:param_3), (:param_4)) "
1931+
"INSERT INTO table1 (a) VALUES (:a_m0), (:a_m1)",
1932+
)
1933+
19031934
def test_insert_from_select_uses_independent_cte(self):
19041935
"""test #7036"""
19051936

0 commit comments

Comments
 (0)