@@ -882,6 +882,7 @@ def create_snapshot(
882882 deployability_index = deployability_index ,
883883 create_render_kwargs = create_render_kwargs ,
884884 rendered_physical_properties = rendered_physical_properties ,
885+ skip_grants = True ,
885886 dry_run = True ,
886887 )
887888
@@ -1442,12 +1443,12 @@ def _execute_create(
14421443 table_name = table_name ,
14431444 model = snapshot .model ,
14441445 is_table_deployable = is_table_deployable ,
1446+ skip_grants = skip_grants ,
14451447 render_kwargs = create_render_kwargs ,
14461448 is_snapshot_deployable = is_snapshot_deployable ,
14471449 is_snapshot_representative = is_snapshot_representative ,
14481450 dry_run = dry_run ,
14491451 physical_properties = rendered_physical_properties ,
1450- skip_grants = skip_grants ,
14511452 )
14521453 if run_pre_post_statements :
14531454 adapter .execute (snapshot .model .render_post_statements (** create_render_kwargs ))
@@ -1612,6 +1613,7 @@ def create(
16121613 model : Model ,
16131614 is_table_deployable : bool ,
16141615 render_kwargs : t .Dict [str , t .Any ],
1616+ skip_grants : bool ,
16151617 ** kwargs : t .Any ,
16161618 ) -> None :
16171619 """Creates the target table or view.
@@ -1755,6 +1757,7 @@ def create(
17551757 model : Model ,
17561758 is_table_deployable : bool ,
17571759 render_kwargs : t .Dict [str , t .Any ],
1760+ skip_grants : bool ,
17581761 ** kwargs : t .Any ,
17591762 ) -> None :
17601763 pass
@@ -1830,10 +1833,10 @@ def promote(
18301833 view_properties = model .render_virtual_properties (** render_kwargs ),
18311834 )
18321835
1833- # Apply grants to the physical layer table
1836+ # Apply grants to the physical layer (referenced table / view) after promotion
18341837 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18351838
1836- # Apply grants to the virtual layer view
1839+ # Apply grants to the virtual layer ( view) after promotion
18371840 self ._apply_grants (model , view_name , GrantsTargetLayer .VIRTUAL )
18381841
18391842 def demote (self , view_name : str , ** kwargs : t .Any ) -> None :
@@ -1848,6 +1851,7 @@ def create(
18481851 model : Model ,
18491852 is_table_deployable : bool ,
18501853 render_kwargs : t .Dict [str , t .Any ],
1854+ skip_grants : bool ,
18511855 ** kwargs : t .Any ,
18521856 ) -> None :
18531857 ctas_query = model .ctas_query (** render_kwargs )
@@ -1893,7 +1897,7 @@ def create(
18931897 )
18941898
18951899 # Apply grants after table creation (unless explicitly skipped by caller)
1896- if not kwargs . get ( " skip_grants" , False ) :
1900+ if not skip_grants :
18971901 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
18981902
18991903 def migrate (
@@ -1935,6 +1939,7 @@ def _replace_query_for_model(
19351939 name : str ,
19361940 query_or_df : QueryOrDF ,
19371941 render_kwargs : t .Dict [str , t .Any ],
1942+ skip_grants : bool = False ,
19381943 ** kwargs : t .Any ,
19391944 ) -> None :
19401945 """Replaces the table for the given model.
@@ -1972,7 +1977,7 @@ def _replace_query_for_model(
19721977 )
19731978
19741979 # Apply grants after table replacement (unless explicitly skipped by caller)
1975- if not kwargs . get ( " skip_grants" , False ) :
1980+ if not skip_grants :
19761981 self ._apply_grants (model , name , GrantsTargetLayer .PHYSICAL )
19771982
19781983 def _get_target_and_source_columns (
@@ -2222,6 +2227,7 @@ def create(
22222227 model : Model ,
22232228 is_table_deployable : bool ,
22242229 render_kwargs : t .Dict [str , t .Any ],
2230+ skip_grants : bool ,
22252231 ** kwargs : t .Any ,
22262232 ) -> None :
22272233 model = t .cast (SeedModel , model )
@@ -2235,22 +2241,34 @@ def create(
22352241 )
22362242 return
22372243
2238- # Skip grants in parent create call since we'll apply them after data insertion
2239- kwargs_no_grants = {** kwargs }
2240- kwargs_no_grants ["skip_grants" ] = True
2241-
2242- super ().create (table_name , model , is_table_deployable , render_kwargs , ** kwargs_no_grants )
2244+ super ().create (
2245+ table_name ,
2246+ model ,
2247+ is_table_deployable ,
2248+ render_kwargs ,
2249+ skip_grants = True , # Skip grants; they're applied after data insertion
2250+ ** kwargs ,
2251+ )
22432252 # For seeds we insert data at the time of table creation.
22442253 try :
22452254 for index , df in enumerate (model .render_seed ()):
22462255 if index == 0 :
22472256 self ._replace_query_for_model (
2248- model , table_name , df , render_kwargs , ** kwargs_no_grants
2257+ model ,
2258+ table_name ,
2259+ df ,
2260+ render_kwargs ,
2261+ skip_grants = True , # Skip grants; they're applied after data insertion
2262+ ** kwargs ,
22492263 )
22502264 else :
22512265 self .adapter .insert_append (
22522266 table_name , df , target_columns_to_types = model .columns_to_types
22532267 )
2268+
2269+ if not skip_grants :
2270+ # Apply grants after seed table creation and data insertion
2271+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
22542272 except Exception :
22552273 self .adapter .drop_table (table_name )
22562274 raise
@@ -2298,6 +2316,7 @@ def create(
22982316 model : Model ,
22992317 is_table_deployable : bool ,
23002318 render_kwargs : t .Dict [str , t .Any ],
2319+ skip_grants : bool ,
23012320 ** kwargs : t .Any ,
23022321 ) -> None :
23032322 assert isinstance (model .kind , (SCDType2ByTimeKind , SCDType2ByColumnKind ))
@@ -2327,11 +2346,13 @@ def create(
23272346 model ,
23282347 is_table_deployable ,
23292348 render_kwargs ,
2349+ skip_grants ,
23302350 ** kwargs ,
23312351 )
23322352
2333- # Apply grants after SCD Type 2 table creation
2334- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2353+ if not skip_grants :
2354+ # Apply grants after SCD Type 2 table creation
2355+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
23352356
23362357 def insert (
23372358 self ,
@@ -2475,14 +2496,17 @@ def create(
24752496 model : Model ,
24762497 is_table_deployable : bool ,
24772498 render_kwargs : t .Dict [str , t .Any ],
2499+ skip_grants : bool ,
24782500 ** kwargs : t .Any ,
24792501 ) -> None :
24802502 if self .adapter .table_exists (table_name ):
24812503 # Make sure we don't recreate the view to prevent deletion of downstream views in engines with no late
24822504 # binding support (because of DROP CASCADE).
24832505 logger .info ("View '%s' already exists" , table_name )
2484- # Always apply grants when present, even if view exists, to handle grants updates
2485- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2506+
2507+ if not skip_grants :
2508+ # Always apply grants when present, even if view exists, to handle grants updates
2509+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24862510 return
24872511
24882512 logger .info ("Creating view '%s'" , table_name )
@@ -2506,8 +2530,9 @@ def create(
25062530 column_descriptions = model .column_descriptions if is_table_deployable else None ,
25072531 )
25082532
2509- # Apply grants after view creation
2510- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2533+ if not skip_grants :
2534+ # Apply grants after view creation
2535+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
25112536
25122537 def migrate (
25132538 self ,
@@ -2684,6 +2709,7 @@ def create(
26842709 model : Model ,
26852710 is_table_deployable : bool ,
26862711 render_kwargs : t .Dict [str , t .Any ],
2712+ skip_grants : bool ,
26872713 ** kwargs : t .Any ,
26882714 ) -> None :
26892715 is_snapshot_deployable : bool = kwargs ["is_snapshot_deployable" ]
@@ -2704,24 +2730,21 @@ def create(
27042730 )
27052731
27062732 # Apply grants after managed table creation
2707- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2733+ if not skip_grants :
2734+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
27082735
27092736 elif not is_table_deployable :
27102737 # Only create the dev preview table as a normal table.
27112738 # For the main table, if the snapshot is cant be deployed to prod (eg upstream is forward-only) do nothing.
27122739 # Any downstream models that reference it will be updated to point to the dev preview table.
27132740 # If the user eventually tries to deploy it, the logic in insert() will see it doesnt exist and create it
2714-
2715- # Create preview table but don't apply grants here since the table is not deployable
2716- # Grants will be applied later when the table becomes deployable
2717- kwargs_no_grants = {** kwargs }
2718- kwargs_no_grants ["skip_grants" ] = True
27192741 super ().create (
27202742 table_name = table_name ,
27212743 model = model ,
27222744 is_table_deployable = is_table_deployable ,
27232745 render_kwargs = render_kwargs ,
2724- ** kwargs_no_grants ,
2746+ skip_grants = skip_grants ,
2747+ ** kwargs ,
27252748 )
27262749
27272750 def insert (
@@ -2748,6 +2771,7 @@ def insert(
27482771 column_descriptions = model .column_descriptions ,
27492772 table_format = model .table_format ,
27502773 )
2774+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
27512775 elif not is_snapshot_deployable :
27522776 # Snapshot isnt deployable; update the preview table instead
27532777 # If the snapshot was deployable, then data would have already been loaded in create() because a managed table would have been created
@@ -2797,7 +2821,7 @@ def migrate(
27972821 )
27982822
27992823 # Apply grants after verifying no schema changes
2800- # This ensures metadata-only changes ( grants) are applied
2824+ # This ensures metadata-only grants changes are applied
28012825 self ._apply_grants (snapshot .model , target_table_name , GrantsTargetLayer .PHYSICAL )
28022826
28032827 def delete (self , name : str , ** kwargs : t .Any ) -> None :
0 commit comments