From d097417025e71286ad5bbde6e0a79caacabbbd64 Mon Sep 17 00:00:00 2001 From: Shai Berger Date: Fri, 28 Jun 2013 06:15:03 +0300 Subject: Support 'pyformat' style parameters in raw queries, Refs #10070 Add support for Oracle, fix an issue with the repr of RawQuerySet, add tests and documentations. Also added a 'supports_paramstyle_pyformat' database feature, True by default, False for SQLite. Thanks Donald Stufft for review of documentation. --- tests/backends/tests.py | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'tests/backends') diff --git a/tests/backends/tests.py b/tests/backends/tests.py index c6cad56ec1..c1a26df7fc 100644 --- a/tests/backends/tests.py +++ b/tests/backends/tests.py @@ -456,13 +456,24 @@ class SqliteChecks(TestCase): class BackendTestCase(TestCase): def create_squares_with_executemany(self, args): + self.create_squares(args, 'format', True) + + def create_squares(self, args, paramstyle, multiple): cursor = connection.cursor() opts = models.Square._meta 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) + if paramstyle=='format': + query = 'INSERT INTO %s (%s, %s) VALUES (%%s, %%s)' % (tbl, f1, f2) + elif paramstyle=='pyformat': + query = 'INSERT INTO %s (%s, %s) VALUES (%%(root)s, %%(square)s)' % (tbl, f1, f2) + else: + raise ValueError("unsupported paramstyle in test") + if multiple: + cursor.executemany(query, args) + else: + cursor.execute(query, args) def test_cursor_executemany(self): #4896: Test cursor.executemany @@ -491,6 +502,35 @@ class BackendTestCase(TestCase): self.create_squares_with_executemany(args) self.assertEqual(models.Square.objects.count(), 9) + @skipUnlessDBFeature('supports_paramstyle_pyformat') + def test_cursor_execute_with_pyformat(self): + #10070: Support pyformat style passing of paramters + args = {'root': 3, 'square': 9} + self.create_squares(args, 'pyformat', multiple=False) + self.assertEqual(models.Square.objects.count(), 1) + + @skipUnlessDBFeature('supports_paramstyle_pyformat') + def test_cursor_executemany_with_pyformat(self): + #10070: Support pyformat style passing of paramters + args = [{'root': i, 'square': i**2} for i in range(-5, 6)] + self.create_squares(args, 'pyformat', multiple=True) + 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) + + @skipUnlessDBFeature('supports_paramstyle_pyformat') + def test_cursor_executemany_with_pyformat_iterator(self): + args = iter({'root': i, 'square': i**2} for i in range(-3, 2)) + self.create_squares(args, 'pyformat', multiple=True) + self.assertEqual(models.Square.objects.count(), 5) + + args = iter({'root': i, 'square': i**2} for i in range(3, 7)) + with override_settings(DEBUG=True): + # same test for DebugCursorWrapper + self.create_squares(args, 'pyformat', multiple=True) + self.assertEqual(models.Square.objects.count(), 9) + def test_unicode_fetches(self): #6254: fetchone, fetchmany, fetchall return strings as unicode objects qn = connection.ops.quote_name -- cgit v1.3