buildaquery 0.2.0__tar.gz → 0.3.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.
Files changed (37) hide show
  1. {buildaquery-0.2.0 → buildaquery-0.3.0}/PKG-INFO +57 -7
  2. {buildaquery-0.2.0 → buildaquery-0.3.0}/README.md +68 -19
  3. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/abstract_syntax_tree/README.md +1 -1
  4. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/compiler/README.md +16 -1
  5. buildaquery-0.3.0/buildaquery/compiler/__init__.py +5 -0
  6. buildaquery-0.3.0/buildaquery/compiler/mysql/README.md +25 -0
  7. buildaquery-0.3.0/buildaquery/compiler/mysql/__init__.py +1 -0
  8. buildaquery-0.3.0/buildaquery/compiler/mysql/mysql_compiler.py +342 -0
  9. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/compiler/postgres/README.md +1 -1
  10. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/compiler/sqlite/README.md +2 -0
  11. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/execution/README.md +5 -1
  12. buildaquery-0.3.0/buildaquery/execution/__init__.py +5 -0
  13. buildaquery-0.3.0/buildaquery/execution/mysql.py +185 -0
  14. buildaquery-0.3.0/buildaquery/tests/test_compiler_mysql.py +341 -0
  15. buildaquery-0.3.0/buildaquery/tests/test_execution_mysql.py +51 -0
  16. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/traversal/README.md +1 -1
  17. {buildaquery-0.2.0 → buildaquery-0.3.0}/pyproject.toml +10 -9
  18. buildaquery-0.2.0/buildaquery/compiler/__init__.py +0 -0
  19. buildaquery-0.2.0/buildaquery/execution/__init__.py +0 -0
  20. {buildaquery-0.2.0 → buildaquery-0.3.0}/LICENSE.txt +0 -0
  21. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/__init__.py +0 -0
  22. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/abstract_syntax_tree/__init__.py +0 -0
  23. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/abstract_syntax_tree/models.py +0 -0
  24. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/compiler/compiled_query.py +0 -0
  25. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/compiler/postgres/postgres_compiler.py +0 -0
  26. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/compiler/sqlite/__init__.py +0 -0
  27. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/compiler/sqlite/sqlite_compiler.py +0 -0
  28. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/execution/base.py +0 -0
  29. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/execution/postgres.py +0 -0
  30. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/execution/sqlite.py +0 -0
  31. /buildaquery-0.2.0/buildaquery/tests/test_ast.py → /buildaquery-0.3.0/buildaquery/tests/test_ast_postgres.py +0 -0
  32. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/tests/test_compiler_postgres.py +0 -0
  33. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/tests/test_compiler_sqlite.py +0 -0
  34. /buildaquery-0.2.0/buildaquery/tests/test_execution.py → /buildaquery-0.3.0/buildaquery/tests/test_execution_postgres.py +0 -0
  35. /buildaquery-0.2.0/buildaquery/tests/test_traversal.py → /buildaquery-0.3.0/buildaquery/tests/test_traversal_postgres.py +0 -0
  36. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/traversal/__init__.py +0 -0
  37. {buildaquery-0.2.0 → buildaquery-0.3.0}/buildaquery/traversal/visitor_pattern.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: buildaquery
3
- Version: 0.2.0
4
- Summary: A Python-based query builder for PostgreSQL.
3
+ Version: 0.3.0
4
+ Summary: A Python-based query builder for PostgreSQL, SQLite, and MySQL.
5
5
  License: MIT
6
6
  License-File: LICENSE.txt
7
7
  Author: Anirudh Bhattacharya
@@ -21,6 +21,7 @@ Classifier: Topic :: Software Development :: Libraries
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Dist: Pygments (==2.19.2)
23
23
  Requires-Dist: colorama (==0.4.6)
24
+ Requires-Dist: mysql-connector-python (==9.4.0)
24
25
  Requires-Dist: packaging (==26.0)
