moose-lib 0.6.11__py3-none-any.whl → 0.6.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of moose-lib might be problematic. Click here for more details.
- moose_lib/data_models.py +17 -0
- moose_lib/dmv2/materialized_view.py +33 -15
- {moose_lib-0.6.11.dist-info → moose_lib-0.6.13.dist-info}/METADATA +1 -1
- {moose_lib-0.6.11.dist-info → moose_lib-0.6.13.dist-info}/RECORD +6 -6
- {moose_lib-0.6.11.dist-info → moose_lib-0.6.13.dist-info}/WHEEL +0 -0
- {moose_lib-0.6.11.dist-info → moose_lib-0.6.13.dist-info}/top_level.txt +0 -0
moose_lib/data_models.py
CHANGED
|
@@ -26,6 +26,15 @@ class ClickhouseSize:
|
|
|
26
26
|
size: int
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
@dataclasses.dataclass
|
|
30
|
+
class ClickhouseDefault:
|
|
31
|
+
expression: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def clickhouse_default(expression: str) -> ClickhouseDefault:
|
|
35
|
+
return ClickhouseDefault(expression=expression)
|
|
36
|
+
|
|
37
|
+
|
|
29
38
|
def clickhouse_decimal(precision: int, scale: int) -> Type[Decimal]:
|
|
30
39
|
return Annotated[Decimal, Field(max_digits=precision, decimal_places=scale)]
|
|
31
40
|
|
|
@@ -135,6 +144,7 @@ class Column(BaseModel):
|
|
|
135
144
|
required: bool
|
|
136
145
|
unique: Literal[False]
|
|
137
146
|
primary_key: bool
|
|
147
|
+
default: str | None = None
|
|
138
148
|
annotations: list[Tuple[str, Any]] = []
|
|
139
149
|
|
|
140
150
|
|
|
@@ -255,6 +265,12 @@ def _to_columns(model: type[BaseModel]) -> list[Column]:
|
|
|
255
265
|
|
|
256
266
|
column_name = field_name if field_info.alias is None else field_info.alias
|
|
257
267
|
|
|
268
|
+
# Extract default expression from metadata, if provided
|
|
269
|
+
default_expr = next(
|
|
270
|
+
(md.expression for md in mds if isinstance(md, ClickhouseDefault)),
|
|
271
|
+
None,
|
|
272
|
+
)
|
|
273
|
+
|
|
258
274
|
columns.append(
|
|
259
275
|
Column(
|
|
260
276
|
name=column_name,
|
|
@@ -262,6 +278,7 @@ def _to_columns(model: type[BaseModel]) -> list[Column]:
|
|
|
262
278
|
required=not optional,
|
|
263
279
|
unique=False,
|
|
264
280
|
primary_key=primary_key,
|
|
281
|
+
default=default_expr,
|
|
265
282
|
annotations=annotations,
|
|
266
283
|
)
|
|
267
284
|
)
|
|
@@ -5,29 +5,33 @@ This module provides classes for defining Materialized Views,
|
|
|
5
5
|
including their SQL statements, target tables, and dependencies.
|
|
6
6
|
"""
|
|
7
7
|
from typing import Any, Optional, Union, Generic, TypeVar
|
|
8
|
-
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, model_validator
|
|
9
9
|
|
|
10
10
|
from moose_lib import ClickHouseEngines
|
|
11
11
|
from .types import BaseTypedResource, T
|
|
12
12
|
from .olap_table import OlapTable, OlapConfig
|
|
13
13
|
from .sql_resource import SqlResource
|
|
14
14
|
|
|
15
|
+
|
|
15
16
|
class MaterializedViewOptions(BaseModel):
|
|
16
17
|
"""Configuration options for creating a Materialized View.
|
|
17
18
|
|
|
18
19
|
Attributes:
|
|
19
20
|
select_statement: The SQL SELECT statement defining the view's data.
|
|
20
21
|
select_tables: List of source tables/views the select statement reads from.
|
|
21
|
-
table_name:
|
|
22
|
+
table_name: (Deprecated in favor of target_table) Optional name of the underlying
|
|
23
|
+
target table storing the materialized data.
|
|
22
24
|
materialized_view_name: The name of the MATERIALIZED VIEW object itself.
|
|
23
|
-
engine: Optional ClickHouse engine for the target table
|
|
25
|
+
engine: Optional ClickHouse engine for the target table (used when creating
|
|
26
|
+
a target table via table_name or inline config).
|
|
24
27
|
order_by_fields: Optional ordering key for the target table (required for
|
|
25
28
|
engines like ReplacingMergeTree).
|
|
26
29
|
model_config: ConfigDict for Pydantic validation
|
|
27
30
|
"""
|
|
28
31
|
select_statement: str
|
|
29
32
|
select_tables: list[Union[OlapTable, SqlResource]]
|
|
30
|
-
|
|
33
|
+
# Backward-compatibility: allow specifying just the table_name and engine
|
|
34
|
+
table_name: Optional[str] = None
|
|
31
35
|
materialized_view_name: str
|
|
32
36
|
engine: Optional[ClickHouseEngines] = None
|
|
33
37
|
order_by_fields: Optional[list[str]] = None
|
|
@@ -35,6 +39,7 @@ class MaterializedViewOptions(BaseModel):
|
|
|
35
39
|
# Ensure arbitrary types are allowed for Pydantic validation
|
|
36
40
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
37
41
|
|
|
42
|
+
|
|
38
43
|
class MaterializedView(SqlResource, BaseTypedResource, Generic[T]):
|
|
39
44
|
"""Represents a ClickHouse Materialized View.
|
|
40
45
|
|
|
@@ -62,25 +67,38 @@ class MaterializedView(SqlResource, BaseTypedResource, Generic[T]):
|
|
|
62
67
|
def __init__(
|
|
63
68
|
self,
|
|
64
69
|
options: MaterializedViewOptions,
|
|
70
|
+
target_table: Optional[OlapTable[T]] = None,
|
|
65
71
|
**kwargs
|
|
66
72
|
):
|
|
67
73
|
self._set_type(options.materialized_view_name, self._get_type(kwargs))
|
|
68
74
|
|
|
75
|
+
# Resolve target table from options
|
|
76
|
+
if target_table:
|
|
77
|
+
self.target_table = target_table
|
|
78
|
+
if self._t != target_table._t:
|
|
79
|
+
raise ValueError("Target table must have the same type as the materialized view")
|
|
80
|
+
else:
|
|
81
|
+
# Backward-compatibility path using table_name/engine/order_by_fields
|
|
82
|
+
if not options.table_name:
|
|
83
|
+
raise ValueError("Name of target table is not specified. Provide 'target_table' or 'table_name'.")
|
|
84
|
+
target_table = OlapTable(
|
|
85
|
+
name=options.table_name,
|
|
86
|
+
config=OlapConfig(
|
|
87
|
+
order_by_fields=options.order_by_fields or [],
|
|
88
|
+
engine=options.engine
|
|
89
|
+
),
|
|
90
|
+
t=self._t
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if target_table.name == options.materialized_view_name:
|
|
94
|
+
raise ValueError("Target table name cannot be the same as the materialized view name")
|
|
95
|
+
|
|
69
96
|
setup = [
|
|
70
|
-
f"CREATE MATERIALIZED VIEW IF NOT EXISTS {options.materialized_view_name} TO {
|
|
71
|
-
f"INSERT INTO {
|
|
97
|
+
f"CREATE MATERIALIZED VIEW IF NOT EXISTS {options.materialized_view_name} TO {target_table.name} AS {options.select_statement}",
|
|
98
|
+
f"INSERT INTO {target_table.name} {options.select_statement}"
|
|
72
99
|
]
|
|
73
100
|
teardown = [f"DROP VIEW IF EXISTS {options.materialized_view_name}"]
|
|
74
101
|
|
|
75
|
-
target_table = OlapTable(
|
|
76
|
-
name=options.table_name,
|
|
77
|
-
config=OlapConfig(
|
|
78
|
-
order_by_fields=options.order_by_fields or [],
|
|
79
|
-
engine=options.engine
|
|
80
|
-
),
|
|
81
|
-
t=self._t
|
|
82
|
-
)
|
|
83
|
-
|
|
84
102
|
super().__init__(
|
|
85
103
|
options.materialized_view_name,
|
|
86
104
|
setup,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
moose_lib/__init__.py,sha256=_XXfHrzRl-M5M1e3CwBQGGblVQYKnU5QJkipghe4bXU,184
|
|
2
2
|
moose_lib/blocks.py,sha256=_wdvC2NC_Y3MMEnB71WTgWbeQ--zPNHk19xjToJW0C0,3185
|
|
3
3
|
moose_lib/commons.py,sha256=FUpRv8D3-LeGcjhcqtDyiimz5izwpCq53h50ydxC_uA,3711
|
|
4
|
-
moose_lib/data_models.py,sha256=
|
|
4
|
+
moose_lib/data_models.py,sha256=PgoFXTzf4C66FlKUowMT4VOrwSRR9_bk36P43ub4LzU,10274
|
|
5
5
|
moose_lib/dmv2-serializer.py,sha256=CL_Pvvg8tJOT8Qk6hywDNzY8MYGhMVdTOw8arZi3jng,49
|
|
6
6
|
moose_lib/internal.py,sha256=UYF42oFujLH1g9GDo_HdP-AYipKTf_lReyVi6qs945A,14397
|
|
7
7
|
moose_lib/main.py,sha256=WAxrM39rp5leAtHxZQZlC8-a8pA8Ksy1TjVQnq12YeA,17354
|
|
@@ -18,7 +18,7 @@ moose_lib/dmv2/consumption.py,sha256=KJV9MKgrnVLIRhlFVZMDhTsXvOaZoMiHk4hnRePdPWA
|
|
|
18
18
|
moose_lib/dmv2/ingest_api.py,sha256=Snek9NGwaJl_BuImSWGtQq91m9D3AJ4qBoGiKZ-9yTQ,2323
|
|
19
19
|
moose_lib/dmv2/ingest_pipeline.py,sha256=q7k8B50Dp_jpJA86Rr9dOGl7-EaGF0LR81TuFXlktxc,7024
|
|
20
20
|
moose_lib/dmv2/life_cycle.py,sha256=wl0k6yzwU1MJ_fO_UkN29buoY5G6ChYZvfwigP9fVfM,1254
|
|
21
|
-
moose_lib/dmv2/materialized_view.py,sha256=
|
|
21
|
+
moose_lib/dmv2/materialized_view.py,sha256=xlYNXiOHhjGq5pE8z0dMrVs-Db01DnOlY14CmLwMDGE,4851
|
|
22
22
|
moose_lib/dmv2/olap_table.py,sha256=4DfF_KMCspCvQLf7DwmkmfyFswCv8J-3NhDcnNTWvKg,31304
|
|
23
23
|
moose_lib/dmv2/registry.py,sha256=janjYszIXDnMfuwkNhoiBmMLar3umQ3Npw9Ms-u6p-8,2373
|
|
24
24
|
moose_lib/dmv2/sql_resource.py,sha256=kUZoGqxhZMHMthtBZGYJBxTFjXkspXiWLXhJRYXgGUM,1864
|
|
@@ -32,7 +32,7 @@ tests/__init__.py,sha256=0Gh4yzPkkC3TzBGKhenpMIxJcRhyrrCfxLSfpTZnPMQ,53
|
|
|
32
32
|
tests/conftest.py,sha256=ZVJNbnr4DwbcqkTmePW6U01zAzE6QD0kNAEZjPG1f4s,169
|
|
33
33
|
tests/test_moose.py,sha256=mBsx_OYWmL8ppDzL_7Bd7xR6qf_i3-pCIO3wm2iQNaA,2136
|
|
34
34
|
tests/test_redis_client.py,sha256=d9_MLYsJ4ecVil_jPB2gW3Q5aWnavxmmjZg2uYI3LVo,3256
|
|
35
|
-
moose_lib-0.6.
|
|
36
|
-
moose_lib-0.6.
|
|
37
|
-
moose_lib-0.6.
|
|
38
|
-
moose_lib-0.6.
|
|
35
|
+
moose_lib-0.6.13.dist-info/METADATA,sha256=eInIciZTxMqwB0xhk48O4L8eSXn-uNyiXmJV9kzrN6U,730
|
|
36
|
+
moose_lib-0.6.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
37
|
+
moose_lib-0.6.13.dist-info/top_level.txt,sha256=XEns2-4aCmGp2XjJAeEH9TAUcGONLnSLy6ycT9FSJh8,16
|
|
38
|
+
moose_lib-0.6.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|