@@ -873,6 +873,7 @@ def create_snapshot(
873873 deployability_index = deployability_index ,
874874 create_render_kwargs = create_render_kwargs ,
875875 rendered_physical_properties = rendered_physical_properties ,
876+ skip_grants = True ,
876877 dry_run = True ,
877878 )
878879
@@ -1411,12 +1412,12 @@ def _execute_create(
14111412 table_name = table_name ,
14121413 model = snapshot .model ,
14131414 is_table_deployable = is_table_deployable ,
1415+ skip_grants = skip_grants ,
14141416 render_kwargs = create_render_kwargs ,
14151417 is_snapshot_deployable = is_snapshot_deployable ,
14161418 is_snapshot_representative = is_snapshot_representative ,
14171419 dry_run = dry_run ,
14181420 physical_properties = rendered_physical_properties ,
1419- skip_grants = skip_grants ,
14201421 )
14211422 if run_pre_post_statements :
14221423 adapter .execute (snapshot .model .render_post_statements (** create_render_kwargs ))
@@ -1580,6 +1581,7 @@ def create(
15801581 model : Model ,
15811582 is_table_deployable : bool ,
15821583 render_kwargs : t .Dict [str , t .Any ],
1584+ skip_grants : bool ,
15831585 ** kwargs : t .Any ,
15841586 ) -> None :
15851587 """Creates the target table or view.
@@ -1723,6 +1725,7 @@ def create(
17231725 model : Model ,
17241726 is_table_deployable : bool ,
17251727 render_kwargs : t .Dict [str , t .Any ],
1728+ skip_grants : bool ,
17261729 ** kwargs : t .Any ,
17271730 ) -> None :
17281731 pass
@@ -1798,10 +1801,10 @@ def promote(
17981801 view_properties = model .render_virtual_properties (** render_kwargs ),
17991802 )
18001803
1801- # Apply grants to the physical layer table
1804+ # Apply grants to the physical layer (referenced table / view) after promotion
18021805 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18031806
1804- # Apply grants to the virtual layer view
1807+ # Apply grants to the virtual layer ( view) after promotion
18051808 self ._apply_grants (model , view_name , GrantsTargetLayer .VIRTUAL )
18061809
18071810 def demote (self , view_name : str , ** kwargs : t .Any ) -> None :
@@ -1816,6 +1819,7 @@ def create(
18161819 model : Model ,
18171820 is_table_deployable : bool ,
18181821 render_kwargs : t .Dict [str , t .Any ],
1822+ skip_grants : bool ,
18191823 ** kwargs : t .Any ,
18201824 ) -> None :
18211825 ctas_query = model .ctas_query (** render_kwargs )
@@ -1861,7 +1865,7 @@ def create(
18611865 )
18621866
18631867 # Apply grants after table creation (unless explicitly skipped by caller)
1864- if not kwargs . get ( " skip_grants" , False ) :
1868+ if not skip_grants :
18651869 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18661870
18671871 def migrate (
@@ -1903,6 +1907,7 @@ def _replace_query_for_model(
19031907 name : str ,
19041908 query_or_df : QueryOrDF ,
19051909 render_kwargs : t .Dict [str , t .Any ],
1910+ skip_grants : bool = False ,
19061911 ** kwargs : t .Any ,
19071912 ) -> None :
19081913 """Replaces the table for the given model.
@@ -1940,7 +1945,7 @@ def _replace_query_for_model(
19401945 )
19411946
19421947 # Apply grants after table replacement (unless explicitly skipped by caller)
1943- if not kwargs . get ( " skip_grants" , False ) :
1948+ if not skip_grants :
19441949 self ._apply_grants (model , name , GrantsTargetLayer .PHYSICAL )
19451950
19461951 def _get_target_and_source_columns (
@@ -2190,6 +2195,7 @@ def create(
21902195 model : Model ,
21912196 is_table_deployable : bool ,
21922197 render_kwargs : t .Dict [str , t .Any ],
2198+ skip_grants : bool ,
21932199 ** kwargs : t .Any ,
21942200 ) -> None :
21952201 model = t .cast (SeedModel , model )
@@ -2203,29 +2209,38 @@ def create(
22032209 )
22042210 return
22052211
2206- # Skip grants in parent create call since we'll apply them after data insertion
2207- kwargs_no_grants = {** kwargs }
2208- kwargs_no_grants ["skip_grants" ] = True
2209-
2210- super ().create (table_name , model , is_table_deployable , render_kwargs , ** kwargs_no_grants )
2212+ super ().create (
2213+ table_name ,
2214+ model ,
2215+ is_table_deployable ,
2216+ render_kwargs ,
2217+ skip_grants = True , # Skip grants; they're applied after data insertion
2218+ ** kwargs ,
2219+ )
22112220 # For seeds we insert data at the time of table creation.
22122221 try :
22132222 for index , df in enumerate (model .render_seed ()):
22142223 if index == 0 :
22152224 self ._replace_query_for_model (
2216- model , table_name , df , render_kwargs , ** kwargs_no_grants
2225+ model ,
2226+ table_name ,
2227+ df ,
2228+ render_kwargs ,
2229+ skip_grants = True , # Skip grants; they're applied after data insertion
2230+ ** kwargs ,
22172231 )
22182232 else :
22192233 self .adapter .insert_append (
22202234 table_name , df , target_columns_to_types = model .columns_to_types
22212235 )
2236+
2237+ if not skip_grants :
2238+ # Apply grants after seed table creation and data insertion
2239+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
22222240 except Exception :
22232241 self .adapter .drop_table (table_name )
22242242 raise
22252243
2226- # Apply grants after seed table creation or data insertion
2227- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2228-
22292244 def insert (
22302245 self ,
22312246 table_name : str ,
@@ -2257,6 +2272,7 @@ def create(
22572272 model : Model ,
22582273 is_table_deployable : bool ,
22592274 render_kwargs : t .Dict [str , t .Any ],
2275+ skip_grants : bool ,
22602276 ** kwargs : t .Any ,
22612277 ) -> None :
22622278 assert isinstance (model .kind , (SCDType2ByTimeKind , SCDType2ByColumnKind ))
@@ -2286,11 +2302,13 @@ def create(
22862302 model ,
22872303 is_table_deployable ,
22882304 render_kwargs ,
2305+ skip_grants ,
22892306 ** kwargs ,
22902307 )
22912308
2292- # Apply grants after SCD Type 2 table creation
2293- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2309+ if not skip_grants :
2310+ # Apply grants after SCD Type 2 table creation
2311+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
22942312
22952313 def insert (
22962314 self ,
@@ -2434,14 +2452,17 @@ def create(
24342452 model : Model ,
24352453 is_table_deployable : bool ,
24362454 render_kwargs : t .Dict [str , t .Any ],
2455+ skip_grants : bool ,
24372456 ** kwargs : t .Any ,
24382457 ) -> None :
24392458 if self .adapter .table_exists (table_name ):
24402459 # Make sure we don't recreate the view to prevent deletion of downstream views in engines with no late
24412460 # binding support (because of DROP CASCADE).
24422461 logger .info ("View '%s' already exists" , table_name )
2443- # Always apply grants when present, even if view exists, to handle grants updates
2444- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2462+
2463+ if not skip_grants :
2464+ # Always apply grants when present, even if view exists, to handle grants updates
2465+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24452466 return
24462467
24472468 logger .info ("Creating view '%s'" , table_name )
@@ -2465,8 +2486,9 @@ def create(
24652486 column_descriptions = model .column_descriptions if is_table_deployable else None ,
24662487 )
24672488
2468- # Apply grants after view creation
2469- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2489+ if not skip_grants :
2490+ # Apply grants after view creation
2491+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24702492
24712493 def migrate (
24722494 self ,
@@ -2643,6 +2665,7 @@ def create(
26432665 model : Model ,
26442666 is_table_deployable : bool ,
26452667 render_kwargs : t .Dict [str , t .Any ],
2668+ skip_grants : bool ,
26462669 ** kwargs : t .Any ,
26472670 ) -> None :
26482671 is_snapshot_deployable : bool = kwargs ["is_snapshot_deployable" ]
@@ -2663,24 +2686,21 @@ def create(
26632686 )
26642687
26652688 # Apply grants after managed table creation
2666- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2689+ if not skip_grants :
2690+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
26672691
26682692 elif not is_table_deployable :
26692693 # Only create the dev preview table as a normal table.
26702694 # For the main table, if the snapshot is cant be deployed to prod (eg upstream is forward-only) do nothing.
26712695 # Any downstream models that reference it will be updated to point to the dev preview table.
26722696 # If the user eventually tries to deploy it, the logic in insert() will see it doesnt exist and create it
2673-
2674- # Create preview table but don't apply grants here since the table is not deployable
2675- # Grants will be applied later when the table becomes deployable
2676- kwargs_no_grants = {** kwargs }
2677- kwargs_no_grants ["skip_grants" ] = True
26782697 super ().create (
26792698 table_name = table_name ,
26802699 model = model ,
26812700 is_table_deployable = is_table_deployable ,
26822701 render_kwargs = render_kwargs ,
2683- ** kwargs_no_grants ,
2702+ skip_grants = skip_grants ,
2703+ ** kwargs ,
26842704 )
26852705
26862706 def insert (
@@ -2707,6 +2727,7 @@ def insert(
27072727 column_descriptions = model .column_descriptions ,
27082728 table_format = model .table_format ,
27092729 )
2730+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
27102731 elif not is_snapshot_deployable :
27112732 # Snapshot isnt deployable; update the preview table instead
27122733 # If the snapshot was deployable, then data would have already been loaded in create() because a managed table would have been created
@@ -2756,7 +2777,7 @@ def migrate(
27562777 )
27572778
27582779 # Apply grants after verifying no schema changes
2759- # This ensures metadata-only changes ( grants) are applied
2780+ # This ensures metadata-only grants changes are applied
27602781 self ._apply_grants (snapshot .model , target_table_name , GrantsTargetLayer .PHYSICAL )
27612782
27622783 def delete (self , name : str , ** kwargs : t .Any ) -> None :
0 commit comments