25
26
  Requires-Dist: pluggy (==1.6.0)
26
27
  Requires-Dist: psycopg (==3.3.3)
@@ -33,7 +34,7 @@ Description-Content-Type: text/markdown
33
34
 
34
35
  # Build-a-Query
35
36
 
36
- 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.
37
+ A Python-based query builder designed to represent, compile, and execute SQL queries using a dialect-agnostic Abstract Syntax Tree (AST). Supports PostgreSQL, SQLite, and MySQL.
37
38
 
38
39
  ## Features
39
40
 
@@ -44,7 +45,11 @@ A Python-based query builder designed to represent, compile, and execute SQL que
44
45
  - **DDL Support**: Basic schema management with `CREATE TABLE` and `DROP TABLE`.
45
46
  - **Visitor Pattern Traversal**: Extensible architecture for analysis and compilation.
46
47
  - **Secure Compilation**: Automatic parameterization to prevent SQL injection.
47
- - **Execution Layer**: Built-in support for executing compiled queries via `psycopg` (PostgreSQL) and the standard library `sqlite3` (SQLite).
48
+ - **Execution Layer**: Built-in support for executing compiled queries via `psycopg` (PostgreSQL), `mysql-connector-python` (MySQL), and the standard library `sqlite3` (SQLite).
49
+
50
+ ## Dialect Notes
51
+ - MySQL does not support `INTERSECT` / `EXCEPT` or `DROP TABLE ... CASCADE` in this implementation (the compiler raises `ValueError`).
52
+ - SQLite does not support `DROP TABLE ... CASCADE` (the compiler raises `ValueError`).
48
53
 
49
54
  ## Installation
50
55
 
@@ -61,6 +66,9 @@ pip install buildaquery
61
66
  - **PostgreSQL database**: A running PostgreSQL instance (version 12+ recommended). You can set this up locally, via Docker, or use a cloud service.
62
67
  - Example with Docker: `docker run --name postgres -e POSTGRES_PASSWORD=yourpassword -d -p 5432:5432 postgres:15`
63
68
  - `psycopg` (automatically installed as a dependency) - the PostgreSQL adapter for Python.
69
+ - **MySQL database**: A running MySQL instance (version 8.0+ recommended).
70
+ - Example with Docker: `docker run --name mysql -e MYSQL_ROOT_PASSWORD=yourpassword -e MYSQL_DATABASE=buildaquery -d -p 3306:3306 mysql:8.0`
71
+ - `mysql-connector-python` (automatically installed as a dependency) - the MySQL adapter for Python.
64
72
  - `python-dotenv` (automatically installed as a dependency) - for loading environment variables from a `.env` file.
65
73
  - **SQLite**: Uses Python's standard library `sqlite3` module.
66
74
  - **SQLite Version**: SQLite 3.x via Python's `sqlite3` module (the exact SQLite version depends on your Python build; check `sqlite3.sqlite_version` at runtime).
@@ -84,6 +92,8 @@ DB_USER=postgres
84
92
  DB_PASSWORD=yourpassword
85
93
  ```
86
94
 
95
+ For MySQL, you can use a connection URL directly in code (e.g., `mysql://user:password@host:3306/dbname`) or set your own environment variables and construct the URL similarly.
96
+
87
97
  ### For Developers
88
98
 
89
99
  Clone the repository and set up the development environment:
@@ -209,7 +219,47 @@ drop_stmt = DropStatementNode(table=users_table, if_exists=True)
209
219
  executor.execute(drop_stmt)
