Uses Psycopg 3 database driver and PostgreSQL. Can be ported to another DB-API 2.0 compliant driver/database.
Implements parameter styles qmark
(like where name = ?
) and named
(like where name = :name
).
Methods are defined in SQL files (see methods.sql) that consist of one or more sections like this:
sql method specifier line
line(s) of SQL code
A SQL method specifier is an annotation-like comment line that start with --!
folowed by JSON with exactly these attributes:
- name - specifies the method name as a valid identifier, K&R style;
- returns - specifies the method return type. Can be one of:
- value - returns a scalar;
- record - returns a dictionary representing a single record;
- recordset - returns a list of dictionaries;
- none - returns
None
- param_mode - specifies the SQL parameter style. Can be one of:
- named -
named
style, as inwhere name = :name
; - positional -
qmark
style, as inwhere name = ?
; - none - no parameters
- named -
Example:
--! {"name": "Roman_64_numerals", "param_mode": "positional", "returns": "recordset"}
Queries can be of any length and complexity. Comments, empty lines and leading/trailing whitespaces in SQL files are ignored.
Important
Psycopg treats percent signs as SQL parameter placeholders. Therefore the PostgreSQL modulo operator (%
) must be doubled as %%
in queries.
Important
SQL files must be UTF-8 encoded.
db_gateway(connection, *sql_files, **autocommit_mode)
where autocommit_mode
(optional) can be autocommit = True
(the default) or autocommit = False
Usage illustration and details in demo files (demo.py, methods.sql and more.methods.sql).
demo.table.ddl.sql creates and populates the demo table in schema tests
.
import json
import psycopg
import dbgw
with psycopg.connect(<CONNECTIONSTRING>) as conn:
db = dbgw.db_gateway(
conn,
<PATH-TO-SQLFILES> + 'methods.sql', <PATH-TO-SQLFILES> + 'more.methods.sql',
autocommit = False
)
res = db.named_recordset({'seq_from':1000, 'seq_to':1099, 'status':5})
print ('\r\nnamed_recordset:', json.dumps(res, indent = 2))
res = db.positional_record(12345)
print ('\r\npositional_record:', json.dumps(res, indent = 2))
res = db.named_value({'seq':54321})
print ('\r\nnamed_value:', res)
res = db.positional_none(13, 123)
db.commit()
print ('\r\npositional_none:', res)
res = db.Roman_64_numerals(10)
print ('\r\nRoman_64_numerals:', json.dumps(res, indent = 2))
res = db.cleanup({'seq':200000});
db.commit()
print ('\r\ncleanup:', res)
Implements Read-Excel-into-PostgreSQL wizardry to ETL an Excel spreadsheet saved as XML (74.9 MB).
Here are the results on a very modest laptop: