From 7bf90e2f4dc211423a409a747a2392922ed7a9c7 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 7 Dec 2007 16:47:00 +0000 Subject: [PATCH] fix to unique bind params, you *can* use the same unique bindparam multiple times in a statement. the collision check is strictly detecting non-unique's that happen to have the same name. --- lib/sqlalchemy/sql/compiler.py | 2 +- test/sql/query.py | 12 ++++-------- test/sql/select.py | 10 +++++++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index aec75e76c3..6795c2fcd6 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -376,7 +376,7 @@ class DefaultCompiler(engine.Compiled): name = self._truncate_bindparam(bindparam) if name in self.binds: existing = self.binds[name] - if existing.unique or bindparam.unique: + if existing is not bindparam and (existing.unique or bindparam.unique): raise exceptions.CompileError("Bind parameter '%s' conflicts with unique bind parameter of the same name" % bindparam.key) self.binds[bindparam.key] = self.binds[name] = bindparam return self.bindparam_string(name) diff --git a/test/sql/query.py b/test/sql/query.py index 6233de7436..f675c9114c 100644 --- a/test/sql/query.py +++ b/test/sql/query.py @@ -170,18 +170,14 @@ class QueryTest(PersistTest): users.insert().execute(user_id = 8, user_name = 'fred') u = bindparam('userid') - s = users.select(or_(users.c.user_name==u, users.c.user_name==u)) + s = users.select(and_(users.c.user_name==u, users.c.user_name==u)) r = s.execute(userid='fred').fetchall() assert len(r) == 1 - def test_unique_conflict(self): u = bindparam('userid', unique=True) - s = users.select(or_(users.c.user_name==u, users.c.user_name==u)) - try: - str(s) - assert False - except exceptions.CompileError, e: - assert str(e) == "Bind parameter '{ANON %d userid}' conflicts with unique bind parameter of the same name" % id(u) + s = users.select(and_(users.c.user_name==u, users.c.user_name==u)) + r = s.execute({u:'fred'}).fetchall() + assert len(r) == 1 def test_bindparams_in_params(self): """test that a _BindParamClause itself can be a key in the params dict""" diff --git a/test/sql/select.py b/test/sql/select.py index d36703af43..66a87d6a04 100644 --- a/test/sql/select.py +++ b/test/sql/select.py @@ -968,7 +968,15 @@ EXISTS (select yay from foo where boo = lar)", assert s2.compile().params == {'myid':8, 'myotherid':7} assert s3.compile().params == {'myid':9, 'myotherid':7} - + # test using same 'unique' param object twice in one compile + s = select([table1.c.myid]).where(table1.c.myid==12).as_scalar() + s2 = select([table1, s], table1.c.myid==s) + self.assert_compile(s2, + "SELECT mytable.myid, mytable.name, mytable.description, (SELECT mytable.myid FROM mytable WHERE mytable.myid = :mytable_myid_2) AS anon_1 FROM mytable WHERE mytable.myid = (SELECT mytable.myid FROM mytable WHERE mytable.myid = :mytable_myid_2)") + positional = s2.compile(dialect=sqlite.dialect()) + pp = positional.get_params() + assert [pp[k] for k in positional.positiontup] == [12, 12] + # check that conflicts with "unique" params are caught s = select([table1], or_(table1.c.myid==7, table1.c.myid==bindparam('mytable_myid_1'))) try: -- 2.47.3