210
220
  ```
211
221
 
212
- For more examples, see the `examples/` directory.
222
+ ### MySQL Quick Start
223
+
224
+ ```python
225
+ from buildaquery.execution.mysql import MySqlExecutor
226
+ from buildaquery.abstract_syntax_tree.models import (
227
+ CreateStatementNode, TableNode, ColumnDefinitionNode,
228
+ InsertStatementNode, ColumnNode, LiteralNode,
229
+ SelectStatementNode, StarNode, DropStatementNode
230
+ )
231
+
232
+ executor = MySqlExecutor(connection_info="mysql://root:password@127.0.0.1:3306/buildaquery")
233
+
234
+ users_table = TableNode(name="users")
235
+ create_stmt = CreateStatementNode(
236
+ table=users_table,
237
+ columns=[
238
+ ColumnDefinitionNode(name="id", data_type="INT AUTO_INCREMENT", primary_key=True),
239
+ ColumnDefinitionNode(name="name", data_type="VARCHAR(255)", not_null=True),
240
+ ColumnDefinitionNode(name="age", data_type="INT")
241
+ ]
242
+ )
243
+ executor.execute(create_stmt)
244
+
245
+ insert_stmt = InsertStatementNode(
246
+ table=users_table,
247
+ columns=[ColumnNode(name="name"), ColumnNode(name="age")],
248
+ values=[LiteralNode(value="Alice"), LiteralNode(value=30)]
249
+ )
250
+ executor.execute(insert_stmt)
251
+
252
+ select_stmt = SelectStatementNode(
253
+ select_list=[StarNode()],
254
+ from_table=users_table
255
+ )
256
+ print(executor.execute(select_stmt))
257
+
258
+ drop_stmt = DropStatementNode(table=users_table, if_exists=True)
259
+ executor.execute(drop_stmt)
260
+ ```
261
+
262
+ For more examples, see the `examples/` directory (including `examples/sample_mysql.py`).
213
263
 
214
264
  ## Development Setup
215
265
 
@@ -249,7 +299,7 @@ poetry run pytest buildaquery/tests
249
299
 
250
300
  #### Integration Tests
251
301
 
252
- Integration tests require a PostgreSQL database. Start the test database using Docker:
302
+ Integration tests require PostgreSQL and MySQL databases (and the `mysql-connector-python` driver). Start the test databases using Docker:
253
303
 
254
304
  ```bash
255
305
  docker-compose up -d
@@ -283,7 +333,7 @@ poetry run python examples/sample_query.py
283
333
 
284
334
  - `buildaquery/abstract_syntax_tree/`: Defines query nodes and AST models.
285
335
  - `buildaquery/traversal/`: Base classes for AST traversal (Visitor/Transformer pattern).
286
- - `buildaquery/compiler/`: Dialect-specific SQL generation (PostgreSQL and SQLite).
336
+ - `buildaquery/compiler/`: Dialect-specific SQL generation (PostgreSQL, SQLite, MySQL).
287
337
  - `buildaquery/execution/`: Database connection and execution logic.
288
338
  - `tests/`: Exhaustive unit and integration tests.
289
339
  - `examples/`: Practical demonstrations of the library.
@@ -1,8 +1,8 @@
1
1
  # Build-a-Query
2
2
 
3
- 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.
3
+ A Python-based query builder designed to represent, compile, and execute SQL queries using a dialect-agnostic Abstract Syntax Tree (AST). Supports PostgreSQL, SQLite, and MySQL.
4
4
 
5
- ## Features
5
+ ## Features
6
6
 
7
7
  - **Dialect-Agnostic AST**: Build queries using high-level Python objects.
8
8
  - **Full DML Support**: Create `SELECT`, `INSERT`, `UPDATE`, and `DELETE` statements.
@@ -11,7 +11,11 @@ A Python-based query builder designed to represent, compile, and execute SQL que
11
11
  - **DDL Support**: Basic schema management with `CREATE TABLE` and `DROP TABLE`.
12
12
  - **Visitor Pattern Traversal**: Extensible architecture for analysis and compilation.
13
13
  - **Secure Compilation**: Automatic parameterization to prevent SQL injection.
