buildaquery 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AnirudhB3000
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,255 @@
1
+ Metadata-Version: 2.4
2
+ Name: buildaquery
3
+ Version: 0.1.0
4
+ Summary: A Python-based query builder for PostgreSQL.
5
+ License: MIT
6
+ License-File: LICENSE.txt
7
+ Author: Anirudh Bhattacharya
8
+ Author-email: anirudhbhattacharya1@gmail.com
9
+ Requires-Python: >=3.12,<4.0
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Topic :: Database
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Dist: Pygments (==2.19.2)
23
+ Requires-Dist: colorama (==0.4.6)
24
+ Requires-Dist: packaging (==26.0)
25
+ Requires-Dist: pluggy (==1.6.0)
26
+ Requires-Dist: psycopg (==3.3.3)
27
+ Requires-Dist: python-dotenv (>=1.2.1,<2.0.0)
28
+ Requires-Dist: typing_extensions (==4.15.0)
29
+ Requires-Dist: tzdata (==2025.3)
30
+ Project-URL: Homepage, https://github.com/AnirudhB3000/buildaquery
31
+ Project-URL: Repository, https://github.com/AnirudhB3000/buildaquery
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Build-a-Query
35
+
36
+ A Python-based query builder designed to represent, compile, and execute SQL queries using a dialect-agnostic Abstract Syntax Tree (AST). Initial support is focused on PostgreSQL.
37
+
38
+ ## Features
39
+
40
+ - **Dialect-Agnostic AST**: Build queries using high-level Python objects.
41
+ - **Full DML Support**: Create `SELECT`, `INSERT`, `UPDATE`, and `DELETE` statements.
42
+ - **Advanced Querying**: Support for CTEs (`WITH`), Subqueries, Set Operations (`UNION`, `INTERSECT`, `EXCEPT`), and Window Functions (`OVER`).
43
+ - **Rich Expression Logic**: Includes `CASE` expressions, `IN`, `BETWEEN`, and type casting.
44
+ - **DDL Support**: Basic schema management with `CREATE TABLE` and `DROP TABLE`.
45
+ - **Visitor Pattern Traversal**: Extensible architecture for analysis and compilation.
46
+ - **Secure Compilation**: Automatic parameterization to prevent SQL injection.
47
+ - **Execution Layer**: Built-in support for executing compiled queries via `psycopg`.
48
+
49
+ ## Installation
50
+
51
+ ### For Users
52
+
53
+ Install Build-a-Query via pip:
54
+
55
+ ```bash
56
+ pip install buildaquery
57
+ ```
58
+
59
+ **Requirements:**
60
+ - Python 3.12+
61
+ - **PostgreSQL database**: A running PostgreSQL instance (version 12+ recommended). You can set this up locally, via Docker, or use a cloud service.
62
+ - Example with Docker: `docker run --name postgres -e POSTGRES_PASSWORD=yourpassword -d -p 5432:5432 postgres:15`
63
+ - `psycopg` (automatically installed as a dependency) - the PostgreSQL adapter for Python.
64
+ - `python-dotenv` (automatically installed as a dependency) - for loading environment variables from a `.env` file.
65
+
66
+ ### Environment Variables
67
+
68
+ To connect to your PostgreSQL database, set the following environment variables (or use a `.env` file with `python-dotenv`):
69
+
70
+ - `DB_HOST`: PostgreSQL host (e.g., `localhost`)
71
+ - `DB_PORT`: PostgreSQL port (e.g., `5432`)
72
+ - `DB_NAME`: Database name (e.g., `mydatabase`)
73
+ - `DB_USER`: Database username (e.g., `postgres`)
74
+ - `DB_PASSWORD`: Database password (e.g., `yourpassword`)
75
+
76
+ Example `.env` file:
77
+ ```
78
+ DB_HOST=localhost
79
+ DB_PORT=5432
80
+ DB_NAME=buildaquery
81
+ DB_USER=postgres
82
+ DB_PASSWORD=yourpassword
83
+ ```
84
+
85
+ ### For Developers
86
+
87
+ Clone the repository and set up the development environment:
88
+
89
+ ```bash
90
+ git clone https://github.com/yourusername/buildaquery.git
91
+ cd buildaquery
92
+ ```
93
+
94
+ Install dependencies using Poetry:
95
+
96
+ ```bash
97
+ poetry install
98
+ ```
99
+
100
+ Activate the virtual environment:
101
+
102
+ ```bash
103
+ poetry shell
104
+ ```
105
+
106
+ ## Quick Start
107
+
108
+ 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).
109
+
110
+ ```python
111
+ from dotenv import load_dotenv
112
+ import os
113
+ from buildaquery.execution.postgres import PostgresExecutor
114
+ from buildaquery.abstract_syntax_tree.models import (
115
+ CreateStatementNode, TableNode, ColumnDefinitionNode,
116
+ InsertStatementNode, ColumnNode, LiteralNode,
117
+ SelectStatementNode, StarNode, DropStatementNode
118
+ )
119
+
120
+ # Load environment variables
121
+ load_dotenv()
122
+
123
+ # Build connection string from environment variables
124
+ db_host = os.getenv('DB_HOST')
125
+ db_port = os.getenv('DB_PORT')
126
+ db_name = os.getenv('DB_NAME')
127
+ db_user = os.getenv('DB_USER')
128
+ db_password = os.getenv('DB_PASSWORD')
129
+
130
+ connection_string = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
131
+
132
+ # Set up executor with your PostgreSQL connection
133
+ executor = PostgresExecutor(connection_info=connection_string)
134
+
135
+ # Define table
136
+ users_table = TableNode(name="users")
137
+
138
+ # Create table
139
+ create_stmt = CreateStatementNode(
140
+ table=users_table,
141
+ columns=[
142
+ ColumnDefinitionNode(name="id", data_type="SERIAL", primary_key=True),
143
+ ColumnDefinitionNode(name="name", data_type="TEXT", not_null=True),
144
+ ColumnDefinitionNode(name="age", data_type="INTEGER")
145
+ ]
146
+ )
147
+ executor.execute(create_stmt)
148
+
149
+ # Insert data
150
+ insert_stmt = InsertStatementNode(
151
+ table=users_table,
152
+ columns=[ColumnNode(name="name"), ColumnNode(name="age")],
153
+ values=[LiteralNode(value="Alice"), LiteralNode(value=30)]
154
+ )
155
+ executor.execute(insert_stmt)
156
+
157
+ # Query data
158
+ select_stmt = SelectStatementNode(
159
+ select_list=[StarNode()], # SELECT *
160
+ from_table=users_table
161
+ )
162
+ results = executor.execute(select_stmt)
163
+ print(results) # [(1, 'Alice', 30)]
164
+
165
+ # Drop table
166
+ drop_stmt = DropStatementNode(table=users_table, if_exists=True)
167
+ executor.execute(drop_stmt)
168
+ ```
169
+
170
+ For more examples, see the `examples/` directory.
171
+
172
+ ## Development Setup
173
+
174
+ ### Prerequisites
175
+
176
+ - Python 3.12+
177
+ - Poetry (for dependency management)
178
+ - Docker (for running integration tests)
179
+
180
+ ### Setting Up the Environment
181
+
182
+ 1. Clone the repository:
183
+ ```bash
184
+ git clone https://github.com/yourusername/buildaquery.git
185
+ cd buildaquery
186
+ ```
187
+
188
+ 2. Install dependencies:
189
+ ```bash
190
+ poetry install
191
+ ```
192
+
193
+ 3. Activate the virtual environment:
194
+ ```bash
195
+ poetry shell
196
+ ```
197
+
198
+ ### Running Tests
199
+
200
+ #### Unit Tests
201
+
202
+ Run unit tests for all modules:
203
+
204
+ ```bash
205
+ poetry run pytest buildaquery/tests
206
+ ```
207
+
208
+ #### Integration Tests
209
+
210
+ Integration tests require a PostgreSQL database. Start the test database using Docker:
211
+
212
+ ```bash
213
+ docker-compose up -d
214
+ ```
215
+
216
+ Then run integration tests:
217
+
218
+ ```bash
219
+ poetry run pytest tests
220
+ ```
221
+
222
+ #### All Tests
223
+
224
+ Run all tests (unit and integration):
225
+
226
+ ```bash
227
+ poetry run all-tests
228
+ ```
229
+
230
+ ### Running Examples
231
+
232
+ Execute the sample script:
233
+
234
+ ```bash
235
+ poetry run python examples/sample_query.py
236
+ ```
237
+
238
+ ## Project Structure
239
+
240
+ - `buildaquery/abstract_syntax_tree/`: Defines query nodes and AST models.
241
+ - `buildaquery/traversal/`: Base classes for AST traversal (Visitor/Transformer pattern).
242
+ - `buildaquery/compiler/`: Dialect-specific SQL generation (currently PostgreSQL).
243
+ - `buildaquery/execution/`: Database connection and execution logic.
244
+ - `tests/`: Exhaustive unit and integration tests.
245
+ - `examples/`: Practical demonstrations of the library.
246
+ - `scripts/`: Utility scripts for testing and maintenance.
247
+
248
+ ## Contributing
249
+
250
+ Contributions are welcome! Please see the contributing guidelines for more information.
251
+
252
+ ## License
253
+
254
+ This project is licensed under the MIT License - see the [LICENSE.txt](LICENSE.txt) file for details.
255
+
@@ -0,0 +1,221 @@
1
+ # Build-a-Query
2
+
3
+ A Python-based query builder designed to represent, compile, and execute SQL queries using a dialect-agnostic Abstract Syntax Tree (AST). Initial support is focused on PostgreSQL.
4
+
5
+ ## Features
6
+
7
+ - **Dialect-Agnostic AST**: Build queries using high-level Python objects.
8
+ - **Full DML Support**: Create `SELECT`, `INSERT`, `UPDATE`, and `DELETE` statements.
9
+ - **Advanced Querying**: Support for CTEs (`WITH`), Subqueries, Set Operations (`UNION`, `INTERSECT`, `EXCEPT`), and Window Functions (`OVER`).
10
+ - **Rich Expression Logic**: Includes `CASE` expressions, `IN`, `BETWEEN`, and type casting.
11
+ - **DDL Support**: Basic schema management with `CREATE TABLE` and `DROP TABLE`.
12
+ - **Visitor Pattern Traversal**: Extensible architecture for analysis and compilation.
13
+ - **Secure Compilation**: Automatic parameterization to prevent SQL injection.
14
+ - **Execution Layer**: Built-in support for executing compiled queries via `psycopg`.
15
+
16
+ ## Installation
17
+
18
+ ### For Users
19
+
20
+ Install Build-a-Query via pip:
21
+
22
+ ```bash
23
+ pip install buildaquery
24
+ ```
25
+
26
+ **Requirements:**
27
+ - Python 3.12+
28
+ - **PostgreSQL database**: A running PostgreSQL instance (version 12+ recommended). You can set this up locally, via Docker, or use a cloud service.
29
+ - Example with Docker: `docker run --name postgres -e POSTGRES_PASSWORD=yourpassword -d -p 5432:5432 postgres:15`
30
+ - `psycopg` (automatically installed as a dependency) - the PostgreSQL adapter for Python.
31
+ - `python-dotenv` (automatically installed as a dependency) - for loading environment variables from a `.env` file.
32
+
33
+ ### Environment Variables
34
+
35
+ To connect to your PostgreSQL database, set the following environment variables (or use a `.env` file with `python-dotenv`):
36
+
37
+ - `DB_HOST`: PostgreSQL host (e.g., `localhost`)
38
+ - `DB_PORT`: PostgreSQL port (e.g., `5432`)
39
+ - `DB_NAME`: Database name (e.g., `mydatabase`)
40
+ - `DB_USER`: Database username (e.g., `postgres`)
41
+ - `DB_PASSWORD`: Database password (e.g., `yourpassword`)
42
+
43
+ Example `.env` file:
44
+ ```
45
+ DB_HOST=localhost
46
+ DB_PORT=5432
47
+ DB_NAME=buildaquery
48
+ DB_USER=postgres
49
+ DB_PASSWORD=yourpassword
50
+ ```
51
+
52
+ ### For Developers
53
+
54
+ Clone the repository and set up the development environment:
55
+
56
+ ```bash
57
+ git clone https://github.com/yourusername/buildaquery.git
58
+ cd buildaquery
59
+ ```
60
+
61
+ Install dependencies using Poetry:
62
+
63
+ ```bash
64
+ poetry install
65
+ ```
66
+
67
+ Activate the virtual environment:
68
+
69
+ ```bash
70
+ poetry shell
71
+ ```
72
+
73
+ ## Quick Start
74
+
75
+ 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).
76
+
77
+ ```python
78
+ from dotenv import load_dotenv
79
+ import os
80
+ from buildaquery.execution.postgres import PostgresExecutor
81
+ from buildaquery.abstract_syntax_tree.models import (
82
+ CreateStatementNode, TableNode, ColumnDefinitionNode,
83
+ InsertStatementNode, ColumnNode, LiteralNode,
84
+ SelectStatementNode, StarNode, DropStatementNode
85
+ )
86
+
87
+ # Load environment variables
88
+ load_dotenv()
89
+
90
+ # Build connection string from environment variables
91
+ db_host = os.getenv('DB_HOST')
92
+ db_port = os.getenv('DB_PORT')
93
+ db_name = os.getenv('DB_NAME')
94
+ db_user = os.getenv('DB_USER')
95
+ db_password = os.getenv('DB_PASSWORD')
96
+
97
+ connection_string = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
98
+
99
+ # Set up executor with your PostgreSQL connection
100
+ executor = PostgresExecutor(connection_info=connection_string)
101
+
102
+ # Define table
103
+ users_table = TableNode(name="users")
104
+
105
+ # Create table
106
+ create_stmt = CreateStatementNode(
107
+ table=users_table,
108
+ columns=[
109
+ ColumnDefinitionNode(name="id", data_type="SERIAL", primary_key=True),
110
+ ColumnDefinitionNode(name="name", data_type="TEXT", not_null=True),
111
+ ColumnDefinitionNode(name="age", data_type="INTEGER")
112
+ ]
113
+ )
114
+ executor.execute(create_stmt)
115
+
116
+ # Insert data
117
+ insert_stmt = InsertStatementNode(
118
+ table=users_table,
119
+ columns=[ColumnNode(name="name"), ColumnNode(name="age")],
120
+ values=[LiteralNode(value="Alice"), LiteralNode(value=30)]
121
+ )
122
+ executor.execute(insert_stmt)
123
+
124
+ # Query data
125
+ select_stmt = SelectStatementNode(
126
+ select_list=[StarNode()], # SELECT *
127
+ from_table=users_table
128
+ )
129
+ results = executor.execute(select_stmt)
130
+ print(results) # [(1, 'Alice', 30)]
131
+
132
+ # Drop table
133
+ drop_stmt = DropStatementNode(table=users_table, if_exists=True)
134
+ executor.execute(drop_stmt)
135
+ ```
136
+
137
+ For more examples, see the `examples/` directory.
138
+
139
+ ## Development Setup
140
+
141
+ ### Prerequisites
142
+
143
+ - Python 3.12+
144
+ - Poetry (for dependency management)
145
+ - Docker (for running integration tests)
146
+
147
+ ### Setting Up the Environment
148
+
149
+ 1. Clone the repository:
150
+ ```bash
151
+ git clone https://github.com/yourusername/buildaquery.git
152
+ cd buildaquery
153
+ ```
154
+
155
+ 2. Install dependencies:
156
+ ```bash
157
+ poetry install
158
+ ```
159
+
160
+ 3. Activate the virtual environment:
161
+ ```bash
162
+ poetry shell
163
+ ```
164
+
165
+ ### Running Tests
166
+
167
+ #### Unit Tests
168
+
169
+ Run unit tests for all modules:
170
+
171
+ ```bash
172
+ poetry run pytest buildaquery/tests
173
+ ```
174
+
175
+ #### Integration Tests
176
+
177
+ Integration tests require a PostgreSQL database. Start the test database using Docker:
178
+
179
+ ```bash
180
+ docker-compose up -d
181
+ ```
182
+
183
+ Then run integration tests:
184
+
185
+ ```bash
186
+ poetry run pytest tests
187
+ ```
188
+
189
+ #### All Tests
190
+
191
+ Run all tests (unit and integration):
192
+
193
+ ```bash
194
+ poetry run all-tests
195
+ ```
196
+
197
+ ### Running Examples
198
+
199
+ Execute the sample script:
200
+
201
+ ```bash
202
+ poetry run python examples/sample_query.py
203
+ ```
204
+
205
+ ## Project Structure
206
+
207
+ - `buildaquery/abstract_syntax_tree/`: Defines query nodes and AST models.
208
+ - `buildaquery/traversal/`: Base classes for AST traversal (Visitor/Transformer pattern).
209
+ - `buildaquery/compiler/`: Dialect-specific SQL generation (currently PostgreSQL).
210
+ - `buildaquery/execution/`: Database connection and execution logic.
211
+ - `tests/`: Exhaustive unit and integration tests.
212
+ - `examples/`: Practical demonstrations of the library.
213
+ - `scripts/`: Utility scripts for testing and maintenance.
214
+
215
+ ## Contributing
216
+
217
+ Contributions are welcome! Please see the contributing guidelines for more information.
218
+
219
+ ## License
220
+
221
+ This project is licensed under the MIT License - see the [LICENSE.txt](LICENSE.txt) file for details.
File without changes
@@ -0,0 +1,54 @@
1
+ # Abstract Syntax Tree (AST)
2
+
3
+ The `abstract_syntax_tree` module defines the data structures used to represent SQL queries as an Abstract Syntax Tree. This representation is agnostic of any specific SQL dialect and serves as the intermediate format that the query builder constructs and the compiler translates into SQL.
4
+
5
+ ## Core Concepts
6
+
7
+ The AST is built using a hierarchy of nodes, all inheriting from the base `ASTNode` class.
8
+
9
+ ### Node Categories
10
+
11
+ - **`ExpressionNode`**: Represents values, column references, and operations (e.g., `LiteralNode`, `ColumnNode`, `BinaryOperationNode`, `FunctionCallNode`).
12
+ - **`StatementNode`**: Represents complete SQL statements. Currently, `SelectStatementNode` is the primary implementation.
13
+ - **`FromClauseNode`**: Represents entities that can appear in a `FROM` clause, such as `TableNode` or `JoinClauseNode`.
14
+
15
+ ## Key Components
16
+
17
+ - **`SelectStatementNode`**: The central node for `SELECT` queries. It encapsulates the select list, `FROM` table/joins, `WHERE` conditions, `GROUP BY`, `HAVING`, `ORDER BY`, and pagination (`LIMIT`, `OFFSET`, `TOP`).
18
+ - **`TopClauseNode`**: A specialized node for limiting results, particularly for dialects that support the `TOP` syntax. It is mutually exclusive with standard `LIMIT`/`OFFSET`.
19
+ - **`JoinClauseNode`**: Represents various types of table joins (INNER, LEFT, etc.) with associated join conditions.
20
+ - **Operations**: Support for both binary (e.g., `+`, `-`, `AND`, `OR`) and unary (e.g., `NOT`, `-`) operations.
21
+
22
+ ## Usage
23
+
24
+ Nodes are typically instantiated and composed to build a tree representing a query. For example:
25
+
26
+ ```python
27
+ from buildaquery.abstract_syntax_tree.models import SelectStatementNode, ColumnNode, TableNode
28
+
29
+ # SELECT * FROM users
30
+ query = SelectStatementNode(
31
+ select_list=[ColumnNode(name="*")],
32
+ from_table=TableNode(name="users")
33
+ )
34
+ ```
35
+
36
+ This tree can then be processed by visitors (see the `traversal` module) for compilation or analysis.
37
+
38
+ ## TODOs
39
+
40
+ To make the AST more robust and capable of representing the full scope of the SQL language, the following enhancements are planned:
41
+
42
+ - **DML Support**:
43
+ - [x] Implement `InsertStatementNode` and `UpdateStatementNode`.
44
+ - [x] Implement `DeleteStatementNode`.
45
+ - **Advanced Query Features**:
46
+ - [x] **CTEs**: Add `WithClauseNode` for common table expressions.
47
+ - [x] **Set Operations**: Implement `UnionNode`, `IntersectNode`, and `ExceptNode`.
48
+ - [x] **DISTINCT**: Add support for `SELECT DISTINCT`.
49
+ - **Richer Expression Logic**:
50
+ - **Specialized Expressions**: Add [x] `CaseExpressionNode`, [x] `InNode`, and [x] `BetweenNode`.
51
+ - [x] **Subqueries**: Enable `SelectStatementNode` to be used within expressions.
52
+ - [x] **Window Functions**: Support `OVER` clauses and partitioning.
53
+ - [x] **Schema & Namespacing**: Update `TableNode` and `ColumnNode` to support qualified names (e.g., `schema.table`) and add a `CastNode` for type casting.
54
+ - **DDL Support**: [x] Add nodes for `CREATE`, `ALTER`, and `DROP` statements for schema management.
@@ -0,0 +1 @@
1
+ from .models import *