]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
`ValuesBase.values` inconsistency fix
authorAubrey Stark-Toller <aubrey@kleetope.net>
Fri, 5 Jan 2018 20:06:23 +0000 (15:06 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 12 Jan 2018 16:30:05 +0000 (11:30 -0500)
Fixed bug in :meth:`.Insert.values` where using the "multi-values"
format in combination with :class:`.Column` objects as keys rather
than strings would fail.   Pull request courtesy Aubrey Stark-Toller.

Change-Id: I9d3b40b5950df8f5bfdc8b1d22f9c3afb277f17f
Pull-request: https://github.com/zzzeek/sqlalchemy/pull/412
Fixes: #4162
(cherry picked from commit ab2165e6d6e9b33f772e9eb3668b3e32175093c4)

doc/build/changelog/unreleased_11/4162.rst [new file with mode: 0644]
lib/sqlalchemy/sql/crud.py
test/sql/test_insert.py

diff --git a/doc/build/changelog/unreleased_11/4162.rst b/doc/build/changelog/unreleased_11/4162.rst
new file mode 100644 (file)
index 0000000..8f831f6
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 4162
+    :versions: 1.2.1
+
+    Fixed bug in :meth:`.Insert.values` where using the "multi-values"
+    format in combination with :class:`.Column` objects as keys rather
+    than strings would fail.   Pull request courtesy Aubrey Stark-Toller.
index 5739c22f9e52f84e79390501673895fc98c2cd05..b71256bd5aeea6e6c2d4c814cc03da0da3d46ee3 100644 (file)
@@ -597,23 +597,28 @@ def _extend_values_for_multiparams(compiler, stmt, values, kw):
     values_0 = values
     values = [values]
 
-    values.extend(
-        [
-            (
-                c,
-                (_create_bind_param(
-                    compiler, c, row[c.key],
-                    name="%s_m%d" % (c.key, i + 1), **kw
-                ) if elements._is_literal(row[c.key])
-                    else compiler.process(
-                        row[c.key].self_group(), **kw))
-                if c.key in row else
-                _process_multiparam_default_bind(compiler, stmt, c, i, kw)
-            )
-            for (c, param) in values_0
-        ]
-        for i, row in enumerate(stmt.parameters[1:])
-    )
+    for i, row in enumerate(stmt.parameters[1:]):
+        extension = []
+        for (col, param) in values_0:
+            if col in row or col.key in row:
+                key = col if col in row else col.key
+
+                if elements._is_literal(row[key]):
+                    new_param = _create_bind_param(
+                        compiler, col, row[key],
+                        name="%s_m%d" % (col.key, i + 1), **kw
+                    )
+                else:
+                    new_param = compiler.process(row[key].self_group(), **kw)
+            else:
+                new_param = _process_multiparam_default_bind(
+                    compiler, stmt, col, i, kw
+                )
+
+            extension.append((col, new_param))
+
+        values.append(extension)
+
     return values
 
 
index d3bc11a9697cdee86e5270b92033313256317651..6d41a4dca565a46f90f9dba24acf9b50ba158462 100644 (file)
@@ -839,6 +839,39 @@ class MultirowTest(_InsertTestBase, fixtures.TablesTest, AssertsCompiledSQL):
             checkparams=checkparams,
             dialect=dialect)
 
+    def test_named_with_column_objects(self):
+        table1 = self.tables.mytable
+
+        values = [
+            {table1.c.myid: 1, table1.c.name: 'a', table1.c.description: 'b'},
+            {table1.c.myid: 2, table1.c.name: 'c', table1.c.description: 'd'},
+            {table1.c.myid: 3, table1.c.name: 'e', table1.c.description: 'f'},
+        ]
+
+        checkparams = {
+            'myid_m0': 1,
+            'myid_m1': 2,
+            'myid_m2': 3,
+            'name_m0': 'a',
+            'name_m1': 'c',
+            'name_m2': 'e',
+            'description_m0': 'b',
+            'description_m1': 'd',
+            'description_m2': 'f',
+        }
+
+        dialect = default.DefaultDialect()
+        dialect.supports_multivalues_insert = True
+
+        self.assert_compile(
+            table1.insert().values(values),
+            'INSERT INTO mytable (myid, name, description) VALUES '
+            '(:myid_m0, :name_m0, :description_m0), '
+            '(:myid_m1, :name_m1, :description_m1), '
+            '(:myid_m2, :name_m2, :description_m2)',
+            checkparams=checkparams,
+            dialect=dialect)
+
     def test_positional(self):
         table1 = self.tables.mytable