Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ All notable changes to this project will be documented in this file.

### Added

* Support named and positional query bind values through `QueryRequest.params`.
* Add an optional Ibis backend with native Parquet results through `Client.query_parquet`.
* Surface errors received during NDJSON query streaming as `QueryError`.
* Add `Client.upload` with typed upload modes and support for file streams.
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ client = Client(username="your_username", password="your_password", verify=False
from altertable_lakehouse.models import QueryRequest

# Stream rows (good for large datasets)
req = QueryRequest(statement="SELECT * FROM my_table")
req = QueryRequest(
statement="SELECT * FROM my_table WHERE age >= $min_age",
params={"min_age": 25},
)
metadata, columns, row_iterator = client.query(req)
print(metadata.values)
print(columns)
Expand Down
1 change: 1 addition & 0 deletions src/altertable_lakehouse/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class QueryRequest(BaseModel):
sanitize: Optional[bool] = None
limit: Optional[int] = None
offset: Optional[int] = None
params: Optional[Union[Dict[str, Union[str, int, float, bool, None]], List[Union[str, int, float, bool, None]]]] = None
timezone: Optional[str] = None
ephemeral: Optional[bool] = None
visible: Optional[bool] = None
Expand Down
8 changes: 8 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ def test_query_all(client):
assert isinstance(res.columns, list)
assert isinstance(res.rows, list)


def test_query_request_serializes_named_and_positional_bind_values():
named = models.QueryRequest(statement="SELECT $min_age", params={"min_age": 25})
positional = models.QueryRequest(statement="SELECT $1", params=[25])

assert named.model_dump(exclude_none=True)["params"] == {"min_age": 25}
assert positional.model_dump(exclude_none=True)["params"] == [25]

def test_upsert_sends_primary_key_without_unsupported_mode(client):
captured = {}

Expand Down
Loading