moose-lib 0.6.50__tar.gz → 0.6.52__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.
- {moose_lib-0.6.50 → moose_lib-0.6.52}/PKG-INFO +1 -1
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/main.py +46 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib.egg-info/PKG-INFO +1 -1
- {moose_lib-0.6.50 → moose_lib-0.6.52}/README.md +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/__init__.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/blocks.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/clients/__init__.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/clients/redis_client.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/commons.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/config/__init__.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/config/config_file.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/config/runtime.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/data_models.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/__init__.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/_registry.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/consumption.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/ingest_api.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/ingest_pipeline.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/life_cycle.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/materialized_view.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/olap_table.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/registry.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/sql_resource.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/stream.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/types.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/view.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2/workflow.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/dmv2-serializer.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/internal.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/query_param.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/streaming/__init__.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/streaming/streaming_function_runner.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/utilities/__init__.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib/utilities/sql.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib.egg-info/SOURCES.txt +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib.egg-info/dependency_links.txt +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib.egg-info/requires.txt +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/moose_lib.egg-info/top_level.txt +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/setup.cfg +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/setup.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/tests/__init__.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/tests/conftest.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/tests/test_moose.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/tests/test_redis_client.py +0 -0
- {moose_lib-0.6.50 → moose_lib-0.6.52}/tests/test_s3queue_config.py +0 -0
|
@@ -19,6 +19,8 @@ from string import Formatter
|
|
|
19
19
|
from temporalio.client import Client as TemporalClient, TLSConfig
|
|
20
20
|
from temporalio.common import RetryPolicy, WorkflowIDConflictPolicy, WorkflowIDReusePolicy
|
|
21
21
|
from datetime import timedelta
|
|
22
|
+
from time import perf_counter
|
|
23
|
+
from humanfriendly import format_timespan
|
|
22
24
|
from .config.runtime import RuntimeClickHouseConfig
|
|
23
25
|
|
|
24
26
|
from moose_lib.commons import EnhancedJSONEncoder
|
|
@@ -182,6 +184,7 @@ class QueryClient:
|
|
|
182
184
|
def execute(self, input, variables, row_type: Type[BaseModel] = None):
|
|
183
185
|
params = {}
|
|
184
186
|
values = {}
|
|
187
|
+
preview_params = {}
|
|
185
188
|
|
|
186
189
|
for i, (_, variable_name, _, _) in enumerate(Formatter().parse(input)):
|
|
187
190
|
if variable_name:
|
|
@@ -196,20 +199,63 @@ class QueryClient:
|
|
|
196
199
|
|
|
197
200
|
params[variable_name] = f'{{p{i}: {t}}}'
|
|
198
201
|
values[f'p{i}'] = value
|
|
202
|
+
preview_params[variable_name] = self._format_value_for_preview(value)
|
|
203
|
+
|
|
199
204
|
clickhouse_query = input.format_map(params)
|
|
205
|
+
preview_query = input.format_map(preview_params)
|
|
200
206
|
|
|
201
207
|
# We are not using the result of the ping
|
|
202
208
|
# but this ensures that if the clickhouse cloud service is idle, we
|
|
203
209
|
# wake it up, before we send the query.
|
|
204
210
|
self.ch_client.ping()
|
|
205
211
|
|
|
212
|
+
print(f"[QueryClient] | Query: {' '.join(preview_query.split())}")
|
|
213
|
+
start = perf_counter()
|
|
206
214
|
val = self.ch_client.query(clickhouse_query, values)
|
|
215
|
+
secs = perf_counter() - start
|
|
216
|
+
if secs < 1:
|
|
217
|
+
print(f"[QueryClient] | Query completed: {secs * 1000:.0f} ms")
|
|
218
|
+
else:
|
|
219
|
+
print(f"[QueryClient] | Query completed: {format_timespan(secs)}")
|
|
207
220
|
|
|
208
221
|
if row_type is None:
|
|
209
222
|
return list(val.named_results())
|
|
210
223
|
else:
|
|
211
224
|
return list(row_type(**row) for row in val.named_results())
|
|
212
225
|
|
|
226
|
+
def _format_value_for_preview(self, value: Any) -> str:
|
|
227
|
+
"""Format a Python value as a ClickHouse SQL literal for preview logging.
|
|
228
|
+
|
|
229
|
+
This does not affect execution; it's only for human-readable query logs.
|
|
230
|
+
"""
|
|
231
|
+
# NULL handling
|
|
232
|
+
if value is None:
|
|
233
|
+
return 'NULL'
|
|
234
|
+
|
|
235
|
+
# Booleans (ClickHouse accepts true/false)
|
|
236
|
+
if isinstance(value, bool):
|
|
237
|
+
return 'true' if value else 'false'
|
|
238
|
+
|
|
239
|
+
# Numbers
|
|
240
|
+
if isinstance(value, (int, float)) and not isinstance(value, bool):
|
|
241
|
+
return str(value)
|
|
242
|
+
|
|
243
|
+
# Strings
|
|
244
|
+
if isinstance(value, str):
|
|
245
|
+
# Escape backslashes and single quotes for ClickHouse single-quoted strings
|
|
246
|
+
escaped = value.replace('\\', '\\\\').replace("'", "\\'")
|
|
247
|
+
return f"'{escaped}'"
|
|
248
|
+
|
|
249
|
+
# Lists / tuples (format as [item1, item2, ...])
|
|
250
|
+
if isinstance(value, (list, tuple)):
|
|
251
|
+
formatted_items = ', '.join(self._format_value_for_preview(v) for v in value)
|
|
252
|
+
return f"[{formatted_items}]"
|
|
253
|
+
|
|
254
|
+
# Fallback: stringify and single-quote
|
|
255
|
+
fallback = str(value)
|
|
256
|
+
escaped_fallback = fallback.replace('\\', '\\\\').replace("'", "\\'")
|
|
257
|
+
return f"'{escaped_fallback}'"
|
|
258
|
+
|
|
213
259
|
def close(self):
|
|
214
260
|
"""Close the ClickHouse client connection."""
|
|
215
261
|
if self.ch_client:
|
|
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
|