Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #12612 -- Corrected handling of parameter formatting in SQLite …

…backend so that executemany raises exceptions when bad parameter counts are provided. Thanks to Niels <niels@pythonheads.nl> for the report, and Gabriel Hurley for the help narrowing down the problem.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12836 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit d18501b0edb990d29562c029337c225fb79b3b49 1 parent ed36a5f
Russell Keith-Magee authored March 23, 2010
14  django/db/backends/sqlite3/base.py
@@ -7,6 +7,7 @@
7 7
 standard library.
8 8
 """
9 9
 
  10
+import re
10 11
 import sys
11 12
 
12 13
 from django.db import utils
@@ -185,6 +186,8 @@ def close(self):
185 186
         if self.settings_dict['NAME'] != ":memory:":
186 187
             BaseDatabaseWrapper.close(self)
187 188
 
  189
+FORMAT_QMARK_REGEX = re.compile(r'(?![^%])%s')
  190
+
188 191
 class SQLiteCursorWrapper(Database.Cursor):
189 192
     """
190 193
     Django uses "format" style placeholders, but pysqlite2 uses "qmark" style.
@@ -192,8 +195,8 @@ class SQLiteCursorWrapper(Database.Cursor):
192 195
     you'll need to use "%%s".
193 196
     """
194 197
     def execute(self, query, params=()):
  198
+        query = self.convert_query(query)
195 199
         try:
196  
-            query = self.convert_query(query, len(params))
197 200
             return Database.Cursor.execute(self, query, params)
198 201
         except Database.IntegrityError, e:
199 202
             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
@@ -201,19 +204,16 @@ def execute(self, query, params=()):
201 204
             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
202 205
 
203 206
     def executemany(self, query, param_list):
  207
+        query = self.convert_query(query)
204 208
         try:
205  
-            query = self.convert_query(query, len(param_list[0]))
206 209
             return Database.Cursor.executemany(self, query, param_list)
207  
-        except (IndexError,TypeError):
208  
-            # No parameter list provided
209  
-            return None
210 210
         except Database.IntegrityError, e:
211 211
             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
212 212
         except Database.DatabaseError, e:
213 213
             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
214 214
 
215  
-    def convert_query(self, query, num_params):
216  
-        return query % tuple("?" * num_params)
  215
+    def convert_query(self, query):
  216
+        return FORMAT_QMARK_REGEX.sub('?', query).replace('%%','%')
217 217
 
218 218
 def _sqlite_extract(lookup_type, dt):
219 219
     if dt is None:
13  tests/regressiontests/backends/tests.py
@@ -66,6 +66,19 @@ def test_django_extract(self):
66 66
         classes = models.SchoolClass.objects.filter(last_updated__day=20)
67 67
         self.assertEqual(len(classes), 1)
68 68
 
  69
+class ParameterHandlingTest(TestCase):
  70
+    def test_bad_parameter_count(self):
  71
+        "An executemany call with too many/not enough parameters will raise an exception (Refs #12612)"
  72
+        cursor = connection.cursor()
  73
+        query = ('INSERT INTO %s (%s, %s) VALUES (%%s, %%s)' % (
  74
+            connection.introspection.table_name_converter('backends_square'),
  75
+            connection.ops.quote_name('root'),
  76
+            connection.ops.quote_name('square')
  77
+        ))
  78
+        self.assertRaises(Exception, cursor.executemany, query, [(1,2,3),])
  79
+        self.assertRaises(Exception, cursor.executemany, query, [(1,),])
  80
+
  81
+
69 82
 def connection_created_test(sender, **kwargs):
70 83
     print 'connection_created signal'
71 84
 

0 notes on commit d18501b

Please sign in to comment.
Something went wrong with that request. Please try again.