Skip to main content

A modern, type-safe, and extensible SQL query builder for Python.

Project description

sqlo

CI PyPI Documentation License

A lightweight and powerful SQL query builder for Python. Build SQL queries with a clean, intuitive API while staying safe from SQL injection. Support for JSON fields, CTEs, batch updates, and more!

Why sqlo?

  • 🪶 Lightweight: Zero dependencies, minimal footprint
  • Simple: Intuitive fluent API, easy to learn
  • 🛡️ Secure by Default: Built-in SQL injection protection
  • 🐍 Pythonic: Fluent API design that feels natural to Python developers
  • 🧩 Composable: Build complex queries from reusable parts
  • 🚀 Extensible: Support for custom dialects and functions
  • 🔍 Type-Safe: Designed with type hints for better IDE support
  • Well-Tested: 99% code coverage with comprehensive security tests

Installation

pip install sqlo

Quick Start

from sqlo import Q

# SELECT query
query = Q.select("id", "name").from_("users").where("active", True)
sql, params = query.build()
# SQL: SELECT `id`, `name` FROM `users` WHERE `active` = %s
# Params: (True,)

# INSERT query
query = Q.insert_into("users").values([
    {"name": "Alice", "email": "alice@example.com"}
])
sql, params = query.build()

Debug Mode

Global Debug Mode

Enable debug mode to automatically print all queries:

from sqlo import Q
# Enable debug mode globally
Q.set_debug(True)
query = Q.select("*").from_("users").where("id", 1)
sql, params = query.build()
# Automatically prints:
# [sqlo DEBUG] SELECT * FROM `users` WHERE `id` = %s
# [sqlo DEBUG] Params: (1,)
# Disable debug mode
Q.set_debug(False)

Query Debug Mode

You can also enable debug mode for a specific query:

from sqlo import Q
query = Q.select("*").from_("users").where("id", 1).debug()
sql, params = query.build(
# Prints debug output for this query only
# [sqlo DEBUG] SELECT * FROM `users` WHERE `id` = %s
# [sqlo DEBUG] Params: (1,)

JSON Field Support

Query JSON columns with ease:

from sqlo import Q, JSON

# Extract JSON fields in SELECT
query = Q.select("id", JSON("data").extract("name").as_("name")).from_("users")
# SQL: SELECT `id`, `data`->>'$.name' AS `name` FROM `users`

# Filter by JSON fields
query = Q.select("*").from_("users").where(JSON("data").extract("age"), 18, ">")
# SQL: SELECT * FROM `users` WHERE `data`->>'$.age' > %s

Batch Updates

Efficiently update multiple rows with different values:

values = [
    {"id": 1, "name": "Alice", "status": "active"},
    {"id": 2, "name": "Bob", "status": "inactive"},
]
query = Q.update("users").batch_update(values, key="id")
# Generates optimized CASE WHEN SQL

Common Table Expressions (CTE)

Build complex queries with CTEs:

from sqlo import Q, func

# Define a CTE
cte = Q.select("user_id", func.count("*").as_("order_count")) \
    .from_("orders") \
    .group_by("user_id") \
    .as_("user_orders")

# Use it in main query
query = Q.select("u.name", "uo.order_count") \
    .with_(cte) \
    .from_("users", alias="u") \
    .join("user_orders uo", "u.id = uo.user_id")

Window Functions

Perform advanced analytics with window functions:

from sqlo import Q, Window, func

# Ranking within partitions
query = Q.select(
    "name",
    "department",
    "salary",
    func.row_number().over(
        Window.partition_by("department").and_order_by("-salary")
    ).as_("rank")
).from_("employees")
# SQL: SELECT `name`, `department`, `salary`,
#   ROW_NUMBER() OVER (PARTITION BY `department` ORDER BY `salary` DESC) AS `rank`
# FROM `employees`

# Running totals
query = Q.select(
    "date",
    "amount",
    func.sum("amount").over(
        Window.order_by("date").rows_between("UNBOUNDED PRECEDING", "CURRENT ROW")
    ).as_("running_total")
).from_("transactions")

# LAG and LEAD for time series
query = Q.select(
    "date",
    "value",
    func.lag("value", 1).over(Window.order_by("date")).as_("prev_value"),
    func.lead("value", 1).over(Window.order_by("date")).as_("next_value")
).from_("metrics")

Documentation

Full documentation is available at https://nan-guo.github.io/sqlo/.

You can also browse the markdown files on GitHub:

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sqlo-0.2.0.tar.gz (131.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sqlo-0.2.0-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file sqlo-0.2.0.tar.gz.

File metadata

  • Download URL: sqlo-0.2.0.tar.gz
  • Upload date:
  • Size: 131.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sqlo-0.2.0.tar.gz
Algorithm Hash digest
SHA256 bd989ad9d92e702054bf6ecd05d71b5b96656c44ef19c76ba5cbcb1b3ee515ae
MD5 d120ea1d9698c8e53fba4d4156070de0
BLAKE2b-256 22f8e167cbaa57c19c7b9d82123b8ea65307354ac17146972f17e228d863c647

See more details on using hashes here.

File details

Details for the file sqlo-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: sqlo-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 24.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sqlo-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a557b3e9e551730887236a3458f78521322f760f5427d6000eda27174c7a34b1
MD5 d74a12cf637d87707f5a074358fb1078
BLAKE2b-256 be7d665d232285faf83d769e660dd154daf0b3b3eb014113879d8dbc38bc6597

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page