A Python-based query builder for PostgreSQL.
Project description
Build-a-Query
A Python-based query builder designed to represent, compile, and execute SQL queries using a dialect-agnostic Abstract Syntax Tree (AST). Supports PostgreSQL and SQLite.
Features
- Dialect-Agnostic AST: Build queries using high-level Python objects.
- Full DML Support: Create
SELECT,INSERT,UPDATE, andDELETEstatements. - Advanced Querying: Support for CTEs (
WITH), Subqueries, Set Operations (UNION,INTERSECT,EXCEPT), and Window Functions (OVER). - Rich Expression Logic: Includes
CASEexpressions,IN,BETWEEN, and type casting. - DDL Support: Basic schema management with
CREATE TABLEandDROP TABLE. - Visitor Pattern Traversal: Extensible architecture for analysis and compilation.
- Secure Compilation: Automatic parameterization to prevent SQL injection.
- Execution Layer: Built-in support for executing compiled queries via
psycopg(PostgreSQL) and the standard librarysqlite3(SQLite).
Installation
For Users
Install Build-a-Query via pip:
pip install buildaquery
Requirements:
- Python 3.12+
- PostgreSQL database: A running PostgreSQL instance (version 12+ recommended). You can set this up locally, via Docker, or use a cloud service.
- Example with Docker:
docker run --name postgres -e POSTGRES_PASSWORD=yourpassword -d -p 5432:5432 postgres:15
- Example with Docker:
psycopg(automatically installed as a dependency) - the PostgreSQL adapter for Python.python-dotenv(automatically installed as a dependency) - for loading environment variables from a.envfile.- SQLite: Uses Python's standard library
sqlite3module.- SQLite Version: SQLite 3.x via Python's
sqlite3module (the exact SQLite version depends on your Python build; checksqlite3.sqlite_versionat runtime).
- SQLite Version: SQLite 3.x via Python's
Environment Variables
To connect to your PostgreSQL database, set the following environment variables (or use a .env file with python-dotenv):
DB_HOST: PostgreSQL host (e.g.,localhost)DB_PORT: PostgreSQL port (e.g.,5432)DB_NAME: Database name (e.g.,mydatabase)DB_USER: Database username (e.g.,postgres)DB_PASSWORD: Database password (e.g.,yourpassword)
Example .env file:
DB_HOST=localhost
DB_PORT=5432
DB_NAME=buildaquery
DB_USER=postgres
DB_PASSWORD=yourpassword
For Developers
Clone the repository and set up the development environment:
git clone https://github.com/yourusername/buildaquery.git
cd buildaquery
Install dependencies using Poetry:
poetry install
Activate the virtual environment:
poetry shell
Quick Start
Here's a simple example of creating a table, inserting data, querying it, and dropping the table. This example uses environment variables for database connection (see Environment Variables section above).
from dotenv import load_dotenv
import os
from buildaquery.execution.postgres import PostgresExecutor
from buildaquery.abstract_syntax_tree.models import (
CreateStatementNode, TableNode, ColumnDefinitionNode,
InsertStatementNode, ColumnNode, LiteralNode,
SelectStatementNode, StarNode, DropStatementNode
)
# Load environment variables
load_dotenv()
# Build connection string from environment variables
db_host = os.getenv('DB_HOST')
db_port = os.getenv('DB_PORT')
db_name = os.getenv('DB_NAME')
db_user = os.getenv('DB_USER')
db_password = os.getenv('DB_PASSWORD')
connection_string = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
# Set up executor with your PostgreSQL connection
executor = PostgresExecutor(connection_info=connection_string)
# Define table
users_table = TableNode(name="users")
# Create table
create_stmt = CreateStatementNode(
table=users_table,
columns=[
ColumnDefinitionNode(name="id", data_type="SERIAL", primary_key=True),
ColumnDefinitionNode(name="name", data_type="TEXT", not_null=True),
ColumnDefinitionNode(name="age", data_type="INTEGER")
]
)
executor.execute(create_stmt)
# Insert data
insert_stmt = InsertStatementNode(
table=users_table,
columns=[ColumnNode(name="name"), ColumnNode(name="age")],
values=[LiteralNode(value="Alice"), LiteralNode(value=30)]
)
executor.execute(insert_stmt)
# Query data
select_stmt = SelectStatementNode(
select_list=[StarNode()], # SELECT *
from_table=users_table
)
results = executor.execute(select_stmt)
print(results) # [(1, 'Alice', 30)]
# Drop table
drop_stmt = DropStatementNode(table=users_table, if_exists=True)
executor.execute(drop_stmt)
SQLite Quick Start
from buildaquery.execution.sqlite import SqliteExecutor
from buildaquery.abstract_syntax_tree.models import (
CreateStatementNode, TableNode, ColumnDefinitionNode,
InsertStatementNode, ColumnNode, LiteralNode,
SelectStatementNode, StarNode, DropStatementNode
)
executor = SqliteExecutor(connection_info="static/test-sqlite/db.sqlite")
users_table = TableNode(name="users")
create_stmt = CreateStatementNode(
table=users_table,
columns=[
ColumnDefinitionNode(name="id", data_type="INTEGER", primary_key=True),
ColumnDefinitionNode(name="name", data_type="TEXT", not_null=True),
ColumnDefinitionNode(name="age", data_type="INTEGER")
]
)
executor.execute(create_stmt)
insert_stmt = InsertStatementNode(
table=users_table,
columns=[ColumnNode(name="name"), ColumnNode(name="age")],
values=[LiteralNode(value="Alice"), LiteralNode(value=30)]
)
executor.execute(insert_stmt)
select_stmt = SelectStatementNode(
select_list=[StarNode()],
from_table=users_table
)
print(executor.execute(select_stmt))
drop_stmt = DropStatementNode(table=users_table, if_exists=True)
executor.execute(drop_stmt)
For more examples, see the examples/ directory.
Development Setup
Prerequisites
- Python 3.12+
- Poetry (for dependency management)
- Docker (for running integration tests)
Setting Up the Environment
-
Clone the repository:
git clone https://github.com/yourusername/buildaquery.git cd buildaquery
-
Install dependencies:
poetry install -
Activate the virtual environment:
poetry shell
Running Tests
Unit Tests
Run unit tests for all modules:
poetry run pytest buildaquery/tests
Integration Tests
Integration tests require a PostgreSQL database. Start the test database using Docker:
docker-compose up -d
Then run integration tests:
poetry run pytest tests
SQLite integration tests use the file-based database at static/test-sqlite/db.sqlite.
All Tests
Run all tests (unit and integration):
poetry run all-tests
Running Examples
Execute the sample script:
poetry run python examples/sample_query.py
Project Structure
buildaquery/abstract_syntax_tree/: Defines query nodes and AST models.buildaquery/traversal/: Base classes for AST traversal (Visitor/Transformer pattern).buildaquery/compiler/: Dialect-specific SQL generation (PostgreSQL and SQLite).buildaquery/execution/: Database connection and execution logic.tests/: Exhaustive unit and integration tests.examples/: Practical demonstrations of the library.scripts/: Utility scripts for testing and maintenance.
Contributing
Contributions are welcome! Please see the contributing guidelines for more information.
License
This project is licensed under the MIT License - see the LICENSE.txt file for details.
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 buildaquery-0.2.0.tar.gz.
File metadata
- Download URL: buildaquery-0.2.0.tar.gz
- Upload date:
- Size: 21.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.12.8 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d8f2502d3ab27eb839dfdcfc2b863452260910ffda5c72f6bde692ab687385c
|
|
| MD5 |
2e6c6007e4555f5af3e1aff711c6c0ec
|
|
| BLAKE2b-256 |
6cb78454a95d125419908c295279ad926c197d51b04f467d893364ce6585ef7b
|
File details
Details for the file buildaquery-0.2.0-py3-none-any.whl.
File metadata
- Download URL: buildaquery-0.2.0-py3-none-any.whl
- Upload date:
- Size: 33.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.12.8 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7fd1ac35a828a7a16c86556af5482c67745374197704858b675da43423208e9d
|
|
| MD5 |
766525746cde9a85bf403dd001770128
|
|
| BLAKE2b-256 |
c2e9505c7ecff06b4f4980dcb87d749dbd1ffda264b277d99ce259ecc05e1d13
|