summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2018-10-23 01:06:24 +0100
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2018-10-23 01:17:15 +0100
commiteeef58b5812f6167dccbaee67fbc88429cdbb784 (patch)
tree291035eff1db8e5d4e3fc2af560cd7dc7e5bb07f
parent1de7d53fb1cc0163f24e2b8bcf3e6bab0e1072d4 (diff)
downloadpsycopg2-eeef58b5812f6167dccbaee67fbc88429cdbb784.tar.gz
Don't barf on Composite passed to execute_values()
Close #794
-rw-r--r--NEWS2
-rw-r--r--lib/extras.py4
-rwxr-xr-xtests/test_fast_executemany.py20
3 files changed, 26 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 7b13cd1..788dafb 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,8 @@ What's new in psycopg 2.7.6
- Fixed hang trying to :sql:`COPY` via `~cursor.execute()` (:ticket:`#781`).
- Fixed segfault accessing the `connection.readonly` and
`connection.deferrable` repeatedly (:ticket:`#790`).
+- `~psycopg2.extras.execute_values()` accepts `~psycopg2.sql.Composable`
+ objects (#794).
- `~psycopg2.errorcodes` map updated to PostgreSQL 11.
diff --git a/lib/extras.py b/lib/extras.py
index 4bb3a48..c33cffc 100644
--- a/lib/extras.py
+++ b/lib/extras.py
@@ -1259,6 +1259,10 @@ def execute_values(cur, sql, argslist, template=None, page_size=100):
[(1, 20, 3), (4, 50, 6), (7, 8, 9)])
'''
+ from psycopg2.sql import Composable
+ if isinstance(sql, Composable):
+ sql = sql.as_string(cur)
+
# we can't just use sql % vals because vals is bytes: if sql is bytes
# there will be some decoding error because of stupid codec used, and Py3
# doesn't implement % on bytes.
diff --git a/tests/test_fast_executemany.py b/tests/test_fast_executemany.py
index ad7a5b1..3a4f3cb 100755
--- a/tests/test_fast_executemany.py
+++ b/tests/test_fast_executemany.py
@@ -83,6 +83,16 @@ class TestExecuteBatch(FastExecuteTestMixin, testutils.ConnectingTestCase):
cur.execute("select id, val from testfast order by id")
self.assertEqual(cur.fetchall(), [(i, i * 10) for i in range(1000)])
+ def test_composed(self):
+ from psycopg2 import sql
+ cur = self.conn.cursor()
+ psycopg2.extras.execute_batch(cur,
+ sql.SQL("insert into {0} (id, val) values (%s, %s)")
+ .format(sql.Identifier('testfast')),
+ ((i, i * 10) for i in range(1000)))
+ cur.execute("select id, val from testfast order by id")
+ self.assertEqual(cur.fetchall(), [(i, i * 10) for i in range(1000)])
+
def test_pages(self):
cur = self.conn.cursor()
psycopg2.extras.execute_batch(cur,
@@ -169,6 +179,16 @@ class TestExecuteValues(FastExecuteTestMixin, testutils.ConnectingTestCase):
cur.execute("select id, val from testfast order by id")
self.assertEqual(cur.fetchall(), [(i, i * 10) for i in range(1000)])
+ def test_composed(self):
+ from psycopg2 import sql
+ cur = self.conn.cursor()
+ psycopg2.extras.execute_values(cur,
+ sql.SQL("insert into {0} (id, val) values %s")
+ .format(sql.Identifier('testfast')),
+ ((i, i * 10) for i in range(1000)))
+ cur.execute("select id, val from testfast order by id")
+ self.assertEqual(cur.fetchall(), [(i, i * 10) for i in range(1000)])
+
def test_pages(self):
cur = self.conn.cursor()
psycopg2.extras.execute_values(cur,