Skip to content
Closed
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 @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- feat(databases): add default_schema field to database objects
- feat(schemas): add key field to table definitions
- feat(tables): support loading from query results

Expand Down
1 change: 1 addition & 0 deletions docs/CreateDatabaseRequest.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Request body for POST /databases
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**default_catalog** | **str** | Optional name the database's auto-created default catalog answers to inside its query scope. Must be a valid SQL identifier (`[a-z0-9_]`, not starting with a digit) and may not collide with the reserved catalog names `hotdata`, `datasets`, or `information_schema`. Defaults to `default` when omitted, so `default.main.<table>` keeps working. | [optional]
**default_schema** | **str** | Optional schema that unqualified table names resolve to inside this database's query scope. Must be a valid SQL identifier (`[a-z0-9_]`, not starting with a digit). When omitted, a database that declares exactly one schema adopts that schema as its default; otherwise unqualified names resolve to `main`. Fully-qualified names (`<catalog>.<schema>.<table>`) are unaffected, and a per-query `default_schema` still takes precedence. | [optional]
**expires_at** | **str** | When this database expires. Accepts either an RFC 3339 timestamp (e.g. `\"2026-06-01T00:00:00Z\"`) or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days) — for example `\"24h\"`, `\"48h\"`, or `\"7d\"`. Omitted (or empty) means the database never expires. Expiry is best-effort: the database will not be deleted before `expires_at`, but cleanup may run later than the exact timestamp. | [optional]
**name** | **str** | Optional free-form display label (for UIs/CLIs). Not unique. Not an identifier — databases are always addressed by `id`. Accepts the legacy `description` key as an alias so clients that predate the rename keep populating this field. | [optional]
**schemas** | [**List[DatabaseDefaultSchemaDecl]**](DatabaseDefaultSchemaDecl.md) | Optional schemas/tables to declare on the database's auto-created default catalog. Tables declared here can be loaded via the standard managed-table load endpoint targeting `default_connection_id`. Omitted or empty means the default catalog starts empty. | [optional]
Expand Down
1 change: 1 addition & 0 deletions docs/CreateDatabaseResponse.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**default_catalog** | **str** | Name the database's default catalog answers to inside its query scope (`default` unless overridden at create time). |
**default_connection_id** | **str** | Internal id of the connection that backs this database's `default` catalog. Workspace-level connection endpoints (list, get, health, delete, cache purge) refuse to act on this id — it is exposed only for the managed-tables load endpoint (`POST /v1/connections/{id}/schemas/{s}/tables/{t}/loads`) so callers can publish parquet into tables declared at database-create time. Addressing it directly in SQL is not the recommended path — use `default` inside an `X-Database-Id` scope instead. |
**default_schema** | **str** | Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. |
**expires_at** | **datetime** | When this database expires. | [optional]
**id** | **str** | |
**name** | **str** | | [optional]
Expand Down
1 change: 1 addition & 0 deletions docs/DatabaseDetailResponse.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Name | Type | Description | Notes
**created_at** | **datetime** | When the database was created. | [optional]
**default_catalog** | **str** | Name the database's default catalog answers to inside its query scope (`default` unless overridden at create time). |
**default_connection_id** | **str** | |
**default_schema** | **str** | Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. |
**expires_at** | **datetime** | When this database expires. | [optional]
**id** | **str** | |
**name** | **str** | | [optional]
Expand Down
1 change: 1 addition & 0 deletions docs/DatabaseSummary.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**created_at** | **datetime** | When the database was created. | [optional]
**default_catalog** | **str** | Name the database's default catalog answers to inside its query scope. |
**default_schema** | **str** | Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. |
**expires_at** | **datetime** | | [optional]
**id** | **str** | |
**name** | **str** | | [optional]
Expand Down
9 changes: 8 additions & 1 deletion hotdata/models/create_database_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ class CreateDatabaseRequest(BaseModel):
Request body for POST /databases
""" # noqa: E501
default_catalog: Optional[StrictStr] = Field(default=None, description="Optional name the database's auto-created default catalog answers to inside its query scope. Must be a valid SQL identifier (`[a-z0-9_]`, not starting with a digit) and may not collide with the reserved catalog names `hotdata`, `datasets`, or `information_schema`. Defaults to `default` when omitted, so `default.main.<table>` keeps working.")
default_schema: Optional[StrictStr] = Field(default=None, description="Optional schema that unqualified table names resolve to inside this database's query scope. Must be a valid SQL identifier (`[a-z0-9_]`, not starting with a digit). When omitted, a database that declares exactly one schema adopts that schema as its default; otherwise unqualified names resolve to `main`. Fully-qualified names (`<catalog>.<schema>.<table>`) are unaffected, and a per-query `default_schema` still takes precedence.")
expires_at: Optional[StrictStr] = Field(default=None, description="When this database expires. Accepts either an RFC 3339 timestamp (e.g. `\"2026-06-01T00:00:00Z\"`) or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days) — for example `\"24h\"`, `\"48h\"`, or `\"7d\"`. Omitted (or empty) means the database never expires. Expiry is best-effort: the database will not be deleted before `expires_at`, but cleanup may run later than the exact timestamp.")
name: Optional[StrictStr] = Field(default=None, description="Optional free-form display label (for UIs/CLIs). Not unique. Not an identifier — databases are always addressed by `id`. Accepts the legacy `description` key as an alias so clients that predate the rename keep populating this field.")
schemas: Optional[List[DatabaseDefaultSchemaDecl]] = Field(default=None, description="Optional schemas/tables to declare on the database's auto-created default catalog. Tables declared here can be loaded via the standard managed-table load endpoint targeting `default_connection_id`. Omitted or empty means the default catalog starts empty.")
__properties: ClassVar[List[str]] = ["default_catalog", "expires_at", "name", "schemas"]
__properties: ClassVar[List[str]] = ["default_catalog", "default_schema", "expires_at", "name", "schemas"]

model_config = ConfigDict(
populate_by_name=True,
Expand Down Expand Up @@ -85,6 +86,11 @@ def to_dict(self) -> Dict[str, Any]:
if self.default_catalog is None and "default_catalog" in self.model_fields_set:
_dict['default_catalog'] = None

# set to None if default_schema (nullable) is None
# and model_fields_set contains the field
if self.default_schema is None and "default_schema" in self.model_fields_set:
_dict['default_schema'] = None

# set to None if expires_at (nullable) is None
# and model_fields_set contains the field
if self.expires_at is None and "expires_at" in self.model_fields_set:
Expand All @@ -108,6 +114,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:

_obj = cls.model_validate({
"default_catalog": obj.get("default_catalog"),
"default_schema": obj.get("default_schema"),
"expires_at": obj.get("expires_at"),
"name": obj.get("name"),
"schemas": [DatabaseDefaultSchemaDecl.from_dict(_item) for _item in obj["schemas"]] if obj.get("schemas") is not None else None
Expand Down
4 changes: 3 additions & 1 deletion hotdata/models/create_database_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ class CreateDatabaseResponse(BaseModel):
""" # noqa: E501
default_catalog: StrictStr = Field(description="Name the database's default catalog answers to inside its query scope (`default` unless overridden at create time).")
default_connection_id: StrictStr = Field(description="Internal id of the connection that backs this database's `default` catalog. Workspace-level connection endpoints (list, get, health, delete, cache purge) refuse to act on this id — it is exposed only for the managed-tables load endpoint (`POST /v1/connections/{id}/schemas/{s}/tables/{t}/loads`) so callers can publish parquet into tables declared at database-create time. Addressing it directly in SQL is not the recommended path — use `default` inside an `X-Database-Id` scope instead.")
default_schema: StrictStr = Field(description="Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time.")
expires_at: Optional[datetime] = Field(default=None, description="When this database expires.")
id: StrictStr
name: Optional[StrictStr] = None
__properties: ClassVar[List[str]] = ["default_catalog", "default_connection_id", "expires_at", "id", "name"]
__properties: ClassVar[List[str]] = ["default_catalog", "default_connection_id", "default_schema", "expires_at", "id", "name"]

