Convenient formatting for psycopg2 SQL queries
Project description
Template Query
Provides an easy and readable way to create formattable template query strings with placeholders for psycopg2. Instead of wrapping arguments with psycopg2.sql classes (e.g. Literal, Identifier) the expected class can be written inside the query.
Quick Example:
>>> TemplateQuery('SELECT * FROM {table@Q} WHERE {@I} {@S} {value@L}').format(
... 'column_name', '>=', table='public.my_table', value=100
... ).as_string(conn)
'SELECT * FROM "public"."my_table" WHERE "column_name" >= 100'
Installation
This package requires psycopg2 and can be installed using pip to download it from PyPI:
$ pip install templatequery
or using setup.py if you have downloaded the source package locally:
$ python setup.py build
$ sudo python setup.py install
Usage
In psycopg2, variables can be inserted into queries using %s placeholders and supplying arguments to cursor.execute but this does not allow for identifier arguments such as table or columns names. The alternative is to use psycopg2.sql.SQL.format but this requires arguments to be converted into Composable objects such as Literal or Identifier.
The TemplateQuery class allows this conversion to be specified inside the query and applied to the formatting arguments automatically.
Normally placeholders are written as {} for positional arguments and {key_name} for keyword arguments. TemplateQuery allows for additional placeholders of the form {key_name@X}, where key_name is optional and X is one of the following formats which applies to the relevant argument a class from psycopg2.sql:
S(wraps withSQL) raw query snippet with no escaping !! beware of SQL injection !!I(wraps withIdentifier) identifier representing names of database objectsP(wraps withPlaceholder) %s style placeholder whose value can be added later
An additional form Q can be used to separate qualified names that are dot-separated, such as "schema.table", into a Composed of individual Identifier objects joined by SQL('.') . Supplying a tuple of identifiers and using the I form will achieve the same result when using psycopg2 >= 2.8
Example Script
from psycopg2 import connect
from psycopg2.extras import execute_values
from templatequery import TemplateQuery
from random import randint
# example database configuration
connection_details = dict(
host='localhost', dbname='test', user='postgres', password='password'
)
# example table containing items
params = dict(
table='public.item',
category='brand',
value='price_cents',
)
# queries
query_create = TemplateQuery(
"DROP TABLE IF EXISTS {table@Q}; "
"CREATE TABLE {table@Q} ("
"id bigserial, "
"{category@I} varchar, "
"{value@I} bigint);"
)
query_insert = TemplateQuery(
"INSERT INTO {table@Q} ({category@I}, {value@I}) "
"VALUES %s"
)
query_analyze = TemplateQuery(
"SELECT "
"{category@I}, AVG({value@I}) {avg_value@I}"
"FROM {table@Q}"
"GROUP BY {category@I}"
"ORDER BY {avg_value@I}"
)
# connect to postgreSQL using a psycopg2 connection
with connect(**connection_details) as conn:
cursor = conn.cursor()
# create table
cursor.execute(query_create.format(**params))
# insert data
# generate test data for columns (brand, price)
# where a higher value gives a character closer to A
data = []
for _ in range(1000):
score = randint(0, 5)
data.append(('FEDCBA'[score], (randint(1, 10000) * (score + 1))))
execute_values(cursor, query_insert.format(**params), data)
conn.commit()
# analyze average prices per category (brand)
cursor.execute(
query_analyze.format(
**params,
avg_value='avg_' + params['value']
)
)
result = cursor.fetchall()
>>> result
[
('F', Decimal('4975.8218390804597701')),
('E', Decimal('10353.853658536585')),
('D', Decimal('15447.445714285714')),
('C', Decimal('21370.236024844720')),
('B', Decimal('25997.774566473988')),
('A', Decimal('31847.215686274510'))
]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file templatequery-0.1.3.tar.gz.
File metadata
- Download URL: templatequery-0.1.3.tar.gz
- Upload date:
- Size: 7.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.0.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.8.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7fa6b30ec2e60d873bccd3b91744c783589d457950780b5bb76c455a6fc79e0
|
|
| MD5 |
81831fe97cd52972f65a0d41909c5d6f
|
|
| BLAKE2b-256 |
b654932e307531a8bcff5c3056aeb4b59becdcbacc8e213b05ec5c22c4e4e2eb
|
File details
Details for the file templatequery-0.1.3-py3-none-any.whl.
File metadata
- Download URL: templatequery-0.1.3-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.0.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.8.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40d00866f428d60cb1cf0e4e691d382c73492d7b097de714d5478f39b16770aa
|
|
| MD5 |
8513a729bda36287f7cff292be976375
|
|
| BLAKE2b-256 |
98706a2bdee982ead2a7ebc8f7e4b0aa8fe113c74a762756a9ae0973c70a41de
|