Skip to content

Commit a3144d1

Browse files
authored
Merge pull request #22 Add table settings support from ilchuk96/table_settings
2 parents d413ef3 + 63c604e commit a3144d1

File tree

5 files changed

+224
-5
lines changed

5 files changed

+224
-5
lines changed

setup.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
license="Apache 2.0",
2222
package_dir={"": "."},
2323
long_description=long_description,
24-
long_description_content_type='text/markdown',
24+
long_description_content_type="text/markdown",
2525
packages=setuptools.find_packages("."),
2626
classifiers=[
2727
"Programming Language :: Python",
@@ -32,11 +32,14 @@
3232
install_requires=requirements, # requirements.txt
3333
options={"bdist_wheel": {"universal": True}},
3434
extras_require={
35-
"yc": ["yandexcloud", ],
35+
"yc": [
36+
"yandexcloud",
37+
],
3638
},
3739
entry_points={
3840
"sqlalchemy.dialects": [
3941
"yql.ydb=ydb_sqlalchemy.sqlalchemy:YqlDialect",
42+
"ydb=ydb_sqlalchemy.sqlalchemy:YqlDialect",
4043
]
4144
},
4245
)

test/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from sqlalchemy.dialects import registry
33

44
registry.register("yql.ydb", "ydb_sqlalchemy.sqlalchemy", "YqlDialect")
5+
registry.register("ydb", "ydb_sqlalchemy.sqlalchemy", "YqlDialect")
56
pytest.register_assert_rewrite("sqlalchemy.testing.assertions")
67

78
from sqlalchemy.testing.plugin.pytestplugin import * # noqa: E402, F401, F403

test/test_core.py

Lines changed: 169 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
from decimal import Decimal
2+
from datetime import date, datetime
23

4+
import pytest
35
import sqlalchemy as sa
46
from sqlalchemy import Table, Column, Integer, Unicode
5-
67
from sqlalchemy.testing.fixtures import TestBase, TablesTest
78

8-
from datetime import date, datetime
9+
import ydb
10+
from ydb._grpc.v4.protos import ydb_common_pb2
11+
12+
from ydb_sqlalchemy.sqlalchemy import types
913

1014

1115
def clear_sql(stm):
@@ -200,3 +204,166 @@ def test_select_types(self, connection):
200204

