55from rich .console import Console as RichConsole
66from rich .tree import Tree
77from sqlglot .dialects .dialect import DialectType
8+ from sqlmesh .core import constants as c
89from sqlmesh .core .console import Console , TerminalConsole , get_console
910from sqlmesh .core .environment import EnvironmentNamingInfo
1011from sqlmesh .core .plan .definition import EvaluatablePlan , SnapshotIntervals
@@ -51,7 +52,7 @@ def evaluate(
5152 }
5253
5354 deployability_index = DeployabilityIndex .create (snapshots , start = plan .start )
54- deployability_index_for_migration = deployability_index
55+ deployability_index_for_creation = deployability_index
5556 if plan .is_dev :
5657 before_promote_snapshots = all_selected_for_backfill_snapshots
5758 after_promote_snapshots = set ()
@@ -71,7 +72,7 @@ def evaluate(
7172 for s in snapshots .values ()
7273 if s .is_paused
7374 and s .is_materialized
74- and not deployability_index_for_migration .is_representative (s )
75+ and not deployability_index_for_creation .is_representative (s )
7576 ]
7677
7778 snapshots_to_intervals = self ._missing_intervals (
@@ -97,7 +98,7 @@ def evaluate(
9798 steps .append (
9899 PhysicalLayerUpdateStep (
99100 snapshots = snapshots_to_create ,
100- deployability_index = deployability_index ,
101+ deployability_index = deployability_index_for_creation ,
101102 )
102103 )
103104
@@ -126,6 +127,8 @@ def evaluate(
126127 )
127128 )
128129
130+ steps .append (UpdateEnvironmentRecordStep ())
131+
129132 if snapshots_with_schema_migration :
130133 steps .append (MigrateSchemasStep (snapshots = snapshots_with_schema_migration ))
131134
@@ -255,6 +258,11 @@ class UpdateVirtualLayerStep:
255258 deployability_index : DeployabilityIndex
256259
257260
261+ @dataclass
262+ class UpdateEnvironmentRecordStep :
263+ pass
264+
265+
258266PlanStep = t .Union [
259267 BeforeAllStep ,
260268 AfterAllStep ,
@@ -264,6 +272,7 @@ class UpdateVirtualLayerStep:
264272 BackfillStep ,
265273 MigrateSchemasStep ,
266274 UpdateVirtualLayerStep ,
275+ UpdateEnvironmentRecordStep ,
267276]
268277
269278
@@ -298,7 +307,9 @@ def explain(self, steps: t.List[PlanStep]) -> None:
298307 if not hasattr (self , handler_name ):
299308 raise SQLMeshError (f"Unexpected step: { step .__class__ .__name__ } " )
300309 handler = getattr (self , handler_name )
301- tree .add (self ._limit_tree (handler (step )))
310+ result = handler (step )
311+ if result :
312+ tree .add (self ._limit_tree (result ))
302313 self .console .print (tree )
303314
304315 def visit_before_all_step (self , step : BeforeAllStep ) -> Tree :
@@ -316,7 +327,11 @@ def visit_after_all_step(self, step: AfterAllStep) -> Tree:
316327 def visit_physical_layer_update_step (self , step : PhysicalLayerUpdateStep ) -> Tree :
317328 tree = Tree ("[bold]Validate SQL and create physical tables if they do not exist[/bold]" )
318329 for snapshot in step .snapshots :
319- is_deployable = step .deployability_index .is_deployable (snapshot )
330+ is_deployable = (
331+ step .deployability_index .is_deployable (snapshot )
332+ if self .environment_naming_info .name != c .PROD
333+ else True
334+ )
320335 display_name = self ._display_name (snapshot )
321336 table_name = snapshot .table_name (is_deployable )
322337 model_tree = Tree (f"{ display_name } -> { table_name } " )
@@ -328,14 +343,18 @@ def visit_physical_layer_update_step(self, step: PhysicalLayerUpdateStep) -> Tre
328343 model_tree .add ("Dry run model query without inserting results" )
329344
330345 if snapshot .is_view :
331- model_tree . add ( f "Create view [underline] { table_name } [/underline] if doesn't exist" )
346+ create_tree = Tree ( "Create view if it doesn't exist" )
332347 elif snapshot .is_forward_only and snapshot .previous_versions :
333348 prod_table = snapshot .table_name (True )
334- model_tree . add (
335- f"Clone [underline] { prod_table } [/underline] into [underline] { table_name } [/underline] and then update its schema if it doesn't exist"
349+ create_tree = Tree (
350+ f"Clone { prod_table } into { table_name } and then update its schema if it doesn't exist"
336351 )
337352 else :
338- model_tree .add (f"Create table [underline]{ table_name } [/underline] if doesn't exist" )
353+ create_tree = Tree ("Create table if it doesn't exist" )
354+
355+ if not is_deployable :
356+ create_tree .add ("[orange1]preview[/orange1]: data will NOT be reused in production" )
357+ model_tree .add (create_tree )
339358
340359 if snapshot .is_model and snapshot .model .post_statements :
341360 model_tree .add ("Run post-statements" )
@@ -378,12 +397,12 @@ def visit_backfill_step(self, step: BackfillStep) -> Tree:
378397 snapshot_id = snapshot .snapshot_id , intervals = intervals
379398 ).format_intervals (snapshot .node .interval_unit )
380399 model_tree .add (
381- f"Incrementally insert records within the range [{ formatted_range } ] into [underline] { table_name } [/underline] "
400+ f"Incrementally insert records within the range [{ formatted_range } ]"
382401 )
383402 elif snapshot .is_view :
384- model_tree .add (f "Recreate view [underline] { table_name } [/underline] " )
403+ model_tree .add ("Recreate view" )
385404 else :
386- model_tree .add (f "Fully refresh table [underline] { table_name } [/underline] " )
405+ model_tree .add ("Fully refresh table" )
387406
388407 if snapshot .model .post_statements :
389408 model_tree .add ("Run post-statements" )
@@ -399,7 +418,7 @@ def visit_backfill_step(self, step: BackfillStep) -> Tree:
399418
400419 def visit_migrate_schemas_step (self , step : MigrateSchemasStep ) -> Tree :
401420 tree = Tree (
402- "[bold]Update schemas of production physical tables to reflect forward-only changes[/bold]"
421+ "[bold]Update schemas (add, drop, alter columns) of production physical tables to reflect forward-only changes[/bold]"
403422 )
404423 for snapshot in step .snapshots :
405424 display_name = self ._display_name (snapshot )
@@ -432,6 +451,11 @@ def visit_update_virtual_layer_step(self, step: UpdateVirtualLayerStep) -> Tree:
432451 tree .add (self ._limit_tree (demote_tree ))
433452 return tree
434453
454+ def visit_update_environment_record_step (
455+ self , step : UpdateEnvironmentRecordStep
456+ ) -> t .Optional [Tree ]:
457+ return None
458+
435459 def _display_name (self , snapshot : SnapshotInfoMixin ) -> str :
436460 return snapshot .display_name (
437461 self .environment_naming_info ,
0 commit comments