@@ -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
@@ -1408,12 +1409,12 @@ def _execute_create(
14081409 table_name = table_name ,
14091410 model = snapshot .model ,
14101411 is_table_deployable = is_table_deployable ,
1412+ skip_grants = skip_grants ,
14111413 render_kwargs = create_render_kwargs ,
14121414 is_snapshot_deployable = is_snapshot_deployable ,
14131415 is_snapshot_representative = is_snapshot_representative ,
14141416 dry_run = dry_run ,
14151417 physical_properties = rendered_physical_properties ,
1416- skip_grants = skip_grants ,
14171418 )
14181419 if run_pre_post_statements :
14191420 adapter .execute (snapshot .model .render_post_statements (** create_render_kwargs ))
@@ -1577,6 +1578,7 @@ def create(
15771578 model : Model ,
15781579 is_table_deployable : bool ,
15791580 render_kwargs : t .Dict [str , t .Any ],
1581+ skip_grants : bool ,
15801582 ** kwargs : t .Any ,
15811583 ) -> None :
15821584 """Creates the target table or view.
@@ -1720,6 +1722,7 @@ def create(
17201722 model : Model ,
17211723 is_table_deployable : bool ,
17221724 render_kwargs : t .Dict [str , t .Any ],
1725+ skip_grants : bool ,
17231726 ** kwargs : t .Any ,
17241727 ) -> None :
17251728 pass
@@ -1795,10 +1798,10 @@ def promote(
17951798 view_properties = model .render_virtual_properties (** render_kwargs ),
17961799 )
17971800
1798- # Apply grants to the physical layer table
1801+ # Apply grants to the physical layer (referenced table / view) after promotion
17991802 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18001803
1801- # Apply grants to the virtual layer view
1804+ # Apply grants to the virtual layer ( view) after promotion
18021805 self ._apply_grants (model , view_name , GrantsTargetLayer .VIRTUAL )
18031806
18041807 def demote (self , view_name : str , ** kwargs : t .Any ) -> None :
@@ -1813,6 +1816,7 @@ def create(
18131816 model : Model ,
18141817 is_table_deployable : bool ,
18151818 render_kwargs : t .Dict [str , t .Any ],
1819+ skip_grants : bool ,
18161820 ** kwargs : t .Any ,
18171821 ) -> None :
18181822 ctas_query = model .ctas_query (** render_kwargs )
@@ -1858,7 +1862,7 @@ def create(
18581862 )
18591863
18601864 # Apply grants after table creation (unless explicitly skipped by caller)
1861- if not kwargs . get ( " skip_grants" , False ) :
1865+ if not skip_grants :
18621866 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18631867
18641868 def migrate (
@@ -1900,6 +1904,7 @@ def _replace_query_for_model(
19001904 name : str ,
19011905 query_or_df : QueryOrDF ,
19021906 render_kwargs : t .Dict [str , t .Any ],
1907+ skip_grants : bool = False ,
19031908 ** kwargs : t .Any ,
19041909 ) -> None :
19051910 """Replaces the table for the given model.
@@ -1937,7 +1942,7 @@ def _replace_query_for_model(
19371942 )
19381943
19391944 # Apply grants after table replacement (unless explicitly skipped by caller)
1940- if not kwargs . get ( " skip_grants" , False ) :
1945+ if not skip_grants :
19411946 self ._apply_grants (model , name , GrantsTargetLayer .PHYSICAL )
19421947
19431948 def _get_target_and_source_columns (
@@ -2187,6 +2192,7 @@ def create(
21872192 model : Model ,
21882193 is_table_deployable : bool ,
21892194 render_kwargs : t .Dict [str , t .Any ],
2195+ skip_grants : bool ,
21902196 ** kwargs : t .Any ,
21912197 ) -> None :
21922198 model = t .cast (SeedModel , model )
@@ -2200,29 +2206,38 @@ def create(
22002206 )
22012207 return
22022208
2203- # Skip grants in parent create call since we'll apply them after data insertion
2204- kwargs_no_grants = {** kwargs }
2205- kwargs_no_grants ["skip_grants" ] = True
2206-
2207- super ().create (table_name , model , is_table_deployable , render_kwargs , ** kwargs_no_grants )
2209+ super ().create (
2210+ table_name ,
2211+ model ,
2212+ is_table_deployable ,
2213+ render_kwargs ,
2214+ skip_grants = True , # Skip grants; they're applied after data insertion
2215+ ** kwargs ,
2216+ )
22082217 # For seeds we insert data at the time of table creation.
22092218 try :
22102219 for index , df in enumerate (model .render_seed ()):
22112220 if index == 0 :
22122221 self ._replace_query_for_model (
2213- model , table_name , df , render_kwargs , ** kwargs_no_grants
2222+ model ,
2223+ table_name ,
2224+ df ,
2225+ render_kwargs ,
2226+ skip_grants = True , # Skip grants; they're applied after data insertion
2227+ ** kwargs ,
22142228 )
22152229 else :
22162230 self .adapter .insert_append (
22172231 table_name , df , target_columns_to_types = model .columns_to_types
22182232 )
2233+
2234+ if not skip_grants :
2235+ # Apply grants after seed table creation and data insertion
2236+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
22192237 except Exception :
22202238 self .adapter .drop_table (table_name )
22212239 raise
22222240
2223- # Apply grants after seed table creation or data insertion
2224- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2225-
22262241 def insert (
22272242 self ,
22282243 table_name : str ,
@@ -2254,6 +2269,7 @@ def create(
22542269 model : Model ,
22552270 is_table_deployable : bool ,
22562271 render_kwargs : t .Dict [str , t .Any ],
2272+ skip_grants : bool ,
22572273 ** kwargs : t .Any ,
22582274 ) -> None :
22592275 assert isinstance (model .kind , (SCDType2ByTimeKind , SCDType2ByColumnKind ))
@@ -2283,11 +2299,13 @@ def create(
22832299 model ,
22842300 is_table_deployable ,
22852301 render_kwargs ,
2302+ skip_grants ,
22862303 ** kwargs ,
22872304 )
22882305
2289- # Apply grants after SCD Type 2 table creation
2290- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2306+ if not skip_grants :
2307+ # Apply grants after SCD Type 2 table creation
2308+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
22912309
22922310 def insert (
22932311 self ,
@@ -2431,14 +2449,17 @@ def create(
24312449 model : Model ,
24322450 is_table_deployable : bool ,
24332451 render_kwargs : t .Dict [str , t .Any ],
2452+ skip_grants : bool ,
24342453 ** kwargs : t .Any ,
24352454 ) -> None :
24362455 if self .adapter .table_exists (table_name ):
24372456 # Make sure we don't recreate the view to prevent deletion of downstream views in engines with no late
24382457 # binding support (because of DROP CASCADE).
24392458 logger .info ("View '%s' already exists" , table_name )
2440- # Always apply grants when present, even if view exists, to handle grants updates
2441- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2459+
2460+ if not skip_grants :
2461+ # Always apply grants when present, even if view exists, to handle grants updates
2462+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24422463 return
24432464
24442465 logger .info ("Creating view '%s'" , table_name )
@@ -2462,8 +2483,9 @@ def create(
24622483 column_descriptions = model .column_descriptions if is_table_deployable else None ,
24632484 )
24642485
2465- # Apply grants after view creation
2466- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2486+ if not skip_grants :
2487+ # Apply grants after view creation
2488+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24672489
24682490 def migrate (
24692491 self ,
@@ -2640,6 +2662,7 @@ def create(
26402662 model : Model ,
26412663 is_table_deployable : bool ,
26422664 render_kwargs : t .Dict [str , t .Any ],
2665+ skip_grants : bool ,
26432666 ** kwargs : t .Any ,
26442667 ) -> None :
26452668 is_snapshot_deployable : bool = kwargs ["is_snapshot_deployable" ]
@@ -2660,24 +2683,21 @@ def create(
26602683 )
26612684
26622685 # Apply grants after managed table creation
2663- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2686+ if not skip_grants :
2687+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
26642688
26652689 elif not is_table_deployable :
26662690 # Only create the dev preview table as a normal table.
26672691 # For the main table, if the snapshot is cant be deployed to prod (eg upstream is forward-only) do nothing.
26682692 # Any downstream models that reference it will be updated to point to the dev preview table.
26692693 # If the user eventually tries to deploy it, the logic in insert() will see it doesnt exist and create it
2670-
2671- # Create preview table but don't apply grants here since the table is not deployable
2672- # Grants will be applied later when the table becomes deployable
2673- kwargs_no_grants = {** kwargs }
2674- kwargs_no_grants ["skip_grants" ] = True
26752694 super ().create (
26762695 table_name = table_name ,
26772696 model = model ,
26782697 is_table_deployable = is_table_deployable ,
26792698 render_kwargs = render_kwargs ,
2680- ** kwargs_no_grants ,
2699+ skip_grants = skip_grants ,
2700+ ** kwargs ,
26812701 )
26822702
26832703 def insert (
@@ -2704,6 +2724,7 @@ def insert(
27042724 column_descriptions = model .column_descriptions ,
27052725 table_format = model .table_format ,
27062726 )
2727+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
27072728 elif not is_snapshot_deployable :
27082729 # Snapshot isnt deployable; update the preview table instead
27092730 # If the snapshot was deployable, then data would have already been loaded in create() because a managed table would have been created
@@ -2753,7 +2774,7 @@ def migrate(
27532774 )
27542775
27552776 # Apply grants after verifying no schema changes
2756- # This ensures metadata-only changes ( grants) are applied
2777+ # This ensures metadata-only grants changes are applied
27572778 self ._apply_grants (snapshot .model , target_table_name , GrantsTargetLayer .PHYSICAL )
27582779
27592780 def delete (self , name : str , ** kwargs : t .Any ) -> None :
0 commit comments