Skip to content

Commit 1460bc1

Browse files
committed
refactor: move private grants method to the end of EngineAdapter
1 parent 7df237e commit 1460bc1

1 file changed

Lines changed: 121 additions & 121 deletions

File tree

sqlmesh/core/engine_adapter/base.py

Lines changed: 121 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,29 +2404,6 @@ def wap_publish(self, table_name: TableName, wap_id: str) -> None:
24042404
"""
24052405
raise NotImplementedError(f"Engine does not support WAP: {type(self)}")
24062406

2407-
def _get_current_grants_config(self, table: exp.Table) -> GrantsConfig:
2408-
"""Returns current grants for a table as a dictionary.
2409-
2410-
This method queries the database and returns the current grants/permissions
2411-
for the given table, parsed into a dictionary format. The it handles
2412-
case-insensitive comparison between these current grants and the desired
2413-
grants from model configuration.
2414-
2415-
Args:
2416-
table: The table/view to query grants for.
2417-
2418-
Returns:
2419-
Dictionary mapping permissions to lists of grantees. Permission names
2420-
should be returned as the database provides them (typically uppercase
2421-
for standard SQL permissions, but engine-specific roles may vary).
2422-
2423-
Raises:
2424-
NotImplementedError: If the engine does not support grants.
2425-
"""
2426-
if not self.SUPPORTS_GRANTS:
2427-
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
2428-
raise NotImplementedError("Subclass must implement get_current_grants")
2429-
24302407
def sync_grants_config(
24312408
self,
24322409
table: exp.Table,
@@ -2454,104 +2431,6 @@ def sync_grants_config(
24542431
if dcl_exprs:
24552432
self.execute(dcl_exprs)
24562433

2457-
def _apply_grants_config_expr(
2458-
self,
2459-
table: exp.Table,
2460-
grant_config: GrantsConfig,
2461-
table_type: DataObjectType = DataObjectType.TABLE,
2462-
) -> t.List[exp.Expression]:
2463-
"""Returns SQLGlot Grant expressions to apply grants to a table.
2464-
2465-
Args:
2466-
table: The table/view to grant permissions on.
2467-
grant_config: Dictionary mapping permissions to lists of grantees.
2468-
table_type: The type of database object (TABLE, VIEW, MATERIALIZED_VIEW).
2469-
2470-
Returns:
2471-
List of SQLGlot expressions for grant operations.
2472-
2473-
Raises:
2474-
NotImplementedError: If the engine does not support grants.
2475-
"""
2476-
if not self.SUPPORTS_GRANTS:
2477-
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
2478-
raise NotImplementedError("Subclass must implement _apply_grants_config_expr")
2479-
2480-
def _revoke_grants_config_expr(
2481-
self,
2482-
table: exp.Table,
2483-
grant_config: GrantsConfig,
2484-
table_type: DataObjectType = DataObjectType.TABLE,
2485-
) -> t.List[exp.Expression]:
2486-
"""Returns SQLGlot expressions to revoke grants from a table.
2487-
2488-
Note: SQLGlot doesn't yet have a Revoke expression type, so implementations
2489-
may return other expression types or handle revokes as strings.
2490-
2491-
Args:
2492-
table: The table/view to revoke permissions from.
2493-
grant_config: Dictionary mapping permissions to lists of grantees.
2494-
table_type: The type of database object (TABLE, VIEW, MATERIALIZED_VIEW).
2495-
2496-
Returns:
2497-
List of SQLGlot expressions for revoke operations.
2498-
2499-
Raises:
2500-
NotImplementedError: If the engine does not support grants.
2501-
"""
2502-
if not self.SUPPORTS_GRANTS:
2503-
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
2504-
raise NotImplementedError("Subclass must implement _revoke_grants_config_expr")
2505-
2506-
@classmethod
2507-
def _diff_grants_configs(
2508-
cls, new_config: GrantsConfig, old_config: GrantsConfig
2509-
) -> t.Tuple[GrantsConfig, GrantsConfig]:
2510-
"""Compute additions and removals between two grants configurations.
2511-
2512-
This method compares new (desired) and old (current) GrantsConfigs case-insensitively
2513-
for both privilege keys and grantees, while preserving original casing
2514-
in the output GrantsConfigs.
2515-
2516-
Args:
2517-
new_config: Desired grants configuration (specified by the user).
2518-
old_config: Current grants configuration (returned by the database).
2519-
2520-
Returns:
2521-
A tuple of (additions, removals) GrantsConfig where:
2522-
- additions contains privileges/grantees present in new_config but not in old_config
2523-
- additions uses keys and grantee strings from new_config (user-specified casing)
2524-
- removals contains privileges/grantees present in old_config but not in new_config
2525-
- removals uses keys and grantee strings from old_config (database-returned casing)
2526-
2527-
Notes:
2528-
- Comparison is case-insensitive using casefold(); original casing is preserved in results.
2529-
- Overlapping grantees (case-insensitive) are excluded from the results.
2530-
"""
2531-
2532-
def _diffs(config1: GrantsConfig, config2: GrantsConfig) -> GrantsConfig:
2533-
diffs: GrantsConfig = {}
2534-
cf_config2 = {k.casefold(): {g.casefold() for g in v} for k, v in config2.items()}
2535-
for key, grantees in config1.items():
2536-
cf_key = key.casefold()
2537-
2538-
# Missing key (add all grantees)
2539-
if cf_key not in cf_config2:
2540-
diffs[key] = grantees.copy()
2541-
continue
2542-
2543-
# Include only grantees not in config2
2544-
cf_grantees2 = cf_config2[cf_key]
2545-
diff_grantees = []
2546-
for grantee in grantees:
2547-
if grantee.casefold() not in cf_grantees2:
2548-
diff_grantees.append(grantee)
2549-
if diff_grantees:
2550-
diffs[key] = diff_grantees
2551-
return diffs
2552-
2553-
return _diffs(new_config, old_config), _diffs(old_config, new_config)
2554-
25552434
@contextlib.contextmanager
25562435
def transaction(
25572436
self,
@@ -3080,6 +2959,127 @@ def _check_identifier_length(self, expression: exp.Expression) -> None:
30802959
f"Identifier name '{name}' (length {name_length}) exceeds {self.dialect.capitalize()}'s max identifier limit of {self.MAX_IDENTIFIER_LENGTH} characters"
30812960
)
30822961

2962+
@classmethod
2963+
def _diff_grants_configs(
2964+
cls, new_config: GrantsConfig, old_config: GrantsConfig
2965+
) -> t.Tuple[GrantsConfig, GrantsConfig]:
2966+
"""Compute additions and removals between two grants configurations.
2967+
2968+
This method compares new (desired) and old (current) GrantsConfigs case-insensitively
2969+
for both privilege keys and grantees, while preserving original casing
2970+
in the output GrantsConfigs.
2971+
2972+
Args:
2973+
new_config: Desired grants configuration (specified by the user).
2974+
old_config: Current grants configuration (returned by the database).
2975+
2976+
Returns:
2977+
A tuple of (additions, removals) GrantsConfig where:
2978+
- additions contains privileges/grantees present in new_config but not in old_config
2979+
- additions uses keys and grantee strings from new_config (user-specified casing)
2980+
- removals contains privileges/grantees present in old_config but not in new_config
2981+
- removals uses keys and grantee strings from old_config (database-returned casing)
2982+
2983+
Notes:
2984+
- Comparison is case-insensitive using casefold(); original casing is preserved in results.
2985+
- Overlapping grantees (case-insensitive) are excluded from the results.
2986+
"""
2987+
2988+
def _diffs(config1: GrantsConfig, config2: GrantsConfig) -> GrantsConfig:
2989+
diffs: GrantsConfig = {}
2990+
cf_config2 = {k.casefold(): {g.casefold() for g in v} for k, v in config2.items()}
2991+
for key, grantees in config1.items():
2992+
cf_key = key.casefold()
2993+
2994+
# Missing key (add all grantees)
2995+
if cf_key not in cf_config2:
2996+
diffs[key] = grantees.copy()
2997+
continue
2998+
2999+
# Include only grantees not in config2
3000+
cf_grantees2 = cf_config2[cf_key]
3001+
diff_grantees = []
3002+
for grantee in grantees:
3003+
if grantee.casefold() not in cf_grantees2:
3004+
diff_grantees.append(grantee)
3005+
if diff_grantees:
3006+
diffs[key] = diff_grantees
3007+
return diffs
3008+
3009+
return _diffs(new_config, old_config), _diffs(old_config, new_config)
3010+
3011+
def _get_current_grants_config(self, table: exp.Table) -> GrantsConfig:
3012+
"""Returns current grants for a table as a dictionary.
3013+
3014+
This method queries the database and returns the current grants/permissions
3015+
for the given table, parsed into a dictionary format. The it handles
3016+
case-insensitive comparison between these current grants and the desired
3017+
grants from model configuration.
3018+
3019+
Args:
3020+
table: The table/view to query grants for.
3021+
3022+
Returns:
3023+
Dictionary mapping permissions to lists of grantees. Permission names
3024+
should be returned as the database provides them (typically uppercase
3025+
for standard SQL permissions, but engine-specific roles may vary).
3026+
3027+
Raises:
3028+
NotImplementedError: If the engine does not support grants.
3029+
"""
3030+
if not self.SUPPORTS_GRANTS:
3031+
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
3032+
raise NotImplementedError("Subclass must implement get_current_grants")
3033+
3034+
def _apply_grants_config_expr(
3035+
self,
3036+
table: exp.Table,
3037+
grant_config: GrantsConfig,
3038+
table_type: DataObjectType = DataObjectType.TABLE,
3039+
) -> t.List[exp.Expression]:
3040+
"""Returns SQLGlot Grant expressions to apply grants to a table.
3041+
3042+
Args:
3043+
table: The table/view to grant permissions on.
3044+
grant_config: Dictionary mapping permissions to lists of grantees.
3045+
table_type: The type of database object (TABLE, VIEW, MATERIALIZED_VIEW).
3046+
3047+
Returns:
3048+
List of SQLGlot expressions for grant operations.
3049+
3050+
Raises:
3051+
NotImplementedError: If the engine does not support grants.
3052+
"""
3053+
if not self.SUPPORTS_GRANTS:
3054+
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
3055+
raise NotImplementedError("Subclass must implement _apply_grants_config_expr")
3056+
3057+
def _revoke_grants_config_expr(
3058+
self,
3059+
table: exp.Table,
3060+
grant_config: GrantsConfig,
3061+
table_type: DataObjectType = DataObjectType.TABLE,
3062+
) -> t.List[exp.Expression]:
3063+
"""Returns SQLGlot expressions to revoke grants from a table.
3064+
3065+
Note: SQLGlot doesn't yet have a Revoke expression type, so implementations
3066+
may return other expression types or handle revokes as strings.
3067+
3068+
Args:
3069+
table: The table/view to revoke permissions from.
3070+
grant_config: Dictionary mapping permissions to lists of grantees.
3071+
table_type: The type of database object (TABLE, VIEW, MATERIALIZED_VIEW).
3072+
3073+
Returns:
3074+
List of SQLGlot expressions for revoke operations.
3075+
3076+
Raises:
3077+
NotImplementedError: If the engine does not support grants.
3078+
"""
3079+
if not self.SUPPORTS_GRANTS:
3080+
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
3081+
raise NotImplementedError("Subclass must implement _revoke_grants_config_expr")
3082+
30833083

30843084
class EngineAdapterWithIndexSupport(EngineAdapter):
30853085
SUPPORTS_INDEXES = True

0 commit comments

Comments
 (0)