Skip to content

Commit 5598f85

Browse files
authored
YDB FQ: integration tests for MS SQL Server (#7871)
1 parent 870de13 commit 5598f85

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1346
-44
lines changed

ydb/library/yql/providers/generic/connector/tests/common_test_cases/base.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ def name(self) -> str:
2424
# ClickHouse has two kinds of network protocols: NATIVE and HTTP,
2525
# so we append protocol name to the test case name
2626
return f'{self.name_}_{EProtocol.Name(self.protocol)}'
27+
case EDataSourceKind.MS_SQL_SERVER:
28+
return self.name_
2729
case EDataSourceKind.MYSQL:
2830
return self.name_
2931
case EDataSourceKind.ORACLE:
@@ -39,11 +41,14 @@ def name(self) -> str:
3941
def database(self) -> Database:
4042
'''
4143
For PG/CH we create a distinct database on every test case.
42-
For YDB/MySQL we use single predefined database.
44+
For YDB/MySQL/Microsoft SQL Server we use single predefined database.
4345
'''
46+
# FIXME: do not hardcode databases here
4447
match self.data_source_kind:
4548
case EDataSourceKind.CLICKHOUSE:
4649
return Database(self.name, self.data_source_kind)
50+
case EDataSourceKind.MS_SQL_SERVER:
51+
return Database("master", self.data_source_kind)
4752
case EDataSourceKind.MYSQL:
4853
return Database("db", self.data_source_kind)
4954
case EDataSourceKind.ORACLE:
@@ -62,6 +67,8 @@ def table_name(self) -> str:
6267
match self.data_source_kind:
6368
case EDataSourceKind.CLICKHOUSE:
6469
return 't' + make_random_string(8)
70+
case EDataSourceKind.MS_SQL_SERVER:
71+
return self.name
6572
case EDataSourceKind.MYSQL:
6673
return self.name
6774
case EDataSourceKind.ORACLE:
@@ -90,6 +97,11 @@ def generic_settings(self) -> GenericSettings:
9097
GenericSettings.ClickHouseCluster(database=self.database.name, protocol=EProtocol.NATIVE)
9198
],
9299
)
100+
case EDataSourceKind.MS_SQL_SERVER:
101+
return GenericSettings(
102+
date_time_format=EDateTimeFormat.YQL_FORMAT,
103+
ms_sql_server_clusters=[GenericSettings.MsSQLServerCluster(database=self.database.name)],
104+
)
93105
case EDataSourceKind.MYSQL:
94106
return GenericSettings(
95107
date_time_format=EDateTimeFormat.YQL_FORMAT,

ydb/library/yql/providers/generic/connector/tests/common_test_cases/select_missing_database.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ def generic_settings(self) -> GenericSettings:
2323
if self.service_name is not None:
2424
cluster.service_name = self.service_name
2525

26+
if self.data_source_kind == EDataSourceKind.MS_SQL_SERVER:
27+
for cluster in gs.ms_sql_server_clusters:
28+
cluster.database = "missing_database"
29+
2630
return gs
2731

2832

ydb/library/yql/providers/generic/connector/tests/common_test_cases/select_positive_common.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ def _column_selection(self) -> Sequence[TestCase]:
9898
EDataSourceKind.POSTGRESQL,
9999
EDataSourceKind.YDB,
100100
EDataSourceKind.MYSQL,
101+
EDataSourceKind.MS_SQL_SERVER,
101102
),
102103
),
103104
# SELECT COL1 FROM table
@@ -112,6 +113,7 @@ def _column_selection(self) -> Sequence[TestCase]:
112113
# NOTE: YQ-2264: doesn't work for PostgreSQL because of implicit cast to lowercase (COL1 -> col1)
113114
EDataSourceKind.YDB,
114115
EDataSourceKind.MYSQL,
116+
EDataSourceKind.MS_SQL_SERVER,
115117
),
116118
),
117119
# SELECT col1 FROM table
@@ -135,6 +137,7 @@ def _column_selection(self) -> Sequence[TestCase]:
135137
EDataSourceKind.POSTGRESQL,
136138
EDataSourceKind.YDB,
137139
EDataSourceKind.MYSQL,
140+
EDataSourceKind.MS_SQL_SERVER,
138141
),
139142
),
140143
# SELECT col2, COL1 FROM table
@@ -149,6 +152,7 @@ def _column_selection(self) -> Sequence[TestCase]:
149152
# NOTE: YQ-2264: doesn't work for PostgreSQL because of implicit cast to lowercase (COL1 -> col1)
150153
EDataSourceKind.YDB,
151154
EDataSourceKind.MYSQL,
155+
EDataSourceKind.MS_SQL_SERVER,
152156
),
153157
),
154158
# SELECT col2, col1 FROM table
@@ -173,6 +177,7 @@ def _column_selection(self) -> Sequence[TestCase]:
173177
# NOTE: YQ-2264: doesn't work for PostgreSQL because of implicit cast to lowercase (COL1 -> col1)
174178
EDataSourceKind.YDB,
175179
EDataSourceKind.MYSQL,
180+
EDataSourceKind.MS_SQL_SERVER,
176181
),
177182
),
178183
# Select the same column multiple times with different aliases
@@ -194,6 +199,7 @@ def _column_selection(self) -> Sequence[TestCase]:
194199
EDataSourceKind.POSTGRESQL,
195200
EDataSourceKind.YDB,
196201
EDataSourceKind.MYSQL,
202+
EDataSourceKind.MS_SQL_SERVER,
197203
),
198204
),
199205
)
@@ -291,11 +297,16 @@ def make_test_cases(self, data_source_kind: EDataSourceKind) -> Sequence[TestCas
291297
EDataSourceKind.POSTGRESQL: [EProtocol.NATIVE],
292298
EDataSourceKind.YDB: [EProtocol.NATIVE],
293299
EDataSourceKind.MYSQL: [EProtocol.NATIVE],
300+
EDataSourceKind.MS_SQL_SERVER: [EProtocol.NATIVE],
294301
}
295302

