tinybird-cli 4.1.1.dev1__tar.gz → 5.0.0.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.
Files changed (46) hide show
  1. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/PKG-INFO +15 -4
  2. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/__cli__.py +2 -2
  3. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/context.py +1 -0
  4. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/datafile.py +26 -6
  5. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/sql_template.py +92 -66
  6. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/pipe.py +8 -0
  7. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tornado_template.py +9 -1
  8. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird_cli.egg-info/PKG-INFO +15 -4
  9. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/setup.cfg +0 -0
  10. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/ch_utils/constants.py +0 -0
  11. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/ch_utils/engine.py +0 -0
  12. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/check_pypi.py +0 -0
  13. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/client.py +0 -0
  14. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/config.py +0 -0
  15. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/connectors.py +0 -0
  16. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/datatypes.py +0 -0
  17. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/feedback_manager.py +0 -0
  18. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/git_settings.py +0 -0
  19. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/sql.py +0 -0
  20. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/sql_template_fmt.py +0 -0
  21. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/sql_toolset.py +0 -0
  22. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/syncasync.py +0 -0
  23. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli.py +0 -0
  24. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
  25. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/branch.py +0 -0
  26. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
  27. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/cli.py +0 -0
  28. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/common.py +0 -0
  29. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/config.py +0 -0
  30. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
  31. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/datasource.py +0 -0
  32. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
  33. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/job.py +0 -0
  34. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
  35. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
  36. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/test.py +0 -0
  37. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  38. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  39. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/token.py +0 -0
  40. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/workspace.py +0 -0
  41. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  42. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird_cli.egg-info/SOURCES.txt +0 -0
  43. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  44. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird_cli.egg-info/entry_points.txt +0 -0
  45. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird_cli.egg-info/requires.txt +0 -0
  46. {tinybird-cli-4.1.1.dev1 → tinybird-cli-5.0.0.dev0}/tinybird_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 4.1.1.dev1
