A simple Python Library for building relational database queries using objects
Project description
Overview
This is pysqlscribe, the Python library intended to make building SQL queries in your code a bit easier!
Motivation
Other query building libraries, such as pypika are fantastic but not actively maintained. Some ORM libraries such as sqlalchemy offer similar (and awesome) capabilities using the core API, but if you're not already using the library in your application, it's a bit of a large dependency to introduce for the purposes of query building.
API
pysqlscribe currently offers several APIs for building queries.
Query
A Query object can be constructed using the QueryRegistry's get_builder if you supply a valid dialect (e.g; "mysql", "postgres", "oracle). For example, "mysql" would be:
from pysqlscribe.query import QueryRegistry
query_builder = QueryRegistry.get_builder("mysql")
query = query_builder.select("test_column", "another_test_column").from_("test_table").build()
Alternatively, you can create the corresponding Query class associated with the dialect directly:
from pysqlscribe.query import MySQLQuery
query_builder = MySQLQuery()
query = query_builder.select("test_column", "another_test_column").from_("test_table").build()
In both cases, the output is:
SELECT `test_column`,`another_test_column` FROM `test_table`
Furthermore, if there are any dialects that we currently don't support, you can create your own by subclassing Query and registering it with the QueryRegistry:
from pysqlscribe.query import QueryRegistry, Query
@QueryRegistry.register("custom")
class CustomQuery(Query):
...
Table
An alternative method for building queries is through the Table object:
from pysqlscribe.table import MySQLTable
table = MySQLTable("test_table", "test_column", "another_test_column")
query = table.select("test_column").build()
Output:
SELECT `test_column` FROM `test_table`
A schema for the table can also be provided as a keyword argument, after the columns:
from pysqlscribe.table import MySQLTable
table = MySQLTable("test_table", "test_column", "another_test_column", schema="test_schema")
query = table.select("test_column").build()
Output:
SELECT `test_column` FROM `test_schema.test_table`
Table also offers a create method in the event you've added a new dialect which doesn't have an associated Table implementation, or if you need to change it for different environments (e.g; sqlite for local development, mysql/postgres/oracle/etc. for deployment):
from pysqlscribe.table import Table
new_dialect_table_class = Table.create(
"new-dialect") # assuming you've registered "new-dialect" with the `QueryRegistry`
table = new_dialect_table_class("test_table", "test_column", "another_test_column")
You can overwrite the original columns supplied to a Table as well, which will delete the old attributes and set new ones:
from pysqlscribe.table import MySQLTable
table = MySQLTable("test_table", "test_column", "another_test_column")
table.test_column # valid
table.fields = ['new_test_column']
table.select("new_test_column")
table.new_test_column # now valid - but `table.test_column` is not anymore
Additionally, you can reference the Column attributes Table object when constructing queries. For example, in a WHERE clause:
from pysqlscribe.table import PostgresTable
table = PostgresTable("employee", "first_name", "last_name", "salary", "location")
table.select("first_name", "last_name", "location").where(table.salary > 1000).build()
Output:
SELECT "first_name","last_name","location" FROM "employee" WHERE salary > 1000
For computing aggregates (e.g; MAX, AVG, COUNT), we have functions available in the aggregate_functions module which will accept both strings or columns:
from pysqlscribe.table import PostgresTable
from pysqlscribe.aggregate_functions import max_
table = PostgresTable(
"employee", "first_name", "last_name", "store_location", "salary"
)
query = (
table.select(table.store_location, max_(table.salary))
.group_by(table.store_location)
.build()
)
# Equivalently:
query_with_strs = (
table.select("store_location", max_("salary"))
.group_by("store_location")
.build()
)
Output:
SELECT "store_location",MAX(salary) FROM "employee" GROUP BY "store_location"
Schema
For associating multiple Tables with a single schema, you can use the Schema:
from pysqlscribe.schema import Schema
schema = Schema("test_schema", tables=["test_table", "another_test_table"], dialect="postgres")
schema.tables # a list of two `Table` objects
This is functionally equivalent to:
from pysqlscribe.table import PostgresTable
table = PostgresTable("test_table", schema="test_schema")
another_table = PostgresTable("another_test_table", schema="test_schema")
Instead of supplying a dialect directly to Schema, you can also set the environment variable PYQUERY_BUILDER_DIALECT:
export PYQUERY_BUILDER_DIALECT = 'postgres'
from pysqlscribe.schema import Schema
schema = Schema("test_schema", tables=["test_table", "another_test_table"])
schema.tables # a list of two `PostgresTable` objects
Alternatively, if you already have existing Table objects you want to associate with the schema, you can supply them directly (in this case, dialect is not needed):
from pysqlscribe.schema import Schema
from pysqlscribe.table import PostgresTable
table = PostgresTable("test_table")
another_table = PostgresTable("another_test_table")
schema = Schema("test_schema", [table, another_table])
Schema also has each table set as an attribute, so in the example above, you can do the following:
schema.test_table # will return the supplied table object with the name `"test_table"`
Supported Dialects
This is anticipated to grow, also there are certainly operations that are missing within dialects.
-
MySQL -
Oracle -
Postgres -
Sqlite
TODO
- Add more dialects
- Support
OFFSETfor Oracle and SQLServer - Support for aliases for tables and columns
- Support subqueries
- Improved injection mitigation
💡 Interested in contributing? Check out the Local Development & Contributions Guide.
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 pysqlscribe-0.0.5.tar.gz.
File metadata
- Download URL: pysqlscribe-0.0.5.tar.gz
- Upload date:
- Size: 4.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.21
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
432e6345c915c98fdedcd664ff5c8e86213b062a623dc0eb18fc52ee332942e1
|
|
| MD5 |
c4d01dd75eb96c21167dd6e03133255a
|
|
| BLAKE2b-256 |
e02ad68fc4708f5e3f1e6db3dcc5db6ad5aaf48aa0efd6320cc8896d35193f05
|
File details
Details for the file pysqlscribe-0.0.5-py3-none-any.whl.
File metadata
- Download URL: pysqlscribe-0.0.5-py3-none-any.whl
- Upload date:
- Size: 5.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.21
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d29df082b6bb2887bc68f62c0754c4c41d7e1dd739e12211a85c5fea052e89f1
|
|
| MD5 |
65d8412ce6963193b85eed7034da7286
|
|
| BLAKE2b-256 |
198b8ebbc50d3dca25961fc4e6cbf1014d85be59ed848b2fe960667866ddcf6b
|