model_config = ConfigDict(
populate_by_name=True,
Expand Down Expand Up @@ -98,6 +99,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
_obj = cls.model_validate({
"default_catalog": obj.get("default_catalog"),
"default_connection_id": obj.get("default_connection_id"),
"default_schema": obj.get("default_schema"),
"expires_at": obj.get("expires_at"),
"id": obj.get("id"),
"name": obj.get("name")
Expand Down
4 changes: 3 additions & 1 deletion hotdata/models/database_detail_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ class DatabaseDetailResponse(BaseModel):
created_at: Optional[datetime] = Field(default=None, description="When the database was created.")
default_catalog: StrictStr = Field(description="Name the database's default catalog answers to inside its query scope (`default` unless overridden at create time).")
default_connection_id: StrictStr
default_schema: StrictStr = Field(description="Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time.")
expires_at: Optional[datetime] = Field(default=None, description="When this database expires.")
id: StrictStr
name: Optional[StrictStr] = None
__properties: ClassVar[List[str]] = ["attachments", "created_at", "default_catalog", "default_connection_id", "expires_at", "id", "name"]
__properties: ClassVar[List[str]] = ["attachments", "created_at", "default_catalog", "default_connection_id", "default_schema", "expires_at", "id", "name"]

model_config = ConfigDict(
populate_by_name=True,
Expand Down Expand Up @@ -115,6 +116,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"created_at": obj.get("created_at"),
"default_catalog": obj.get("default_catalog"),
"default_connection_id": obj.get("default_connection_id"),
"default_schema": obj.get("default_schema"),
"expires_at": obj.get("expires_at"),
"id": obj.get("id"),
"name": obj.get("name")
Expand Down
4 changes: 3 additions & 1 deletion hotdata/models/database_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ class DatabaseSummary(BaseModel):
""" # noqa: E501
created_at: Optional[datetime] = Field(default=None, description="When the database was created.")
default_catalog: StrictStr = Field(description="Name the database's default catalog answers to inside its query scope.")
default_schema: StrictStr = Field(description="Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time.")
expires_at: Optional[datetime] = None
id: StrictStr
name: Optional[StrictStr] = None
__properties: ClassVar[List[str]] = ["created_at", "default_catalog", "expires_at", "id", "name"]
__properties: ClassVar[List[str]] = ["created_at", "default_catalog", "default_schema", "expires_at", "id", "name"]

model_config = ConfigDict(
populate_by_name=True,
Expand Down Expand Up @@ -103,6 +104,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
_obj = cls.model_validate({
"created_at": obj.get("created_at"),
"default_catalog": obj.get("default_catalog"),
"default_schema": obj.get("default_schema"),
"expires_at": obj.get("expires_at"),
"id": obj.get("id"),
"name": obj.get("name")
Expand Down
1 change: 1 addition & 0 deletions test/test_create_database_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def make_instance(self, include_optional) -> CreateDatabaseRequest:
if include_optional:
return CreateDatabaseRequest(
default_catalog = '',
default_schema = '',
expires_at = '',
name = '',
schemas = [
Expand Down
2 changes: 2 additions & 0 deletions test/test_create_database_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def make_instance(self, include_optional) -> CreateDatabaseResponse:
return CreateDatabaseResponse(
default_catalog = '',
default_connection_id = '',
default_schema = '',
expires_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
id = '',
name = ''
Expand All @@ -46,6 +47,7 @@ def make_instance(self, include_optional) -> CreateDatabaseResponse:
return CreateDatabaseResponse(
default_catalog = '',
default_connection_id = '',
default_schema = '',
id = '',
)
"""
Expand Down
2 changes: 2 additions & 0 deletions test/test_database_detail_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def make_instance(self, include_optional) -> DatabaseDetailResponse:
created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
default_catalog = '',
default_connection_id = '',
default_schema = '',
expires_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
id = '',
name = ''
Expand All @@ -57,6 +58,7 @@ def make_instance(self, include_optional) -> DatabaseDetailResponse:
],
default_catalog = '',
default_connection_id = '',
default_schema = '',
id = '',
)
"""
Expand Down
2 changes: 2 additions & 0 deletions test/test_database_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ def make_instance(self, include_optional) -> DatabaseSummary:
return DatabaseSummary(
created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
default_catalog = '',
default_schema = '',
expires_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
id = '',
name = ''
)
else:
return DatabaseSummary(
default_catalog = '',
default_schema = '',
id = '',
)
"""
Expand Down
2 changes: 2 additions & 0 deletions test/test_list_databases_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def make_instance(self, include_optional) -> ListDatabasesResponse:
hotdata.models.database_summary.DatabaseSummary(
created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
default_catalog = '',
default_schema = '',
expires_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
id = '',
name = '', )
Expand All @@ -51,6 +52,7 @@ def make_instance(self, include_optional) -> ListDatabasesResponse:
hotdata.models.database_summary.DatabaseSummary(
created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
default_catalog = '',
default_schema = '',
expires_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
id = '',
name = '', )
Expand Down
Loading