Skip to content

Commit 01ae6b7

Browse files
committed
refactor: move private grants method to the end of EngineAdapter
1 parent 4092633 commit 01ae6b7

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
@@ -2399,29 +2399,6 @@ def wap_publish(self, table_name: TableName, wap_id: str) -> None:
23992399
"""
24002400
raise NotImplementedError(f"Engine does not support WAP: {type(self)}")
24012401

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

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

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

30793079
class EngineAdapterWithIndexSupport(EngineAdapter):
30803080
SUPPORTS_INDEXES = True

0 commit comments

Comments
 (0)