14
- - **Execution Layer**: Built-in support for executing compiled queries via `psycopg` (PostgreSQL) and the standard library `sqlite3` (SQLite).
14
+ - **Execution Layer**: Built-in support for executing compiled queries via `psycopg` (PostgreSQL), `mysql-connector-python` (MySQL), and the standard library `sqlite3` (SQLite).
15
+
16
+ ## Dialect Notes
17
+ - MySQL does not support `INTERSECT` / `EXCEPT` or `DROP TABLE ... CASCADE` in this implementation (the compiler raises `ValueError`).
18
+ - SQLite does not support `DROP TABLE ... CASCADE` (the compiler raises `ValueError`).
15
19
 
16
20
  ## Installation
17
21
 
@@ -28,13 +32,16 @@ pip install buildaquery
28
32
  - **PostgreSQL database**: A running PostgreSQL instance (version 12+ recommended). You can set this up locally, via Docker, or use a cloud service.
29
33
  - Example with Docker: `docker run --name postgres -e POSTGRES_PASSWORD=yourpassword -d -p 5432:5432 postgres:15`
30
34
  - `psycopg` (automatically installed as a dependency) - the PostgreSQL adapter for Python.
35
+ - **MySQL database**: A running MySQL instance (version 8.0+ recommended).
36
+ - Example with Docker: `docker run --name mysql -e MYSQL_ROOT_PASSWORD=yourpassword -e MYSQL_DATABASE=buildaquery -d -p 3306:3306 mysql:8.0`
37
+ - `mysql-connector-python` (automatically installed as a dependency) - the MySQL adapter for Python.
31
38
  - `python-dotenv` (automatically installed as a dependency) - for loading environment variables from a `.env` file.
32
39
  - **SQLite**: Uses Python's standard library `sqlite3` module.
33
40
  - **SQLite Version**: SQLite 3.x via Python's `sqlite3` module (the exact SQLite version depends on your Python build; check `sqlite3.sqlite_version` at runtime).
34
41
 
35
42
  ### Environment Variables
36
43
 
37
- To connect to your PostgreSQL database, set the following environment variables (or use a `.env` file with `python-dotenv`):
44
+ To connect to your PostgreSQL database, set the following environment variables (or use a `.env` file with `python-dotenv`):
38
45
 
39
46
  - `DB_HOST`: PostgreSQL host (e.g., `localhost`)
40
47
  - `DB_PORT`: PostgreSQL port (e.g., `5432`)
@@ -42,14 +49,16 @@ To connect to your PostgreSQL database, set the following environment variables
42
49
  - `DB_USER`: Database username (e.g., `postgres`)
43
50
  - `DB_PASSWORD`: Database password (e.g., `yourpassword`)
44
51
 
45
- Example `.env` file:
46
- ```
47
- DB_HOST=localhost
48
- DB_PORT=5432
49
- DB_NAME=buildaquery
50
- DB_USER=postgres
51
- DB_PASSWORD=yourpassword
52
- ```
52
+ Example `.env` file:
53
+ ```
54
+ DB_HOST=localhost
55
+ DB_PORT=5432
56
+ DB_NAME=buildaquery
57
+ DB_USER=postgres
58
+ DB_PASSWORD=yourpassword
59
+ ```
60
+
61
+ For MySQL, you can use a connection URL directly in code (e.g., `mysql://user:password@host:3306/dbname`) or set your own environment variables and construct the URL similarly.
53
62
 
54
63
  ### For Developers
55
64
 
@@ -72,7 +81,7 @@ Activate the virtual environment:
72
81
  poetry shell
73
82
  ```
74
83
 
75
- ## Quick Start
84
+ ## Quick Start
76
85
 
77
86
  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).
78
87
 
@@ -176,7 +185,47 @@ drop_stmt = DropStatementNode(table=users_table, if_exists=True)
176
185
  executor.execute(drop_stmt)
177
186
  ```
178
187
 
