Dynamic building of filtered database queries
Project description
Datasiphon
Package for applying dictionary filter to some form of query on database to retrieve filtered data or acquire filtered query
Installation
Use the package manager pip to install datasiphon.
pip install datasiphon
Usage
from datasiphon import SqlQueryBuilder
import sqlalchemy as sa
# Create a filter
filter_ = {
"name": {"eq": "John"},
}
table = sa.Table("users", sa.MetaData(), autoload=True, autoload_with=engine)
# Build a query
query = table.select()
# set up builder with table base
builder = SqlQueryBuilder({"users": table})
# build a query with filter
new_query = builder.build(query, filter_)
Supported Database types
SQL package (No ORM)
- implemented using
sqlalchemypackage, expected to work withTableandSelectobjects
Building query
- Prerequisite
- base
SELECTquery (Selectobject) from actualTableobjects (nottextobjects) - filter (dictionary/
QsRootfromqstionpackage), optional, optimally parsed usingqstionpackage -> similiar to npm'sqspackage - restrictions (optional) - objects that restrict specific columns and operators that can be used in filter
- base
- Usage
from siphon import sql
# Create a filter with strict form
filter_ = {
"name": {"eq": "John"},
}
# build a query with filter
new_query = sql.SqlQueryBuilder({"users": table}).build(query, filter_)
filter_is validated before building the query, expecting specific format representing valid structure of applicable filter for given backend (currently only SQL backend is supported)- allowed format represents nestings containing one of :
- junctions (AND, OR) -> for combining multiple conditions with desired logical operators
# Example correct - joining or with different fields filter_ = { "or": { "name": {"eq": "John"}, "age": {"gt": 20} } } # example correct - joining or with same field, different operators filter_ = { "name": { "or": { "eq": "John", "ne": "John" } } } filter_ = { "or": { "name": {"eq": "John"}, "age": {"gt": 20} }, "and": { "name": {"eq": "John"}, "age": {"gt": 20} } }
- operators (eq, ne...) -> for applying conditions on fields -> must always follow a field name (not directly but always has to be nested deeper than field name)
# Example correct - applying eq operator on field name filter_ = { "name": {"eq": "John"} } # Example - incorrect - applying eq operator before field name filter_ = { "eq": { "name": "John" } }
- field name -> for applying conditions on fields -> must always contain an operator (not directly but always has to be nested deeper than field name)
# Example correct - applying eq operator on field name filter_ = { "name": {"eq": "John"} } # Example - incorrect - applying eq operator before field name filter_ = { "eq": { "name": "John" } }
-
if using restriction model - builder will raise error when trying to apply operator that is restricted for given field (column)
from siphon import ColumnFilterRestriction, AnyValue from siphon.sql_filter import SQLEq, SQLNe # Example of correct restriction model usage # This restriction will forbid applying eq operator on field `name` - AnyValue signifies that any value is forbidden restriction = ColumnFilterRestriction( "name", SQLEq.generate_restriction(AnyValue) ) # Example of specific value restriction # This restriction will forbid applying eq operator on field `name` with value "John" restriction = ColumnFilterRestriction( "name", SQLEq.generate_restriction("John") ) # Alternate approach to generate restriction restriction = ColumnFilterRestriction.from_dict( "name", {"eq": AnyValue} ) restriction = ColumnFilterRestriction.from_dict( "name", {"eq": "John"} ) # Applying restriction to builder builder = SqlQueryBuilder({"users": table}) # Restrictions are optional positional argument builder.build(query, filter_, restriction) # different restriction for different column age_restriction = ColumnFilterRestriction( "age", SQLNe.generate_restriction(20) ) builder.build(query, filter_, restriction, age_restriction)
-
using multiple condition without specifying junctions will result in an
ANDjunction between them# Example correct - applying eq operator on field name filter_ = { "name": {"eq": "John"}, "age": {"gt": 20} } # will be treated as filter_ = { "and": { "name": {"eq": "John"}, "age": {"gt": 20} } } filter_ = { "name": { "eq": "John", "ne": "John" } } # will be treated as filter_ = { "and": { "name": { "eq": "John", "ne": "John" } } }
-
generating query: recursively collecting items from filter, and applying filtering directly to exported columns of given query
Manipulating FilterExpression object
FilterExpressionobject is a tree-like structure representing filter dictionary in a way that can be easily manipulated- Expressions can be added via
add_expressionmethod - Expressions can be replaced via
replace_expressionmethod - Expressions can be removed via
remove_expressionmethod - Expressions can be retrieved via
find_expressionmethod
Reconstructing filter from FilterExpression and SqlKeywordFilter objects
- since
FilterExpressionobject is a tree-like structure builded originally from filter dictionary, it can be easily reconstructed along withSqlKeywordFilterobject to represent the same filter as original dictionary - this objects can be manipulated directly to adjust filter or to be used in different context
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 datasiphon-0.3.11.tar.gz.
File metadata
- Download URL: datasiphon-0.3.11.tar.gz
- Upload date:
- Size: 22.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
449861ed98c2270d951f4b86272f2599654a7c49f4bf6a9111638cbb4c206bf4
|
|
| MD5 |
b46484cce29f263e61c047c29e76866e
|
|
| BLAKE2b-256 |
2c61144faf2a2392a3a0c917dcaaebdfb17addd22e755eab517cc22f72c3facb
|
File details
Details for the file datasiphon-0.3.11-py3-none-any.whl.
File metadata
- Download URL: datasiphon-0.3.11-py3-none-any.whl
- Upload date:
- Size: 14.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d93d27d1be4efcab6a36c83191965aaebaaa5d52afcc6a9089a01a814ed0d9a5
|
|
| MD5 |
d4acdd19a1aa8db7f508ba70196dd699
|
|
| BLAKE2b-256 |
0688c340307c394144cca22ed331889e7d3a2801bbce3bfbc3e0c8449609f70f
|