296303
base_test_cases = None
297304

298-
if data_source_kind in [EDataSourceKind.YDB, EDataSourceKind.MYSQL]:
305+
if data_source_kind in [
306+
EDataSourceKind.YDB,
307+
EDataSourceKind.MYSQL,
308+
EDataSourceKind.MS_SQL_SERVER,
309+
]:
299310
base_test_cases = self._column_selection()
300311
elif data_source_kind in [EDataSourceKind.CLICKHOUSE, EDataSourceKind.POSTGRESQL]:
301312
base_test_cases = list(

ydb/library/yql/providers/generic/connector/tests/datasource/clickhouse/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ services:
1212
- 8123
1313
fq-connector-go:
1414
container_name: fq-tests-ch-fq-connector-go
15-
image: ghcr.io/ydb-platform/fq-connector-go:v0.5.2@sha256:c007dc10b89aa0342bea93d843cca7097e66b2e45310010d9321259aeee453cc
15+
image: ghcr.io/ydb-platform/fq-connector-go:v0.5.3@sha256:7b8ccac5aaa14814333ddbb0f91e60039e158018972759506b1f4ce7899b83a9
1616
ports:
1717
- 2130
1818
volumes:
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from typing import Sequence, Mapping
2+
3+
from ydb.library.yql.providers.generic.connector.api.common.data_source_pb2 import EDataSourceKind
4+
import ydb.library.yql.providers.generic.connector.tests.common_test_cases.select_missing_database as select_missing_database
5+
import ydb.library.yql.providers.generic.connector.tests.common_test_cases.select_missing_table as select_missing_table
6+
import ydb.library.yql.providers.generic.connector.tests.common_test_cases.select_positive_common as select_positive_common
7+
import select_datetime
8+
import select_positive
9+
10+
# import select_positive_with_schema
11+
12+
from ydb.library.yql.providers.generic.connector.tests.utils.settings import Settings
13+
14+
15+
class Collection(object):
16+
_test_cases: Mapping[str, Sequence]
17+
18+
def __init__(self, ss: Settings):
19+
self._test_cases = {
20+
'select_missing_database': select_missing_database.Factory(ss).make_test_cases(
21+
EDataSourceKind.MS_SQL_SERVER
22+
),
23+
'select_missing_table': select_missing_table.Factory(ss).make_test_cases(EDataSourceKind.MS_SQL_SERVER),
24+
'select_positive': select_positive.Factory().make_test_cases()
25+
+ select_positive_common.Factory(ss).make_test_cases(EDataSourceKind.MS_SQL_SERVER),
26+
'select_datetime': select_datetime.Factory().make_test_cases(),
27+
}
28+
29+
def get(self, key: str) -> Sequence:
30+
if key not in self._test_cases:
31+
raise ValueError(f'no such test: {key}')
32+
33+
return self._test_cases[key]
34+
35+
def ids(self, key: str) -> Sequence[str]:
36+
if key not in self._test_cases:
37+
raise ValueError(f'no such test: {key}')
38+
39+
return [tc.name for tc in self._test_cases[key]]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from typing import Final
2+
import pathlib
3+
4+
import pytest
5+
6+
7+
from ydb.library.yql.providers.generic.connector.api.common.data_source_pb2 import EDataSourceKind
8+
from ydb.library.yql.providers.generic.connector.tests.utils.settings import Settings
9+
10+
11+
docker_compose_dir: Final = pathlib.Path("ydb/library/yql/providers/generic/connector/tests/datasource/ms_sql_server")
12+
13+
14+
@pytest.fixture
15+
def settings() -> Settings:
16+
return Settings.from_env(docker_compose_dir=docker_compose_dir, data_source_kinds=[EDataSourceKind.MS_SQL_SERVER])
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[mysqld]
2+
character-set-server = utf8
3+
collation-server = utf8_unicode_ci
4+
skip-character-set-client-handshake
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
services:
2+
fq-connector-go:
3+
container_name: fq-tests-mssql-fq-connector-go
4+
image: ghcr.io/ydb-platform/fq-connector-go:v0.5.3@sha256:7b8ccac5aaa14814333ddbb0f91e60039e158018972759506b1f4ce7899b83a9
5+
ports:
6+
- 2130
7+
volumes:
8+
- ../../fq-connector-go/:/opt/ydb/cfg/
9+
ms_sql_server:
10+
build:
11+
context: ./init
12+
dockerfile: Dockerfile
13+
container_name: fq-tests-mssql-ms_sql_server
14+
environment:
15+
ACCEPT_EULA: "Y"
16+
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: "false"
17+
LANG: ru_RU.UTF-8
18+
SA_PASSWORD: Qwerty12345!
19+
ports:
20+
- 1433:1433
21+
version: "3.4"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM mcr.microsoft.com/mssql/server:2022-latest
2+
3+
# Create a config directory
4+
USER root
5+
RUN mkdir -p /usr/config
6+
WORKDIR /usr/config
7+
8+
# Bundle config source
9+
COPY . /usr/config
10+
11+
# Grant permissions for to our scripts to be executable
12+
RUN chmod +x /usr/config/entrypoint.sh
13+
RUN chmod +x /usr/config/configure-db.sh
14+
15+
USER mssql
16+
17+
ENTRYPOINT ["./entrypoint.sh"]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
set -x
3+
4+
# Wait 60 seconds for SQL Server to start up by ensuring that
5+
# calling SQLCMD does not return an error code, which will ensure that sqlcmd is accessible
6+
# and that system and user databases return "0" which means all databases are in an "online" state
7+
# https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-databases-transact-sql?view=sql-server-2017
8+
9+
ERRCODE=1
10+
i=0
11+
12+
while [[ $i -lt 60 ]] && [[ $ERRCODE -ne 0 ]]; do
13+
i=$i+1
14+
DBSTATUS=$(/opt/mssql-tools18/bin/sqlcmd -C -U sa -P $SA_PASSWORD -Q "SET NOCOUNT ON; Select SUM(state) from sys.databases")
15+
ERRCODE=$?
16+
echo "$i $DBSTATUS $ERRCODE"
17+
sleep 1
18+
done
19+
20+
if [[ "$ERRCODE" -ne 0 ]]; then
21+
echo "SQL Server took more than 60 seconds to start up or one or more databases are not in an ONLINE state"
22+
exit 1
23+
fi
24+
25+
# Run the setup script to create the DB and the schema in the DB
26+
/opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P $SA_PASSWORD -d master -i setup.sql

0 commit comments

Comments
 (0)