@@ -872,6 +872,7 @@ def create_snapshot(
872872 deployability_index = deployability_index ,
873873 create_render_kwargs = create_render_kwargs ,
874874 rendered_physical_properties = rendered_physical_properties ,
875+ skip_grants = True ,
875876 dry_run = True ,
876877 )
877878
@@ -1422,12 +1423,12 @@ def _execute_create(
14221423 table_name = table_name ,
14231424 model = snapshot .model ,
14241425 is_table_deployable = is_table_deployable ,
1426+ skip_grants = skip_grants ,
14251427 render_kwargs = create_render_kwargs ,
14261428 is_snapshot_deployable = is_snapshot_deployable ,
14271429 is_snapshot_representative = is_snapshot_representative ,
14281430 dry_run = dry_run ,
14291431 physical_properties = rendered_physical_properties ,
1430- skip_grants = skip_grants ,
14311432 )
14321433 if run_pre_post_statements :
14331434 adapter .execute (snapshot .model .render_post_statements (** create_render_kwargs ))
@@ -1591,6 +1592,7 @@ def create(
15911592 model : Model ,
15921593 is_table_deployable : bool ,
15931594 render_kwargs : t .Dict [str , t .Any ],
1595+ skip_grants : bool ,
15941596 ** kwargs : t .Any ,
15951597 ) -> None :
15961598 """Creates the target table or view.
@@ -1734,6 +1736,7 @@ def create(
17341736 model : Model ,
17351737 is_table_deployable : bool ,
17361738 render_kwargs : t .Dict [str , t .Any ],
1739+ skip_grants : bool ,
17371740 ** kwargs : t .Any ,
17381741 ) -> None :
17391742 pass
@@ -1809,10 +1812,10 @@ def promote(
18091812 view_properties = model .render_virtual_properties (** render_kwargs ),
18101813 )
18111814
1812- # Apply grants to the physical layer table
1815+ # Apply grants to the physical layer (referenced table / view) after promotion
18131816 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18141817
1815- # Apply grants to the virtual layer view
1818+ # Apply grants to the virtual layer ( view) after promotion
18161819 self ._apply_grants (model , view_name , GrantsTargetLayer .VIRTUAL )
18171820
18181821 def demote (self , view_name : str , ** kwargs : t .Any ) -> None :
@@ -1827,6 +1830,7 @@ def create(
18271830 model : Model ,
18281831 is_table_deployable : bool ,
18291832 render_kwargs : t .Dict [str , t .Any ],
1833+ skip_grants : bool ,
18301834 ** kwargs : t .Any ,
18311835 ) -> None :
18321836 ctas_query = model .ctas_query (** render_kwargs )
@@ -1872,7 +1876,7 @@ def create(
18721876 )
18731877
18741878 # Apply grants after table creation (unless explicitly skipped by caller)
1875- if not kwargs . get ( " skip_grants" , False ) :
1879+ if not skip_grants :
18761880 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18771881
18781882 def migrate (
@@ -1914,6 +1918,7 @@ def _replace_query_for_model(
19141918 name : str ,
19151919 query_or_df : QueryOrDF ,
19161920 render_kwargs : t .Dict [str , t .Any ],
1921+ skip_grants : bool = False ,
19171922 ** kwargs : t .Any ,
19181923 ) -> None :
19191924 """Replaces the table for the given model.
@@ -1951,7 +1956,7 @@ def _replace_query_for_model(
19511956 )
19521957
19531958 # Apply grants after table replacement (unless explicitly skipped by caller)
1954- if not kwargs . get ( " skip_grants" , False ) :
1959+ if not skip_grants :
19551960 self ._apply_grants (model , name , GrantsTargetLayer .PHYSICAL )
19561961
19571962 def _get_target_and_source_columns (
@@ -2201,6 +2206,7 @@ def create(
22012206 model : Model ,
22022207 is_table_deployable : bool ,
22032208 render_kwargs : t .Dict [str , t .Any ],
2209+ skip_grants : bool ,
22042210 ** kwargs : t .Any ,
22052211 ) -> None :
22062212 model = t .cast (SeedModel , model )
@@ -2214,29 +2220,38 @@ def create(
22142220 )
22152221 return
22162222
2217- # Skip grants in parent create call since we'll apply them after data insertion
2218- kwargs_no_grants = {** kwargs }
2219- kwargs_no_grants ["skip_grants" ] = True
2220-
2221- super ().create (table_name , model , is_table_deployable , render_kwargs , ** kwargs_no_grants )
2223+ super ().create (
2224+ table_name ,
2225+ model ,
2226+ is_table_deployable ,
2227+ render_kwargs ,
2228+ skip_grants = True , # Skip grants; they're applied after data insertion
2229+ ** kwargs ,
2230+ )
22222231 # For seeds we insert data at the time of table creation.
22232232 try :
22242233 for index , df in enumerate (model .render_seed ()):
22252234 if index == 0 :
22262235 self ._replace_query_for_model (
2227- model , table_name , df , render_kwargs , ** kwargs_no_grants
2236+ model ,
2237+ table_name ,
2238+ df ,
2239+ render_kwargs ,
2240+ skip_grants = True , # Skip grants; they're applied after data insertion
2241+ ** kwargs ,
22282242 )
22292243 else :
22302244 self .adapter .insert_append (
22312245 table_name , df , target_columns_to_types = model .columns_to_types
22322246 )
2247+
2248+ if not skip_grants :
2249+ # Apply grants after seed table creation and data insertion
2250+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
22332251 except Exception :
22342252 self .adapter .drop_table (table_name )
22352253 raise
22362254
2237- # Apply grants after seed table creation or data insertion
2238- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2239-
22402255 def insert (
22412256 self ,
22422257 table_name : str ,
@@ -2268,6 +2283,7 @@ def create(
22682283 model : Model ,
22692284 is_table_deployable : bool ,
22702285 render_kwargs : t .Dict [str , t .Any ],
2286+ skip_grants : bool ,
22712287 ** kwargs : t .Any ,
22722288 ) -> None :
22732289 assert isinstance (model .kind , (SCDType2ByTimeKind , SCDType2ByColumnKind ))
@@ -2297,11 +2313,13 @@ def create(
22972313 model ,
22982314 is_table_deployable ,
22992315 render_kwargs ,
2316+ skip_grants ,
23002317 ** kwargs ,
23012318 )
23022319
2303- # Apply grants after SCD Type 2 table creation
2304- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2320+ if not skip_grants :
2321+ # Apply grants after SCD Type 2 table creation
2322+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
23052323
23062324 def insert (
23072325 self ,
@@ -2445,14 +2463,17 @@ def create(
24452463 model : Model ,
24462464 is_table_deployable : bool ,
24472465 render_kwargs : t .Dict [str , t .Any ],
2466+ skip_grants : bool ,
24482467 ** kwargs : t .Any ,
24492468 ) -> None :
24502469 if self .adapter .table_exists (table_name ):
24512470 # Make sure we don't recreate the view to prevent deletion of downstream views in engines with no late
24522471 # binding support (because of DROP CASCADE).
24532472 logger .info ("View '%s' already exists" , table_name )
2454- # Always apply grants when present, even if view exists, to handle grants updates
2455- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2473+
2474+ if not skip_grants :
2475+ # Always apply grants when present, even if view exists, to handle grants updates
2476+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24562477 return
24572478
24582479 logger .info ("Creating view '%s'" , table_name )
@@ -2476,8 +2497,9 @@ def create(
24762497 column_descriptions = model .column_descriptions if is_table_deployable else None ,
24772498 )
24782499
2479- # Apply grants after view creation
2480- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2500+ if not skip_grants :
2501+ # Apply grants after view creation
2502+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24812503
24822504 def migrate (
24832505 self ,
@@ -2654,6 +2676,7 @@ def create(
26542676 model : Model ,
26552677 is_table_deployable : bool ,
26562678 render_kwargs : t .Dict [str , t .Any ],
2679+ skip_grants : bool ,
26572680 ** kwargs : t .Any ,
26582681 ) -> None :
26592682 is_snapshot_deployable : bool = kwargs ["is_snapshot_deployable" ]
@@ -2674,24 +2697,21 @@ def create(
26742697 )
26752698
26762699 # Apply grants after managed table creation
2677- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2700+ if not skip_grants :
2701+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
26782702
26792703 elif not is_table_deployable :
26802704 # Only create the dev preview table as a normal table.
26812705 # For the main table, if the snapshot is cant be deployed to prod (eg upstream is forward-only) do nothing.
26822706 # Any downstream models that reference it will be updated to point to the dev preview table.
26832707 # If the user eventually tries to deploy it, the logic in insert() will see it doesnt exist and create it
2684-
2685- # Create preview table but don't apply grants here since the table is not deployable
2686- # Grants will be applied later when the table becomes deployable
2687- kwargs_no_grants = {** kwargs }
2688- kwargs_no_grants ["skip_grants" ] = True
26892708 super ().create (
26902709 table_name = table_name ,
26912710 model = model ,
26922711 is_table_deployable = is_table_deployable ,
26932712 render_kwargs = render_kwargs ,
2694- ** kwargs_no_grants ,
2713+ skip_grants = skip_grants ,
2714+ ** kwargs ,
26952715 )
26962716
26972717 def insert (
@@ -2718,6 +2738,7 @@ def insert(
27182738 column_descriptions = model .column_descriptions ,
27192739 table_format = model .table_format ,
27202740 )
2741+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
27212742 elif not is_snapshot_deployable :
27222743 # Snapshot isnt deployable; update the preview table instead
27232744 # If the snapshot was deployable, then data would have already been loaded in create() because a managed table would have been created
@@ -2767,7 +2788,7 @@ def migrate(
27672788 )
27682789
27692790 # Apply grants after verifying no schema changes
2770- # This ensures metadata-only changes ( grants) are applied
2791+ # This ensures metadata-only grants changes are applied
27712792 self ._apply_grants (snapshot .model , target_table_name , GrantsTargetLayer .PHYSICAL )
27722793
27732794 def delete (self , name : str , ** kwargs : t .Any ) -> None :
0 commit comments