201205
row = connection.execute(sa.select(tb)).fetchone()
202206
assert row == (1, "Hello World!", 3.5, True, now, today)
207+
208+
209+
class TestWithClause(TablesTest):
210+
run_create_tables = "each"
211+
212+
@staticmethod
213+
def _create_table_and_get_desc(connection, metadata, **kwargs):
214+
table = Table(
215+
"clause_with_test",
216+
metadata,
217+
Column("id", types.UInt32, primary_key=True),
218+
**kwargs,
219+
)
220+
table.create(connection)
221+
222+
session: ydb.Session = connection.connection.driver_connection.pool.acquire()
223+
table_description = session.describe_table("/local/" + table.name)
224+
session.delete()
225+
return table_description
226+
227+
@pytest.mark.parametrize(
228+
"auto_partitioning_by_size,res",
229+
[
230+
(None, ydb_common_pb2.FeatureFlag.Status.ENABLED),
231+
(True, ydb_common_pb2.FeatureFlag.Status.ENABLED),
232+
(False, ydb_common_pb2.FeatureFlag.Status.DISABLED),
233+
],
234+
)
235+
def test_auto_partitioning_by_size(self, connection, auto_partitioning_by_size, res, metadata):
236+
desc = self._create_table_and_get_desc(
237+
connection, metadata, ydb_auto_partitioning_by_size=auto_partitioning_by_size
238+
)
239+
assert desc.partitioning_settings.partitioning_by_size == res
240+
241+
@pytest.mark.parametrize(
242+
"auto_partitioning_by_load,res",
243+
[
244+
(None, ydb_common_pb2.FeatureFlag.Status.DISABLED),
245+
(True, ydb_common_pb2.FeatureFlag.Status.ENABLED),
246+
(False, ydb_common_pb2.FeatureFlag.Status.DISABLED),
247+
],
248+
)
249+
def test_auto_partitioning_by_load(self, connection, auto_partitioning_by_load, res, metadata):
250+
desc = self._create_table_and_get_desc(
251+
connection,
252+
metadata,
253+
ydb_auto_partitioning_by_load=auto_partitioning_by_load,
254+
)
255+
assert desc.partitioning_settings.partitioning_by_load == res
256+
257+
@pytest.mark.parametrize(
258+
"auto_partitioning_partition_size_mb,res",
259+
[
260+
(None, 2048),
261+
(2000, 2000),
262+
],
263+
)
264+
def test_auto_partitioning_partition_size_mb(self, connection, auto_partitioning_partition_size_mb, res, metadata):
265+
desc = self._create_table_and_get_desc(
266+
connection,
267+
metadata,
268+
ydb_auto_partitioning_partition_size_mb=auto_partitioning_partition_size_mb,
269+
)
270+
assert desc.partitioning_settings.partition_size_mb == res
271+
272+
@pytest.mark.parametrize(
273+
"auto_partitioning_min_partitions_count,res",
274+
[
275+
(None, 1),
276+
(10, 10),
277+
],
278+
)
279+
def test_auto_partitioning_min_partitions_count(
280+
self,
281+
connection,
282+
auto_partitioning_min_partitions_count,
283+
res,
284+
metadata,
285+
):
286+
desc = self._create_table_and_get_desc(
287+
connection,
288+
metadata,
289+
ydb_auto_partitioning_min_partitions_count=auto_partitioning_min_partitions_count,
290+
)
291+
assert desc.partitioning_settings.min_partitions_count == res
292+
293+
@pytest.mark.parametrize(
294+
"auto_partitioning_max_partitions_count,res",
295+
[
296+
(None, 0),
297+
(10, 10),
298+
],
299+
)
300+
def test_auto_partitioning_max_partitions_count(
301+
self,
302+
connection,
303+
auto_partitioning_max_partitions_count,
304+
res,
305+
metadata,
306+
):
307+
desc = self._create_table_and_get_desc(
308+
connection,
309+
metadata,
310+
ydb_auto_partitioning_max_partitions_count=auto_partitioning_max_partitions_count,
311+
)
312+
assert desc.partitioning_settings.max_partitions_count == res
313+
314+
@pytest.mark.parametrize(
315+
"uniform_partitions,res",
316+
[
317+
(None, 1),
318+
(10, 10),
319+
],
320+
)
321+
def test_uniform_partitions(
322+
self,
323+
connection,
324+
uniform_partitions,
325+
res,
326+
metadata,
327+
):
328+
desc = self._create_table_and_get_desc(
329+
connection,
330+
metadata,
331+
ydb_uniform_partitions=uniform_partitions,
332+
)
333+
# it not only do the initiation partition but also set up the minimum partition count
334+
assert desc.partitioning_settings.min_partitions_count == res
335+
336+
@pytest.mark.parametrize(
337+
"partition_at_keys,res",
338+
[
339+
(None, 1),
340+
((100, 1000), 3),
341+
],
342+
)
343+
def test_partition_at_keys(
344+
self,
345+
connection,
346+
partition_at_keys,
347+
res,
348+
metadata,
349+
):
350+
desc = self._create_table_and_get_desc(
351+
connection,
352+
metadata,
353+
ydb_partition_at_keys=partition_at_keys,
354+
)
355+
assert desc.partitioning_settings.min_partitions_count == res
356+
357+
def test_several_keys(self, connection, metadata):
358+
desc = self._create_table_and_get_desc(
359+
connection,
360+
metadata,
361+
ydb_auto_partitioning_by_size=True,
362+
ydb_auto_partitioning_by_load=True,
363+
ydb_auto_partitioning_min_partitions_count=3,
364+
ydb_auto_partitioning_max_partitions_count=5,
365+
)
366+
assert desc.partitioning_settings.partitioning_by_size == 1
367+
assert desc.partitioning_settings.partitioning_by_load == 1
368+
assert desc.partitioning_settings.min_partitions_count == 3
369+
assert desc.partitioning_settings.max_partitions_count == 5

