summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2012-01-22 16:41:20 +0000
committerAymeric Augustin <aymeric.augustin@m4x.org>2012-01-22 16:41:20 +0000
commit7beb0db79b468b5cc6f20b05873a631ace989a84 (patch)
treecbd05cb494038b412287c3e6968b3bb853d8e3cb
parent4d030e540dc7b64d783510ba0d46c40f9713d305 (diff)
Fixed #10320 -- Made it possible to use executemany with iterators. Thanks MockSoul for the report.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17387 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/db/backends/oracle/base.py3
-rw-r--r--django/db/backends/util.py10
-rw-r--r--tests/regressiontests/backends/tests.py39
3 files changed, 40 insertions, 12 deletions
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index 105730c69c..f1ee987ba8 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -670,6 +670,9 @@ class FormatStylePlaceholderCursor(object):
raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def executemany(self, query, params=None):
+ # cx_Oracle doesn't support iterators, convert them to lists
+ if params is not None and not isinstance(params, (list, tuple)):
+ params = list(params)
try:
args = [(':arg%d' % i) for i in range(len(params[0]))]
except (IndexError, TypeError):
diff --git a/django/db/backends/util.py b/django/db/backends/util.py
index 3ba1cb00cd..32e0f4f702 100644
--- a/django/db/backends/util.py
+++ b/django/db/backends/util.py
@@ -47,7 +47,7 @@ class CursorDebugWrapper(CursorWrapper):
'time': "%.3f" % duration,
})
logger.debug('(%.3f) %s; args=%s' % (duration, sql, params),
- extra={'duration':duration, 'sql':sql, 'params':params}
+ extra={'duration': duration, 'sql': sql, 'params': params}
)
def executemany(self, sql, param_list):
@@ -58,12 +58,16 @@ class CursorDebugWrapper(CursorWrapper):
finally:
stop = time()
duration = stop - start
+ try:
+ times = len(param_list)
+ except TypeError: # param_list could be an iterator
+ times = '?'
self.db.queries.append({
- 'sql': '%s times: %s' % (len(param_list), sql),
+ 'sql': '%s times: %s' % (times, sql),
'time': "%.3f" % duration,
})
logger.debug('(%.3f) %s; args=%s' % (duration, sql, param_list),
- extra={'duration':duration, 'sql':sql, 'params':param_list}
+ extra={'duration': duration, 'sql': sql, 'params': param_list}
)
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index 436da8c2d0..cfb662ee80 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -14,6 +14,7 @@ from django.db.backends.signals import connection_created
from django.db.backends.postgresql_psycopg2 import version as pg_version
from django.db.utils import ConnectionHandler, DatabaseError, load_backend
from django.test import TestCase, skipUnlessDBFeature, TransactionTestCase
+from django.test.utils import override_settings
from django.utils import unittest
from . import models
@@ -308,23 +309,43 @@ class EscapingChecks(TestCase):
class BackendTestCase(TestCase):
- def test_cursor_executemany(self):
- #4896: Test cursor.executemany
+
+ def create_squares_with_executemany(self, args):
cursor = connection.cursor()
- qn = connection.ops.quote_name
opts = models.Square._meta
- f1, f2 = opts.get_field('root'), opts.get_field('square')
- query = ('INSERT INTO %s (%s, %s) VALUES (%%s, %%s)'
- % (connection.introspection.table_name_converter(opts.db_table), qn(f1.column), qn(f2.column)))
- cursor.executemany(query, [(i, i**2) for i in range(-5, 6)])
+ tbl = connection.introspection.table_name_converter(opts.db_table)
+ f1 = connection.ops.quote_name(opts.get_field('root').column)
+ f2 = connection.ops.quote_name(opts.get_field('square').column)
+ query = 'INSERT INTO %s (%s, %s) VALUES (%%s, %%s)' % (tbl, f1, f2)
+ cursor.executemany(query, args)
+
+ def test_cursor_executemany(self):
+ #4896: Test cursor.executemany
+ args = [(i, i**2) for i in range(-5, 6)]
+ self.create_squares_with_executemany(args)
self.assertEqual(models.Square.objects.count(), 11)
for i in range(-5, 6):
square = models.Square.objects.get(root=i)
self.assertEqual(square.square, i**2)
+ def test_cursor_executemany_with_empty_params_list(self):
#4765: executemany with params=[] does nothing
- cursor.executemany(query, [])
- self.assertEqual(models.Square.objects.count(), 11)
+ args = []
+ self.create_squares_with_executemany(args)
+ self.assertEqual(models.Square.objects.count(), 0)
+
+ def test_cursor_executemany_with_iterator(self):
+ #10320: executemany accepts iterators
+ args = iter((i, i**2) for i in range(-3, 2))
+ self.create_squares_with_executemany(args)
+ self.assertEqual(models.Square.objects.count(), 5)
+
+ args = iter((i, i**2) for i in range(3, 7))
+ with override_settings(DEBUG=True):
+ # same test for DebugCursorWrapper
+ self.create_squares_with_executemany(args)
+ self.assertEqual(models.Square.objects.count(), 9)
+
def test_unicode_fetches(self):
#6254: fetchone, fetchmany, fetchall return strings as unicode objects