moose-lib 0.6.119__tar.gz → 0.6.121__tar.gz
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-0.6.119 → moose_lib-0.6.121}/PKG-INFO +1 -1
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/olap_table.py +77 -60
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/internal.py +16 -8
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib.egg-info/PKG-INFO +1 -1
- {moose_lib-0.6.119 → moose_lib-0.6.121}/README.md +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/__init__.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/blocks.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/clients/__init__.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/clients/redis_client.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/commons.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/config/__init__.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/config/config_file.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/config/runtime.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/data_models.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/__init__.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/_registry.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/consumption.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/ingest_api.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/ingest_pipeline.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/life_cycle.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/materialized_view.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/registry.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/sql_resource.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/stream.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/types.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/view.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2/workflow.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/dmv2_serializer.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/main.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/query_builder.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/query_param.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/streaming/__init__.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/streaming/streaming_function_runner.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/utilities/__init__.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib/utilities/sql.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib.egg-info/SOURCES.txt +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib.egg-info/dependency_links.txt +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib.egg-info/requires.txt +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/moose_lib.egg-info/top_level.txt +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/setup.cfg +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/setup.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/tests/__init__.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/tests/conftest.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/tests/test_moose.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/tests/test_olap_table_versioning.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/tests/test_query_builder.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/tests/test_redis_client.py +0 -0
- {moose_lib-0.6.119 → moose_lib-0.6.121}/tests/test_s3queue_config.py +0 -0
|
@@ -21,6 +21,7 @@ from ._registry import _tables
|
|
|
21
21
|
from ..data_models import Column, is_array_nested_type, is_nested_type, _to_columns
|
|
22
22
|
from .life_cycle import LifeCycle
|
|
23
23
|
|
|
24
|
+
|
|
24
25
|
@dataclass
|
|
25
26
|
class InsertOptions:
|
|
26
27
|
"""Options for insert operations.
|
|
@@ -38,6 +39,7 @@ class InsertOptions:
|
|
|
38
39
|
validate: bool = True
|
|
39
40
|
skip_validation_on_retry: bool = False
|
|
40
41
|
|
|
42
|
+
|
|
41
43
|
@dataclass
|
|
42
44
|
class FailedRecord(Generic[T]):
|
|
43
45
|
"""Represents a failed record during insertion with error details.
|
|
@@ -51,6 +53,7 @@ class FailedRecord(Generic[T]):
|
|
|
51
53
|
error: str
|
|
52
54
|
index: Optional[int] = None
|
|
53
55
|
|
|
56
|
+
|
|
54
57
|
@dataclass
|
|
55
58
|
class ValidationError:
|
|
56
59
|
"""Validation error for a record with detailed error information.
|
|
@@ -66,6 +69,7 @@ class ValidationError:
|
|
|
66
69
|
index: Optional[int] = None
|
|
67
70
|
path: Optional[str] = None
|
|
68
71
|
|
|
72
|
+
|
|
69
73
|
@dataclass
|
|
70
74
|
class ValidationResult(Generic[T]):
|
|
71
75
|
"""Result of data validation with success/failure breakdown.
|
|
@@ -79,6 +83,7 @@ class ValidationResult(Generic[T]):
|
|
|
79
83
|
invalid: List[ValidationError]
|
|
80
84
|
total: int
|
|
81
85
|
|
|
86
|
+
|
|
82
87
|
@dataclass
|
|
83
88
|
class InsertResult(Generic[T]):
|
|
84
89
|
"""Result of an insert operation with detailed success/failure information.
|
|
@@ -94,14 +99,18 @@ class InsertResult(Generic[T]):
|
|
|
94
99
|
total: int
|
|
95
100
|
failed_records: Optional[List[FailedRecord[T]]] = None
|
|
96
101
|
|
|
102
|
+
|
|
97
103
|
class OlapConfig(BaseModel):
|
|
98
104
|
model_config = {"extra": "forbid"} # Reject unknown fields for a clean API
|
|
99
|
-
|
|
105
|
+
|
|
100
106
|
"""Configuration for OLAP tables (e.g., ClickHouse tables).
|
|
101
107
|
|
|
102
108
|
Attributes:
|
|
103
109
|
order_by_fields: List of column names to use for the ORDER BY clause.
|
|
104
110
|
Crucial for `ReplacingMergeTree` and performance.
|
|
111
|
+
order_by_expression: An arbitrary ClickHouse expression for ORDER BY. Example:
|
|
112
|
+
`order_by_expression="(id, name)"` is equivalent to order_by_fields=["id", "name"], or
|
|
113
|
+
"tuple()" for no sorting.
|
|
105
114
|
partition_by: Optional PARTITION BY expression (single ClickHouse SQL expression).
|
|
106
115
|
engine: The ClickHouse table engine to use. Can be either a ClickHouseEngines enum value
|
|
107
116
|
(for backward compatibility) or an EngineConfig instance (recommended).
|
|
@@ -112,6 +121,7 @@ class OlapConfig(BaseModel):
|
|
|
112
121
|
These are alterable settings that can be changed without recreating the table.
|
|
113
122
|
"""
|
|
114
123
|
order_by_fields: list[str] = []
|
|
124
|
+
order_by_expression: Optional[str] = None
|
|
115
125
|
partition_by: Optional[str] = None
|
|
116
126
|
engine: Optional[Union[ClickHouseEngines, EngineConfig]] = None
|
|
117
127
|
version: Optional[str] = None
|
|
@@ -119,6 +129,13 @@ class OlapConfig(BaseModel):
|
|
|
119
129
|
life_cycle: Optional[LifeCycle] = None
|
|
120
130
|
settings: Optional[dict[str, str]] = None
|
|
121
131
|
|
|
132
|
+
def model_post_init(self, __context):
|
|
133
|
+
has_fields = bool(self.order_by_fields)
|
|
134
|
+
has_expr = isinstance(self.order_by_expression, str) and len(self.order_by_expression) > 0
|
|
135
|
+
if has_fields and has_expr:
|
|
136
|
+
raise ValueError("Provide either order_by_fields or order_by_expression, not both.")
|
|
137
|
+
|
|
138
|
+
|
|
122
139
|
class OlapTable(TypedMooseResource, Generic[T]):
|
|
123
140
|
"""Represents an OLAP table (e.g., a ClickHouse table) typed with a Pydantic model.
|
|
124
141
|
|
|
@@ -155,11 +172,11 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
155
172
|
f"OlapTable with name {name} and version {config.version or 'unversioned'} already exists"
|
|
156
173
|
)
|
|
157
174
|
_tables[registry_key] = self
|
|
158
|
-
|
|
175
|
+
|
|
159
176
|
# Check if using legacy enum-based engine configuration
|
|
160
177
|
if config.engine and isinstance(config.engine, ClickHouseEngines):
|
|
161
178
|
logger = Logger(action="OlapTable")
|
|
162
|
-
|
|
179
|
+
|
|
163
180
|
# Special case for S3Queue - more detailed migration message
|
|
164
181
|
if config.engine == ClickHouseEngines.S3Queue:
|
|
165
182
|
logger.highlight(
|
|
@@ -179,7 +196,7 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
179
196
|
f" New: from moose_lib.blocks import {engine_name}Engine; engine={engine_name}Engine()\n"
|
|
180
197
|
"The new API provides better type safety and configuration options."
|
|
181
198
|
)
|
|
182
|
-
|
|
199
|
+
|
|
183
200
|
# Also emit a Python warning for development environments
|
|
184
201
|
warnings.warn(
|
|
185
202
|
f"Table '{name}' uses deprecated ClickHouseEngines enum. "
|
|
@@ -343,9 +360,9 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
343
360
|
)
|
|
344
361
|
|
|
345
362
|
def _validate_insert_parameters(
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
363
|
+
self,
|
|
364
|
+
data: Union[List[T], Iterator[T]],
|
|
365
|
+
options: Optional[InsertOptions]
|
|
349
366
|
) -> Tuple[bool, str, bool]:
|
|
350
367
|
"""Validate input parameters and strategy compatibility.
|
|
351
368
|
|
|
@@ -372,11 +389,11 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
372
389
|
return is_stream, strategy, should_validate
|
|
373
390
|
|
|
374
391
|
def _perform_pre_insertion_validation(
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
392
|
+
self,
|
|
393
|
+
data: List[T],
|
|
394
|
+
should_validate: bool,
|
|
395
|
+
strategy: str,
|
|
396
|
+
options: Optional[InsertOptions] = None
|
|
380
397
|
) -> Tuple[List[T], List[ValidationError]]:
|
|
381
398
|
"""Perform pre-insertion validation for array data.
|
|
382
399
|
|
|
@@ -421,11 +438,11 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
421
438
|
return data, []
|
|
422
439
|
|
|
423
440
|
def _handle_validation_errors(
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
441
|
+
self,
|
|
442
|
+
validation_errors: List[ValidationError],
|
|
443
|
+
strategy: str,
|
|
444
|
+
data: List[T],
|
|
445
|
+
options: Optional[InsertOptions]
|
|
429
446
|
) -> None:
|
|
430
447
|
"""Handle validation errors based on the specified strategy.
|
|
431
448
|
|
|
@@ -448,10 +465,10 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
448
465
|
)
|
|
449
466
|
|
|
450
467
|
def _check_validation_thresholds(
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
468
|
+
self,
|
|
469
|
+
validation_errors: List[ValidationError],
|
|
470
|
+
total_records: int,
|
|
471
|
+
options: Optional[InsertOptions]
|
|
455
472
|
) -> None:
|
|
456
473
|
"""Check if validation errors exceed configured thresholds.
|
|
457
474
|
|
|
@@ -464,14 +481,14 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
464
481
|
validation_failed_ratio = validation_failed_count / total_records
|
|
465
482
|
|
|
466
483
|
if (options and options.allow_errors is not None and
|
|
467
|
-
|
|
484
|
+
validation_failed_count > options.allow_errors):
|
|
468
485
|
raise ValueError(
|
|
469
486
|
f"Too many validation failures: {validation_failed_count} > {options.allow_errors}. "
|
|
470
487
|
f"Errors: {', '.join(e.error for e in validation_errors)}"
|
|
471
488
|
)
|
|
472
489
|
|
|
473
490
|
if (options and options.allow_errors_ratio is not None and
|
|
474
|
-
|
|
491
|
+
validation_failed_ratio > options.allow_errors_ratio):
|
|
475
492
|
raise ValueError(
|
|
476
493
|
f"Validation failure ratio too high: {validation_failed_ratio:.3f} > "
|
|
477
494
|
f"{options.allow_errors_ratio}. Errors: {', '.join(e.error for e in validation_errors)}"
|
|
@@ -492,13 +509,13 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
492
509
|
return {**settings, "wait_end_of_query": 1}
|
|
493
510
|
|
|
494
511
|
def _prepare_insert_options(
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
512
|
+
self,
|
|
513
|
+
table_name: str,
|
|
514
|
+
data: Union[List[T], Iterator[T]],
|
|
515
|
+
validated_data: List[T],
|
|
516
|
+
is_stream: bool,
|
|
517
|
+
strategy: str,
|
|
518
|
+
options: Optional[InsertOptions]
|
|
502
519
|
) -> tuple[str, bytes, dict]:
|
|
503
520
|
"""Prepare insert options for JSONEachRow raw SQL insert, returning settings dict."""
|
|
504
521
|
# Base settings for all inserts
|
|
@@ -511,7 +528,7 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
511
528
|
}
|
|
512
529
|
settings = self._with_wait_end_settings(base_settings)
|
|
513
530
|
if (strategy == "discard" and options and
|
|
514
|
-
|
|
531
|
+
(options.allow_errors is not None or options.allow_errors_ratio is not None)):
|
|
515
532
|
if options.allow_errors is not None:
|
|
516
533
|
settings["input_format_allow_errors_num"] = options.allow_errors
|
|
517
534
|
if options.allow_errors_ratio is not None:
|
|
@@ -536,13 +553,13 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
536
553
|
return quote_identifier(table_name), json_lines, settings
|
|
537
554
|
|
|
538
555
|
def _create_success_result(
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
556
|
+
self,
|
|
557
|
+
data: Union[List[T], Iterator[T]],
|
|
558
|
+
validated_data: List[T],
|
|
559
|
+
validation_errors: List[ValidationError],
|
|
560
|
+
is_stream: bool,
|
|
561
|
+
should_validate: bool,
|
|
562
|
+
strategy: str
|
|
546
563
|
) -> InsertResult[T]:
|
|
547
564
|
"""Create appropriate result based on input type.
|
|
548
565
|
|
|
@@ -585,10 +602,10 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
585
602
|
return result
|
|
586
603
|
|
|
587
604
|
def _retry_individual_records(
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
605
|
+
self,
|
|
606
|
+
client: Client,
|
|
607
|
+
records: List[T],
|
|
608
|
+
options: InsertOptions
|
|
592
609
|
) -> InsertResult[T]:
|
|
593
610
|
successful: List[T] = []
|
|
594
611
|
failed: List[FailedRecord[T]] = []
|
|
@@ -642,13 +659,13 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
642
659
|
)
|
|
643
660
|
|
|
644
661
|
def _insert_array_data(
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
662
|
+
self,
|
|
663
|
+
client: Client,
|
|
664
|
+
table_name: str,
|
|
665
|
+
data: List[T],
|
|
666
|
+
should_validate: bool,
|
|
667
|
+
strategy: str,
|
|
668
|
+
options: Optional[InsertOptions]
|
|
652
669
|
) -> InsertResult[T]:
|
|
653
670
|
"""Insert array data into the table with validation and error handling.
|
|
654
671
|
|
|
@@ -701,12 +718,12 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
701
718
|
)
|
|
702
719
|
|
|
703
720
|
def _insert_stream(
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
721
|
+
self,
|
|
722
|
+
client: Client,
|
|
723
|
+
table_name: str,
|
|
724
|
+
data: Iterator[T],
|
|
725
|
+
strategy: str,
|
|
726
|
+
options: Optional[InsertOptions]
|
|
710
727
|
) -> InsertResult[T]:
|
|
711
728
|
"""Insert data from an iterator into the table.
|
|
712
729
|
|
|
@@ -769,9 +786,9 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
769
786
|
raise ValueError(f"Too many errors during stream insert: {e}")
|
|
770
787
|
|
|
771
788
|
def insert(
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
789
|
+
self,
|
|
790
|
+
data: Union[List[T], Iterator[T]],
|
|
791
|
+
options: Optional[InsertOptions] = None
|
|
775
792
|
) -> InsertResult[T]:
|
|
776
793
|
"""Insert data into the table with validation and error handling.
|
|
777
794
|
|
|
@@ -872,7 +889,7 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
872
889
|
if is_array_nested_type(data_type):
|
|
873
890
|
# For Array(Nested(...)), wrap each item in its own array and recurse
|
|
874
891
|
if (isinstance(value, list) and
|
|
875
|
-
|
|
892
|
+
(len(value) == 0 or isinstance(value[0], dict))):
|
|
876
893
|
nested_columns = data_type.element_type.columns
|
|
877
894
|
result[col.name] = [
|
|
878
895
|
[self._map_to_clickhouse_record(item, nested_columns)]
|
|
@@ -884,4 +901,4 @@ class OlapTable(TypedMooseResource, Generic[T]):
|
|
|
884
901
|
result[col.name] = self._map_to_clickhouse_record(value, data_type.columns)
|
|
885
902
|
# All other types: leave as is
|
|
886
903
|
|
|
887
|
-
return result
|
|
904
|
+
return result
|
|
@@ -160,7 +160,7 @@ class TableConfig(BaseModel):
|
|
|
160
160
|
|
|
161
161
|
name: str
|
|
162
162
|
columns: List[Column]
|
|
163
|
-
order_by: List[str]
|
|
163
|
+
order_by: List[str] | str
|
|
164
164
|
partition_by: Optional[str]
|
|
165
165
|
engine_config: Optional[EngineConfigDict] = Field(None, discriminator='engine')
|
|
166
166
|
version: Optional[str] = None
|
|
@@ -367,7 +367,7 @@ def _convert_basic_engine_instance(engine: "EngineConfig") -> Optional[EngineCon
|
|
|
367
367
|
MergeTreeEngine, ReplacingMergeTreeEngine,
|
|
368
368
|
AggregatingMergeTreeEngine, SummingMergeTreeEngine
|
|
369
369
|
)
|
|
370
|
-
|
|
370
|
+
|
|
371
371
|
if isinstance(engine, MergeTreeEngine):
|
|
372
372
|
return MergeTreeConfigDict()
|
|
373
373
|
elif isinstance(engine, ReplacingMergeTreeEngine):
|
|
@@ -395,7 +395,7 @@ def _convert_replicated_engine_instance(engine: "EngineConfig") -> Optional[Engi
|
|
|
395
395
|
ReplicatedMergeTreeEngine, ReplicatedReplacingMergeTreeEngine,
|
|
396
396
|
ReplicatedAggregatingMergeTreeEngine, ReplicatedSummingMergeTreeEngine
|
|
397
397
|
)
|
|
398
|
-
|
|
398
|
+
|
|
399
399
|
if isinstance(engine, ReplicatedMergeTreeEngine):
|
|
400
400
|
return ReplicatedMergeTreeConfigDict(
|
|
401
401
|
keeper_path=engine.keeper_path,
|
|
@@ -432,7 +432,7 @@ def _convert_engine_instance_to_config_dict(engine: "EngineConfig") -> EngineCon
|
|
|
432
432
|
EngineConfigDict with engine-specific configuration
|
|
433
433
|
"""
|
|
434
434
|
from moose_lib.blocks import S3QueueEngine
|
|
435
|
-
|
|
435
|
+
|
|
436
436
|
# Try S3Queue first
|
|
437
437
|
if isinstance(engine, S3QueueEngine):
|
|
438
438
|
return S3QueueConfigDict(
|
|
@@ -443,17 +443,17 @@ def _convert_engine_instance_to_config_dict(engine: "EngineConfig") -> EngineCon
|
|
|
443
443
|
compression=engine.compression,
|
|
444
444
|
headers=engine.headers
|
|
445
445
|
)
|
|
446
|
-
|
|
446
|
+
|
|
447
447
|
# Try basic engines
|
|
448
448
|
basic_config = _convert_basic_engine_instance(engine)
|
|
449
449
|
if basic_config:
|
|
450
450
|
return basic_config
|
|
451
|
-
|
|
451
|
+
|
|
452
452
|
# Try replicated engines
|
|
453
453
|
replicated_config = _convert_replicated_engine_instance(engine)
|
|
454
454
|
if replicated_config:
|
|
455
455
|
return replicated_config
|
|
456
|
-
|
|
456
|
+
|
|
457
457
|
# Fallback for any other EngineConfig subclass
|
|
458
458
|
return BaseEngineConfigDict(engine=engine.__class__.__name__.replace("Engine", ""))
|
|
459
459
|
|
|
@@ -558,10 +558,18 @@ def to_infra_map() -> dict:
|
|
|
558
558
|
f"{table.name}_{table.config.version}" if table.config.version else table.name
|
|
559
559
|
)
|
|
560
560
|
|
|
561
|
+
# Determine ORDER BY: list of fields or single expression
|
|
562
|
+
has_fields = bool(table.config.order_by_fields)
|
|
563
|
+
has_expr = table.config.order_by_expression is not None
|
|
564
|
+
if has_fields and has_expr:
|
|
565
|
+
raise ValueError(f"Table {table.name}: Provide either order_by_fields or order_by_expression, not both.")
|
|
566
|
+
|
|
567
|
+
order_by_value = table.config.order_by_expression if has_expr else table.config.order_by_fields
|
|
568
|
+
|
|
561
569
|
tables[id_key] = TableConfig(
|
|
562
570
|
name=table.name,
|
|
563
571
|
columns=table._column_list,
|
|
564
|
-
order_by=
|
|
572
|
+
order_by=order_by_value,
|
|
565
573
|
partition_by=table.config.partition_by,
|
|
566
574
|
engine_config=engine_config,
|
|
567
575
|
version=table.config.version,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|