Modified: trunk/docs/contents/pg/db_wrapper.rst (960 => 961)
--- trunk/docs/contents/pg/db_wrapper.rst 2019-01-04 17:49:21 UTC (rev 960)
+++ trunk/docs/contents/pg/db_wrapper.rst 2019-01-04 19:43:23 UTC (rev 961)
@@ -508,7 +508,7 @@
query_prepared -- execute a prepared statement
----------------------------------------------
-.. method:: DB.query_prepared([arg1, [arg2, ...]], [name=...])
+.. method:: DB.query_prepared(name, [arg1, [arg2, ...]])
Execute a prepared statement
@@ -524,9 +524,8 @@
:raises pg.OperationalError: prepared statement does not exist
This methods works like the :meth:`DB.query` method, except that instead of
-passing the SQL command, you pass the name of a prepared statement via the
-keyword-only argument *name*. If you don't pass a name, the unnamed
-statement will be executed, if you created one before.
+passing the SQL command, you pass the name of a prepared statement. If you
+pass an empty name, the unnamed statement will be executed.
You must have created the corresponding named or unnamed statement with
the :meth:`DB.prepare` method before, otherwise an :exc:`pg.OperationalError`
@@ -537,7 +536,7 @@
prepare -- create a prepared statement
--------------------------------------
-.. method:: DB.prepare(command, [name])
+.. method:: DB.prepare(name, command)
Create a prepared statement
@@ -550,10 +549,10 @@
This method creates a prepared statement for the given command with the
given name for later execution with the :meth:`DB.query_prepared` method.
-The name can be empty or left out to create an unnamed statement, in which
-case any pre-existing unnamed statement is automatically replaced;
-otherwise a :exc:`pg.ProgrammingError` is raised if the statement name is
-already defined in the current database session.
+The name can be empty to create an unnamed statement, in which case any
+pre-existing unnamed statement is automatically replaced; otherwise a
+:exc:`pg.ProgrammingError` is raised if the statement name is already
+defined in the current database session.
The SQL command may optionally contain positional parameters of the form
``$1``, ``$2``, etc instead of literal data. The corresponding values
@@ -562,21 +561,20 @@
Example::
- db.prepare("update employees set phone=$2 where ein=$1",
- name='update employees')
+ db.prepare('change phone',
+ "update employees set phone=$2 where ein=$1",
while True:
ein = input("Employee ID? ")
if not ein:
break
phone = input("Phone? ")
- rows = db.query_prepared(ein, phone,
- name='update employees).getresult()[0][0]
+ db.query_prepared('change phone', ein, phone)
.. note::
- The DB wrapper sometimes issues parameterized queries behind the scenes
- (for instance to find unknown database types) which could replace the
- unnamed statement. So we advice to always name prepared statements.
+ We recommend always using named queries, since unnamed queries have a
+ limited lifetime and can be automatically replaced or destroyed by
+ various operations on the database.
.. versionadded:: 5.1
Modified: trunk/pg.py (960 => 961)
--- trunk/pg.py 2019-01-04 17:49:21 UTC (rev 960)
+++ trunk/pg.py 2019-01-04 19:43:23 UTC (rev 961)
@@ -1869,18 +1869,15 @@
return self.query(*self.adapter.format_query(
command, parameters, types, inline))
- def query_prepared(self, *args, **kwargs):
+ def query_prepared(self, name, *args):
"""Execute a prepared SQL statement.
This works like the query() method, except that instead of passing
- the SQL command, you pass the name of a prepared statement via
- the keyword-only argument `name`. If you don't pass a name, the
- unnamed statement will be executed, if you created one before.
+ the SQL command, you pass the name of a prepared statement. If you
+ pass an empty name, the unnamed statement will be executed.
"""
if not self.db:
raise _int_error('Connection is not valid')
- # use kwargs because Python 2 does not support keyword-only arguments
- name = kwargs.get('name')
if name is None:
name = ''
if args:
@@ -1889,18 +1886,18 @@
self._do_debug('EXECUTE', name)
return self.db.query_prepared(name)
- def prepare(self, command, name=None):
+ def prepare(self, name, command):
"""Create a prepared SQL statement.
This creates a prepared statement for the given command with the
the given name for later execution with the query_prepared() method.
- The name can be empty or left out to create an unnamed statement,
- in which case any pre-existing unnamed statement is automatically
- replaced; otherwise it is an error if the statement name is already
- defined in the current database session.
- If any parameters are used, they can be referred to in the query as
- numbered parameters of the form $1.
+ The name can be empty to create an unnamed statement, in which case
+ any pre-existing unnamed statement is automatically replaced;
+ otherwise it is an error if the statement name is already
+ defined in the current database session. We recommend always using
+ named queries, since unnamed queries have a limited lifetime and
+ can be automatically replaced or destroyed by various operations.
"""
if not self.db:
raise _int_error('Connection is not valid')
Modified: trunk/tests/test_classic_dbwrapper.py (960 => 961)
--- trunk/tests/test_classic_dbwrapper.py 2019-01-04 17:49:21 UTC (rev 960)
+++ trunk/tests/test_classic_dbwrapper.py 2019-01-04 19:43:23 UTC (rev 961)
@@ -971,73 +971,78 @@
def testPrepare(self):
p = self.db.prepare
- self.assertIsNone(p("select 'hello'", 'my query'))
- self.assertIsNone(p("select 'world'", 'my other query'))
+ self.assertIsNone(p('my query', "select 'hello'"))
+ self.assertIsNone(p('my other query', "select 'world'"))
self.assertRaises(pg.ProgrammingError,
p, 'my query', "select 'hello, too'")
def testPrepareUnnamed(self):
p = self.db.prepare
- self.assertIsNone(p("select null"))
- self.assertIsNone(p("select null", None))
- self.assertIsNone(p("select null", ''))
- self.assertIsNone(p("select null", name=None))
- self.assertIsNone(p("select null", name=''))
+ self.assertIsNone(p('', "select null"))
+ self.assertIsNone(p(None, "select null"))
def testQueryPreparedWithoutParams(self):
f = self.db.query_prepared
self.assertRaises(pg.OperationalError, f, 'q')
p = self.db.prepare
- p("select 17", name='q1')
- p("select 42", name='q2')
- r = f(name='q1').getresult()[0][0]
+ p('q1', "select 17")
+ p('q2', "select 42")
+ r = f('q1').getresult()[0][0]
self.assertEqual(r, 17)
- r = f(name='q2').getresult()[0][0]
+ r = f('q2').getresult()[0][0]
self.assertEqual(r, 42)
def testQueryPreparedWithParams(self):
p = self.db.prepare
- p("select 1 + $1 + $2 + $3", name='sum')
- p("select initcap($1) || ', ' || $2 || '!'", name='cat')
+ p('sum', "select 1 + $1 + $2 + $3")
+ p('cat', "select initcap($1) || ', ' || $2 || '!'")
f = self.db.query_prepared
- r = f(2, 3, 5, name='sum').getresult()[0][0]
+ r = f('sum', 2, 3, 5).getresult()[0][0]
self.assertEqual(r, 11)
- r = f('hello', 'world', name='cat').getresult()[0][0]
+ r = f('cat', 'hello', 'world').getresult()[0][0]
self.assertEqual(r, 'Hello, world!')
def testQueryPreparedUnnamedWithOutParams(self):
f = self.db.query_prepared
- self.assertRaises(pg.OperationalError, f)
+ self.assertRaises(pg.OperationalError, f, None)
+ self.assertRaises(pg.OperationalError, f, '')
p = self.db.prepare
# make sure all types are known so that we will not
# generate other anonymous queries in the background
- p("select 'no name'::varchar")
- r = f().getresult()[0][0]
- self.assertEqual(r, 'no name')
- r = f(name=None).getresult()[0][0]
- self.assertEqual(r, 'no name')
- r = f(name='').getresult()[0][0]
- self.assertEqual(r, 'no name')
+ p('', "select 'empty'::varchar")
+ r = f(None).getresult()[0][0]
+ self.assertEqual(r, 'empty')
+ r = f('').getresult()[0][0]
+ self.assertEqual(r, 'empty')
+ p(None, "select 'none'::varchar")
+ r = f(None).getresult()[0][0]
+ self.assertEqual(r, 'none')
+ r = f('').getresult()[0][0]
+ self.assertEqual(r, 'none')
def testQueryPreparedUnnamedWithParams(self):
p = self.db.prepare
- p("select 1 + $1 + $2")
+ p('', "select 1 + $1 + $2")
f = self.db.query_prepared
- r = f(2, 3).getresult()[0][0]
+ r = f('', 2, 3).getresult()[0][0]
self.assertEqual(r, 6)
- r = f(2, 3, name=None).getresult()[0][0]
+ r = f(None, 2, 3).getresult()[0][0]
self.assertEqual(r, 6)
- r = f(2, 3, name='').getresult()[0][0]
- self.assertEqual(r, 6)
+ p(None, "select 2 + $1 + $2")
+ f = self.db.query_prepared
+ r = f('', 3, 4).getresult()[0][0]
+ self.assertEqual(r, 9)
+ r = f(None, 3, 4).getresult()[0][0]
+ self.assertEqual(r, 9)
def testDescribePrepared(self):
- self.db.prepare("select 1 as first, 2 as second", 'count')
+ self.db.prepare('count', "select 1 as first, 2 as second")
f = self.db.describe_prepared
r = f('count').listfields()
self.assertEqual(r, ('first', 'second'))
def testDescribePreparedUnnamed(self):
- self.db.prepare("select null as anon")
+ self.db.prepare('', "select null as anon")
f = self.db.describe_prepared
r = f().listfields()
self.assertEqual(r, ('anon',))
@@ -1052,14 +1057,14 @@
e = pg.OperationalError
self.assertRaises(e, f, 'myquery')
p = self.db.prepare
- p("select 1", 'q1')
- p("select 2", 'q2')
+ p('q1', "select 1")
+ p('q2', "select 2")
f('q1')
f('q2')
self.assertRaises(e, f, 'q1')
self.assertRaises(e, f, 'q2')
- p("select 1", 'q1')
- p("select 2", 'q2')
+ p('q1', "select 1")
+ p('q2', "select 2")
f()
self.assertRaises(e, f, 'q1')
self.assertRaises(e, f, 'q2')