A Python-based SQL query builder with a fluent and composable interface, built on expressql.
Project description
🧩 recordsql
recordsql is a Python-based SQL query builder that offers a fluent and composable interface for generating complex SQL statements — safely and efficiently.
📦 Installation
Install the required dependency and the pip package
pip install expressql
pip install recordsql
🚀 Features
- Fluent, chainable API for building SQL queries
- Support for
SELECT,INSERT,UPDATE,DELETE,WITH,JOIN,COUNT, andEXISTS - Parameterized placeholders for SQL injection safety
- Full support for multiple JOIN types (INNER, LEFT, RIGHT, FULL)
- Modular, composable components for query reuse
🛠️ Usage
Here are some examples of how to use recordsql to build SQL queries.
1. SELECT Query
from recordsql import SELECT, cols, text, col
# Define columns
name, age, email, total_purchases, signup_date, infractions = cols(
"name", "age", "email", "total_purchases", "signup_date", "infractions"
)
# Build a SELECT query
select_query = SELECT(name, age, email, total_purchases).FROM("customers").WHERE(
((signup_date - col("CURRENT_TIMESTAMP")) > (text("1 year").DATETIME())) &
(total_purchases > 1000) &
(infractions == 0)
).ORDER_BY(total_purchases, "DESC", (signup_date - col("CURRENT_TIMESTAMP"), "ASC")).LIMIT(10).OFFSET(1)
print(*select_query.placeholder_pair(), sep="\n")
2. WITH Query and JOINs
from recordsql import WITH, JoinQuery, cols, num, col
# Define columns and values
name, age, email, total_purchases = cols("name", "age", "email", "total_purchases")
current_store_id = num(1275682)
# Build a WITH query
with_query = WITH(select_query.AS("customer_data")).SELECT(
name, age, email, total_purchases
).FROM("customer_data").WHERE(
(total_purchases > 1000) & (infractions == 0)
).ORDER_BY(total_purchases, "DESC").LIMIT(10).OFFSET(1)
# Add JOINs
with_query.INNER_JOIN(
table_name="prices",
on=(current_store_id == col("store_id"))
).LEFT_JOIN(
table_name="orders",
on=(current_store_id == col("store_id"))
)
print(*with_query.placeholder_pair(), sep="\n")
Click to reveal output
WITH customer_data AS (SELECT name, age, email, total_purchases FROM "customers" WHERE ((signup_date-CURRENT_TIMESTAMP) > DATETIME(?)) AND (total_purchases > ?) AND (infractions = ?) ORDER BY total_purchases DESC, (signup_date-CURRENT_TIMESTAMP) ASC LIMIT 10 OFFSET 1) SELECT name, age, email, total_purchases FROM "customer_data" INNER JOIN "prices" ON ? = store_id LEFT JOIN "orders" ON ? = store_id WHERE (total_purchases > ?) AND (infractions = ?) ORDER BY total_purchases DESC LIMIT 10 OFFSET 1
['1 year', 1000, 0, 1000, 0, 1275682, 1275682]
3. UPDATE Query
from recordsql import UPDATE, col
# Build an UPDATE query
update_query = UPDATE("customers").SET(
name="John Doe",
age=30,
email="johndoe@gmail.com"
).WHERE(col("customer_id") == 12345).RETURNING("name", "age", "email")
print(*update_query.placeholder_pair(), sep="\n")
4. INSERT Query
from recordsql import INSERT
# Build an INSERT query
insert_query = INSERT("col1", "col2").INTO("table_name").VALUES(
(1, 2),
(3, 4),
(5, 6)
).ON_CONFLICT(
do="UPDATE",
conflict_cols=["col1"],
set={"col2": 10},
where=col("col1") == 1
).RETURNING("col1", "col2")
print(*insert_query.placeholder_pair(), sep="\n")
5. COUNT and EXISTS Queries
from recordsql import COUNT, EXISTS, col, text
# Build a COUNT query
count_query = COUNT().FROM("customers").WHERE(
((signup_date - col("CURRENT_TIMESTAMP")) > (text("1 year").DATETIME())) &
(total_purchases > 1000) &
(infractions == 0)
).GROUP_BY(name).HAVING(total_purchases > 1000)
print(*count_query.placeholder_pair(), sep="\n")
# Build an EXISTS query
exists_query = EXISTS().FROM("customers").WHERE(
((signup_date - col("CURRENT_TIMESTAMP")) > (text("1 year").DATETIME())) &
(total_purchases > 1000) &
(infractions == 0)
)
print(*exists_query.placeholder_pair(), sep="\n")
6. DELETE Query
from recordsql import DELETE, col, text
# Build a DELETE query
delete_query = DELETE().FROM("customers").WHERE(
((signup_date - col("CURRENT_TIMESTAMP")) > (text("1 year").DATETIME())) &
(total_purchases > 1000) &
(infractions == 0)
)
print(*delete_query.placeholder_pair(), sep="\n")
📝 Output
The queries generated by recordsql are parameterized and safe for execution. Here’s an example output:
WITH customer_data AS (
SELECT * FROM "customers"
WHERE ((signup_date - CURRENT_TIMESTAMP) > DATETIME(?))
AND (total_purchases > ?)
AND (infractions = ?)
ORDER BY total_purchases DESC, (signup_date - CURRENT_TIMESTAMP) ASC
LIMIT 10 OFFSET 1
)
SELECT * FROM "customer_data"
WHERE (total_purchases > ?)
AND (infractions = ?)
ORDER BY total_purchases DESC, (signup_date - CURRENT_TIMESTAMP) ASC
LIMIT 10 OFFSET 1
Placeholders:
['1 year', 1000, 0, 1000, 0]
📖 Documentation
Full documentation is available and includes:
- Installation Guide: Detailed installation instructions
- Quick Start: Get started with recordsql in minutes
- Advanced Examples: Complex query patterns and best practices
- API Reference: Complete API documentation with type hints
Building Documentation Locally
To build the documentation locally:
cd docs
poetry run sphinx-build -b html . _build/html
Or using make:
cd docs
make html # On Unix/Linux/macOS
make.bat html # On Windows
The generated documentation will be in docs/_build/html/. Open index.html in your browser to view it.
For more details on contributing to documentation, see docs/README.md.
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 recordsql-0.2.2.tar.gz.
File metadata
- Download URL: recordsql-0.2.2.tar.gz
- Upload date:
- Size: 30.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
76f275b60c448a82cd62e63f2e075d6414f1c5a48382d5372b2a88e559dfaceb
|
|
| MD5 |
36ebba62a6d817e2518e9c939dde1c1c
|
|
| BLAKE2b-256 |
93deadf5e4c2aeea4d16b0191326f1ee6968d28f69ed6925f533e758637f2dfc
|
Provenance
The following attestation bundles were made for recordsql-0.2.2.tar.gz:
Publisher:
python-publish.yml on Grayjou/recordsql
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recordsql-0.2.2.tar.gz -
Subject digest:
76f275b60c448a82cd62e63f2e075d6414f1c5a48382d5372b2a88e559dfaceb - Sigstore transparency entry: 1204744256
- Sigstore integration time:
-
Permalink:
Grayjou/recordsql@23bf1c8e95e3c45506b4e9dceb5ffb91ab1c6956 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/Grayjou
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@23bf1c8e95e3c45506b4e9dceb5ffb91ab1c6956 -
Trigger Event:
release
-
Statement type:
File details
Details for the file recordsql-0.2.2-py3-none-any.whl.
File metadata
- Download URL: recordsql-0.2.2-py3-none-any.whl
- Upload date:
- Size: 42.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73b6cc63faca2d5e94c332a627cc619005b7669c73dbe960b836fbdd712af042
|
|
| MD5 |
17e12b6d5a12cfe5e53b06dda6db0d4e
|
|
| BLAKE2b-256 |
26d96954b0fee717581282e9bc3e4d064221541ce4d8f029e72fea2ba7de16a8
|
Provenance
The following attestation bundles were made for recordsql-0.2.2-py3-none-any.whl:
Publisher:
python-publish.yml on Grayjou/recordsql
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recordsql-0.2.2-py3-none-any.whl -
Subject digest:
73b6cc63faca2d5e94c332a627cc619005b7669c73dbe960b836fbdd712af042 - Sigstore transparency entry: 1204744271
- Sigstore integration time:
-
Permalink:
Grayjou/recordsql@23bf1c8e95e3c45506b4e9dceb5ffb91ab1c6956 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/Grayjou
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@23bf1c8e95e3c45506b4e9dceb5ffb91ab1c6956 -
Trigger Event:
release
-
Statement type: