tinybird 4.6.19__tar.gz → 4.6.19.dev0__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.
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/PKG-INFO +1 -16
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/ch_utils/constants.py +0 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/ch_utils/engine.py +32 -49
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/client.py +0 -37
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/service_datasources.py +8 -7
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/sql.py +10 -3
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/sql_template.py +71 -53
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/sql_template_fmt.py +13 -8
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/sql_toolset.py +5 -62
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/syncasync.py +11 -9
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/client.py +23 -51
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/cicd.py +0 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/cli.py +2 -4
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/common.py +89 -23
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/config.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection_kafka.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection_s3.py +18 -13
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/create.py +6 -3
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build.py +3 -2
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build_pipe.py +4 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/diff.py +1 -2
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_common.py +10 -9
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_connection.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_datasource.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_pipe.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +7 -6
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/playground.py +4 -3
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datasource.py +8 -7
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/deployment_common.py +5 -3
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/infra.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/logs.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/materialization.py +1 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/project.py +4 -4
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +4 -4
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/token.py +5 -2
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/watch.py +1 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/branch.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/cicd.py +0 -2
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/cli.py +9 -5
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/common.py +94 -27
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/config.py +2 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/datasource.py +1 -1
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/pipe.py +13 -9
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +4 -4
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/workspace.py +13 -11
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tornado_template.py +17 -12
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird.egg-info/PKG-INFO +1 -16
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird.egg-info/SOURCES.txt +0 -1
- tinybird-4.6.19/pyproject.toml +0 -228
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/setup.cfg +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/config.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/context.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/datafile/common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/datatypes.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/git_settings.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/prompts.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/build_common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/job.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.19 → tinybird-4.6.19.dev0}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird
|
|
3
|
-
Version: 4.6.19
|
|
3
|
+
Version: 4.6.19.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,26 +52,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
-
4.6.19
|
|
56
|
-
********
|
|
57
|
-
|
|
58
|
-
- `Changed` ``tb datasource append`` and ``tb datasource replace`` submit remote CSV, NDJSON, and Parquet URLs through the v1 import endpoint by default.
|
|
59
|
-
|
|
60
|
-
4.6.18
|
|
61
|
-
********
|
|
62
|
-
|
|
63
|
-
- `Fixed` CLI commands (for example ``tb migrate-to-forward``) no longer abort on startup when the best-effort refresh of the cached workspace id/name fails for a reason other than authentication.
|
|
64
|
-
|
|
65
55
|
4.6.17
|
|
66
56
|
********
|
|
67
57
|
|
|
68
58
|
- `Added` ``tb job retry <job_id>`` to retry eligible import and S3/GCS sync jobs in ``error`` or ``cancelled`` status.
|
|
69
59
|
|
|
70
|
-
4.6.18
|
|
71
|
-
********
|
|
72
|
-
|
|
73
|
-
- `Added` ``Markdown`` is now a valid ``FORMAT`` for SQL queries (for example ``tb sql "SELECT 1 FORMAT Markdown"``), returned as a Markdown table.
|
|
74
|
-
|
|
75
60
|
4.6.16
|
|
76
61
|
********
|
|
77
62
|
|
|
@@ -440,64 +440,35 @@ def get_engine_config(engine: str):
|
|
|
440
440
|
)
|
|
441
441
|
|
|
442
442
|
|
|
443
|
-
def
|
|
444
|
-
|
|
445
|
-
) -> None:
|
|
446
|
-
if schema is not None and columns is not None:
|
|
447
|
-
raise ValueError("You can not use 'schema' and 'columns' at the same time")
|
|
448
|
-
_, (params, options) = get_engine_config(engine)
|
|
449
|
-
schema_columns = parse_table_structure(schema) if schema is not None else (columns or [])
|
|
450
|
-
engine_settings = {key.replace("engine_", ""): value for key, value in args.items()}
|
|
451
|
-
|
|
452
|
-
for arg in engine_settings:
|
|
453
|
-
if not hasattr(TableDetails, arg):
|
|
454
|
-
raise ValueError(f"engine_{arg} is not a valid option")
|
|
455
|
-
|
|
443
|
+
def engine_params(columns, params: List[EngineParam], args: Dict):
|
|
444
|
+
params_values = []
|
|
456
445
|
for p in params:
|
|
457
|
-
if p.required and p.name not in
|
|
446
|
+
if p.required and p.name not in args:
|
|
458
447
|
raise ValueError(f"Missing required parameter '{p.name}'")
|
|
459
|
-
param_value =
|
|
448
|
+
param_value = args.get(p.name, None) or p.default_value
|
|
460
449
|
if not param_value:
|
|
461
450
|
continue
|
|
462
451
|
if p.is_valid:
|
|
463
452
|
check_is_valid(
|
|
464
|
-
valid_check=p.is_valid,
|
|
465
|
-
check_type="parameter",
|
|
466
|
-
columns=schema_columns,
|
|
467
|
-
tb_param=p.tb_param,
|
|
468
|
-
value=param_value,
|
|
453
|
+
valid_check=p.is_valid, check_type="parameter", columns=columns, tb_param=p.tb_param, value=param_value
|
|
469
454
|
)
|
|
470
|
-
|
|
471
|
-
for o in options:
|
|
472
|
-
if o.required and o.name not in engine_settings:
|
|
473
|
-
raise ValueError(f"Missing required option '{o.name}'")
|
|
474
|
-
option_value = engine_settings.get(o.name) or o.default_value
|
|
475
|
-
if o.is_valid:
|
|
476
|
-
check_is_valid(
|
|
477
|
-
valid_check=o.is_valid,
|
|
478
|
-
check_type="option",
|
|
479
|
-
columns=schema_columns,
|
|
480
|
-
tb_param=o.tb_param,
|
|
481
|
-
value=option_value,
|
|
482
|
-
)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
def engine_params(params: List[EngineParam], args: Dict) -> List[str]:
|
|
486
|
-
params_values = []
|
|
487
|
-
for p in params:
|
|
488
|
-
param_value = args.get(p.name, None) or p.default_value
|
|
489
|
-
if not param_value:
|
|
490
|
-
continue
|
|
491
455
|
params_values.append(param_value)
|
|
492
456
|
return params_values
|
|
493
457
|
|
|
494
458
|
|
|
495
|
-
def engine_options(options: List[EngineOption], args: Dict)
|
|
459
|
+
def engine_options(columns, options: List[EngineOption], args: Dict):
|
|
496
460
|
options_values = []
|
|
497
461
|
engine_settings = ""
|
|
498
462
|
|
|
499
463
|
for o in options:
|
|
464
|
+
if o.required and o.name not in args:
|
|
465
|
+
raise ValueError(f"Missing required option '{o.name}'")
|
|
500
466
|
option_value = args.get(o.name) or o.default_value
|
|
467
|
+
if o.is_valid:
|
|
468
|
+
check_is_valid(
|
|
469
|
+
valid_check=o.is_valid, check_type="option", columns=columns, tb_param=o.tb_param, value=option_value
|
|
470
|
+
)
|
|
471
|
+
|
|
501
472
|
if option_value:
|
|
502
473
|
if o.sql.lower() == "settings":
|
|
503
474
|
engine_settings = f"{o.sql} {option_value}"
|
|
@@ -519,7 +490,7 @@ def check_is_valid(
|
|
|
519
490
|
columns: List[Dict[str, Any]],
|
|
520
491
|
tb_param: str,
|
|
521
492
|
value: str,
|
|
522
|
-
)
|
|
493
|
+
):
|
|
523
494
|
"""
|
|
524
495
|
>>> check_is_valid(sorting_key_is_valid, 'option', ['column-name'], 'sorting_key', 'date')
|
|
525
496
|
|
|
@@ -536,13 +507,15 @@ def check_is_valid(
|
|
|
536
507
|
raise ValueError(f"Invalid value '{value}' for {check_type} '{tb_param}', reason: {e}")
|
|
537
508
|
|
|
538
509
|
|
|
539
|
-
def build_engine(
|
|
540
|
-
|
|
510
|
+
def build_engine(
|
|
511
|
+
engine: str, columns: Optional[List], params: List[EngineParam], options: List[EngineOption], args: Dict
|
|
512
|
+
):
|
|
513
|
+
return f"{engine}({', '.join(engine_params(columns, params, args))}) {' '.join(engine_options(columns, options, args))}".strip()
|
|
541
514
|
|
|
542
515
|
|
|
543
516
|
def engine_full_from_dict(
|
|
544
517
|
engine: str, args: dict, schema: Optional[str] = None, columns: Optional[List[Dict[str, Any]]] = None
|
|
545
|
-
)
|
|
518
|
+
):
|
|
546
519
|
"""
|
|
547
520
|
>>> schema = ''
|
|
548
521
|
>>> engine_full_from_dict('wadus', {}, schema=schema)
|
|
@@ -633,10 +606,20 @@ def engine_full_from_dict(
|
|
|
633
606
|
'ReplacingMergeTree(updated_at) PARTITION BY (tuple()) ORDER BY (project_id) SETTINGS index_granularity = 32'
|
|
634
607
|
"""
|
|
635
608
|
|
|
636
|
-
|
|
637
|
-
|
|
609
|
+
if schema is not None and columns is not None:
|
|
610
|
+
raise ValueError("You can not use 'schema' and 'columns' at the same time")
|
|
611
|
+
engine_config = get_engine_config(engine)
|
|
612
|
+
name, (params, options) = engine_config
|
|
613
|
+
if columns is None and schema is not None:
|
|
614
|
+
columns = parse_table_structure(schema)
|
|
615
|
+
|
|
638
616
|
engine_settings = {key.replace("engine_", ""): value for key, value in args.items()}
|
|
639
|
-
|
|
617
|
+
|
|
618
|
+
for arg in engine_settings:
|
|
619
|
+
if not hasattr(TableDetails, arg):
|
|
620
|
+
raise ValueError(f"engine_{arg} is not a valid option")
|
|
621
|
+
|
|
622
|
+
return build_engine(name, columns, params, options, engine_settings)
|
|
640
623
|
|
|
641
624
|
|
|
642
625
|
def engine_params_from_engine_full(engine_full: str) -> Dict[str, Any]:
|
|
@@ -408,16 +408,6 @@ class TinyB:
|
|
|
408
408
|
format: str = "csv",
|
|
409
409
|
replace_options: Optional[Set[str]] = None,
|
|
410
410
|
) -> Dict[str, Any]:
|
|
411
|
-
if mode in ("append", "replace"):
|
|
412
|
-
return await self.datasource_append_url(
|
|
413
|
-
table_name,
|
|
414
|
-
url,
|
|
415
|
-
mode=mode,
|
|
416
|
-
sql_condition=sql_condition,
|
|
417
|
-
format=format,
|
|
418
|
-
replace_options=replace_options,
|
|
419
|
-
)
|
|
420
|
-
|
|
421
411
|
params = {"name": table_name, "url": url, "mode": mode, "debug": "blocks_block_log", "format": format}
|
|
422
412
|
|
|
423
413
|
if sql_condition:
|
|
@@ -434,33 +424,6 @@ class TinyB:
|
|
|
434
424
|
|
|
435
425
|
return await self.wait_for_job(res["id"], status_callback, backoff_multiplier=1.5, maximum_backoff_seconds=20)
|
|
436
426
|
|
|
437
|
-
async def datasource_append_url(
|
|
438
|
-
self,
|
|
439
|
-
datasource_name: str,
|
|
440
|
-
url: str,
|
|
441
|
-
mode: str = "append",
|
|
442
|
-
sql_condition: Optional[str] = None,
|
|
443
|
-
format: str = "csv",
|
|
444
|
-
replace_options: Optional[Set[str]] = None,
|
|
445
|
-
) -> Dict[str, Any]:
|
|
446
|
-
params = {"format": format, "url": url}
|
|
447
|
-
if sql_condition:
|
|
448
|
-
params["replace_condition"] = sql_condition
|
|
449
|
-
if replace_options:
|
|
450
|
-
for option in replace_options:
|
|
451
|
-
params[option] = "true"
|
|
452
|
-
|
|
453
|
-
res = await self._req(
|
|
454
|
-
f"/v1/datasources/{quote(datasource_name, safe='')}/{mode}?{urlencode(params, safe='')}",
|
|
455
|
-
method="POST",
|
|
456
|
-
data=b"",
|
|
457
|
-
)
|
|
458
|
-
if not isinstance(res, dict):
|
|
459
|
-
raise RuntimeError("We couldn't confirm that your import started. Please try again.")
|
|
460
|
-
if "error" in res:
|
|
461
|
-
raise Exception(res["error"])
|
|
462
|
-
return res
|
|
463
|
-
|
|
464
427
|
async def datasource_delete(self, datasource_name: str, force: bool = False, dry_run: bool = False):
|
|
465
428
|
params = {"force": "true" if force else "false", "dry_run": "true" if dry_run else "false"}
|
|
466
429
|
return await self._req(f"/v0/datasources/{datasource_name}?{urlencode(params)}", method="DELETE")
|
|
@@ -39,7 +39,6 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
39
39
|
{"name": "result_rows", "type": "UInt64"},
|
|
40
40
|
{"name": "url", "type": "Nullable(String)"},
|
|
41
41
|
{"name": "error", "type": "UInt8"},
|
|
42
|
-
{"name": "error_message", "type": "Nullable(String)"},
|
|
43
42
|
{"name": "status_code", "type": "Int32"},
|
|
44
43
|
{"name": "request_id", "type": "String"},
|
|
45
44
|
{"name": "parameters", "type": "Map(String, String)"},
|
|
@@ -444,21 +443,25 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
444
443
|
"dateColumn": "run_validation",
|
|
445
444
|
"engine": {
|
|
446
445
|
"engine": "MergeTree",
|
|
447
|
-
"sorting_key": "
|
|
446
|
+
"sorting_key": "database, host, run_validation, query_hash",
|
|
448
447
|
"partition_key": "toYYYYMM(run_validation)",
|
|
449
448
|
},
|
|
450
449
|
"columns": [
|
|
450
|
+
{"name": "host", "type": "LowCardinality(String)"},
|
|
451
451
|
{"name": "version", "type": "LowCardinality(String)"},
|
|
452
452
|
{"name": "stable_version", "type": "LowCardinality(String)"},
|
|
453
453
|
{"name": "query_hash", "type": "UInt64"},
|
|
454
454
|
{"name": "query_last_execution", "type": "DateTime"},
|
|
455
|
-
{"name": "
|
|
456
|
-
{"name": "
|
|
455
|
+
{"name": "region", "type": "String"},
|
|
456
|
+
{"name": "workspace", "type": "String"},
|
|
457
|
+
{"name": "database", "type": "String"},
|
|
458
|
+
{"name": "pipe_name", "type": "String"},
|
|
457
459
|
{"name": "query_id", "type": "String"},
|
|
458
460
|
{"name": "query", "type": "String"},
|
|
459
461
|
{"name": "error_code", "type": "Int16"},
|
|
460
462
|
{"name": "error", "type": "String"},
|
|
461
463
|
{"name": "fix_suggestion", "type": "String"},
|
|
464
|
+
{"name": "fix_suggestion_ai", "type": "String"},
|
|
462
465
|
{"name": "run_validation", "type": "DateTime"},
|
|
463
466
|
],
|
|
464
467
|
},
|
|
@@ -677,7 +680,6 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
677
680
|
{"name": "result_rows", "type": "UInt64"},
|
|
678
681
|
{"name": "url", "type": "Nullable(String)"},
|
|
679
682
|
{"name": "error", "type": "UInt8"},
|
|
680
|
-
{"name": "error_message", "type": "Nullable(String)"},
|
|
681
683
|
{"name": "status_code", "type": "Int32"},
|
|
682
684
|
{"name": "request_id", "type": "String"},
|
|
683
685
|
{"name": "parameters", "type": "Map(String, String)"},
|
|
@@ -782,7 +784,7 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
782
784
|
},
|
|
783
785
|
{
|
|
784
786
|
"name": "organization.metrics_logs",
|
|
785
|
-
"description": "Metrics of your organization's dedicated
|
|
787
|
+
"description": "Metrics of your organization's dedicated clusters",
|
|
786
788
|
"dateColumn": "timestamp",
|
|
787
789
|
"engine": {
|
|
788
790
|
"engine": "MergeTree",
|
|
@@ -796,7 +798,6 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
796
798
|
{"name": "metric", "type": "LowCardinality(String)"},
|
|
797
799
|
{"name": "value", "type": "String"},
|
|
798
800
|
{"name": "description", "type": "LowCardinality(String)"},
|
|
799
|
-
{"name": "organization_id", "type": "String"},
|
|
800
801
|
],
|
|
801
802
|
},
|
|
802
803
|
{
|
|
@@ -129,9 +129,15 @@ class TableProjection:
|
|
|
129
129
|
def add_projection_sql(self):
|
|
130
130
|
return f"ADD {self.to_sql()}"
|
|
131
131
|
|
|
132
|
+
def drop_projection_sql(self):
|
|
133
|
+
return f"DROP PROJECTION IF EXISTS {self.name}"
|
|
134
|
+
|
|
132
135
|
def materialize_projection_sql(self):
|
|
133
136
|
return f"MATERIALIZE PROJECTION IF EXISTS {self.name}"
|
|
134
137
|
|
|
138
|
+
def clear_projection_sql(self):
|
|
139
|
+
return f"CLEAR PROJECTION IF EXISTS {self.name}"
|
|
140
|
+
|
|
135
141
|
|
|
136
142
|
def as_subquery(sql: str) -> str:
|
|
137
143
|
return f"""(\n{sql}\n)"""
|
|
@@ -669,9 +675,10 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
669
675
|
)
|
|
670
676
|
advance_single_char()
|
|
671
677
|
return schema[begin:i]
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
678
|
+
else:
|
|
679
|
+
# backticked name
|
|
680
|
+
advance_single_char()
|
|
681
|
+
return get_backticked()
|
|
675
682
|
|
|
676
683
|
def parse_expr(lookup: Iterable[SyntaxExpr]) -> str:
|
|
677
684
|
nonlocal i, line, pos
|
|
@@ -84,7 +84,6 @@ class SQLTemplateException(ValueError):
|
|
|
84
84
|
JOB_TIMESTAMP_PARAM = "job_timestamp"
|
|
85
85
|
DEFAULT_PARAM_NAMES = ["format", "q"]
|
|
86
86
|
RESERVED_PARAM_NAMES = [
|
|
87
|
-
"__tb__csv_header",
|
|
88
87
|
"__tb__semver",
|
|
89
88
|
"debug_source_tables",
|
|
90
89
|
"debug",
|
|
@@ -143,7 +142,8 @@ def transform_type(
|
|
|
143
142
|
if x is None:
|
|
144
143
|
if defined:
|
|
145
144
|
raise SQLTemplateException(REQUIRED_PARAM_NOT_DEFINED, documentation="/cli/advanced-templates.html")
|
|
146
|
-
|
|
145
|
+
else:
|
|
146
|
+
return None
|
|
147
147
|
if tester == "String":
|
|
148
148
|
if x is not None:
|
|
149
149
|
return transform(x)
|
|
@@ -167,11 +167,12 @@ def _and(*args, **kwargs):
|
|
|
167
167
|
tk = k.rsplit("__", 1)
|
|
168
168
|
if len(tk) == 1:
|
|
169
169
|
return "="
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
else:
|
|
171
|
+
if tk[1] in operands:
|
|
172
|
+
return operands[tk[1]]
|
|
173
|
+
raise SQLTemplateException(
|
|
174
|
+
f"operand {tk[1]} not supported", documentation="/cli/advanced-templates.html#sql_and"
|
|
175
|
+
)
|
|
175
176
|
|
|
176
177
|
return Expression(
|
|
177
178
|
" and ".join([f"{_name(k)} {_op(k)} {expression_wrapper(v, k)}" for k, v in kwargs.items() if v is not None])
|
|
@@ -276,7 +277,8 @@ def columns(x, default=None, fn=None):
|
|
|
276
277
|
|
|
277
278
|
if fn:
|
|
278
279
|
return Expression(",".join(f"{fn}({str(column(c, c))}) as {c}" for c in _columns))
|
|
279
|
-
|
|
280
|
+
else:
|
|
281
|
+
return Expression(",".join(str(column(c, c)) for c in _columns))
|
|
280
282
|
|
|
281
283
|
|
|
282
284
|
def column(x, default=None):
|
|
@@ -366,10 +368,11 @@ def boolean(x, default=None):
|
|
|
366
368
|
if default is None:
|
|
367
369
|
return 0
|
|
368
370
|
return boolean(default)
|
|
369
|
-
|
|
371
|
+
elif isinstance(x, Placeholder):
|
|
370
372
|
return boolean(default)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
+
elif isinstance(x, str):
|
|
374
|
+
if x == "0" or x.lower() == "false":
|
|
375
|
+
return 0
|
|
373
376
|
|
|
374
377
|
return int(bool(x))
|
|
375
378
|
|
|
@@ -400,7 +403,8 @@ def array_type(types):
|
|
|
400
403
|
raise SQLTemplateException(
|
|
401
404
|
REQUIRED_PARAM_NOT_DEFINED, documentation="/cli/advanced-templates.html"
|
|
402
405
|
)
|
|
403
|
-
|
|
406
|
+
else:
|
|
407
|
+
return None
|
|
404
408
|
values = []
|
|
405
409
|
list_values = x if type(x) == list else x.split(",") # noqa: E721
|
|
406
410
|
for i, t in enumerate(list_values):
|
|
@@ -740,11 +744,12 @@ def __date_diff(
|
|
|
740
744
|
|
|
741
745
|
if unit == "days":
|
|
742
746
|
return int(diff / 86400)
|
|
743
|
-
|
|
747
|
+
elif unit == "hours":
|
|
744
748
|
return int(diff / 3600)
|
|
745
|
-
|
|
749
|
+
elif unit == "minutes":
|
|
746
750
|
return int(diff / 60)
|
|
747
|
-
|
|
751
|
+
else:
|
|
752
|
+
return int(diff)
|
|
748
753
|
except Exception:
|
|
749
754
|
if none_if_error:
|
|
750
755
|
return None
|
|
@@ -1343,9 +1348,9 @@ def escape_single_quote_str(s):
|
|
|
1343
1348
|
def expression_wrapper(x, name, escape_arrays: bool = False):
|
|
1344
1349
|
if type(x) in (unicode_type, bytes, str):
|
|
1345
1350
|
return "'" + sqlescape_for_string_expression(x) + "'"
|
|
1346
|
-
|
|
1351
|
+
elif isinstance(x, Placeholder):
|
|
1347
1352
|
return "'__no_value__'"
|
|
1348
|
-
|
|
1353
|
+
elif isinstance(x, Comment):
|
|
1349
1354
|
return "-- {x} \n"
|
|
1350
1355
|
if x is None:
|
|
1351
1356
|
truncated_name = name[:20] + "..." if len(name) > 20 else name
|
|
@@ -1356,7 +1361,10 @@ def expression_wrapper(x, name, escape_arrays: bool = False):
|
|
|
1356
1361
|
logging.warning(f"expression_wrapper -> list :{x}:")
|
|
1357
1362
|
|
|
1358
1363
|
try:
|
|
1359
|
-
|
|
1364
|
+
result = (
|
|
1365
|
+
f"[{','.join(escape_single_quote_str(item) if isinstance(item, str) else str(item) for item in x)}]"
|
|
1366
|
+
)
|
|
1367
|
+
return result
|
|
1360
1368
|
except Exception as e:
|
|
1361
1369
|
logging.error(f"Error escaping array: {e}")
|
|
1362
1370
|
return x
|
|
@@ -1417,18 +1425,20 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1417
1425
|
# secret available: Always use workspace secret regardless of test mode
|
|
1418
1426
|
template_execution_results.add_ch_param(x)
|
|
1419
1427
|
return Symbol("{" + sqlescape(x) + ": String}")
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1428
|
+
else:
|
|
1429
|
+
# secret not available: Check test mode and defaults
|
|
1430
|
+
is_test_mode = TB_SECRET_IN_TEST_MODE in template_execution_results
|
|
1431
|
+
if default is not None:
|
|
1432
|
+
# Use provided default value
|
|
1433
|
+
return default
|
|
1434
|
+
elif is_test_mode:
|
|
1435
|
+
# In test mode without default - return placeholder
|
|
1436
|
+
return Symbol("{" + sqlescape(x) + ": String}")
|
|
1437
|
+
else:
|
|
1438
|
+
# Not in test mode, no secret, no default - raise error
|
|
1439
|
+
raise SQLTemplateException(
|
|
1440
|
+
f"Cannot access secret '{x}'. Check the secret exists in the Workspace and the token has the required scope."
|
|
1441
|
+
)
|
|
1432
1442
|
except Exception:
|
|
1433
1443
|
raise SQLTemplateException(
|
|
1434
1444
|
f"Cannot access secret '{x}'. Check the secret exists in the Workspace and the token has the required scope."
|
|
@@ -1512,12 +1522,14 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1512
1522
|
|
|
1513
1523
|
if line:
|
|
1514
1524
|
raise SQLTemplateException(f"{message.strip()} line {line[0]}")
|
|
1515
|
-
|
|
1525
|
+
else:
|
|
1526
|
+
raise SQLTemplateException(f"{message.strip()}")
|
|
1516
1527
|
except Exception as e:
|
|
1517
1528
|
if isinstance(e, SQLTemplateException):
|
|
1518
1529
|
raise e
|
|
1519
|
-
|
|
1520
|
-
|
|
1530
|
+
else:
|
|
1531
|
+
logging.exception(f"Error on unbound local error: {e}")
|
|
1532
|
+
raise ValueError(str(e))
|
|
1521
1533
|
except TypeError as e:
|
|
1522
1534
|
error = str(e)
|
|
1523
1535
|
if "not supported between instances of 'Placeholder' and " in str(e):
|
|
@@ -1948,27 +1960,29 @@ def get_var_data(content, node_id=None):
|
|
|
1948
1960
|
# ast.Constant nodes, so .value holds str/bytes/int/float/bool/None.
|
|
1949
1961
|
if type(x) == ast.Constant: # noqa: E721
|
|
1950
1962
|
return x.value
|
|
1951
|
-
|
|
1963
|
+
elif type(x) == ast.Name: # noqa: E721
|
|
1952
1964
|
return x.id
|
|
1953
|
-
|
|
1965
|
+
elif type(x) == ast.List: # noqa: E721
|
|
1954
1966
|
# List can hold different types
|
|
1955
1967
|
return _get_list_var_data(x)
|
|
1956
|
-
|
|
1968
|
+
elif type(x) == ast.BinOp: # noqa: E721
|
|
1957
1969
|
# in this case there could be several variables
|
|
1958
1970
|
# if that's the case the left one is the main
|
|
1959
1971
|
r = node_to_value(x.left)
|
|
1960
1972
|
if not r:
|
|
1961
1973
|
r = node_to_value(x.right)
|
|
1962
1974
|
return r
|
|
1963
|
-
|
|
1975
|
+
elif type(x) == ast.UnaryOp and type(x.operand) == ast.Constant: # noqa: E721
|
|
1964
1976
|
if type(x.op) == ast.USub: # noqa: E721
|
|
1965
1977
|
return x.operand.value * -1
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1978
|
+
else:
|
|
1979
|
+
return x.operand.value
|
|
1980
|
+
else:
|
|
1981
|
+
try:
|
|
1982
|
+
return x.id
|
|
1983
|
+
except Exception:
|
|
1984
|
+
# don't let this ruin the parsing
|
|
1985
|
+
pass
|
|
1972
1986
|
return None
|
|
1973
1987
|
|
|
1974
1988
|
def _get_list_var_data(x):
|
|
@@ -1980,7 +1994,7 @@ def get_var_data(content, node_id=None):
|
|
|
1980
1994
|
# ast.Bytes/ast.Str/ast.Num/ast.NameConstant (removed in 3.14).
|
|
1981
1995
|
if type(first_elem) == ast.Constant: # noqa: E721
|
|
1982
1996
|
return [elem.value for elem in x.elts]
|
|
1983
|
-
|
|
1997
|
+
elif type(first_elem) == ast.Name: # noqa: E721
|
|
1984
1998
|
return [elem.id for elem in x.elts]
|
|
1985
1999
|
|
|
1986
2000
|
return []
|
|
@@ -1999,7 +2013,8 @@ def get_var_data(content, node_id=None):
|
|
|
1999
2013
|
# to just `ast.parse(content)` once we confirm all environments use patched Python versions.
|
|
2000
2014
|
def parse_content(content, retries=0):
|
|
2001
2015
|
try:
|
|
2002
|
-
|
|
2016
|
+
parsed = ast.parse(content)
|
|
2017
|
+
return parsed
|
|
2003
2018
|
except Exception as e:
|
|
2004
2019
|
if "AST constructor recursion depth mismatch" not in str(e):
|
|
2005
2020
|
raise e
|
|
@@ -2027,7 +2042,8 @@ def get_var_data(content, node_id=None):
|
|
|
2027
2042
|
if type(x) == ast.Call: # noqa: E721
|
|
2028
2043
|
# Nested calls are traversed via `ast.iter_child_nodes` below.
|
|
2029
2044
|
continue
|
|
2030
|
-
|
|
2045
|
+
else:
|
|
2046
|
+
args.append(node_to_value(x))
|
|
2031
2047
|
|
|
2032
2048
|
kwargs = {}
|
|
2033
2049
|
for x in node.keywords:
|
|
@@ -2515,7 +2531,8 @@ def format_SQLTemplateException_message(e: SQLTemplateException, vars_and_types:
|
|
|
2515
2531
|
f"{REQUIRED_PARAM_NOT_DEFINED}. Check the parameters {join_with_different_last_separator(vars_with_default_none)}. Please provide a value or set a default value in the pipe code.",
|
|
2516
2532
|
e.documentation,
|
|
2517
2533
|
)
|
|
2518
|
-
|
|
2534
|
+
else:
|
|
2535
|
+
raise e
|
|
2519
2536
|
|
|
2520
2537
|
|
|
2521
2538
|
def render_sql_template(
|
|
@@ -2896,12 +2913,12 @@ def render_sql_template(
|
|
|
2896
2913
|
# https://gitlab.com/tinybird/analytics/-/issues/943
|
|
2897
2914
|
if "length" in v and not v["length"]:
|
|
2898
2915
|
raise SQLTemplateException("length cannot be used as a variable name or as a function inside of a template")
|
|
2899
|
-
|
|
2916
|
+
elif "missing 1 required positional argument" in str(e):
|
|
2900
2917
|
raise SQLTemplateException(
|
|
2901
2918
|
"one of the transform type functions is missing an argument",
|
|
2902
2919
|
documentation="/cli/advanced-templates.html#transform-types-functions",
|
|
2903
2920
|
)
|
|
2904
|
-
|
|
2921
|
+
elif "not callable" in str(e) or "unhashable type" in str(e):
|
|
2905
2922
|
raise SQLTemplateException(
|
|
2906
2923
|
"wrong syntax, you might be using a not valid function inside a control block",
|
|
2907
2924
|
documentation="/cli/advanced-templates.html",
|
|
@@ -3046,7 +3063,7 @@ def render_template_with_secrets(
|
|
|
3046
3063
|
)
|
|
3047
3064
|
return '""'
|
|
3048
3065
|
return value
|
|
3049
|
-
|
|
3066
|
+
elif default is not None:
|
|
3050
3067
|
if isinstance(default, str) and len(default) == 0:
|
|
3051
3068
|
if empty_secret_raises:
|
|
3052
3069
|
raise SQLTemplateException(
|
|
@@ -3054,9 +3071,10 @@ def render_template_with_secrets(
|
|
|
3054
3071
|
)
|
|
3055
3072
|
return '""'
|
|
3056
3073
|
return default
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3074
|
+
else:
|
|
3075
|
+
raise SQLTemplateException(
|
|
3076
|
+
f"Cannot access secret '{secret_name}'. Check the secret exists in the Workspace and the token has the required scope."
|
|
3077
|
+
)
|
|
3060
3078
|
|
|
3061
3079
|
# Create the template
|
|
3062
3080
|
t = Template(content, name=name, autoescape=None)
|
|
@@ -33,7 +33,8 @@ class TBLine(Line):
|
|
|
33
33
|
Tinybird => This is overriden from the base Line because we want SQL inside a template to be indented
|
|
34
34
|
https://github.com/tconbeer/sqlfmt/blob/c11775b92d8a45f0e91d871b81a88a894d620bec/src/sqlfmt/line.py#L92
|
|
35
35
|
"""
|
|
36
|
-
|
|
36
|
+
prefix = INDENT * (self.depth[0] + self.depth[1])
|
|
37
|
+
return prefix
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
def from_nodes(
|
|
@@ -105,7 +106,8 @@ def _format_jinja_node(self, node: Node, max_length: int) -> bool:
|
|
|
105
106
|
|
|
106
107
|
return tag.is_blackened
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
else:
|
|
110
|
+
return False
|
|
109
111
|
|
|
110
112
|
|
|
111
113
|
# Some monkey patching
|
|
@@ -156,7 +158,8 @@ class TinybirdNodeManager(NodeManager):
|
|
|
156
158
|
TokenType.SET_OPERATOR,
|
|
157
159
|
):
|
|
158
160
|
return " ".join(token.token.split())
|
|
159
|
-
|
|
161
|
+
else:
|
|
162
|
+
return token.token
|
|
160
163
|
|
|
161
164
|
|
|
162
165
|
class TinybirdDialect(ClickHouse):
|
|
@@ -227,11 +230,12 @@ class TinybirdDialect(ClickHouse):
|
|
|
227
230
|
Creates and returns an analyzer that uses the Dialect's rules for lexing
|
|
228
231
|
Custom NodeManager for Tinybird
|
|
229
232
|
"""
|
|
230
|
-
|
|
233
|
+
analyzer = Analyzer(
|
|
231
234
|
line_length=line_length,
|
|
232
235
|
rules=self.get_rules(),
|
|
233
236
|
node_manager=TinybirdNodeManager(self.case_sensitive_names, self.lower_keywords),
|
|
234
237
|
)
|
|
238
|
+
return analyzer
|
|
235
239
|
|
|
236
240
|
|
|
237
241
|
@dataclass
|
|
@@ -249,10 +253,11 @@ class TBMode(Mode):
|
|
|
249
253
|
def _calc_str(self) -> str:
|
|
250
254
|
if self.is_multiline:
|
|
251
255
|
return self.token.token + "\n"
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
+
else:
|
|
257
|
+
marker, comment_text = self._comment_parts()
|
|
258
|
+
if comment_text == "":
|
|
259
|
+
return marker + "\n"
|
|
260
|
+
return marker + " " + comment_text + "\n"
|
|
256
261
|
|
|
257
262
|
|
|
258
263
|
Comment._calc_str = property(_calc_str)
|