diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-02-21 10:49:38 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-02-21 10:49:38 -0500 |
| commit | abe6c0f08a49859d8a2c36f4011e6f81ebf7ecb2 (patch) | |
| tree | b31e1d926289b3a3a1f019be3a441ba81e212315 | |
| parent | 509c81d736c5d80e82e55629aebc1dedd86370f7 (diff) | |
| download | sqlalchemy-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-- | CHANGES | 6 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 14 | ||||
| -rw-r--r-- | test/sql/test_compiler.py | 44 |
3 files changed, 62 insertions, 2 deletions
@@ -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')) |
