tinybird-cli 6.5.3.dev0__py3-none-any.whl → 6.5.4.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tinybird/__cli__.py CHANGED
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
4
4
  __url__ = 'https://www.tinybird.co/docs/cli'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '6.5.3.dev0'
8
- __revision__ = '78e5916'
7
+ __version__ = '6.5.4.dev0'
8
+ __revision__ = 'a87d7b3'
tinybird/client.py CHANGED
@@ -470,10 +470,26 @@ class TinyB:
470
470
  async def datasource_truncate(self, datasource_name: str):
471
471
  return await self._req(f"/v0/datasources/{datasource_name}/truncate", method="POST", data="")
472
472
 
473
- async def datasource_delete_rows(self, datasource_name: str, delete_condition: str, dry_run: bool = False):
474
- params = {"delete_condition": delete_condition}
473
+ async def datasource_delete_rows(
474
+ self,
475
+ datasource_name: str,
476
+ delete_condition: str,
477
+ dry_run: bool = False,
478
+ lightweight: bool = False,
479
+ wait: bool = True,
480
+ partition: Optional[str] = None,
481
+ projection_mode: Optional[str] = None,
482
+ ):
483
+ params: Dict[str, Any] = {"delete_condition": delete_condition}
484
+ if lightweight:
485
+ params["wait"] = "true" if wait else "false"
486
+ if partition:
487
+ params["partition"] = partition
488
+ if projection_mode:
489
+ params["projection_mode"] = projection_mode
490
+ return await self._req(f"/v1/datasources/{datasource_name}/delete", method="POST", data=params)
475
491
  if dry_run:
476
- params.update({"dry_run": "true"})
492
+ params["dry_run"] = "true"
477
493
  return await self._req(f"/v0/datasources/{datasource_name}/delete", method="POST", data=params)
478
494
 