179
- For more examples, see the `examples/` directory.
188
+ ### MySQL Quick Start
189
+
190
+ ```python
191
+ from buildaquery.execution.mysql import MySqlExecutor
192
+ from buildaquery.abstract_syntax_tree.models import (
193
+ CreateStatementNode, TableNode, ColumnDefinitionNode,
194
+ InsertStatementNode, ColumnNode, LiteralNode,
195
+ SelectStatementNode, StarNode, DropStatementNode
196
+ )
197
+
198
+ executor = MySqlExecutor(connection_info="mysql://root:password@127.0.0.1:3306/buildaquery")
199
+
200
+ users_table = TableNode(name="users")
201
+ create_stmt = CreateStatementNode(
202
+ table=users_table,
203
+ columns=[
204
+ ColumnDefinitionNode(name="id", data_type="INT AUTO_INCREMENT", primary_key=True),
205
+ ColumnDefinitionNode(name="name", data_type="VARCHAR(255)", not_null=True),
206
+ ColumnDefinitionNode(name="age", data_type="INT")
207
+ ]
208
+ )
209
+ executor.execute(create_stmt)
210
+
211
+ insert_stmt = InsertStatementNode(
212
+ table=users_table,
213
+ columns=[ColumnNode(name="name"), ColumnNode(name="age")],
214
+ values=[LiteralNode(value="Alice"), LiteralNode(value=30)]
215
+ )
216
+ executor.execute(insert_stmt)
217
+
218
+ select_stmt = SelectStatementNode(
219
+ select_list=[StarNode()],
220
+ from_table=users_table
221
+ )
222
+ print(executor.execute(select_stmt))
223
+
224
+ drop_stmt = DropStatementNode(table=users_table, if_exists=True)
225
+ executor.execute(drop_stmt)
226
+ ```
227
+
228
+ For more examples, see the `examples/` directory (including `examples/sample_mysql.py`).
180
229
 
181
230
  ## Development Setup
182
231
 
@@ -214,9 +263,9 @@ Run unit tests for all modules:
214
263
  poetry run pytest buildaquery/tests
215
264
  ```
216
265
 
217
- #### Integration Tests
218
-
219
- Integration tests require a PostgreSQL database. Start the test database using Docker:
266
+ #### Integration Tests
267
+
268
+ Integration tests require PostgreSQL and MySQL databases (and the `mysql-connector-python` driver). Start the test databases using Docker:
220
269
 
221
270
  ```bash
222
271
  docker-compose up -d
@@ -250,9 +299,9 @@ poetry run python examples/sample_query.py
250
299
 
251
300
  - `buildaquery/abstract_syntax_tree/`: Defines query nodes and AST models.
252
301
  - `buildaquery/traversal/`: Base classes for AST traversal (Visitor/Transformer pattern).
253
- - `buildaquery/compiler/`: Dialect-specific SQL generation (PostgreSQL and SQLite).
302
+ - `buildaquery/compiler/`: Dialect-specific SQL generation (PostgreSQL, SQLite, MySQL).
254
303
  - `buildaquery/execution/`: Database connection and execution logic.
255
- - `tests/`: Exhaustive unit and integration tests.
304
+ - `tests/`: Exhaustive unit and integration tests.
256
305
  - `examples/`: Practical demonstrations of the library.
257
306
  - `scripts/`: Utility scripts for testing and maintenance.
258
307
 
@@ -2,7 +2,7 @@
2
2
 
3
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
4
 
5
- **SQLite Version**: SQLite 3.x via Python's `sqlite3` module (the exact SQLite version depends on your Python build; check `sqlite3.sqlite_version` at runtime).
5
+ **Dialect Notes**: The AST is dialect-agnostic and compilers target PostgreSQL, SQLite, and MySQL.
6
6
 
7
7
  ## Core Concepts
8
8
 
@@ -44,12 +44,22 @@ The initial implementation supports PostgreSQL.
44
44
  - **Core AST Coverage**: Supports the same AST nodes as PostgreSQL where SQLite syntax allows.
