Skip to content

Commit 423c9ce

Browse files
committed
feat(connectors): BI-6585 Add column tables support for YDB
1 parent fcbf752 commit 423c9ce

File tree

7 files changed

+93
-4
lines changed

7 files changed

+93
-4
lines changed

lib/dl_connector_ydb/dl_connector_ydb/core/ydb/adapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _list_table_names_i(self, db_name: str, show_dot: bool = False) -> Iterable[
117117
]
118118
children.sort()
119119
for full_path, child in children:
120-
if child.is_any_table():
120+
if child.is_any_table() or child.is_view() or child.is_column_table():
121121
yield full_path.removeprefix(unprefix)
122122
elif child.is_directory():
123123
queue.append(full_path)

lib/dl_connector_ydb/dl_connector_ydb_tests/db/api/base.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
)
2525
from dl_connector_ydb_tests.db.config import (
2626
API_TEST_CONFIG,
27+
COLUMN_TABLE_SCHEMA,
2728
DB_CORE_URL,
29+
SA_TYPE_TO_YDB_TYPE_NAME,
2830
TABLE_DATA,
2931
TABLE_NAME,
3032
TABLE_SCHEMA,
@@ -102,6 +104,41 @@ def dataset_params(self, sample_table: DbTable) -> dict:
102104
)
103105

104106

107+
class YDBColumnDatasetTestBase(YDBDatasetTestBase):
108+
@pytest.fixture(scope="class")
109+
def sample_table(self, db: Db) -> DbTable:
110+
table_name = TABLE_NAME + "_column"
111+
112+
db_table = make_table(
113+
db=db,
114+
name=table_name,
115+
columns=[
116+
C(name=name, user_type=user_type, sa_type=sa_type) for name, user_type, sa_type in COLUMN_TABLE_SCHEMA
117+
],
118+
data=[], # to avoid producing a sample data
119+
create_in_db=False,
120+
)
121+
122+
column_definitions_list = []
123+
for name, _, sa_type in COLUMN_TABLE_SCHEMA:
124+
target_type = SA_TYPE_TO_YDB_TYPE_NAME[sa_type]
125+
if name == "id":
126+
target_type += " NOT NULL"
127+
128+
column_definitions_list.append(f"{name} {target_type}")
129+
column_definitions = ", ".join(column_definitions_list)
130+
131+
query = f"CREATE TABLE `{table_name}` ({column_definitions}, PRIMARY KEY (id)) WITH (STORE = COLUMN)"
132+
db.get_current_connection().connection.cursor().execute_scheme(query)
133+
134+
db.create_table(db_table.table)
135+
db.insert_into_table(db_table.table, TABLE_DATA)
136+
137+
yield db_table
138+
139+
db.get_current_connection().connection.cursor().execute_scheme(f"DROP TABLE `{table_name}`;")
140+
141+
105142
class YDBDataApiTestBase(YDBDatasetTestBase, StandardizedDataApiTestBase):
106143
mutation_caches_enabled = False
107144

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
from dl_api_client.dsmaker.primitives import Dataset
22
from dl_api_lib_testing.connector.dataset_suite import DefaultConnectorDatasetTestSuite
33

4-
from dl_connector_ydb_tests.db.api.base import YDBDatasetTestBase
5-
from dl_connector_ydb_tests.db.config import TABLE_SCHEMA
4+
from dl_connector_ydb_tests.db.api.base import (
5+
YDBColumnDatasetTestBase,
6+
YDBDatasetTestBase,
7+
)
8+
from dl_connector_ydb_tests.db.config import (
9+
COLUMN_TABLE_SCHEMA,
10+
TABLE_SCHEMA,
11+
)
612

713

814
class TestYDBDataset(YDBDatasetTestBase, DefaultConnectorDatasetTestSuite):
@@ -12,3 +18,10 @@ def check_basic_dataset(self, ds: Dataset, annotation: dict) -> None:
1218
assert field_names == {column[0] for column in TABLE_SCHEMA}
1319