3
+ Version: 5.0.0.dev0
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,7 +18,18 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
- 4.1.1.dev0
21
+ 5.0.0.dev0
22
+ ************
23
+
24
+ - `Changed` Make `insertion_date`` column explicit. This column is no longer inferred, it must be present in the Data Source file.
25
+
26
+ 4.1.2.dev0
27
+ ************
28
+
29
+ - `Added` parameter to `tb pipe regression-test` --relative-change
30
+
31
+
32
+ 4.1.1
22
33
  ************
23
34
 
24
35
  - `Fixed` workspace info gathering when switching branches. We were prioritizing the general workspace properties over the user ones.
@@ -27,7 +38,7 @@ Changelog
27
38
  ************
28
39
 
29
40
  - `Added` `tb token create` command to be able to create static and JWT tokens from the CLI. You can check more information at https://www.tinybird.co/blog-posts/jwt-api-endpoints-public-beta
30
- - `Fixed` `tb init --git` to pin `tinybird-cli>=4,<5` in `requirements.txt` to avoid issues with the latest version of the CLI.
41
+ - `Fixed` `tb init --git` to pin `tinybird-cli>=4,<5` in `requirements.txt` to avoid issues with the latest version of the CLI.
31
42
 
32
43
  4.0.0
33
44
  ************
@@ -85,7 +96,7 @@ This is a major release, please read the commands affected below and consider up
85
96
  ************
86
97
 
87
98
  - `Changed` fixed major version of tinybird-cli to lower than 4 when using `tb init --git`
88
- - `Changed` behavior when running `tb deploy` on a branch to push the connection settings to the backend. This change is the backend that decides what to do.
99
+ - `Changed` behavior when running `tb deploy` on a branch to push the connection settings to the backend. This change is the backend that decides what to do.
89
100
  - `Changed` `tb pipe sink` commands are now available
90
101
  - `Fixed` regression tests query when filtering by specific parameter
91
102
  - `Fixed` Avoid `tb fmt` to error if there's a `CASE` in the sql
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
4
4
  __url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '4.1.1.dev1'
8
- __revision__ = '29bdc3e'
7
+ __version__ = '5.0.0.dev0'
8
+ __revision__ = '2147517'
@@ -7,6 +7,7 @@ hfi_frequency: ContextVar[float] = ContextVar("hfi_frequency")
7
7
  hfi_frequency_gatherer: ContextVar[float] = ContextVar("hfi_frequency_gatherer")
8
8
  use_gatherer: ContextVar[bool] = ContextVar("use_gatherer")
9
9
  allow_gatherer_fallback: ContextVar[bool] = ContextVar("allow_gatherer_fallback")
10
+ gatherer_allow_s3_backup_on_user_errors: ContextVar[bool] = ContextVar("gatherer_allow_s3_backup_on_user_errors")
10
11
  disable_template_security_validation: ContextVar[bool] = ContextVar("disable_template_security_validation")
11
12
  origin: ContextVar[str] = ContextVar("origin")
12
13
  request_id: ContextVar[str] = ContextVar("request_id")
@@ -773,7 +773,7 @@ def parse_pipe(
773
773
  for node in doc.nodes:
774
774
  sql = node.get("sql", "")
775
775
  if sql.strip()[0] == "%":
776
- sql, _ = render_sql_template(sql[1:], test_mode=True, name=node["name"])
776
+ sql, _, _ = render_sql_template(sql[1:], test_mode=True, name=node["name"])
777
777
  # it'll fail with a ModuleNotFoundError when the toolset is not available but it returns the parsed doc
778
778
  from tinybird.sql_toolset import format_sql as toolset_format_sql
779
779
 
@@ -785,7 +785,7 @@ def parse_pipe(
785
785
  )
786
786
  )
787
787
  except ValueError as e:
788
- t, template_variables = get_template_and_variables(sql, name=node["name"])
788
+ t, template_variables, _ = get_template_and_variables(sql, name=node["name"])
789
789
 
790
790
  if sql.strip()[0] != "%" and len(template_variables) > 0:
791
791
  raise click.ClickException(FeedbackManager.error_template_start(filename=filename))
@@ -1492,7 +1492,7 @@ async def process_file(
1492
1492
  is_template = False
1493
1493
  if sql[0] == "%":
1494
1494
  try:
1495
- sql_rendered, _ = render_sql_template(sql[1:], test_mode=True)
1495
+ sql_rendered, _, _ = render_sql_template(sql[1:], test_mode=True)
1496
1496
  except Exception as e:
1497
1497
  raise click.ClickException(
1498
1498
  FeedbackManager.error_parsing_node(node=node["name"], pipe=name, error=str(e))
@@ -1766,6 +1766,7 @@ class PipeChecker(unittest.TestCase):
1766
1766
  only_response_times: bool,
1767
1767
  ignore_order: bool,
1768
1768
  validate_processed_bytes: bool,
1769
+ relative_change: float,
1769
1770
  *args,
1770
1771
  **kwargs,
1771
1772
  ) -> None:
@@ -1784,6 +1785,7 @@ class PipeChecker(unittest.TestCase):
1784
1785
  self.only_response_times = only_response_times
1785
1786
  self.ignore_order = ignore_order
1786
1787
  self.validate_processed_bytes = validate_processed_bytes
1788
+ self.relative_change = relative_change
1787
1789
 
1788
1790
  parsed = urlparse(self.current_pipe_url)
1789
1791
  self.checker_pipe_url = f"{parsed.scheme}://{parsed.netloc}/v0/pipes/{self.checker_pipe_name}.json"
@@ -1901,12 +1903,13 @@ class PipeChecker(unittest.TestCase):
1901
1903
  for _, (current_data_e, check_fixtures_data_e) in enumerate(zip(current_data, checker_data)):
1902
1904
  self.assertEqual(list(current_data_e.keys()), list(check_fixtures_data_e.keys()))
1903
1905
  for x in current_data_e.keys():
1904
- if isinstance(current_data_e[x], float):
1906
+ if isinstance(current_data_e[x], (float, int)):
1905
1907
  d = abs(current_data_e[x] - check_fixtures_data_e[x])
1908
+
1906
1909
  try:
1907
1910
  self.assertLessEqual(
1908
1911
  d / current_data_e[x],
1909
- 0.01,
1912
+ self.relative_change,
1910
1913
  f"key {x}. old value: {current_data_e[x]}, new value: {check_fixtures_data_e[x]}\n{self.diff(current_data_e, check_fixtures_data_e)}",
1911
1914
  )
1912
1915
  except ZeroDivisionError:
@@ -2057,6 +2060,7 @@ class PipeCheckerRunner:
2057
2060
  only_response_times: bool,
2058
2061
  ignore_order: bool,
2059
2062
  validate_processed_bytes: bool,
2063
+ relative_change: float,
2060
2064
  ) -> PipeChecker:
2061
2065
  return PipeChecker(
2062
2066
  request,
@@ -2066,6 +2070,7 @@ class PipeCheckerRunner:
2066
2070
  only_response_times,
2067
2071
  ignore_order,
2068
2072
  validate_processed_bytes,
2073
+ relative_change,
2069
2074
  )
2070
2075
 
2071
2076
  def _delta_percentage(self, checker: float, current: float) -> float:
@@ -2085,6 +2090,7 @@ class PipeCheckerRunner:
2085
2090
  only_response_times: bool,
2086
2091
  ignore_order: bool,
2087
2092
  validate_processed_bytes: bool,
2093
+ relative_change: float,
2088
2094
  failfast: bool,
2089
2095
  custom_output: bool = False,
2090
2096
  debug: bool = False,
@@ -2123,7 +2129,13 @@ class PipeCheckerRunner:
2123
2129
  for _, request in enumerate(pipe_requests_to_check):
2124
2130
  suite.addTest(
2125
2131
  self._get_checker(
2126
- request, checker_pipe_name, token, only_response_times, ignore_order, validate_processed_bytes
2132
+ request,
2133
+ checker_pipe_name,
2134
+ token,
2135
+ only_response_times,
2136
+ ignore_order,
2137
+ validate_processed_bytes,
2138
+ relative_change,
2127
2139
  )
2128
2140
  )
2129
2141
 
@@ -2264,6 +2276,7 @@ async def check_pipe(
2264
2276
  populate: bool,
2265
2277
  cl: TinyB,
2266
2278
  limit: int = 0,
2279
+ relative_change: float = 0.01,
2267
2280
  sample_by_params: int = 0,
2268
2281
  only_response_times=False,
2269
2282
  matches: Optional[List[str]] = None,
@@ -2342,6 +2355,7 @@ async def check_pipe(
2342
2355
  only_response_times,
2343
2356
  ignore_order,
2344
2357
  validate_processed_bytes,
2358
+ relative_change,
2345
2359
  failfast,
2346
2360
  )
2347
2361
 
@@ -2556,6 +2570,7 @@ async def new_pipe(
2556
2570
  run_tests: bool = False,
2557
2571
  as_standard: bool = False,
2558
2572
  tests_to_run: int = 0,
2573
+ tests_relative_change: float = 0.01,
2559
2574
  tests_to_sample_by_params: int = 0,
2560
2575
  tests_filter_by: Optional[List[str]] = None,
2561
2576
  tests_failfast: bool = False,
@@ -2600,6 +2615,7 @@ async def new_pipe(
2600
2615
  tb_client,
2601
2616
  only_response_times=only_response_times,
2602
2617
  limit=tests_to_run,
2618
+ relative_change=tests_relative_change,
2603
2619
  sample_by_params=tests_to_sample_by_params,
2604
2620
  matches=tests_filter_by,
2605
2621
  failfast=tests_failfast,
@@ -3206,6 +3222,7 @@ async def exec_file(
3206
3222
  run_tests=False,
3207
3223
  as_standard=False,
3208
3224
  tests_to_run: int = 0,
3225
+ tests_relative_change: float = 0.01,
3209
3226
  tests_to_sample_by_params: int = 0,
3210
3227
  tests_filter_by: Optional[List[str]] = None,
3211
3228
  tests_failfast: bool = False,
@@ -3235,6 +3252,7 @@ async def exec_file(
3235
3252
  run_tests=run_tests,
3236
3253
  as_standard=as_standard,
3237
3254
  tests_to_run=tests_to_run,
3255
+ tests_relative_change=tests_relative_change,
3238
3256
  tests_to_sample_by_params=tests_to_sample_by_params,
3239
3257
  tests_filter_by=tests_filter_by,
3240
3258
  tests_failfast=tests_failfast,
@@ -3805,6 +3823,7 @@ async def folder_push(
3805
3823
  raise_on_exists: bool = False,
3806
3824
  verbose: bool = True,
3807
3825
  tests_to_run: int = 0,
3826
+ tests_relative_change: float = 0.01,
3808
3827
  tests_sample_by_params: int = 0,
3809
3828
  tests_filter_by: Optional[List[str]] = None,
3810
3829
  tests_failfast: bool = False,
@@ -3991,6 +4010,7 @@ async def folder_push(
3991
4010
  run_tests,
3992
4011
  as_standard,
3993
4012
  tests_to_run,
4013
+ tests_relative_change,
3994
4014
  tests_sample_by_params,
3995
4015
  tests_filter_by,
3996
4016
  tests_failfast,
@@ -42,6 +42,24 @@ class SQLTemplateException(ValueError):
42
42
 
43
43
 
44
44
  DEFAULT_PARAM_NAMES = ["format", "q"]
45
+ RESERVED_PARAM_NAMES = [
46
+ "__tb__semver",
47
+ "debug_source_tables",
48
+ "debug",
49
+ "explain",
50
+ "finalize_aggregations",
51
+ "output_format_json_quote_64bit_integers",
52
+ "output_format_json_quote_denormals",
53
+ "output_format_parquet_string_as_string",
54
+ "pipeline",
55
+ "playground",
56
+ "q",
57
+ "query_id",
58
+ "release_replacements",
59
+ "tag",
60
+ "template_parameters",
61
+ "token",
62
+ ]
45
63
 
46
64
  parameter_types = [
47
65
  "String",
@@ -1771,6 +1789,8 @@ def get_template_and_variables(sql: str, name: Optional[str], escape_arrays: boo
1771
1789
  it is important to NOT MODIFY THESE OBJECTS.
1772
1790
  Neither render_sql_template() or generate() modify them, so neither should you
1773
1791
  """
1792
+ variable_warnings = []
1793
+
1774
1794
  try:
1775
1795
  t = Template(sql, name)
1776
1796
  template_variables = get_var_names(t)
@@ -1780,10 +1800,12 @@ def get_template_and_variables(sql: str, name: Optional[str], escape_arrays: boo
1780
1800
  name = variable["name"]
1781
1801
  line = variable["line"]
1782
1802
  raise ValueError(f'"{name}" can not be used as a variable name, line {line}')
1803
+ if variable["name"] in RESERVED_PARAM_NAMES:
1804
+ variable_warnings.append(variable["name"])
1783
1805
 
1784
1806
  wrap_vars(t, escape_arrays=escape_arrays)
1785
1807
 
1786
- return t, template_variables
1808
+ return t, template_variables, variable_warnings
1787
1809
  except SecurityException as e:
1788
1810
  raise SQLTemplateException(e)
1789
1811
 
@@ -1836,96 +1858,96 @@ def render_sql_template(
1836
1858
  variables: Optional[dict] = None,
1837
1859
  test_mode: bool = False,
1838
1860
  name: Optional[str] = None,
1839
- ) -> Tuple[str, dict]:
1861
+ ) -> Tuple[str, dict, list]:
1840
1862
  """
1841
1863
  >>> render_sql_template("select * from table where f = {{Float32(foo)}}", { 'foo': -1 })
1842
- ("select * from table where f = toFloat32('-1.0')", {})
1864
+ ("select * from table where f = toFloat32('-1.0')", {}, [])
1843
1865
  >>> render_sql_template("{% if defined(open) %}ERROR{% else %}YEAH!{% end %}")
1844
- ('YEAH!', {})
1866
+ ('YEAH!', {}, [])
1845
1867
  >>> render_sql_template("{% if defined(close) %}ERROR{% else %}YEAH!{% end %}")
1846
- ('YEAH!', {})
1868
+ ('YEAH!', {}, [])
1847
1869
  >>> render_sql_template("{% if defined(input) %}ERROR{% else %}YEAH!{% end %}")
1848
- ('YEAH!', {})
1870
+ ('YEAH!', {}, [])
1849
1871
  >>> render_sql_template("{% if defined(print) %}ERROR{% else %}YEAH!{% end %}")
1850
- ('YEAH!', {})
1872
+ ('YEAH!', {}, [])
1851
1873
  >>> render_sql_template("select * from table where str = {{foo}}", { 'foo': 'test' })
1852
- ("select * from table where str = 'test'", {})
1874
+ ("select * from table where str = 'test'", {}, [])
1853
1875
  >>> render_sql_template("select * from table where f = {{foo}}", { 'foo': 1.0 })
1854
- ('select * from table where f = 1.0', {})
1876
+ ('select * from table where f = 1.0', {}, [])
1855
1877
  >>> render_sql_template("select {{Boolean(foo)}} from table", { 'foo': True })
1856
- ('select 1 from table', {})
1878
+ ('select 1 from table', {}, [])
1857
1879
  >>> render_sql_template("select {{Boolean(foo)}} from table", { 'foo': False })
1858
- ('select 0 from table', {})
1880
+ ('select 0 from table', {}, [])
1859
1881
  >>> render_sql_template("select * from table where f = {{Float32(foo)}}", { 'foo': 1 })
1860
- ("select * from table where f = toFloat32('1.0')", {})
1882
+ ("select * from table where f = toFloat32('1.0')", {}, [])
1861
1883
  >>> render_sql_template("select * from table where f = {{foo}}", { 'foo': "';drop table users;" })
1862
- ("select * from table where f = '\\\\';drop table users;'", {})
1884
+ ("select * from table where f = '\\\\';drop table users;'", {}, [])
1863
1885
  >>> render_sql_template("select * from {{symbol(foo)}}", { 'foo': 'table-name' })
1864
- ('select * from `table-name`', {})
1886
+ ('select * from `table-name`', {}, [])
1865
1887
  >>> render_sql_template("select * from {{symbol(foo)}}", { 'foo': '"table-name"' })
1866
- ('select * from `table-name`', {})
1888
+ ('select * from `table-name`', {}, [])
1867
1889
  >>> render_sql_template("select * from {{table(foo)}}", { 'foo': '"table-name"' })
1868
- ('select * from table-name', {})
1890
+ ('select * from table-name', {}, [])
1869
1891
  >>> render_sql_template("select * from {{Int32(foo)}}", { 'foo': 'non_int' })
1870
1892
  Traceback (most recent call last):
1871
1893
  ...
1872
1894
  tinybird.sql_template.SQLTemplateException: Template Syntax Error: Error validating 'non_int' to type Int32
1873
1895
  >>> render_sql_template("select * from table where f = {{Float32(foo)}}", test_mode=True)
1874
- ("select * from table where f = toFloat32('0.0')", {})
1896
+ ("select * from table where f = toFloat32('0.0')", {}, [])
1875
1897
  >>> render_sql_template("SELECT * FROM query_log__dev where a = {{test}}", test_mode=True)
1876
- ("SELECT * FROM query_log__dev where a = '__placeholder__'", {})
1898
+ ("SELECT * FROM query_log__dev where a = '__placeholder__'", {}, [])
1877
1899
  >>> render_sql_template("SELECT {{test}}", {'token':'testing'})
1878
1900
  Traceback (most recent call last):
1879
1901
  ...
1880
1902
  tinybird.sql_template.SQLTemplateException: Template Syntax Error: expression "test" evaluated to null
1881
1903
  >>> render_sql_template('{% if test %}SELECT 1{% else %} select 2 {% end %}')
1882
- (' select 2 ', {})
1904
+ (' select 2 ', {}, [])
1883
1905
  >>> render_sql_template('{% if Int32(test, 1) %}SELECT 1{% else %} select 2 {% end %}')
1884
- ('SELECT 1', {})
1906
+ ('SELECT 1', {}, [])
1885
1907
  >>> render_sql_template('{% for v in test %}SELECT {{v}} {% end %}',test_mode=True)
1886
- ("SELECT '__placeholder__' SELECT '__placeholder__' SELECT '__placeholder__' ", {})
1908
+ ("SELECT '__placeholder__' SELECT '__placeholder__' SELECT '__placeholder__' ", {}, [])
1887
1909
  >>> render_sql_template("select {{Int32(foo, 1)}}", test_mode=True)
1888
- ("select toInt32('1')", {})
1910
+ ("select toInt32('1')", {}, [])
1889
1911
  >>> render_sql_template("SELECT count() c FROM test_table where a > {{Float32(myvar)}} {% if defined(my_condition) %} and c = Int32({{my_condition}}){% end %}", {'myvar': 1.0})
1890
- ("SELECT count() c FROM test_table where a > toFloat32('1.0') ", {})
1912
+ ("SELECT count() c FROM test_table where a > toFloat32('1.0') ", {}, [])
1891
1913
  >>> render_sql_template("SELECT count() c FROM where {{sql_and(a=a, b=b)}}", {'a': '1', 'b': '2'})
1892
- ("SELECT count() c FROM where a = '1' and b = '2'", {})
1914
+ ("SELECT count() c FROM where a = '1' and b = '2'", {}, [])
1893
1915
  >>> render_sql_template("SELECT count() c FROM where {{sql_and(a=a, b=b)}}", {'b': '2'})
1894
- ("SELECT count() c FROM where b = '2'", {})
1916
+ ("SELECT count() c FROM where b = '2'", {}, [])
1895
1917
  >>> render_sql_template("SELECT count() c FROM where {{sql_and(a=Int(a, defined=False), b=Int(b, defined=False))}}", {'b': '2'})
1896
- ('SELECT count() c FROM where b = 2', {})
1918
+ ('SELECT count() c FROM where b = 2', {}, [])
1897
1919
  >>> render_sql_template("SELECT count() c FROM where {{sql_and(a__in=Array(a), b=b)}}", {'a': 'a,b,c','b': '2'})
1898
- ("SELECT count() c FROM where a in ['a','b','c'] and b = '2'", {})
1920
+ ("SELECT count() c FROM where a in ['a','b','c'] and b = '2'", {}, [])
1899
1921
  >>> render_sql_template("SELECT count() c FROM where {{sql_and(a__not_in=Array(a), b=b)}}", {'a': 'a,b,c','b': '2'})
1900
- ("SELECT count() c FROM where a not in ['a','b','c'] and b = '2'", {})
1922
+ ("SELECT count() c FROM where a not in ['a','b','c'] and b = '2'", {}, [])
1901
1923
  >>> render_sql_template("SELECT c FROM where a > {{Date(start)}}", test_mode=True)
1902
- ("SELECT c FROM where a > '2019-01-01'", {})
1924
+ ("SELECT c FROM where a > '2019-01-01'", {}, [])
1903
1925
  >>> render_sql_template("SELECT c FROM where a > {{DateTime(start)}}", test_mode=True)
1904
- ("SELECT c FROM where a > '2019-01-01 00:00:00'", {})
1926
+ ("SELECT c FROM where a > '2019-01-01 00:00:00'", {}, [])
1905
1927
  >>> render_sql_template("SELECT c FROM where a > {{DateTime(start)}}", {'start': '2018-09-07 23:55:00'})
1906
- ("SELECT c FROM where a > '2018-09-07 23:55:00'", {})
1928
+ ("SELECT c FROM where a > '2018-09-07 23:55:00'", {}, [])
1907
1929
  >>> render_sql_template('SELECT * FROM tracker {% if defined(start) %} {{DateTime(start)}} and {{DateTime(end)}} {% end %}', {'start': '2019-08-01 00:00:00', 'end': '2019-08-02 00:00:00'})
1908
- ("SELECT * FROM tracker '2019-08-01 00:00:00' and '2019-08-02 00:00:00' ", {})
1930
+ ("SELECT * FROM tracker '2019-08-01 00:00:00' and '2019-08-02 00:00:00' ", {}, [])
1909
1931
  >>> render_sql_template('SELECT * from test limit {{Int(limit)}}', test_mode=True)
1910
- ('SELECT * from test limit 0', {})
1932
+ ('SELECT * from test limit 0', {}, [])
1911
1933
  >>> render_sql_template('SELECT {{symbol(attr)}} from test', test_mode=True)
1912
- ('SELECT `placeholder` from test', {})
1934
+ ('SELECT `placeholder` from test', {}, [])
1913
1935
  >>> render_sql_template('SELECT {{Array(foo)}}', {'foo': 'a,b,c,d'})
1914
- ("SELECT ['a','b','c','d']", {})
1936
+ ("SELECT ['a','b','c','d']", {}, [])
1915
1937
  >>> render_sql_template("SELECT {{Array(foo, 'Int32')}}", {'foo': '1,2,3,4'})
1916
- ('SELECT [1,2,3,4]', {})
1938
+ ('SELECT [1,2,3,4]', {}, [])
1917
1939
  >>> render_sql_template("SELECT {{Array(foo, 'Int32')}}", test_mode=True)
1918
- ('SELECT [0,0]', {})
1940
+ ('SELECT [0,0]', {}, [])
1919
1941
  >>> render_sql_template("SELECT {{Array(foo)}}", test_mode=True)
1920
- ("SELECT ['__placeholder__0','__placeholder__1']", {})
1942
+ ("SELECT ['__placeholder__0','__placeholder__1']", {}, [])
1921
1943
  >>> render_sql_template("{{max_threads(2)}} SELECT 1")
1922
- ('-- max_threads 2\\n SELECT 1', {'max_threads': 2})
1944
+ ('-- max_threads 2\\n SELECT 1', {'max_threads': 2}, [])
1923
1945
  >>> render_sql_template("SELECT {{String(foo)}}", test_mode=True)
1924
- ("SELECT '__placeholder__'", {})
1946
+ ("SELECT '__placeholder__'", {}, [])
1925
1947
  >>> render_sql_template("SELECT {{String(foo, 'test')}}", test_mode=True)
1926
- ("SELECT 'test'", {})
1948
+ ("SELECT 'test'", {}, [])
1927
1949
  >>> render_sql_template("SELECT {{String(foo, 'test')}}", {'foo': 'tt'})
1928
- ("SELECT 'tt'", {})
1950
+ ("SELECT 'tt'", {}, [])
1929
1951
  >>> render_sql_template("SELECT {{String(format, 'test')}}", {'format': 'tt'})
1930
1952
  Traceback (most recent call last):
1931
1953
  ...
@@ -1943,25 +1965,25 @@ def render_sql_template(
1943
1965
  ...
1944
1966
  tinybird.sql_template.SQLTemplateException: Template Syntax Error: Missing column() default value, use `column(column_name, 'default_column_name')`
1945
1967
  >>> render_sql_template("SELECT {{column(agg)}}", {'agg': 'foo'})
1946
- ('SELECT `foo`', {})
1968
+ ('SELECT `foo`', {}, [])
1947
1969
  >>> render_sql_template("SELECT {{column(agg)}}", {'agg': '"foo"'})
1948
- ('SELECT `foo`', {})
1970
+ ('SELECT `foo`', {}, [])
1949
1971
  >>> render_sql_template('{% if not defined(test) %}error("This is an error"){% end %}', {})
1950
- ('error("This is an error")', {})
1972
+ ('error("This is an error")', {}, [])
1951
1973
  >>> render_sql_template('{% if not defined(test) %}custom_error({error: "This is an error"}){% end %}', {})
1952
- ('custom_error({error: "This is an error"})', {})
1974
+ ('custom_error({error: "This is an error"})', {}, [])
1953
1975
  >>> render_sql_template("SELECT {{String(foo + 'abcd')}}", test_mode=True)
1954
- ("SELECT '__placeholder__'", {})
1976
+ ("SELECT '__placeholder__'", {}, [])
1955
1977
  >>> render_sql_template("SELECT {{columns(agg)}}", {})
1956
1978
  Traceback (most recent call last):
1957
1979
  ...
1958
1980
  tinybird.sql_template.SQLTemplateException: Template Syntax Error: Missing columns() default value, use `columns(column_names, 'default_column_name')`
1959
1981
  >>> render_sql_template("SELECT {{columns(agg, 'a,b,c')}} FROM table", {})
1960
- ('SELECT `a`,`b`,`c` FROM table', {})
1982
+ ('SELECT `a`,`b`,`c` FROM table', {}, [])
1961
1983
  >>> render_sql_template("SELECT {{columns(agg, 'a,b,c')}} FROM table", {'agg': 'foo'})
1962
- ('SELECT `foo` FROM table', {})
1984
+ ('SELECT `foo` FROM table', {}, [])
1963
1985
  >>> render_sql_template("SELECT {{columns('a,b,c')}} FROM table", {})
1964
- ('SELECT `a`,`b`,`c` FROM table', {})
1986
+ ('SELECT `a`,`b`,`c` FROM table', {}, [])
1965
1987
  >>> render_sql_template("% {% if whatever(passenger_count) %}{% end %}", test_mode=True)
1966
1988
  Traceback (most recent call last):
1967
1989
  ...
@@ -1971,13 +1993,13 @@ def render_sql_template(
1971
1993
  ...
1972
1994
  SyntaxError: invalid syntax
1973
1995
  >>> render_sql_template("SELECT * FROM dim_fecha_evento where foo like {{sql_unescape(String(pepe), '%')}}", {"pepe": 'raul_el_bueno_is_the_best_%'})
1974
- ("SELECT * FROM dim_fecha_evento where foo like 'raul_el_bueno_is_the_best_%'", {})
1996
+ ("SELECT * FROM dim_fecha_evento where foo like 'raul_el_bueno_is_the_best_%'", {}, [])
1975
1997
  >>> render_sql_template("SELECT * FROM table WHERE field={{String(field_filter)}}", {"field_filter": 'action."test run"'})
1976
- ('SELECT * FROM table WHERE field=\\'action.\\\\"test run\\\\"\\'', {})
1998
+ ('SELECT * FROM table WHERE field=\\'action.\\\\"test run\\\\"\\'', {}, [])
1977
1999
  >>> render_sql_template("SELECT {{Int128(foo)}} as x, {{Int128(bar)}} as y", {'foo': -170141183460469231731687303715884105728, 'bar': 170141183460469231731687303715884105727})
1978
- ("SELECT toInt128('-170141183460469231731687303715884105728') as x, toInt128('170141183460469231731687303715884105727') as y", {})
2000
+ ("SELECT toInt128('-170141183460469231731687303715884105728') as x, toInt128('170141183460469231731687303715884105727') as y", {}, [])
1979
2001
  >>> render_sql_template("SELECT {{Int256(foo)}} as x, {{Int256(bar)}} as y", {'foo': -57896044618658097711785492504343953926634992332820282019728792003956564819968, 'bar': 57896044618658097711785492504343953926634992332820282019728792003956564819967})
1980
- ("SELECT toInt256('-57896044618658097711785492504343953926634992332820282019728792003956564819968') as x, toInt256('57896044618658097711785492504343953926634992332820282019728792003956564819967') as y", {})
2002
+ ("SELECT toInt256('-57896044618658097711785492504343953926634992332820282019728792003956564819968') as x, toInt256('57896044618658097711785492504343953926634992332820282019728792003956564819967') as y", {}, [])
1981
2003
  >>> render_sql_template('% SELECT * FROM {% import os %}{{ os.popen("whoami").read() }}')
1982
2004
  Traceback (most recent call last):
1983
2005
  ...
@@ -1999,21 +2021,21 @@ def render_sql_template(
1999
2021
  ...
2000
2022
  tinybird.sql_template.SQLTemplateException: Template Syntax Error: Invalid BinOp: Pow()
2001
2023
  >>> render_sql_template("% SELECT {{Array(click_selector, 'String', 'pre,pro')}}")
2002
- ("% SELECT ['pre','pro']", {})
2024
+ ("% SELECT ['pre','pro']", {}, [])
2003
2025
  >>> render_sql_template("% SELECT {{Array(click_selector, 'String', 'pre,pro')}}", {'click_selector': 'hi,hello'})
2004
- ("% SELECT ['hi','hello']", {})
2026
+ ("% SELECT ['hi','hello']", {}, [])
2005
2027
  >>> render_sql_template("% SELECT now() > {{DateTime64(variable, '2020-09-09 10:10:10.000')}}", {})
2006
- ("% SELECT now() > '2020-09-09 10:10:10.000'", {})
2028
+ ("% SELECT now() > '2020-09-09 10:10:10.000'", {}, [])
2007
2029
  >>> render_sql_template("% SELECT {% if defined(x) %} x, 1", {})
2008
2030
  Traceback (most recent call last):
2009
2031
  ...
2010
2032
  tinybird.tornado_template.UnClosedIfError: Missing {% end %} block for if at line 1
2011
2033
  >>> render_sql_template("% SELECT * FROM employees WHERE 0 {% for kv in JSON(payload) %} OR department = {{kv['dp']}} {% end %}")
2012
- ('% SELECT * FROM employees WHERE 0 ', {})
2034
+ ('% SELECT * FROM employees WHERE 0 ', {}, [])
2013
2035
  >>> render_sql_template("% SELECT * FROM employees WHERE 0 {% for kv in JSON(payload, '[{\\"dp\\":\\"Sales\\"}]') %} OR department = {{kv['dp']}} {% end %}")
2014
- ("% SELECT * FROM employees WHERE 0 OR department = 'Sales' ", {})
2036
+ ("% SELECT * FROM employees WHERE 0 OR department = 'Sales' ", {}, [])
2015
2037
  >>> render_sql_template("% SELECT * FROM employees WHERE 0 {% for kv in JSON(payload) %} OR department = {{kv['dp']}} {% end %}", { 'payload': '[{"dp":"Design"},{"dp":"Marketing"}]'})
2016
- ("% SELECT * FROM employees WHERE 0 OR department = 'Design' OR department = 'Marketing' ", {})
2038
+ ("% SELECT * FROM employees WHERE 0 OR department = 'Design' OR department = 'Marketing' ", {}, [])
2017
2039
  >>> render_sql_template("% {% for kv in JSON(payload) %} department = {{kv['dp']}} {% end %}", test_mode=True)
2018
2040
  Traceback (most recent call last):
2019
2041
  ...
@@ -2023,22 +2045,26 @@ def render_sql_template(
2023
2045
  ...
2024
2046
  tinybird.sql_template.SQLTemplateException: Template Syntax Error: Error parsing JSON: '' - Expecting value: line 1 column 1 (char 0)
2025
2047
  >>> render_sql_template("% {% if defined(test) %}{% set _groupByCSV = ','.join(test) %} SELECT test as aa, {{Array(test, 'String')}} as test, {{_groupByCSV}} as a {% end %}", {"test": "1,2"})
2026
- ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
2048
+ ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {}, [])
2027
2049
  >>> render_sql_template("% {% if defined(test) %}{% set _groupByCSV = ','.join(test) %} SELECT test as aa, {{Array(test, 'String')}} as test, {{_groupByCSV}} as a {% end %}", {"test": ["1","2"]})
2028
- ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
2050
+ ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {}, [])
2029
2051
  >>> render_sql_template("% {% if defined(test) %}{% set _total = sum(test) %} SELECT test as aa, {{Array(test, 'Int32')}} as test, {{_total}} as a {% end %}", {"test": "1,2"})
2030
- ('% SELECT test as aa, [1,2] as test, 3 as a ', {})
2052
+ ('% SELECT test as aa, [1,2] as test, 3 as a ', {}, [])
2031
2053
  >>> render_sql_template("% {% if defined(test) %}{% set _groupByCSV = ','.join(test) %} SELECT test as aa, {{Array(test, 'String')}} as test, {{_groupByCSV}} as a {% end %}", {"test": ["1","2"]})
2032
- ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
2054
+ ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {}, [])
2033
2055
  >>> render_sql_template("% SELECT {% if defined(x) %} x, 1")
2034
2056
  Traceback (most recent call last):
2035
2057
  ...
2036
2058
  tinybird.tornado_template.UnClosedIfError: Missing {% end %} block for if at line 1
2059
+ >>> render_sql_template("select * from table where str = {{pipeline}}", { 'pipeline': 'test' })
2060
+ ("select * from table where str = 'test'", {}, ['pipeline'])
2037
2061
  """
2038
2062
  escape_split_to_array = ff_split_to_array_escape.get(False)
2039
2063
  bypass_preprocess_variables = ff_preprocess_parameters_circuit_breaker.get(False)
2040
2064
 
2041
- t, template_variables = get_template_and_variables(sql, name, escape_arrays=escape_split_to_array)
2065
+ t, template_variables, variable_warnings = get_template_and_variables(
2066
+ sql, name, escape_arrays=escape_split_to_array
2067
+ )
2042
2068
 
2043
2069
  if not bypass_preprocess_variables and variables is not None:
2044
2070
  processed_variables = preprocess_variables(variables, t)
@@ -2070,7 +2096,7 @@ def render_sql_template(
2070
2096
  v.update(type_fns)
2071
2097
 
2072
2098
  try:
2073
- return generate(t, **v)
2099
+ return *generate(t, **v), variable_warnings
2074
2100
  except NameError as e:
2075
2101
  raise SQLTemplateException(e, documentation="/cli/advanced-templates.html#defined")
2076
2102
  except SQLTemplateException:
@@ -539,6 +539,12 @@ async def print_pipe(ctx: Context, pipe: str, query: str, format_: str):
539
539
  help="When set, the checker will get Main Workspace requests",
540
540
  hidden=True,
541
541
  )
542
+ @click.option(
543
+ "--relative-change",
544
+ type=float,
545
+ default=0.01,
546
+ help="When set, the checker will validate the new version has less than this distance with the current version",
547
+ )
542
548
  @click.pass_context
543
549
  @coro
544
550
  async def regression_test(
@@ -556,6 +562,7 @@ async def regression_test(
556
562
  ignore_order: bool,
557
563
  validate_processed_bytes: bool,
558
564
  check_requests_from_main: bool,
565
+ relative_change: float,
559
566
  ):
560
567
  """
561
568
  Run regression tests on Tinybird
@@ -583,6 +590,7 @@ async def regression_test(
583
590
  no_versions=no_versions,
584
591
  run_tests=True,
585
592
  tests_to_run=limit,
593
+ tests_relative_change=relative_change,
586
594
  tests_sample_by_params=sample_by_params,
587
595
  tests_filter_by=match,
588
596
  tests_failfast=failfast,
@@ -892,7 +892,15 @@ def _parse(reader: _TemplateReader, template, in_block=None, in_loop=None):
892
892
  reader.consume(2)
893
893
  if not contents:
894
894
  reader.raise_parse_error("Empty expression")
895
- body.chunks.append(_Expression(contents, line))
895
+
896
+ try:
897
+ body.chunks.append(_Expression(contents, line))
898
+ except SyntaxError:
899
+ operator, _, _ = contents.partition(" ")
900
+
901
+ if "from" in operator:
902
+ reader.raise_parse_error('"from" is a forbidden word')
903
+ raise
896
904
  continue
897
905
 
898
906
  # Block
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 4.1.1.dev1
3
+ Version: 5.0.0.dev0
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,7 +18,18 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
- 4.1.1.dev0
21
+ 5.0.0.dev0
22
+ ************
23
+
24
+ - `Changed` Make `insertion_date`` column explicit. This column is no longer inferred, it must be present in the Data Source file.
25
+
26
+ 4.1.2.dev0
27
+ ************
28
+
29
+ - `Added` parameter to `tb pipe regression-test` --relative-change
30
+
31
+
32
+ 4.1.1
22
33
  ************
