]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
merged -r5987:5991 of trunk
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 29 May 2009 21:57:15 +0000 (21:57 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 29 May 2009 21:57:15 +0000 (21:57 +0000)
CHANGES
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/sql/expression.py
test/sql/query.py
test/sql/select.py

diff --git a/CHANGES b/CHANGES
index 4f47bfe09f93c54826b74e14f4855574d5b75e10..94a0acf88ad370dc9dac5e3923c1a7d6204df81b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,21 @@ CHANGES
 - orm
     - Fixed bug introduced in 0.5.4 whereby Composite types
       fail when default-holding columns are flushed.
+
+- sql
+    - Removed an obscure feature of execute() (including connection,
+      engine, Session) whereby a bindparam() construct can be sent as 
+      a key to the params dictionary.  This usage is undocumented
+      and is at the core of an issue whereby the bindparam() object
+      created implicitly by a text() construct may have the same 
+      hash value as a string placed in the params dictionary and
+      may result in an inappropriate match when computing the final
+      bind parameters.   Internal checks for this condition would
+      add significant latency to the critical task of parameter 
+      rendering, so the behavior is removed.  This is a backwards
+      incompatible change for any application that may have been
+      using this feature, however the feature has never been
+      documented.
     
 0.5.4p2
 =======
index db864daa002a2e445a6ed7e3041ca088b55d3523..66018934e15e964a862bf2751b439e4fca27cef2 100644 (file)
@@ -225,7 +225,7 @@ class SQLCompiler(engine.Compiled):
             params = util.column_dict(params)
             pd = {}
             for bindparam, name in self.bind_names.iteritems():
-                for paramname in (bindparam, bindparam.key, bindparam.shortname, name):
+                for paramname in (bindparam.key, bindparam.shortname, name):
                     if paramname in params:
                         pd[name] = params[paramname]
                         break
index 3fd95642e6b1154f678961804524ed410085c0ee..68696ae8e41ea6ca10d91ac0184d5104b59f6ae4 100644 (file)
@@ -2098,7 +2098,7 @@ class _TextClause(ClauseElement):
         if bindparams is not None:
             for b in bindparams:
                 self.bindparams[b.key] = b
-
+                
     @property
     def type(self):
         if self.typemap is not None and len(self.typemap) == 1:
index b124428c63d64541a6cd3e78e9f712f37b04d0a9..4e1faa1c50fca119ce2e2e8b19757c48a49bd196 100644 (file)
@@ -313,21 +313,6 @@ class QueryTest(TestBase):
         r = s.execute(userid='fred').fetchall()
         assert len(r) == 1
 
-        u = bindparam('userid', unique=True)
-        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"""
-
-        users.insert().execute(user_id = 7, user_name = 'jack')
-        users.insert().execute(user_id = 8, user_name = 'fred')
-
-        u = bindparam('userid')
-        r = users.select(users.c.user_name==u).execute({u:'fred'}).fetchall()
-        assert len(r) == 1
-
     def test_bindparam_shortname(self):
         """test the 'shortname' field on BindParamClause."""
         users.insert().execute(user_id = 7, user_name = 'jack')
index 4bee94e1426d6f645dc8477408a03c6f3dbf8959..ee0cb6b392ecba4644b3b5856b962a4423d1b5ce 100644 (file)
@@ -1157,7 +1157,21 @@ UNION SELECT mytable.myid FROM mytable"
         s = select([table1], or_(table1.c.myid==7, table1.c.myid==8, table1.c.myid==bindparam('myid_1')))
         self.assertRaisesMessage(exc.CompileError, "conflicts with unique bind parameter of the same name", str, s)
 
-
+    def test_binds_no_hash_collision(self):
+        """test that construct_params doesn't corrupt dict due to hash collisions"""
+        
+        total_params = 100000
+        
+        in_clause = [':in%d' % i for i in range(total_params)]
+        params = dict(('in%d' % i, i) for i in range(total_params))
+        sql = 'text clause %s' % ', '.join(in_clause)
+        t = text(sql)
+        assert len(t.bindparams) == total_params
+        c = t.compile()
+        pp = c.construct_params(params)
+        assert len(set(pp)) == total_params
+        assert len(set(pp.values())) == total_params
+        
 
     def test_bind_as_col(self):
         t = table('foo', column('id'))