Query.Farm SQL Manipulation
A Python library for intelligent SQL predicate manipulation using SQLGlot. This library provides tools to safely remove specific predicates from SQL WHERE clauses and filter SQL statements based on column availability.
Features
- Predicate Removal: Safely remove specific predicates from complex
SQL WHEREclauses while preserving logical structure - Column Filtering: Filter SQL statements to only include predicates referencing allowed columns
- Intelligent Logic Handling: Properly handles
AND/ORlogic, nested expressions,CASEstatements, and parentheses - SQLGlot Integration: Built on top of SQLGlot for robust SQL parsing and manipulation
- Multiple Dialect Support: Works with various SQL dialects (default: DuckDB)
Installation
pip install query-farm-sql-manipulation
Requirements
- Python >= 3.12
- SQLGlot >= 26.33.0
Quick Start
Basic Predicate Removal
import sqlglot
from query_farm_sql_manipulation import transforms
# Parse a SQL statement
sql = 'SELECT * FROM data WHERE x = 1 AND y = 2'
statement = sqlglot.parse_one(sql, dialect="duckdb")
# Find the predicate you want to remove
predicates = list(statement.find_all(sqlglot.expressions.Predicate))
target_predicate = predicates[0] # x = 1
# Remove the predicate
transforms.remove_expression_part(target_predicate)
# Result: SELECT * FROM data WHERE y = 2
print(statement.sql())
Column-Based Filtering
from query_farm_sql_manipulation import transforms
# Filter SQL to only include predicates with allowed columns
sql = 'SELECT * FROM data WHERE color = "red" AND size > 10 AND type = "car"'
allowed_columns = {"color", "type"}
filtered = transforms.filter_column_references_statement(
sql=sql,
allowed_column_names=allowed_columns,
dialect="duckdb"
)
# Result: SELECT * FROM data WHERE color = "red" AND type = "car"
print(filtered.sql())
API Reference
remove_expression_part(child: sqlglot.Expression) -> None
Removes the specified expression from its parent, respecting logical structure.
Parameters:
child: The SQLGlot expression to remove
Raises:
ValueError: If the expression cannot be safely removed
Supported Parent Types:
AND/ORexpressions: Replaces parent with the remaining operandWHEREclauses: Removes the entire WHERE clause if it becomes emptyParentheses: Recursively removes the parentNOTexpressions: Removes the entire NOT expressionCASEstatements: Removes conditional branches
filter_column_references_statement(*, sql: str, allowed_column_names: Container[str], dialect: str = "duckdb") -> sqlglot.Expression
Filters a SQL statement to remove predicates containing columns not in the allowed set.
Parameters:
sql: The SQL statement to filterallowed_column_names: Container of column names that should be preserveddialect: SQL dialect for parsing (default: "duckdb")
Returns:
- Filtered SQLGlot expression with non-allowed columns removed
Raises:
ValueError: If a column can't be cleanly removed due to interactions with allowed columns
Examples
Complex Logic Handling
The library intelligently handles complex logical expressions:
# Original: (x = 1 AND y = 2) OR z = 3
# Remove y = 2: x = 1 OR z = 3
# Original: NOT (x = 1 AND y = 2)
# Remove x = 1: NOT y = 2 (which becomes y <> 2)
# Original: CASE WHEN x = 1 THEN 'yes' WHEN x = 2 THEN 'maybe' ELSE 'no' END
# Remove x = 1: CASE WHEN x = 2 THEN 'maybe' ELSE 'no' END
Column Filtering with Complex Expressions
sql = '''
SELECT * FROM users
WHERE age > 18
AND (status = 'active' OR role = 'admin')
AND department IN ('engineering', 'sales')
'''
# Only keep predicates involving 'age' and 'role'
allowed_columns = {'age', 'role'}
result = transforms.filter_column_references_statement(
sql=sql,
allowed_column_names=allowed_columns
)
# Result: SELECT * FROM users WHERE age > 18 AND role = 'admin'
Error Handling
The library will raise ValueError when predicates cannot be safely removed:
# This will raise ValueError because x = 1 is part of a larger expression
sql = "SELECT * FROM data WHERE result = (x = 1)"
# Cannot remove x = 1 because it's used as a value, not a predicate
Supported SQL Constructs
- Logical Operators:
AND,OR,NOT - Comparison Operators:
=,<>,<,>,<=,>=,LIKE,IN,IS NULL, etc. - Complex Expressions:
CASEstatements, subqueries, function calls - Nested Logic: Parentheses and nested boolean expressions
- Multiple Dialects: DuckDB, PostgreSQL, MySQL, SQLite, and more via SQLGlot
Testing
Run the test suite:
pytest src/query_farm_sql_manipulation/test_transforms.py
The test suite includes comprehensive examples of:
- Basic predicate removal scenarios
- Complex logical expression handling
- Error cases and edge conditions
- Column filtering with various SQL constructs
Contributing
This project uses:
- Rye for dependency management
- pytest for testing
- mypy for type checking
- ruff for linting
Author
This Python module was created by Query.Farm.
License
MIT Licensed.
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 query_farm_sql_manipulation-0.1.4.tar.gz.
File metadata
- Download URL: query_farm_sql_manipulation-0.1.4.tar.gz
- Upload date:
- Size: 8.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c188b7515a0134ea42211b114ba27dffcc426899926b251437df7c5e4261f015
|
|
| MD5 |
41a3b616c07455e84166122ca94b8398
|
|
| BLAKE2b-256 |
4f4b54c8c083cb3ddd1c175eb245d8bb0a06f2d037892c03f150f8aec691f11d
|
File details
Details for the file query_farm_sql_manipulation-0.1.4-py3-none-any.whl.
File metadata
- Download URL: query_farm_sql_manipulation-0.1.4-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72777479bfca6089430625aff3bdc071bbc815dc07b3c51ad3ef130e1a7676ba
|
|
| MD5 |
91e6070ec3f7a08202e875030aaf6dd7
|
|
| BLAKE2b-256 |
62eab9b2547e43882adb8263d49e3e6080c62286aa233f4ffe2f9bac6943829c
|