refactor: remove legacy ktx compatibility shims (#211)

* refactor: remove legacy ktx compatibility shims

* fix: restore overlay collision guidance
This commit is contained in:
Andrey Avtomonov 2026-05-24 16:57:23 +02:00 committed by GitHub
parent a954a29a76
commit 96952fb43c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
59 changed files with 294 additions and 342 deletions

View file

@ -327,7 +327,7 @@ def introspect_database_response(
now: NowProvider | None = None,
) -> DatabaseIntrospectionResponse:
driver = _driver_name(request.driver)
if driver not in {"postgres", "postgresql"}:
if driver != "postgres":
raise ValueError('database introspection supports only driver "postgres"')
rows = (load_rows or _load_postgres_rows)(request)

View file

@ -13,7 +13,7 @@ from semantic_layer.models import QueryResult, SourceDefinition
class SemanticLayerQueryRequest(BaseModel):
model_config = ConfigDict(populate_by_name=True)
model_config = ConfigDict(extra="forbid")
sources: list[dict[str, Any]]
query: dict[str, Any]

View file

@ -5,7 +5,7 @@ from concurrent.futures import ProcessPoolExecutor
from typing import Literal
import sqlglot
from pydantic import BaseModel, ConfigDict, Field
from pydantic import BaseModel, Field
from sqlglot import exp
SqlAnalysisClause = Literal["select", "where", "join", "groupBy", "having", "orderBy"]
@ -23,8 +23,6 @@ class AnalyzeSqlBatchRequest(BaseModel):
class AnalyzeSqlBatchResult(BaseModel):
model_config = ConfigDict(populate_by_name=True)
tables_touched: list[str] = Field(default_factory=list)
columns_by_clause: dict[SqlAnalysisClause, list[str]] = Field(default_factory=dict)
error: str | None = None

View file

@ -1,9 +1,8 @@
from __future__ import annotations
from dataclasses import asdict
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field
from pydantic import BaseModel, Field
from semantic_layer.table_identifier_parser import (
ParseTableIdentifierItem as SharedParseTableIdentifierItem,
parse_table_identifier_batch,
@ -30,8 +29,6 @@ class ParseTableIdentifierBatchRequest(BaseModel):
class ParsedIdentifier(BaseModel):
model_config = ConfigDict(populate_by_name=True)
ok: bool
catalog: str | None = None
schema_: str | None = Field(default=None, alias="schema")
@ -60,7 +57,15 @@ def parse_table_identifier_response(
)
return ParseTableIdentifierBatchResponse(
results={
key: ParsedIdentifier.model_validate(asdict(value))
key: ParsedIdentifier(
ok=value.ok,
catalog=value.catalog,
schema=value.schema_,
name=value.name,
canonical_table=value.canonical_table,
reason=value.reason,
detail=value.detail,
)
for key, value in shared_results.items()
}
)

View file

@ -138,6 +138,18 @@ def test_introspect_database_response_rejects_non_postgres_driver() -> None:
)
def test_introspect_database_response_rejects_legacy_postgresql_driver() -> None:
with pytest.raises(ValueError, match='supports only driver "postgres"'):
introspect_database_response(
DatabaseIntrospectionRequest(
connection_id="warehouse",
driver="postgresql",
url="postgresql://readonly@example.test/warehouse",
),
load_rows=lambda request: DatabaseIntrospectionRows([], [], []),
)
def test_database_introspection_request_rejects_empty_schema_list() -> None:
with pytest.raises(ValueError, match="at least one schema"):
DatabaseIntrospectionRequest(

View file

@ -3,6 +3,8 @@ from __future__ import annotations
import json
from pathlib import Path
import pytest
from ktx_daemon.semantic_layer import (
SemanticLayerQueryRequest,
ValidateSourcesRequest,
@ -95,6 +97,16 @@ def test_query_semantic_layer_emits_plan_and_sql_debug_events(
assert "public.orders" not in captured.err
def test_semantic_layer_request_rejects_project_id_field_name() -> None:
with pytest.raises(ValueError):
SemanticLayerQueryRequest(
sources=[],
dialect="postgres",
project_id="a" * 64,
query={"measures": ["orders.order_count"]},
)
def test_validate_semantic_layer_reports_duplicate_measure_names() -> None:
invalid_source = {
**ORDERS_SOURCE,

View file

@ -201,7 +201,7 @@ class SourceLoader:
name = col.get("name")
if name in base_by_name:
raise ValueError(
f"column '{name}' in columns patches a manifest column on '{base.name}' move it to 'column_overrides:'"
f"column '{name}' in columns patches a manifest column on '{base.name}' - move it to 'column_overrides:'"
)
source.columns.append(SourceColumn(**col))