Skip to content

Commit e54168f

Browse files
authored
Merge pull request #4 from hotdata-dev/docs/ibis-support-overview
feat: managed database writes and hotdata SDK 0.2.0
2 parents 9b96213 + 3356374 commit e54168f

9 files changed

Lines changed: 616 additions & 287 deletions

File tree

.github/workflows/publish.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v[0-9]*'
7+
8+
concurrency:
9+
group: pypi-publish-${{ github.ref_name }}
10+
cancel-in-progress: false
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
build:
17+
name: Build distribution
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
21+
22+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
23+
with:
24+
python-version: '3.12'
25+
26+
- name: Install build tooling
27+
run: python -m pip install --upgrade build twine
28+
29+
- name: Verify tag matches pyproject version
30+
run: |
31+
# Release tags must start with `v` followed by a PEP 440 version (e.g. v1.2.3, v1.2.3a1).
32+
if [[ ! "$GITHUB_REF_NAME" =~ ^v[0-9] ]]; then
33+
echo "Release tag '$GITHUB_REF_NAME' must start with 'v' followed by a digit (e.g. v1.0.0)" >&2
34+
exit 1
35+
fi
36+
tag="${GITHUB_REF_NAME#v}"
37+
pkg_version=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
38+
if [ "$tag" != "$pkg_version" ]; then
39+
echo "Release tag ($tag) does not match pyproject.toml version ($pkg_version)" >&2
40+
exit 1
41+
fi
42+
43+
- name: Build sdist and wheel
44+
run: python -m build
45+
46+
- name: Check distribution metadata
47+
run: python -m twine check --strict dist/*
48+
49+
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
50+
with:
51+
name: dist
52+
path: dist/
53+
54+
publish:
55+
name: Publish to PyPI
56+
needs: build
57+
runs-on: ubuntu-latest
58+
environment:
59+
name: pypi
60+
url: https://pypi.org/p/ibis-hotdata
61+
permissions:
62+
id-token: write
63+
steps:
64+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
65+
with:
66+
name: dist
67+
path: dist/
68+
69+
- name: Publish via Trusted Publishing
70+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0

README.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Experimental [Ibis](https://ibis-project.org/) backend for [Hotdata](https://www.hotdata.dev/docs/api-reference): compile expressions with Ibis, run federated SQL over the Hotdata API. REST calls use the official **[hotdata](https://github.com/hotdata-dev/sdk-python)** Python SDK. Repo examples use **httpx** (listed under the **dev** dependency group).
44

5-
**Requirements:** Python 3.10+, **ibis-framework** 10.x, **hotdata** ≥0.1.
5+
**Requirements:** Python 3.10+, **ibis-framework** 10.x, **hotdata** ≥0.2.
66

77
## Install
88

@@ -19,8 +19,7 @@ uv pip install ibis-hotdata
1919
- **Typed table discovery** — load schema metadata from Hotdata information schema and map SQL types into Ibis types.
2020
- **Arrow and pandas results** — materialize expressions as pandas DataFrames, PyArrow tables, or local Arrow record batches.
2121
- **Raw SQL escape hatch** — use `con.sql(..., dialect="postgres")` when Hotdata-specific federated SQL is clearer than modeled Ibis expressions.
22-
- **Dataset upload helpers** — upload local pandas or PyArrow data as Parquet-backed Hotdata datasets through `create_table`.
23-
- **Dataset cleanup** — delete Hotdata-managed datasets through the limited `drop_table` implementation.
22+
- **Managed database writes** — create managed connections with `create_database`, load local pandas or PyArrow data through `create_table`, and clean up with `drop_table` / `drop_database`.
2423

2524
## Connect
2625

@@ -69,19 +68,18 @@ Supported today:
6968
- **SQL-backed expressions:** Ibis expressions compile with the Postgres SQLGlot compiler and execute through Hotdata. Common `SELECT` workloads such as projection, filtering, joins, grouping, aggregation, ordering, limits, scalar expressions, and `con.sql(...)` work when the generated SQL is accepted by Hotdata.
7069
- **Result materialization:** `.execute()` returns pandas objects. `.to_pyarrow()` and `.to_pyarrow_batches()` use the Arrow IPC result data exposed by Hotdata without converting through JSON rows; batches are split locally after the result is downloaded.
7170
- **Raw SQL escape hatch:** `con.sql("SELECT ...", dialect="postgres")` is the most reliable way to use Hotdata-specific federated table names or SQL that Ibis does not model directly.
72-
- **Uploads and datasets:** `upload_file` plus `create_dataset_from_upload` can create Hotdata datasets; query them as `datasets.<schema>.<table>` after creation.
73-
- **Limited `create_table`:** `con.create_table("name", pandas_df)` and `con.create_table("name", pyarrow_table)` serialize local data to Parquet, upload it, and create a Hotdata dataset. Schema-only calls create an empty Parquet-backed dataset.
74-
- **Dataset-only `drop_table`:** `con.drop_table(...)` deletes matching Hotdata-managed datasets. It does not drop external source tables.
71+
- **Managed database lifecycle:** `create_database("sales", schema="public", tables=["orders"])` registers a managed connection (Ibis catalog). `create_table("orders", pandas_df, database=("sales", "public"))` uploads Parquet and loads it with replace mode. Query as `sales.public.orders` in SQL. `drop_table` clears a managed table; `drop_database` deletes the connection.
72+
- **Parquet uploads:** `create_table` accepts pandas DataFrames, PyArrow tables, or schema-only empty tables. Tables must live in a managed connection — declare them with `create_database(..., tables=[...])` first. Loads always use replace mode; pass `overwrite=True` to replace an existing synced table (the default `overwrite=False` raises if the table already exists).
7573

7674
Not supported as full Ibis backend features:
7775

78-
- **General DDL and mutations:** Arbitrary remote `CREATE TABLE` / `DROP TABLE`, inserts, updates, deletes, overwrites, and schema-altering operations are not implemented. `create_table` and `drop_table` are limited to Hotdata datasets as described above.
76+
- **General DDL and mutations:** Arbitrary remote DDL, inserts, updates, deletes, and schema-altering operations on external connections are not implemented. Managed-database writes are limited to `create_database`, `create_table`, `drop_table`, and `drop_database` as described above.
7977
- **Temporary tables and in-memory registration:** `supports_temporary_tables` is false, and in-memory tables are not uploaded automatically for joins.
8078
- **Python UDFs:** `supports_python_udfs` is false.
8179
- **Transactions and sessions as database state:** Hotdata sandbox sessions can be passed as `session_id`, but the backend does not expose transaction APIs.
8280
- **Backend-native SQL dialect:** Compilation uses Ibis' Postgres dialect as the closest fit. Hotdata SQL and federation rules are authoritative, so not every Ibis expression that compiles is guaranteed to execute remotely.
8381
- **Complete Ibis compliance:** The backend is experimental and has focused test coverage for connection, discovery, schema mapping, execution, uploads, and Arrow results. It has not yet been validated against the full Ibis backend test suite.
84-
- **Hotdata platform APIs beyond SQL datasets:** embeddings, indexes, query history management, sandbox lifecycle management, and other Hotdata-specific APIs are outside the Ibis backend surface.
82+
- **Hotdata platform APIs beyond SQL and managed databases:** embeddings, indexes, query history management, sandbox lifecycle management, and other Hotdata-specific APIs are outside the Ibis backend surface.
8583

8684
## Development
8785

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ classifiers = [
2424
]
2525
dependencies = [
2626
"ibis-framework>=10.0,<11",
27-
"hotdata>=0.1.0",
27+
"hotdata>=0.2.0",
2828
"pyarrow>=15",
2929
"pyarrow-hotfix>=0.6",
3030
"pandas>=2",

0 commit comments

Comments
 (0)