7171from sqlmesh .core .plan import Plan
7272from sqlmesh .core .scheduler import Scheduler
7373from sqlmesh .core .schema_loader import create_schema_file
74+ from sqlmesh .core .selector import Selector
7475from sqlmesh .core .snapshot import (
7576 Snapshot ,
7677 SnapshotEvaluator ,
@@ -545,58 +546,7 @@ def snapshots(self) -> t.Dict[str, Snapshot]:
545546 If one of the snapshots has been previosly stored in the persisted state, the stored
546547 instance will be returned.
547548 """
548- prod = self .state_reader .get_environment (c .PROD )
549- remote_snapshots = (
550- {
551- snapshot .name : snapshot
552- for snapshot in self .state_reader .get_snapshots (prod .snapshots ).values ()
553- }
554- if prod
555- else {}
556- )
557-
558- fingerprint_cache : t .Dict [str , SnapshotFingerprint ] = {}
559- models = self ._models .copy ()
560- audits = self ._audits .copy ()
561- projects = {config .project for config in self .configs .values ()}
562-
563- for name , snapshot in remote_snapshots .items ():
564- if name not in models and snapshot .project not in projects :
565- models [name ] = snapshot .model
566-
567- for audit in snapshot .audits :
568- if name not in audits :
569- audits [name ] = audit
570-
571- snapshots = {}
572-
573- for model in models .values ():
574- if model .name not in self ._models and model .name in remote_snapshots :
575- snapshot = remote_snapshots [model .name ]
576- ttl = snapshot .ttl
577- project = snapshot .project
578- else :
579- config = self .config_for_model (model )
580- ttl = config .snapshot_ttl
581- project = config .project
582-
583- snapshot = Snapshot .from_model (
584- model ,
585- nodes = models ,
586- audits = audits ,
587- cache = fingerprint_cache ,
588- ttl = ttl ,
589- project = project ,
590- )
591- snapshots [model .name ] = snapshot
592-
593- stored_snapshots = self .state_reader .get_snapshots (snapshots .values ())
594-
595- for snapshot in stored_snapshots .values ():
596- # Keep the original model instance to preserve the query cache.
597- snapshot .node = snapshots [snapshot .name ].node
598-
599- return {name : stored_snapshots .get (s .snapshot_id , s ) for name , s in snapshots .items ()}
549+ return self ._snapshots ()
600550
601551 def render (
602552 self ,
@@ -728,6 +678,7 @@ def plan(
728678 no_auto_categorization : t .Optional [bool ] = None ,
729679 effective_from : t .Optional [TimeLike ] = None ,
730680 include_unmodified : t .Optional [bool ] = None ,
681+ select_models : t .Optional [t .Collection [str ]] = None ,
731682 ) -> Plan :
732683 """Interactively create a migration plan.
733684
@@ -762,6 +713,7 @@ def plan(
762713 option determines the behavior.
763714 effective_from: The effective date from which to apply forward-only changes on production.
764715 include_unmodified: Indicates whether to include unmodified models in the target development environment.
716+ model_selections: A list of model selection strings to filter the models that should be included into this plan.
765717
766718 Returns:
767719 The populated Plan object.
@@ -783,8 +735,18 @@ def plan(
783735 if include_unmodified is None :
784736 include_unmodified = self .config .include_unmodified
785737
738+ models_override : t .Optional [UniqueKeyDict [str , Model ]] = None
739+ if select_models :
740+ models_override = Selector (self .state_reader , self ._models , self .path ).select_models (
741+ select_models , environment , fallback_env_name = create_from or c .PROD
742+ )
743+
786744 plan = Plan (
787- context_diff = self ._context_diff (environment or c .PROD , create_from = create_from ),
745+ context_diff = self ._context_diff (
746+ environment or c .PROD ,
747+ snapshots = self ._snapshots (models_override ),
748+ create_from = create_from ,
749+ ),
788750 start = start ,
789751 end = end ,
790752 execution_time = execution_time ,
@@ -1178,6 +1140,62 @@ def _model_tables(self) -> t.Dict[str, str]:
11781140 for name , snapshot in self .snapshots .items ()
11791141 }
11801142
1143+ def _snapshots (
1144+ self , models_override : t .Optional [UniqueKeyDict [str , Model ]] = None
1145+ ) -> t .Dict [str , Snapshot ]:
1146+ prod = self .state_reader .get_environment (c .PROD )
1147+ remote_snapshots = (
1148+ {
1149+ snapshot .name : snapshot
1150+ for snapshot in self .state_reader .get_snapshots (prod .snapshots ).values ()
1151+ }
1152+ if prod
1153+ else {}
1154+ )
1155+
1156+ fingerprint_cache : t .Dict [str , SnapshotFingerprint ] = {}
1157+ models = (models_override or self ._models ).copy ()
1158+ audits = self ._audits .copy ()
1159+ projects = {config .project for config in self .configs .values ()}
1160+
1161+ for name , snapshot in remote_snapshots .items ():
1162+ if name not in models and snapshot .project not in projects :
1163+ models [name ] = snapshot .model
1164+
1165+ for audit in snapshot .audits :
1166+ if name not in audits :
1167+ audits [name ] = audit
1168+
1169+ snapshots = {}
1170+
1171+ for model in models .values ():
1172+ if model .name not in self ._models and model .name in remote_snapshots :
1173+ snapshot = remote_snapshots [model .name ]
1174+ ttl = snapshot .ttl
1175+ project = snapshot .project
1176+ else :
1177+ config = self .config_for_model (model )
1178+ ttl = config .snapshot_ttl
1179+ project = config .project
1180+
1181+ snapshot = Snapshot .from_model (
1182+ model ,
1183+ nodes = models ,
1184+ audits = audits ,
1185+ cache = fingerprint_cache ,
1186+ ttl = ttl ,
1187+ project = project ,
1188+ )
1189+ snapshots [model .name ] = snapshot
1190+
1191+ stored_snapshots = self .state_reader .get_snapshots (snapshots .values ())
1192+
1193+ for snapshot in stored_snapshots .values ():
1194+ # Keep the original model instance to preserve the query cache.
1195+ snapshot .node = snapshots [snapshot .name ].node
1196+
1197+ return {name : stored_snapshots .get (s .snapshot_id , s ) for name , s in snapshots .items ()}
1198+
11811199 def _context_diff (
11821200 self ,
11831201 environment : str ,
0 commit comments