23
34
 
24
35
  - `Fixed` workspace info gathering when switching branches. We were prioritizing the general workspace properties over the user ones.
@@ -27,7 +38,7 @@ Changelog
27
38
  ************
28
39
 
29
40
  - `Added` `tb token create` command to be able to create static and JWT tokens from the CLI. You can check more information at https://www.tinybird.co/blog-posts/jwt-api-endpoints-public-beta
30
- - `Fixed` `tb init --git` to pin `tinybird-cli>=4,<5` in `requirements.txt` to avoid issues with the latest version of the CLI.
41
+ - `Fixed` `tb init --git` to pin `tinybird-cli>=4,<5` in `requirements.txt` to avoid issues with the latest version of the CLI.
31
42
 
32
43
  4.0.0
33
44
  ************
@@ -85,7 +96,7 @@ This is a major release, please read the commands affected below and consider up
85
96
  ************
86
97
 
87
98
  - `Changed` fixed major version of tinybird-cli to lower than 4 when using `tb init --git`
88
- - `Changed` behavior when running `tb deploy` on a branch to push the connection settings to the backend. This change is the backend that decides what to do.
99
+ - `Changed` behavior when running `tb deploy` on a branch to push the connection settings to the backend. This change is the backend that decides what to do.
89
100
  - `Changed` `tb pipe sink` commands are now available
90
101
  - `Fixed` regression tests query when filtering by specific parameter
91
102
  - `Fixed` Avoid `tb fmt` to error if there's a `CASE` in the sql