SQL utilities
sqlorm provides the SQL
class to quickly and easily compose SQL statements.
Composable pieces of parametrized SQL
An SQL
object is just a piece of SQL that can be combined with other SQL
objects to build a statement.
from sqlorm import SQL
# combine pieces of sql
q = SQL("SELECT * FROM table")
q = SQL("SELECT", "*", "FROM", "table")
q = SQL("SELECT *") + SQL("FROM table")
Use SQL.Param
to embed parameters in your queries:
with engine as tx:
q = SQL("SELECT * FROM table WHERE id =", SQL.Param(1))
task = tx.fetchone(q)
Note
Parameters automatically use the apropriate paramstyle placeholder defined by the underlying DBAPI driver (default is "qmark").
Use .render()
to render an SQL object to a tuple containing the sql string and its parameters:
q = SQL("SELECT * FROM table WHERE id =", SQL.Param(1))
assert str(q) == "SELECT * FROM table WHERE id = ?"
stmt, params = q.render()
assert stmt == "SELECT * FROM table WHERE id = ?"
assert params == [1]
Use Python operators to combine:
column = SQL("column_name")
s = column == SQL.Param("value") # column_name = ?
s = column > SQL.Param("value") # column_name > ?
s = column == SQL.Param("value") & column != SQL.Param("value2") # (column_name = ? AND column_name != ?)
s = column == SQL.Param("value") | column == SQL.Param("value2") # (column_name = ? OR column_name = ?)
s = ~column # NOT column_name
s = SQL.Param("value").in_(column) # ? IN column
Or any custom sql operators:
s = column.op("MATCH", SQL.Param("my text"))
Calling methods on SQL
objects can be used to build full SQL statements in pure python using method chaining.
sql_object.keyword(*args)
is the same as sql_object + SQL("KEYWORD", *args)
(underscores in keyword are replaced by spaces and trimmed)
q = SQL().select("*").from_("table").where(column == SQL.Param("value")).order_by(column)
# is the same as
q = SQL("SELECT", "*", "FROM", "table", "WHERE", column == SQL.Param("value"), "ORDER BY", column)
Useful shortcuts:
SQL.select()
instead ofSQL().select()
SQL.insert_into()
instead ofSQL().insert_into()
SQL.update()
instead ofSQL().update()
SQL.delete_from()
instead ofSQL().delete_from()
Handling list of SQL pieces
Use SQL.List
to manage lists of SQL
objects. A few subclasses exists:
SQL.List
renders a comma separated list of the rendered itemsSQL.Tuple
renders a parentheses enclosed comma separated list of the rendered itemsSQL.And
andSQL.Or
renders a parentheses enclosed list separated by the boolean operator of the rendered items (this is used when combining using&
and|
)
q = SQL.select(SQL.List(["col1", "col2"])).from_("table") # SELECT col1, col2 FROM table
q = SQL.insert_into("table", SQL.Tuple(["col1", "col2"])).values(SQL.Tuple([SQL.Param("value1"), SQL.Param("value2")])) # INSERT INTO table (col1, col2) VALUES (?, ?)
l = SQL.List()
l.append("col1") # SQL.List objects are subclasses of python's list
Handling columns
SQL.Col
and SQL.Cols
can be used to respectively represent a column and manage a list of columns:
q = SQL.select(SQL.Cols(["col1", "col2"], table="alias")).from_("table AS alias") # SELECT alias.col1, alias.col2 FROM table AS alias
q = SQL.select(SQL.Cols(["col1", "col2"], prefix="prefix_")).from_("table") # SELECT col1 AS prefix_col1, col2 AS prefix_col2 FROM table
q = SQL.select(SQL.Cols([SQL.Col("col1", prefix="prefix_"), SQL.Col("col2", alias="colalias")])).from_("table") # SELECT col1 AS prefix_col1, col2 AS colalias FROM table
columns = SQL.Cols(["col1", "col2", "col3"])
prefixed_cols = columns.prefixed("prefix_") # returns a new column list with all column prefixed
cols_with_table = columns.aliased_table("table") # returns a new column list with all column specifying the table name
s = columns["col1"] == SQL.Param("value") # access individual columns
s = columns.col2 == SQL.Param("value")
Easily generate insert and update statements
with engine as tx:
tx.execute(SQL.insert("table", {"col1": "value1"}))
tx.execute(SQL.update("table", {"col1": "value1"}).where("id =", SQL.Param(1)))
Call SQL functions
Use SQL.funcs.function_name()
where function_name is the SQL function name to render SQL function calls. All arguments are automatically wrapped in SQL.Param
unless they are already an SQL
object.
q = SQL("SELECT * FROM table WHERE col =", SQL.funcs.lower("value"))
q = SQL("SELECT", SQL.funcs.count(SQL("*")), "FROM table")
Templates
Templates are the underlying mechanism of sql functions.
- code in curly braces will be evaluated and be inserted in the final statement as is
- code in python format markers will be evaluated and inserted as parameters
from sqlorm import SQLTemplate
tpl = SQLTemplate("SELECT * FROM {table} WHERE created_at >= %(created_at)s")
stmt, params = tpl.render({"table": "my_table", "created_at": "2024-01-01"})