Skip to content

Commit 03c7eb4

Browse files
committed
refactor: move private grants method to the end of EngineAdapter
1 parent 0f1f0c0 commit 03c7eb4

File tree

1 file changed

+121
-121
lines changed

1 file changed

+121
-121
lines changed

sqlmesh/core/engine_adapter/base.py

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

2399-
def _get_current_grants_config(self, table: exp.Table) -> GrantsConfig:
2400-
"""Returns current grants for a table as a dictionary.
2401-
2402-
This method queries the database and returns the current grants/permissions
2403-
for the given table, parsed into a dictionary format. The it handles
2404-
case-insensitive comparison between these current grants and the desired
2405-
grants from model configuration.
2406-
2407-
Args:
2408-
table: The table/view to query grants for.
2409-
2410-
Returns:
2411-
Dictionary mapping permissions to lists of grantees. Permission names
2412-
should be returned as the database provides them (typically uppercase
2413-
for standard SQL permissions, but engine-specific roles may vary).
2414-
2415-
Raises:
2416-
NotImplementedError: If the engine does not support grants.
2417-
"""
2418-
if not self.SUPPORTS_GRANTS:
2419-
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
2420-
raise NotImplementedError("Subclass must implement get_current_grants")
2421-
24222399
def sync_grants_config(
24232400
self,
24242401
table: exp.Table,
@@ -2446,104 +2423,6 @@ def sync_grants_config(
24462423
if dcl_exprs:
24472424
self.execute(dcl_exprs)
24482425

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

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

30763076
class EngineAdapterWithIndexSupport(EngineAdapter):
30773077
SUPPORTS_INDEXES = True

0 commit comments

Comments
 (0)