mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-25 18:33:44 +03:00
More doc love for the sql module
This commit is contained in:
parent
9926942260
commit
49461c2c39
|
@ -151,6 +151,24 @@ Psycopg converts :sql:`json` values into Python objects but :sql:`jsonb` values
|
|||
See :ref:`adapt-json` for further details.
|
||||
|
||||
|
||||
.. _faq-identifier:
|
||||
.. cssclass:: faq
|
||||
|
||||
How can I pass field/table names to a query?
|
||||
The arguments in the `~cursor.execute()` methods can only represent data
|
||||
to pass to the query: they cannot represent a table or field name::
|
||||
|
||||
# This doesn't work
|
||||
cur.execute("insert into %s values (%s)", ["my_table", 42])
|
||||
|
||||
If you want to build a query dynamically you can use the objects exposed
|
||||
by the `psycopg2.sql` module::
|
||||
|
||||
cur.execute(
|
||||
sql.SQL("insert into %s values (%%s)") % [sql.Identifier("my_table")],
|
||||
[42])
|
||||
|
||||
|
||||
.. _faq-bytea-9.0:
|
||||
.. cssclass:: faq
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
The module contains objects and functions useful to generate SQL dynamically,
|
||||
in a convenient and safe way. SQL identifiers (e.g. names of tables and
|
||||
fields) cannot be passed to the `~cursor.execute()` function like query
|
||||
fields) cannot be passed to the `~cursor.execute()` method like query
|
||||
arguments::
|
||||
|
||||
# This will not work
|
||||
|
@ -45,7 +45,7 @@ in the presence of a table or field name with containing characters to escape,
|
|||
or will present a potentially exploitable weakness.
|
||||
|
||||
The objects exposed by the `!psycopg2.sql` module allow generating SQL
|
||||
statements on the fly, separating clearly the variable parts in the statement
|
||||
statements on the fly, separating clearly the variable parts of the statement
|
||||
from the query parameters::
|
||||
|
||||
from psycopg2 import sql
|
||||
|
|
|
@ -132,9 +132,10 @@ query:
|
|||
>>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar",)) # correct
|
||||
>>> cur.execute("INSERT INTO foo VALUES (%s)", ["bar"]) # correct
|
||||
|
||||
- Only variable values should be bound via this method: it shouldn't be used
|
||||
to set table or field names. For these elements, ordinary string formatting
|
||||
should be used before running `~cursor.execute()`.
|
||||
- Only query values should be bound via this method: it shouldn't be used to
|
||||
merge table or field names to the query. If you need to generate dynamically
|
||||
an SQL query (for instance choosing dynamically a table name) you can use
|
||||
the facilities provided by the `psycopg2.sql` module.
|
||||
|
||||
|
||||
|
||||
|
|
58
lib/sql.py
58
lib/sql.py
|
@ -78,9 +78,10 @@ class Composed(Composable):
|
|||
|
||||
Example::
|
||||
|
||||
>>> sql.Composed([sql.SQL("insert into "), sql.Identifier("table")]) \\
|
||||
... .as_string(conn)
|
||||
'insert into "table"'
|
||||
>>> comp = sql.Composed(
|
||||
... [sql.SQL("insert into "), sql.Identifier("table")])
|
||||
>>> print(comp.as_string(conn))
|
||||
insert into "table"
|
||||
|
||||
.. automethod:: join
|
||||
"""
|
||||
|
@ -119,8 +120,8 @@ class Composed(Composable):
|
|||
Example::
|
||||
|
||||
>>> fields = sql.Identifier('foo') + sql.Identifier('bar') # a Composed
|
||||
>>> fields.join(', ').as_string(conn)
|
||||
'"foo", "bar"'
|
||||
>>> print(fields.join(', ').as_string(conn))
|
||||
"foo", "bar"
|
||||
|
||||
"""
|
||||
if isinstance(joiner, basestring):
|
||||
|
@ -155,9 +156,8 @@ class SQL(Composable):
|
|||
>>> query = sql.SQL("select %s from %s") % [
|
||||
... sql.SQL(', ').join([sql.Identifier('foo'), sql.Identifier('bar')]),
|
||||
... sql.Identifier('table')]
|
||||
>>> query.as_string(conn)
|
||||
select "foo", "bar" from "table"'
|
||||
|
||||
>>> print(query.as_string(conn))
|
||||
select "foo", "bar" from "table"
|
||||
|
||||
.. automethod:: join
|
||||
"""
|
||||
|
@ -184,8 +184,8 @@ class SQL(Composable):
|
|||
Example::
|
||||
|
||||
>>> snip - sql.SQL(', ').join(map(sql.Identifier, ['foo', 'bar', 'baz']))
|
||||
>>> snip.as_string(conn)
|
||||
'"foo", "bar", "baz"'
|
||||
>>> print(snip.as_string(conn))
|
||||
"foo", "bar", "baz"
|
||||
"""
|
||||
if isinstance(seq, Composed):
|
||||
seq = seq._seq
|
||||
|
@ -214,6 +214,15 @@ class Identifier(Composable):
|
|||
|
||||
.. __: https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html# \
|
||||
SQL-SYNTAX-IDENTIFIERS
|
||||
|
||||
Example::
|
||||
|
||||
>>> t1 = sql.Identifier("foo")
|
||||
>>> t2 = sql.Identifier("ba'r")
|
||||
>>> t3 = sql.Identifier('ba"z')
|
||||
>>> print(sql.SQL(', ').join([t1, t2, t3]).as_string(conn))
|
||||
"foo", "ba'r", "ba""z"
|
||||
|
||||
"""
|
||||
def __init__(self, string):
|
||||
if not isinstance(string, basestring):
|
||||
|
@ -239,6 +248,14 @@ class Literal(Composable):
|
|||
The string returned by `!as_string()` follows the normal :ref:`adaptation
|
||||
rules <python-types-adaptation>` for Python objects.
|
||||
|
||||
Example::
|
||||
|
||||
>>> s1 = sql.Literal("foo")
|
||||
>>> s2 = sql.Literal("ba'r")
|
||||
>>> s3 = sql.Literal(42)
|
||||
>>> print(sql.SQL(', ').join([s1, s2, s3]).as_string(conn))
|
||||
'foo', 'ba''r', 42
|
||||
|
||||
"""
|
||||
def __init__(self, wrapped):
|
||||
self._wrapped = wrapped
|
||||
|
@ -277,17 +294,20 @@ class Placeholder(Composable):
|
|||
|
||||
Examples::
|
||||
|
||||
>>> (sql.SQL("insert into table (%s) values (%s)") % [
|
||||
... sql.SQL(', ').join(map(sql.Identifier, names)),
|
||||
... sql.SQL(', ').join(sql.Placeholder() * 3)
|
||||
... ]).as_string(conn)
|
||||
'insert into table ("foo", "bar", "baz") values (%s, %s, %s)'
|
||||
>>> names = ['foo', 'bar', 'baz']
|
||||
|
||||
>>> (sql.SQL("insert into table (%s) values (%s)") % [
|
||||
>>> q1 = sql.SQL("insert into table (%s) values (%s)") % [
|
||||
... sql.SQL(', ').join(map(sql.Identifier, names)),
|
||||
... sql.SQL(', ').join(map(sql.Placeholder, names))
|
||||
... ]).as_string(conn)
|
||||
'insert into table ("foo", "bar", "baz") values (%(foo)s, %(bar)s, %(baz)s)'
|
||||
... sql.SQL(', ').join(sql.Placeholder() * 3)]
|
||||
>>> print(q1.as_string(conn))
|
||||
insert into table ("foo", "bar", "baz") values (%s, %s, %s)
|
||||
|
||||
>>> q2 = sql.SQL("insert into table (%s) values (%s)") % [
|
||||
... sql.SQL(', ').join(map(sql.Identifier, names)),
|
||||
... sql.SQL(', ').join(map(sql.Placeholder, names))]
|
||||
>>> print(q2.as_string(conn))
|
||||
insert into table ("foo", "bar", "baz") values (%(foo)s, %(bar)s, %(baz)s)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name=None):
|
||||
|
|
Loading…
Reference in New Issue
Block a user