479
495
  async def datasource_dependencies(
@@ -879,6 +879,11 @@ class FeedbackManager:
879
879
  success_delete_rows_datasource = success_message(
880
880
  "** Data Source '{datasource}' rows deleted matching condition \"{delete_condition}\""
881
881
  )
882
+ success_lightweight_delete_rows_datasource = success_message(
883
+ "** Data Source '{datasource}' rows deleted matching condition \"{delete_condition}\""
884
+ "\n Rows affected: {rows_affected}"
885
+ "\n Partitions scanned: {partitions_scanned} (done: {partitions_done}, in progress: {partitions_in_progress})"
886
+ )
882
887
  success_dry_run_delete_rows_datasource = success_message(
883
888
  "** [DRY RUN] Data Source '{datasource}' rows '{rows}' matching condition \"{delete_condition}\" to be deleted"
884
889
  )
tinybird/sql_toolset.py CHANGED
@@ -158,7 +158,7 @@ def has_unoptimized_join(sql: str, left_table: Optional[Union[Tuple[str, str], T
158
158
  raise UnoptimizedJoinException(sql)
159
159
 
160
160
 
161
- def format_where_for_mutation_command(where_clause: str) -> str:
161
+ def format_where_for_mutation_command(where_clause: str, lightweight: bool = False) -> str:
162
162
  """
163
163
  >>> format_where_for_mutation_command("numnights = 99")
164
164
  'DELETE WHERE numnights = 99'
@@ -170,11 +170,14 @@ def format_where_for_mutation_command(where_clause: str) -> str:
170
170
  "DELETE WHERE reservationid = \\\\'\\\\\\\\\\\\'foo\\\\'"
171
171
  >>> format_where_for_mutation_command("reservationid = '\\\\'foo'")
172
172
  "DELETE WHERE reservationid = \\\\'\\\\\\\\\\\\'foo\\\\'"
173
+ >>> format_where_for_mutation_command("number < 3", lightweight=True)
174
+ 'UPDATE _row_exists = 0 WHERE number < 3'
173
175
  """
174
176
  formatted_condition = chquery.format(f"""SELECT {where_clause}""").split("SELECT ")[1]
175
177
  formatted_condition = formatted_condition.replace("\\", "\\\\").replace("'", "''")
176
178
  quoted_condition = chquery.format(f"SELECT '{formatted_condition}'").split("SELECT ")[1]
177
- return f"DELETE WHERE {quoted_condition[1:-1]}"
179
+ prefix = "UPDATE _row_exists = 0 WHERE" if lightweight else "DELETE WHERE"
180
+ return f"{prefix} {quoted_condition[1:-1]}"
178
181
 
179
182
 
180
183
  # Functions that take table/dictionary names as string literal arguments.
@@ -363,23 +363,70 @@ async def datasource_truncate(ctx, datasource_name, yes, cascade):
363
363
  @click.argument("datasource_name")
364
364
  @click.option("--sql-condition", default=None, help="SQL WHERE condition to remove rows", hidden=True, required=True)
365
365
  @click.option("--yes", is_flag=True, default=False, help="Do not ask for confirmation")
366
- @click.option("--wait", is_flag=True, default=False, help="Wait for delete job to finish, disabled by default")
366
+ @click.option(
367
+ "--wait/--no-wait",
368
+ default=None,
369
+ help="Wait for the delete to finish. Defaults to true with --lightweight-delete (sync request), "
370
+ "false otherwise (returns a job id).",
371
+ )
367
372
  @click.option("--dry-run", is_flag=True, default=False, help="Run the command without deleting anything")
373
+ @click.option(
374
+ "--lightweight-delete",
375
+ "lightweight",
376
+ is_flag=True,
377
+ default=False,
378
+ help="Use ClickHouse lightweight DELETE. Defaults to waiting inline and returning rows_affected; "
379
+ "pass --no-wait to enqueue a job instead. Not compatible with --dry-run.",
380
+ )
381
+ @click.option(
382
+ "--partition",
383
+ default=None,
384
+ help="Restrict the lightweight delete to a single partition expression. Only valid with --lightweight-delete.",
385
+ )
386
+ @click.option(
387
+ "--projection-mode",
388
+ type=click.Choice(["throw", "drop", "rebuild"]),
389
+ default=None,
390
+ help="How ClickHouse should handle table projections when running the lightweight DELETE. "
391
+ "throw: fail the DELETE if the table has any projection defined (ClickHouse default). "
392
+ "drop: drop the affected projections so the DELETE can proceed; they will need to be recreated. "
393
+ "rebuild: rebuild the affected projections after the DELETE finishes. "
394
+ "Only valid with --lightweight-delete.",
395
+ )
368
396
  @click.pass_context
369
397
  @coro
370
- async def datasource_delete_rows(ctx, datasource_name, sql_condition, yes, wait, dry_run):
398
+ async def datasource_delete_rows(
399
+ ctx, datasource_name, sql_condition, yes, wait, dry_run, lightweight, partition, projection_mode
400
+ ):
371
401
  """
372
402
  Delete rows from a datasource
373
403
 
374
404
  - Delete rows with SQL condition: `tb datasource delete [datasource_name] --sql-condition "country='ES'"`
375
405
 
376
406
  - Delete rows with SQL condition and wait for the job to finish: `tb datasource delete [datasource_name] --sql-condition "country='ES'" --wait`
407
+
408
+ - Use ClickHouse lightweight DELETE (synchronous, no job): `tb datasource delete [datasource_name] --sql-condition "country='ES'" --lightweight-delete`
409
+
410
+ - Use ClickHouse lightweight DELETE and return immediately with a job id: `tb datasource delete [datasource_name] --sql-condition "country='ES'" --lightweight-delete --no-wait`
377
411
  """
378
412
 
379
413
  semver: str = ctx.ensure_object(dict)["config"]["semver"]
380
414
  await warn_if_in_live(semver)
381
415
 
382
416
  client: TinyB = ctx.ensure_object(dict)["client"]
417
+ if lightweight and dry_run:
418
+ raise CLIDatasourceException(
419
+ FeedbackManager.error_exception(error="--lightweight-delete is not compatible with --dry-run")
420
+ )
421
+ if (partition or projection_mode) and not lightweight:
422
+ raise CLIDatasourceException(
423
+ FeedbackManager.error_exception(error="--partition and --projection-mode require --lightweight-delete")
424
+ )
425
+ # Lightweight delete is sync by default (the endpoint blocks and returns
426
+ # rows_affected); the classic /v0/ delete is async by default (returns a
427
+ # job id). The tri-state --wait/--no-wait lets users override either.
428
+ if wait is None:
429
+ wait = lightweight
383
430
  if (
384
431
  dry_run
385
432
  or yes
@@ -390,7 +437,15 @@ async def datasource_delete_rows(ctx, datasource_name, sql_condition, yes, wait,
390
437
  )
391
438
  ):
392
439
  try:
393
- res = await client.datasource_delete_rows(datasource_name, sql_condition, dry_run)
440
+ res = await client.datasource_delete_rows(
441
+ datasource_name,
442
+ sql_condition,
443
+ dry_run,
444
+ lightweight=lightweight,
445
+ wait=wait,
446
+ partition=partition,
447
+ projection_mode=projection_mode,
448
+ )
394
449
  if dry_run:
395
450
  click.echo(
396
451
  FeedbackManager.success_dry_run_delete_rows_datasource(
@@ -398,10 +453,24 @@ async def datasource_delete_rows(ctx, datasource_name, sql_condition, yes, wait,
398
453
  )
399
454
  )
400
455
  return
456
+ # Lightweight sync path returns rows_affected directly, no job involved.
457
+ if lightweight and wait:
458
+ mutation = res.get("mutation") or {}
459
+ click.echo(
460
+ FeedbackManager.success_lightweight_delete_rows_datasource(
461
+ datasource=datasource_name,
462
+ delete_condition=sql_condition,
463
+ rows_affected=res.get("rows_affected", 0),
464
+ partitions_scanned=mutation.get("partitions_scanned", 0),
465
+ partitions_done=mutation.get("partitions_done", 0),
466
+ partitions_in_progress=mutation.get("partitions_in_progress", 0),
467
+ )
468
+ )
469
+ return
401
470
  job_id = res["job_id"]
402
471
  job_url = res["job_url"]
403
472
  click.echo(FeedbackManager.info_datasource_delete_rows_job_url(url=job_url))
404
- if wait:
473
+ if wait and not lightweight:
405
474
  progress_symbols = ["-", "\\", "|", "/"]
406
475
  progress_str = "Waiting for the job to finish"
407
476
  # TODO: Use click.echo instead of print and see if the behavior is the same
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird_cli
3
- Version: 6.5.3.dev0
3
+ Version: 6.5.4.dev0
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli
6
6
  Author: Tinybird
@@ -43,6 +43,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
43
43
  Changelog
44
44
  ----------
45
45
 
46
+ 6.5.3
47
+ ***********
48
+
49
+ - `Added` ``tb datasource delete`` now accepts ``--lightweight-delete``, ``--partition`` and ``--projection-mode``, backed by the ``POST /v1/datasources/{name}/delete`` endpoint that uses ClickHouse's lightweight ``DELETE FROM`` instead of the heavy ``ALTER TABLE ... DELETE`` mutation. Lightweight delete is synchronous by default and returns the affected row count plus a partition-level mutation block; pass ``--no-wait`` to enqueue a job and receive the v0-compatible envelope.
50
+
46
51
  6.5.1
47
52
  ***********
48
53
 
@@ -1,16 +1,16 @@
1
- tinybird/__cli__.py,sha256=LPmuAgokLbFvufBGm125_2-R8lK3ZGoEclRW298xcNg,236
1
+ tinybird/__cli__.py,sha256=Wf0VS-wmsRJS_MkAzra29SE6k7aD2D1mjYB3EoflQZ0,236
2
2
  tinybird/check_pypi.py,sha256=_4NkharLyR_ELrAdit-ftqIWvOf7jZNPt3i76frlo9g,975
3
- tinybird/client.py,sha256=ZgwGrip9cuF5DJiS1vFbEpXvEOC7UqAaaxZnqRwG4Fo,51808
3
+ tinybird/client.py,sha256=Tql8VEj9OJIRN7znUsEGkJ5XSwLMR2lKk5GpxTqgL14,52360
4
4
  tinybird/config.py,sha256=g74rE9jbVcyFj1bms5T3VEITLr21_WFy79Uj5ovvj90,7413
5
5
  tinybird/context.py,sha256=o4yvlXPkMLmdh-XJl3wpmqPAMeRRz5ScKzKlHHKn_I8,1201
6
6
  tinybird/datafile_common.py,sha256=MyMobDF6UOFFEsXnHrUWuOb0kJ6tkzZpiq1CjL7RlKY,237598
7
7
  tinybird/datatypes.py,sha256=Lr8BIaRP--qzuZFpAdv20uQaeE1BOAMmuEwWVHheFPw,11355
8
- tinybird/feedback_manager.py,sha256=OehfKVruCHwUNN1bHIbDICvOaIovc3hb6RjGHTyIkBc,67667
8
+ tinybird/feedback_manager.py,sha256=ZnRsExCkEZKuslmSxn3m706-0UIZ_qOpdek9ar16KOI,68001
9
9
  tinybird/git_settings.py,sha256=mqWgeboOlOFsSo97qyv595UCR2R1QCAqT4GTawBNPBg,3935
10
10
  tinybird/sql.py,sha256=qdqxsq1WPiGTk-SmZWaxvZb936ISdo1ChZhnC_uXeUE,49351
11
11
  tinybird/sql_template.py,sha256=nSzUdaQe18Da_8qlgLW7tsZl1pOa2kDaBa8TdrF6pJ4,128667
12
12
  tinybird/sql_template_fmt.py,sha256=Ma4qcs-2r8ZXQC4GUmrCqYz34DsnGF8k5lE2Jwnr314,10638
13
- tinybird/sql_toolset.py,sha256=xWY-EtixaZKUPuNY4WBz2fDwwNnmbgtdLsmI2wy67UA,27220
13
+ tinybird/sql_toolset.py,sha256=TvWeH3DsB13SfJ97V_t_ZaFTJ1IAtsrxQ8E3FLL8_tE,27442
14
14
  tinybird/syncasync.py,sha256=rIPmCvygWSFqfnlVqhZH4N9gVVTvD6DEPsfoxGizYrI,27776
15
15
  tinybird/tb_cli.py,sha256=q1LGAsBVVMJsjR2HK62Pu6vpVtLzNmH8wHrEVUUdVkU,744
16
16
  tinybird/tornado_template.py,sha256=1_0nYFk_xJh_TMHh6AKkJILvnNY6xYmaM-uJ3Ofv7e8,42085
@@ -23,7 +23,7 @@ tinybird/tb_cli_modules/cli.py,sha256=KvgZfdYRvgKG5QAiFmlfLbVGI-xmuxbs-EdkAslqrE
23
23
  tinybird/tb_cli_modules/common.py,sha256=763GkBOgXIcB48UnuSjnGfxdfoSx5iqCniK15R0Aq5Y,77366
24
24
  tinybird/tb_cli_modules/config.py,sha256=0kFDmsDcjKon32rgFGMHHKSbv4j5dOrXtVOlyuAyEkk,11510
25
25
  tinybird/tb_cli_modules/connection.py,sha256=JO2v2xTGoiMeThzCncvxMFUHLghyyGXNF0FcAvi5ZOk,24543
26
- tinybird/tb_cli_modules/datasource.py,sha256=b12ClLFISGHqK7zrLZBX5OT-8Nxd2oW734-Xon0dTE8,32541
26
+ tinybird/tb_cli_modules/datasource.py,sha256=9j4cw02k8txabdUoRHap-oPwECbbBnzugsFIf6o_ljY,35688
27
27
  tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
28
28
  tinybird/tb_cli_modules/fmt.py,sha256=edQap4tAqWMWogSIx5zriT75naLi73XTB3NwatmcrFw,3518
29
29
  tinybird/tb_cli_modules/job.py,sha256=BxiqChDYa_4W4tFXHIUz2bOzkx8WMFywynjiPWgDlnE,2936
@@ -36,8 +36,8 @@ tinybird/tb_cli_modules/token.py,sha256=JXATKTlbXohP9ZDZjlz8E4VYG6zrknKZhuz_wh1z
36
36
  tinybird/tb_cli_modules/workspace.py,sha256=Ssu-jKk7lp4Gh3qX5DXhIbImyhs9aCvL09u_T75zw1I,12421
37
37
  tinybird/tb_cli_modules/workspace_members.py,sha256=ksXsjd233y9-sNlz4Qb-meZbX4zn1B84e_bSm2i8rhg,8731
38
38
  tinybird/tb_cli_modules/tinyunit/tinyunit.py,sha256=50uqMgJD2BqSVONtCm55nuGRWhBNZWRc2GP1Qb8URdg,11246
39
- tinybird_cli-6.5.3.dev0.dist-info/METADATA,sha256=2d95ALNGay1rEmgOesllyu-kiWnf6JGleP8yRWnqytY,82319
40
- tinybird_cli-6.5.3.dev0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
41
- tinybird_cli-6.5.3.dev0.dist-info/entry_points.txt,sha256=PKPKuPmA4IfJYnCFHHUiw-aAWZuBomFvwCklv1OyCjE,43
42
- tinybird_cli-6.5.3.dev0.dist-info/top_level.txt,sha256=ZIQJTPCzMqnfDzM_hEGZrJqDSEcKnIK_49T86DGWpyQ,78
43
- tinybird_cli-6.5.3.dev0.dist-info/RECORD,,
39
+ tinybird_cli-6.5.4.dev0.dist-info/METADATA,sha256=iftt91TP5EZwKaP-bhiMd6WA-k9WZrPSLvyqfDMUE78,82821
40
+ tinybird_cli-6.5.4.dev0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
41
+ tinybird_cli-6.5.4.dev0.dist-info/entry_points.txt,sha256=PKPKuPmA4IfJYnCFHHUiw-aAWZuBomFvwCklv1OyCjE,43
42
+ tinybird_cli-6.5.4.dev0.dist-info/top_level.txt,sha256=ZIQJTPCzMqnfDzM_hEGZrJqDSEcKnIK_49T86DGWpyQ,78
43
+ tinybird_cli-6.5.4.dev0.dist-info/RECORD,,