wait_container_ready.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import ydb
44
import time
55

6+
67
def wait_container_ready(driver):
78
driver.wait(timeout=30)
89

ydb_sqlalchemy/sqlalchemy/__init__.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,39 @@ def get_bind_types(
343343

344344

345345
class YqlDDLCompiler(DDLCompiler):
346-
pass
346+
def post_create_table(self, table: sa.Table) -> str:
347+
ydb_opts = table.dialect_options["ydb"]
348+
with_clause_list = self._render_table_partitioning_settings(ydb_opts)
349+
if with_clause_list:
350+
with_clause_text = ",\n".join(with_clause_list)
351+
return f"\nWITH (\n\t{with_clause_text}\n)"
352+
return ""
353+
354+
def _render_table_partitioning_settings(self, ydb_opts: Dict[str, Any]) -> List[str]:
355+
table_partitioning_settings = []
356+
if ydb_opts["auto_partitioning_by_size"] is not None:
357+
auto_partitioning_by_size = "ENABLED" if ydb_opts["auto_partitioning_by_size"] else "DISABLED"
358+
table_partitioning_settings.append(f"AUTO_PARTITIONING_BY_SIZE = {auto_partitioning_by_size}")
359+
if ydb_opts["auto_partitioning_by_load"] is not None:
360+
auto_partitioning_by_load = "ENABLED" if ydb_opts["auto_partitioning_by_load"] else "DISABLED"
361+
table_partitioning_settings.append(f"AUTO_PARTITIONING_BY_LOAD = {auto_partitioning_by_load}")
362+
if ydb_opts["auto_partitioning_partition_size_mb"] is not None:
363+
table_partitioning_settings.append(
364+
f"AUTO_PARTITIONING_PARTITION_SIZE_MB = {ydb_opts['auto_partitioning_partition_size_mb']}"
365+
)
366+
if ydb_opts["auto_partitioning_min_partitions_count"] is not None:
367+
table_partitioning_settings.append(
368+
f"AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = {ydb_opts['auto_partitioning_min_partitions_count']}"
369+
)
370+
if ydb_opts["auto_partitioning_max_partitions_count"] is not None:
371+
table_partitioning_settings.append(
372+
f"AUTO_PARTITIONING_MAX_PARTITIONS_COUNT = {ydb_opts['auto_partitioning_max_partitions_count']}"
373+
)
374+
if ydb_opts["uniform_partitions"] is not None:
375+
table_partitioning_settings.append(f"UNIFORM_PARTITIONS = {ydb_opts['uniform_partitions']}")
376+
if ydb_opts["partition_at_keys"] is not None:
377+
table_partitioning_settings.append(f"PARTITION_AT_KEYS = {ydb_opts['partition_at_keys']}")
378+
return table_partitioning_settings
347379

348380

349381
def upsert(table):
@@ -425,6 +457,21 @@ class YqlDialect(StrCompileDialect):
425457
ddl_compiler = YqlDDLCompiler
426458
type_compiler = YqlTypeCompiler
427459

460+
construct_arguments = [
461+
(
462+
sa.schema.Table,
463+
{
464+
"auto_partitioning_by_size": None,
465+
"auto_partitioning_by_load": None,
466+
"auto_partitioning_partition_size_mb": None,
467+
"auto_partitioning_min_partitions_count": None,
468+
"auto_partitioning_max_partitions_count": None,
469+
"uniform_partitions": None,
470+
"partition_at_keys": None,
471+
},
472+
),
473+
]
474+
428475
@classmethod
429476
def import_dbapi(cls: Any):
430477
return dbapi

0 commit comments

Comments
 (0)