@@ -893,6 +893,7 @@ def create_snapshot(
893893 deployability_index = deployability_index ,
894894 create_render_kwargs = create_render_kwargs ,
895895 rendered_physical_properties = rendered_physical_properties ,
896+ skip_grants = True ,
896897 dry_run = True ,
897898 )
898899
@@ -1455,12 +1456,12 @@ def _execute_create(
14551456 table_name = table_name ,
14561457 model = snapshot .model ,
14571458 is_table_deployable = is_table_deployable ,
1459+ skip_grants = skip_grants ,
14581460 render_kwargs = create_render_kwargs ,
14591461 is_snapshot_deployable = is_snapshot_deployable ,
14601462 is_snapshot_representative = is_snapshot_representative ,
14611463 dry_run = dry_run ,
14621464 physical_properties = rendered_physical_properties ,
1463- skip_grants = skip_grants ,
14641465 )
14651466 if run_pre_post_statements :
14661467 evaluation_strategy .run_post_statements (
@@ -1695,6 +1696,7 @@ def create(
16951696 model : Model ,
16961697 is_table_deployable : bool ,
16971698 render_kwargs : t .Dict [str , t .Any ],
1699+ skip_grants : bool ,
16981700 ** kwargs : t .Any ,
16991701 ) -> None :
17001702 """Creates the target table or view.
@@ -1856,6 +1858,7 @@ def create(
18561858 model : Model ,
18571859 is_table_deployable : bool ,
18581860 render_kwargs : t .Dict [str , t .Any ],
1861+ skip_grants : bool ,
18591862 ** kwargs : t .Any ,
18601863 ) -> None :
18611864 pass
@@ -1937,10 +1940,10 @@ def promote(
19371940 view_properties = model .render_virtual_properties (** render_kwargs ),
19381941 )
19391942
1940- # Apply grants to the physical layer table
1943+ # Apply grants to the physical layer (referenced table / view) after promotion
19411944 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
19421945
1943- # Apply grants to the virtual layer view
1946+ # Apply grants to the virtual layer ( view) after promotion
19441947 self ._apply_grants (model , view_name , GrantsTargetLayer .VIRTUAL )
19451948
19461949 def demote (self , view_name : str , ** kwargs : t .Any ) -> None :
@@ -1961,6 +1964,7 @@ def create(
19611964 model : Model ,
19621965 is_table_deployable : bool ,
19631966 render_kwargs : t .Dict [str , t .Any ],
1967+ skip_grants : bool ,
19641968 ** kwargs : t .Any ,
19651969 ) -> None :
19661970 ctas_query = model .ctas_query (** render_kwargs )
@@ -2006,7 +2010,7 @@ def create(
20062010 )
20072011
20082012 # Apply grants after table creation (unless explicitly skipped by caller)
2009- if not kwargs . get ( " skip_grants" , False ) :
2013+ if not skip_grants :
20102014 self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
20112015
20122016 def migrate (
@@ -2048,6 +2052,7 @@ def _replace_query_for_model(
20482052 name : str ,
20492053 query_or_df : QueryOrDF ,
20502054 render_kwargs : t .Dict [str , t .Any ],
2055+ skip_grants : bool = False ,
20512056 ** kwargs : t .Any ,
20522057 ) -> None :
20532058 """Replaces the table for the given model.
@@ -2085,7 +2090,7 @@ def _replace_query_for_model(
20852090 )
20862091
20872092 # Apply grants after table replacement (unless explicitly skipped by caller)
2088- if not kwargs . get ( " skip_grants" , False ) :
2093+ if not skip_grants :
20892094 self ._apply_grants (model , name , GrantsTargetLayer .PHYSICAL )
20902095
20912096 def _get_target_and_source_columns (
@@ -2335,6 +2340,7 @@ def create(
23352340 model : Model ,
23362341 is_table_deployable : bool ,
23372342 render_kwargs : t .Dict [str , t .Any ],
2343+ skip_grants : bool ,
23382344 ** kwargs : t .Any ,
23392345 ) -> None :
23402346 model = t .cast (SeedModel , model )
@@ -2348,22 +2354,34 @@ def create(
23482354 )
23492355 return
23502356
2351- # Skip grants in parent create call since we'll apply them after data insertion
2352- kwargs_no_grants = {** kwargs }
2353- kwargs_no_grants ["skip_grants" ] = True
2354-
2355- super ().create (table_name , model , is_table_deployable , render_kwargs , ** kwargs_no_grants )
2357+ super ().create (
2358+ table_name ,
2359+ model ,
2360+ is_table_deployable ,
2361+ render_kwargs ,
2362+ skip_grants = True , # Skip grants; they're applied after data insertion
2363+ ** kwargs ,
2364+ )
23562365 # For seeds we insert data at the time of table creation.
23572366 try :
23582367 for index , df in enumerate (model .render_seed ()):
23592368 if index == 0 :
23602369 self ._replace_query_for_model (
2361- model , table_name , df , render_kwargs , ** kwargs_no_grants
2370+ model ,
2371+ table_name ,
2372+ df ,
2373+ render_kwargs ,
2374+ skip_grants = True , # Skip grants; they're applied after data insertion
2375+ ** kwargs ,
23622376 )
23632377 else :
23642378 self .adapter .insert_append (
23652379 table_name , df , target_columns_to_types = model .columns_to_types
23662380 )
2381+
2382+ if not skip_grants :
2383+ # Apply grants after seed table creation and data insertion
2384+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
23672385 except Exception :
23682386 self .adapter .drop_table (table_name )
23692387 raise
@@ -2411,6 +2429,7 @@ def create(
24112429 model : Model ,
24122430 is_table_deployable : bool ,
24132431 render_kwargs : t .Dict [str , t .Any ],
2432+ skip_grants : bool ,
24142433 ** kwargs : t .Any ,
24152434 ) -> None :
24162435 assert isinstance (model .kind , (SCDType2ByTimeKind , SCDType2ByColumnKind ))
@@ -2440,11 +2459,13 @@ def create(
24402459 model ,
24412460 is_table_deployable ,
24422461 render_kwargs ,
2462+ skip_grants ,
24432463 ** kwargs ,
24442464 )
24452465
2446- # Apply grants after SCD Type 2 table creation
2447- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2466+ if not skip_grants :
2467+ # Apply grants after SCD Type 2 table creation
2468+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
24482469
24492470 def insert (
24502471 self ,
@@ -2588,14 +2609,17 @@ def create(
25882609 model : Model ,
25892610 is_table_deployable : bool ,
25902611 render_kwargs : t .Dict [str , t .Any ],
2612+ skip_grants : bool ,
25912613 ** kwargs : t .Any ,
25922614 ) -> None :
25932615 if self .adapter .table_exists (table_name ):
25942616 # Make sure we don't recreate the view to prevent deletion of downstream views in engines with no late
25952617 # binding support (because of DROP CASCADE).
25962618 logger .info ("View '%s' already exists" , table_name )
2597- # Always apply grants when present, even if view exists, to handle grants updates
2598- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2619+
2620+ if not skip_grants :
2621+ # Always apply grants when present, even if view exists, to handle grants updates
2622+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
25992623 return
26002624
26012625 logger .info ("Creating view '%s'" , table_name )
@@ -2619,8 +2643,9 @@ def create(
26192643 column_descriptions = model .column_descriptions if is_table_deployable else None ,
26202644 )
26212645
2622- # Apply grants after view creation
2623- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2646+ if not skip_grants :
2647+ # Apply grants after view creation
2648+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
26242649
26252650 def migrate (
26262651 self ,
@@ -2936,6 +2961,7 @@ def create(
29362961 model : Model ,
29372962 is_table_deployable : bool ,
29382963 render_kwargs : t .Dict [str , t .Any ],
2964+ skip_grants : bool ,
29392965 ** kwargs : t .Any ,
29402966 ) -> None :
29412967 is_snapshot_deployable : bool = kwargs ["is_snapshot_deployable" ]
@@ -2956,24 +2982,21 @@ def create(
29562982 )
29572983
29582984 # Apply grants after managed table creation
2959- self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
2985+ if not skip_grants :
2986+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
29602987
29612988 elif not is_table_deployable :
29622989 # Only create the dev preview table as a normal table.
29632990 # For the main table, if the snapshot is cant be deployed to prod (eg upstream is forward-only) do nothing.
29642991 # Any downstream models that reference it will be updated to point to the dev preview table.
29652992 # If the user eventually tries to deploy it, the logic in insert() will see it doesnt exist and create it
2966-
2967- # Create preview table but don't apply grants here since the table is not deployable
2968- # Grants will be applied later when the table becomes deployable
2969- kwargs_no_grants = {** kwargs }
2970- kwargs_no_grants ["skip_grants" ] = True
29712993 super ().create (
29722994 table_name = table_name ,
29732995 model = model ,
29742996 is_table_deployable = is_table_deployable ,
29752997 render_kwargs = render_kwargs ,
2976- ** kwargs_no_grants ,
2998+ skip_grants = skip_grants ,
2999+ ** kwargs ,
29773000 )
29783001
29793002 def insert (
@@ -3000,6 +3023,7 @@ def insert(
30003023 column_descriptions = model .column_descriptions ,
30013024 table_format = model .table_format ,
30023025 )
3026+ self ._apply_grants (model , table_name , GrantsTargetLayer .PHYSICAL )
30033027 elif not is_snapshot_deployable :
30043028 # Snapshot isnt deployable; update the preview table instead
30053029 # If the snapshot was deployable, then data would have already been loaded in create() because a managed table would have been created
@@ -3049,7 +3073,7 @@ def migrate(
30493073 )
30503074
30513075 # Apply grants after verifying no schema changes
3052- # This ensures metadata-only changes ( grants) are applied
3076+ # This ensures metadata-only grants changes are applied
30533077 self ._apply_grants (snapshot .model , target_table_name , GrantsTargetLayer .PHYSICAL )
30543078
30553079 def delete (self , name : str , ** kwargs : t .Any ) -> None :
0 commit comments