From: Mike Bayer Date: Tue, 21 Feb 2012 15:49:38 +0000 (-0500) Subject: - [bug] A warning is emitted when a not-present X-Git-Tag: rel_0_7_6~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=abe6c0f08a49859d8a2c36f4011e6f81ebf7ecb2;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - [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] --- diff --git a/CHANGES b/CHANGES index c1869f5556..d45f616a00 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 de18c48f91..1db88c68c9 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 6330ee34e9..528a495583 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'))