45
45
  - **TOP Translation**: Maps `TopClauseNode` to `LIMIT`, with optional implicit `ORDER BY`.
46
46
  - **CASCADE Handling**: Raises a `ValueError` when `DropStatementNode.cascade=True`, because SQLite does not support `DROP TABLE ... CASCADE`.
47
+
48
+ ### MySQL (`MySqlCompiler`)
49
+
50
+ #### Key Features:
51
+ - **`%s` Placeholders**: Uses MySQL-compatible parameter style.
52
+ - **Core AST Coverage**: Supports the same AST nodes as PostgreSQL where MySQL syntax allows.
53
+ - **TOP Translation**: Maps `TopClauseNode` to `LIMIT`, with optional implicit `ORDER BY`.
54
+ - **Set Operation Limits**: Raises a `ValueError` for `INTERSECT` and `EXCEPT` (unsupported in MySQL).
55
+ - **CASCADE Handling**: Raises a `ValueError` when `DropStatementNode.cascade=True`, because MySQL does not support `DROP TABLE ... CASCADE`.
47
56
 
48
57
  ## Usage Example
49
58
 
50
59
  ```python
51
60
  from buildaquery.compiler.postgres.postgres_compiler import PostgresCompiler
52
61
  from buildaquery.compiler.sqlite.sqlite_compiler import SqliteCompiler
62
+ from buildaquery.compiler.mysql.mysql_compiler import MySqlCompiler
53
63
 
54
64
  compiler = PostgresCompiler()
55
65
  compiled = compiler.compile(ast_root)
@@ -61,4 +71,9 @@ sqlite_compiler = SqliteCompiler()
61
71
  compiled = sqlite_compiler.compile(ast_root)
62
72
  print(compiled.sql) # "SELECT * FROM users WHERE id = ?"
63
73
  print(compiled.params) # [123]
64
- ```
74
+
75
+ mysql_compiler = MySqlCompiler()
76
+ compiled = mysql_compiler.compile(ast_root)
77
+ print(compiled.sql) # "SELECT * FROM users WHERE id = %s"
78
+ print(compiled.params) # [123]
79
+ ```
@@ -0,0 +1,5 @@
1
+ from buildaquery.compiler.postgres.postgres_compiler import PostgresCompiler
2
+ from buildaquery.compiler.sqlite.sqlite_compiler import SqliteCompiler
3
+ from buildaquery.compiler.mysql.mysql_compiler import MySqlCompiler
4
+
5
+ __all__ = ["PostgresCompiler", "SqliteCompiler", "MySqlCompiler"]
@@ -0,0 +1,25 @@
1
+ # MySQL Compiler
2
+
3
+ The `MySqlCompiler` translates the AST into MySQL-compatible SQL with `%s` placeholders.
4
+
5
+ ## Notes
6
+
7
+ - **Placeholders**: Uses `%s` for parameters (compatible with `mysql-connector-python`).
8
+ - **TOP Translation**: `TopClauseNode` is translated into `LIMIT`, with optional implicit `ORDER BY`.
9
+ - **Unsupported Operations**:
10
+ - `INTERSECT` and `EXCEPT` raise `ValueError` (MySQL does not support them).
11
+ - `DROP TABLE ... CASCADE` raises `ValueError`.
12
+
13
+ ## Example
14
+
15
+ ```python
16
+ from buildaquery.compiler.mysql.mysql_compiler import MySqlCompiler
17
+ from buildaquery.abstract_syntax_tree.models import SelectStatementNode, StarNode, TableNode
18
+
19
+ compiler = MySqlCompiler()
20
+ query = SelectStatementNode(select_list=[StarNode()], from_table=TableNode(name="users"))
21
+ compiled = compiler.compile(query)
22
+
23
+ print(compiled.sql) # SELECT * FROM users
24
+ print(compiled.params) # []
25
+ ```
@@ -0,0 +1 @@
1
+ # Intentionally left empty to mark mysql as a package.