summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-02-21 10:49:38 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2012-02-21 10:49:38 -0500
commitabe6c0f08a49859d8a2c36f4011e6f81ebf7ecb2 (patch)
treeb31e1d926289b3a3a1f019be3a441ba81e212315
parent509c81d736c5d80e82e55629aebc1dedd86370f7 (diff)
downloadsqlalchemy-abe6c0f08a49859d8a2c36f4011e6f81ebf7ecb2.tar.gz
- [bug] A warning is emitted when a not-present
column is stated in the values() clause of an insert() or update() construct. Will move to an exception in 0.8. [ticket:2413]
-rw-r--r--CHANGES6
-rw-r--r--lib/sqlalchemy/sql/compiler.py14
-rw-r--r--test/sql/test_compiler.py44
3 files changed, 62 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index c1869f555..d45f616a0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -49,6 +49,12 @@ CHANGES
so that .key takes precedence, but this
is not decided on yet. [ticket:2392]
+ - [bug] A warning is emitted when a not-present
+ column is stated in the values() clause
+ of an insert() or update() construct.
+ Will move to an exception in 0.8.
+ [ticket:2413]
+
- [bug] A significant change to how labeling
is applied to columns in SELECT statements
allows "truncated" labels, that is label names
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index de18c48f9..1db88c68c 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -1145,7 +1145,6 @@ class SQLCompiler(engine.Compiled):
for k, v in stmt.parameters.iteritems():
parameters.setdefault(sql._column_as_key(k), v)
-
# create a list of column assignment clauses as tuples
values = []
@@ -1204,7 +1203,7 @@ class SQLCompiler(engine.Compiled):
# "defaults", "primary key cols", etc.
for c in stmt.table.columns:
if c.key in parameters and c.key not in check_columns:
- value = parameters[c.key]
+ value = parameters.pop(c.key)
if sql._is_literal(value):
value = self._create_crud_bind_param(
c, value, required=value is required)
@@ -1300,6 +1299,17 @@ class SQLCompiler(engine.Compiled):
self.prefetch.append(c)
elif c.server_onupdate is not None:
self.postfetch.append(c)
+
+ if parameters and stmt.parameters:
+ check = set(parameters).intersection(
+ sql._column_as_key(k) for k in stmt.parameters
+ )
+ if check:
+ util.warn(
+ "Unconsumed column names: %s" %
+ (", ".join(check))
+ )
+
return values
def visit_delete(self, delete_stmt):
diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py
index 6330ee34e..528a49558 100644
--- a/test/sql/test_compiler.py
+++ b/test/sql/test_compiler.py
@@ -2855,6 +2855,50 @@ class CRUDTest(fixtures.TestBase, AssertsCompiledSQL):
self.assert_compile(i, "INSERT INTO foo (x, y) VALUES ((:param_1 + :x2), :y)",
params={'x2':1, 'y':2})
+ def test_unconsumed_names(self):
+ t = table("t", column("x"), column("y"))
+ t2 = table("t2", column("q"), column("z"))
+ assert_raises_message(
+ exc.SAWarning,
+ "Unconsumed column names: z",
+ t.insert().values(x=5, z=5).compile,
+ )
+ assert_raises_message(
+ exc.SAWarning,
+ "Unconsumed column names: z",
+ t.update().values(x=5, z=5).compile,
+ )
+
+ assert_raises_message(
+ exc.SAWarning,
+ "Unconsumed column names: j",
+ t.update().values(x=5, j=7).values({t2.c.z:5}).
+ where(t.c.x==t2.c.q).compile,
+ )
+
+ # bindparam names don't get counted
+ i = t.insert().values(x=3 + bindparam('x2'))
+ self.assert_compile(
+ i,
+ "INSERT INTO t (x) VALUES ((:param_1 + :x2))"
+ )
+
+ # even if in the params list
+ i = t.insert().values(x=3 + bindparam('x2'))
+ self.assert_compile(
+ i,
+ "INSERT INTO t (x) VALUES ((:param_1 + :x2))",
+ params={"x2":1}
+ )
+
+ assert_raises_message(
+ exc.SAWarning,
+ "Unconsumed column names: j",
+ t.update().values(x=5, j=7).compile,
+ column_keys=['j']
+ )
+
+
def test_labels_no_collision(self):
t = table('foo', column('id'), column('foo_id'))