1420
assert ds.annotation == annotation
21+
22+
23+
class TestYDBColumnDataset(YDBColumnDatasetTestBase, DefaultConnectorDatasetTestSuite):
24+
def check_basic_dataset(self, ds: Dataset) -> None:
25+
assert ds.id
26+
field_names = {field.title for field in ds.result_schema}
27+
assert field_names == {column[0] for column in COLUMN_TABLE_SCHEMA}

lib/dl_connector_ydb/dl_connector_ydb_tests/db/config.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,36 @@ class CoreSslConnectionSettings:
7979
("some_timestamp", UserDataType.genericdatetime, sa.TIMESTAMP),
8080
("some_interval", UserDataType.integer, dl_sqlalchemy_ydb.dialect.YqlInterval),
8181
)
82+
83+
COLUMN_TABLE_SCHEMA = (
84+
("id", UserDataType.integer, sa.Integer),
85+
("distinct_string", UserDataType.string, sa.String),
86+
("some_int32", UserDataType.integer, sa.Integer),
87+
("some_int64", UserDataType.integer, sa.BigInteger),
88+
("some_uint8", UserDataType.integer, sa.SmallInteger),
89+
("some_double", UserDataType.float, sa.Float),
90+
("some_string", UserDataType.string, sa.String),
91+
("some_utf8", UserDataType.string, sa.Unicode),
92+
("some_date", UserDataType.date, sa.Date),
93+
("some_datetime", UserDataType.genericdatetime, sa.DATETIME),
94+
("some_timestamp", UserDataType.genericdatetime, sa.TIMESTAMP),
95+
("some_interval", UserDataType.integer, dl_sqlalchemy_ydb.dialect.YqlInterval),
96+
)
97+
98+
SA_TYPE_TO_YDB_TYPE_NAME = {
99+
sa.Integer: "Int32",
100+
sa.String: "String",
101+
sa.BigInteger: "Int64",
102+
sa.SmallInteger: "Int8",
103+
sa.Boolean: "Bool",
104+
sa.Float: "Double",
105+
sa.Unicode: "Utf8",
106+
sa.Date: "Date",
107+
sa.DATETIME: "Datetime",
108+
sa.TIMESTAMP: "Timestamp",
109+
dl_sqlalchemy_ydb.dialect.YqlInterval: "Interval",
110+
}
111+
82112
TABLE_DATA = [
83113
{
84114
"id": 1,
@@ -246,8 +276,13 @@ class CoreSslConnectionSettings:
246276
"some_interval": 1234,
247277
},
248278
]
279+
280+
# Leave only values in COLUMN_TABLE_SCHEMA
281+
COLUMN_TABLE_DATA = [{key: value for key, value in row.items() if key in COLUMN_TABLE_SCHEMA} for row in TABLE_DATA]
282+
249283
TABLE_NAME = "test_table_h"
250284

285+
251286
DASHSQL_QUERY = r"""
252287
select
253288
id,

lib/dl_connector_ydb/docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ services:
99
YDB_GRPC_ENABLE_TLS: 1
1010
GRPC_TLS_PORT: "51902"
1111
YDB_GRPC_TLS_DATA_PATH: "/ydb_certs"
12+
YDB_FEATURE_FLAGS: "enable_views,enable_olap_schema_operations"
13+
YDB_ENABLE_COLUMN_TABLES: "true"
1214
hostname: "db-ydb"
1315
ports:
1416
- "51900:51900"

lib/dl_connector_ydb/docker-compose/Dockerfile.db-ydb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM cr.yandex/yc/yandex-docker-local-ydb:latest
1+
FROM ydbplatform/local-ydb:latest@sha256:1252f37e5f3fd6c490a8e6c34f927cb8b3dd8323db2aa14ffa21dd09dd6ebcdc
22

33
RUN apt update && apt install -y python3
44

lib/dl_type_transformer/dl_type_transformer/type_transformer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ def make_datetime(value: Any) -> Optional[datetime.datetime]:
7272
def make_int(value: Any) -> Optional[int]:
7373
if value is None:
7474
return None
75+
# if isinstance(value, datetime.timedelta):
76+
# return int(value.total_seconds())
7577
if isinstance(value, float) and (math.isinf(value) or math.isnan(value)):
7678
return None
7779
return int(value)

0 commit comments

Comments
 (0)