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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ con = ibis.hotdata.connect(
verify_ssl=True, # False to skip TLS verification, or path to CA bundle
default_connection=None, # default catalog (connection id); auto-detected if only one exists
default_schema=None, # default schema; auto-detected if only one exists
database_id=None, # bind an existing managed database id at connect time
database_id=None, # bind an existing instant database id at connect time
poll_interval_s=0.25, # polling interval for async queries
poll_timeout_s=600.0, # max time to wait for a query result
)
Expand All @@ -83,9 +83,9 @@ con = ibis.connect(
)
```

## Managed databases
## Instant databases

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: (not blocking) README.md:263 in the "What's supported" table still reads `create_database` / `drop_database` (managed). That parenthetical is prose, not an identifier, so it should probably become (instant) to match the new section heading.


Managed databases are the primary way to bring data into Hotdata with Ibis. Declare a database and its tables, upload data, and query immediately.
Instant databases are the primary way to bring data into Hotdata with Ibis. Declare a database and its tables, upload data, and query immediately.

### Create and load

Expand Down
6 changes: 3 additions & 3 deletions examples/04_ibis_table_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
(multi-column projections, joins across tables, filters, ordering) -- not
just a single trivial column.

Ad hoc/federated querying (raw ``Connection`` tables, no managed database) is
Ad hoc/federated querying (raw ``Connection`` tables, no instant database) is

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: (not blocking) Lines 2 and 5 of this same module docstring were missed:

  • L2: """Ibis table expressions against a managed Hotdata database, executed to pandas.
  • L5: aggregate against two small managed tables (customer, orders). Distinct from

L2 is the same term being renamed, so the file now reads "managed Hotdata database" in the summary line and "instant database" ten lines later. (L5's "managed tables" is arguably a separate term — your call.)

not used here: it's a deprecated path, and every query now requires a
database scope server-side regardless.

Expand Down Expand Up @@ -40,7 +40,7 @@


def setup(api_url: str, token: str, workspace_id: str) -> str:
"""Create the managed database and load small customer/orders tables."""
"""Create the instant database and load small customer/orders tables."""
con = ibis.hotdata.connect(api_url=api_url, token=token, workspace_id=workspace_id)
database_id = con.create_database(DATABASE, tables=["customer", "orders"], schema=SCHEMA)

Expand Down Expand Up @@ -120,7 +120,7 @@ def main() -> None:
token = os.environ["HOTDATA_API_KEY"]
workspace_id = os.environ["HOTDATA_WORKSPACE"]

print("== SETUP (managed database: customer, orders) ==")
print("== SETUP (instant database: customer, orders) ==")
database_id = setup(API_BASE_URL, token, workspace_id)
print(f"created database_id={database_id}")

Expand Down
8 changes: 4 additions & 4 deletions examples/05_roundtrip_demo.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""Ibis <-> Hotdata round trip: create a managed database, upload data, read it back.
"""Ibis <-> Hotdata round trip: create an instant database, upload data, read it back.

Demonstrates the managed-database read contract that ``hotdata-dlt-destination``'s
Demonstrates the instant-database read contract that ``hotdata-dlt-destination``'s
live ibis backend depends on: bind ``database_id`` (the id returned by
``create_database``, not its display name -- Hotdata database names are not
unique) at connect time, then read through the ``"default"`` catalog -- both
Expand Down Expand Up @@ -34,7 +34,7 @@


def write(api_url: str, token: str, workspace_id: str) -> str:
"""Create the managed database and upload a small pandas DataFrame into it."""
"""Create the instant database and upload a small pandas DataFrame into it."""
con = ibis.hotdata.connect(api_url=api_url, token=token, workspace_id=workspace_id)
database_id = con.create_database(DATABASE, tables=["spans"], schema=SCHEMA)

Expand Down Expand Up @@ -97,7 +97,7 @@ def main() -> None:
database_id = write(API_BASE_URL, token, workspace_id)
print(f"created database_id={database_id}")

print("\n== READ, via the managed-database contract ==")
print("\n== READ, via the instant-database contract ==")
read_via_ibis(API_BASE_URL, token, workspace_id, database_id)

print("\n== CLEANUP ==")
Expand Down
22 changes: 11 additions & 11 deletions src/ibis_hotdata/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def do_connect(
Optional default **database** (remote schema name). If omitted and only
one schema exists for the default connection, it is chosen automatically.
database_id
Optional managed database id to bind at connect time. When set, all
Optional instant database id to bind at connect time. When set, all
queries use this database's ``X-Database-Id`` header and ``"default"``
catalog references resolve to the underlying connection automatically —
without needing to call ``create_table`` first.
Expand Down Expand Up @@ -335,7 +335,7 @@ def _resolve_connection(self, name_or_id: str) -> dict[str, Any]:
raise com.IbisError(f"Unknown Hotdata connection {name_or_id!r}")

def _find_managed_connection(self, database_id: str) -> dict[str, Any] | None:
"""Look up a managed database by id.
"""Look up an instant database by id.

Returns the detail dict if found, ``None`` if not found.
Raises :class:`~ibis.common.exceptions.IbisError` on API failures.
Expand All @@ -348,10 +348,10 @@ def _find_managed_connection(self, database_id: str) -> dict[str, Any] | None:
raise _ibis_err_from_hotdata(exc) from exc

def _resolve_managed_connection(self, database_id: str) -> dict[str, Any]:
"""Resolve a managed database by id, returning its detail dict."""
"""Resolve an instant database by id, returning its detail dict."""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: (not blocking) The private helpers got renamed, but the two public API docstrings and their user-facing error messages still say "managed":

  • backend.py:572 — """Create a managed Hotdata connection (Ibis catalog) with optional declared tables."""
  • backend.py:582 — "Hotdata create_database creates a managed connection (catalog); "
  • backend.py:601 — """Delete a managed Hotdata connection (Ibis catalog)."""
  • backend.py:608 — "Hotdata drop_database deletes a managed connection (catalog); "

These are the most user-visible strings of the set (they show up in help(con.create_database) and in raised UnsupportedOperationError text), so leaving them on the old term partly defeats the rename. If "managed connection" is deliberately a different concept from "managed database" here, ignore this — but the surrounding code uses the two interchangeably (_resolve_managed_connection is the "instant database" lookup).

result = self._find_managed_connection(database_id)
if result is None:
raise com.IbisError(f"Unknown managed database {database_id!r}")
raise com.IbisError(f"Unknown instant database {database_id!r}")
return result

def _managed_table_synced(
Expand Down Expand Up @@ -399,15 +399,15 @@ def _table_location(
db_record = self._resolve_managed_connection(conn)
conn_id = db_record["default_connection_id"]
# Always update both cached values so they stay in sync across multiple
# create_table / drop_table calls, even if different managed databases are used.
# create_table / drop_table calls, even if different instant databases are used.
self._database_id = db_record["id"]
self._database_connection_id = conn_id
return conn_id, schema

def _resolve_database_connection_id(self) -> str | None:
"""Return the actual connection_id for the current managed database context.
"""Return the actual connection_id for the current instant database context.

Managed database SQL uses ``"default"`` as the catalog, but the information
Instant database SQL uses ``"default"`` as the catalog, but the information
schema REST API still needs the real ``connection_id``. This method resolves
that mapping lazily and caches the result.
"""
Expand All @@ -432,7 +432,7 @@ def get_schema(
) -> sch.Schema:
conn = catalog or self.current_catalog
schema_name = database or self.current_database
# Managed database tables use "default" as the SQL catalog but the info
# Instant database tables use "default" as the SQL catalog but the info
# schema REST API needs the real connection_id.
api_conn = (
(self._resolve_database_connection_id() or conn)
Expand Down Expand Up @@ -665,7 +665,7 @@ def create_table(
) -> ir.Table:
"""Upload local data into a declared managed table.

``database``'s first element must be the managed database id returned
``database``'s first element must be the instant database id returned
by ``create_database``, not its display name — Hotdata database names
are not unique.

Expand All @@ -679,7 +679,7 @@ def create_table(
data = self._local_table_to_parquet(obj, schema)
connection_id, schema_name = self._table_location(database)
# Cache the resolved connection_id so get_schema can use it for info schema
# API calls when the "default" catalog is used in managed database contexts.
# API calls when the "default" catalog is used in instant database contexts.
self._database_connection_id = connection_id
if not overwrite and self._managed_table_synced(connection_id, schema_name, name):
raise com.IbisInputError(
Expand All @@ -695,7 +695,7 @@ def create_table(
)
except HotdataAPIError as exc:
raise _ibis_err_from_hotdata(exc) from exc
# Managed database SQL requires "default" as the catalog prefix, not the
# Instant database SQL requires "default" as the catalog prefix, not the
# raw connection_id. _table_location always sets _database_id when resolving
# a managed connection, so we can always use the "default" catalog here.
return self.table(name, database=("default", schema_name))
Expand Down
2 changes: 1 addition & 1 deletion src/ibis_hotdata/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def create_managed_database(
schema: str = "public",
tables: Sequence[str] = (),
) -> dict[str, Any]:
"""POST ``/v1/databases`` — creates a managed database.
"""POST ``/v1/databases`` — creates an instant database.

The database is created with an auto-provisioned default catalog.
"""
Expand Down
6 changes: 3 additions & 3 deletions tests/test_hotdata_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from conftest import mock_presigned_upload_flow
from pytest_httpserver import HTTPServer

# Managed database identifiers for mocked Hotdata (SQL shape ``sales.public.orders``).
# Instant database identifiers for mocked Hotdata (SQL shape ``sales.public.orders``).
MANAGED_DB_ID = "db_sales" # databases API id
MANAGED_CONN = "conn_sales" # default_connection_id (backing connection for loads)
MANAGED_NAME = "sales" # description
Expand Down Expand Up @@ -595,12 +595,12 @@ def test_drop_table_raises_for_unknown_database(httpserver: HTTPServer, srv: str

con = ibis.hotdata.connect(api_url=srv, token="tok", workspace_id="ws", verify_ssl=False)

with pytest.raises(com.IbisError, match="Unknown managed database"):
with pytest.raises(com.IbisError, match="Unknown instant database"):
con.drop_table("demo", database=(TPCH_CONN, PUBLIC))


def test_drop_table_force_ignores_unknown_database(httpserver: HTTPServer, srv: str):
# force=True silently swallows the "Unknown managed database" IbisError
# force=True silently swallows the "Unknown instant database" IbisError
httpserver.expect_request(f"/v1/databases/{TPCH_CONN}").respond_with_data(
json.dumps({"detail": "not found"}), status=404, content_type="application/json"
)
Expand Down
Loading