Skip to content

Commit 471f723

Browse files
committed
refactor: move private grants method to the end of EngineAdapter
1 parent 9abf7b2 commit 471f723

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

2367-
def _get_current_grants_config(self, table: exp.Table) -> GrantsConfig:
2368-
"""Returns current grants for a table as a dictionary.
2369-
2370-
This method queries the database and returns the current grants/permissions
2371-
for the given table, parsed into a dictionary format. The it handles
2372-
case-insensitive comparison between these current grants and the desired
2373-
grants from model configuration.
2374-
2375-
Args:
2376-
table: The table/view to query grants for.
2377-
2378-
Returns:
2379-
Dictionary mapping permissions to lists of grantees. Permission names
2380-
should be returned as the database provides them (typically uppercase
2381-
for standard SQL permissions, but engine-specific roles may vary).
2382-
2383-
Raises:
2384-
NotImplementedError: If the engine does not support grants.
2385-
"""
2386-
if not self.SUPPORTS_GRANTS:
2387-
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
2388-
raise NotImplementedError("Subclass must implement get_current_grants")
2389-
23902367
def sync_grants_config(
23912368
self,
23922369
table: exp.Table,
@@ -2414,104 +2391,6 @@ def sync_grants_config(
24142391
if dcl_exprs:
24152392
self.execute(dcl_exprs)
24162393

2417-
def _apply_grants_config_expr(
2418-
self,
2419-
table: exp.Table,
2420-
grant_config: GrantsConfig,
2421-
table_type: DataObjectType = DataObjectType.TABLE,
2422-
) -> t.List[exp.Expression]:
2423-
"""Returns SQLGlot Grant expressions to apply grants to a table.
2424-
2425-
Args:
2426-
table: The table/view to grant permissions on.
2427-
grant_config: Dictionary mapping permissions to lists of grantees.
2428-
table_type: The type of database object (TABLE, VIEW, MATERIALIZED_VIEW).
2429-
2430-
Returns:
2431-
List of SQLGlot expressions for grant operations.
2432-
2433-
Raises:
2434-
NotImplementedError: If the engine does not support grants.
2435-
"""
2436-
if not self.SUPPORTS_GRANTS:
2437-
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
2438-
raise NotImplementedError("Subclass must implement _apply_grants_config_expr")
2439-
2440-
def _revoke_grants_config_expr(
2441-
self,
2442-
table: exp.Table,
2443-
grant_config: GrantsConfig,
2444-
table_type: DataObjectType = DataObjectType.TABLE,
2445-
) -> t.List[exp.Expression]:
2446-
"""Returns SQLGlot expressions to revoke grants from a table.
2447-
2448-
Note: SQLGlot doesn't yet have a Revoke expression type, so implementations
2449-
may return other expression types or handle revokes as strings.
2450-
2451-
Args:
2452-
table: The table/view to revoke permissions from.
2453-
grant_config: Dictionary mapping permissions to lists of grantees.
2454-
table_type: The type of database object (TABLE, VIEW, MATERIALIZED_VIEW).
2455-
2456-
Returns:
2457-
List of SQLGlot expressions for revoke operations.
2458-
2459-
Raises:
2460-
NotImplementedError: If the engine does not support grants.
2461-
"""
2462-
if not self.SUPPORTS_GRANTS:
2463-
raise NotImplementedError(f"Engine does not support grants: {type(self)}")
2464-
raise NotImplementedError("Subclass must implement _revoke_grants_config_expr")
2465-
2466-
@classmethod
2467-
def _diff_grants_configs(
2468-
cls, new_config: GrantsConfig, old_config: GrantsConfig
2469-
) -> t.Tuple[GrantsConfig, GrantsConfig]:
2470-
"""Compute additions and removals between two grants configurations.
2471-
2472-
This method compares new (desired) and old (current) GrantsConfigs case-insensitively
2473-
for both privilege keys and grantees, while preserving original casing
2474-
in the output GrantsConfigs.
2475-
2476-
Args:
2477-
new_config: Desired grants configuration (specified by the user).
2478-
old_config: Current grants configuration (returned by the database).
2479-
2480-
Returns:
2481-
A tuple of (additions, removals) GrantsConfig where:
2482-
- additions contains privileges/grantees present in new_config but not in old_config
2483-
- additions uses keys and grantee strings from new_config (user-specified casing)
2484-
- removals contains privileges/grantees present in old_config but not in new_config
2485-
- removals uses keys and grantee strings from old_config (database-returned casing)
2486-
2487-
Notes:
2488-
- Comparison is case-insensitive using casefold(); original casing is preserved in results.
2489-
- Overlapping grantees (case-insensitive) are excluded from the results.
2490-
"""
2491-
2492-
def _diffs(config1: GrantsConfig, config2: GrantsConfig) -> GrantsConfig:
2493-
diffs: GrantsConfig = {}
2494-
cf_config2 = {k.casefold(): {g.casefold() for g in v} for k, v in config2.items()}
2495-
for key, grantees in config1.items():
2496-
cf_key = key.casefold()
2497-
2498-
# Missing key (add all grantees)
2499-
if cf_key not in cf_config2:
2500-
diffs[key] = grantees.copy()
2501-
continue
2502-
2503-
# Include only grantees not in config2
2504-
cf_grantees2 = cf_config2[cf_key]
2505-
diff_grantees = []
2506-
for grantee in grantees:
2507-
if grantee.casefold() not in cf_grantees2:
2508-
diff_grantees.append(grantee)
2509-
if diff_grantees:
2510-
diffs[key] = diff_grantees
2511-
return diffs
2512-
2513-
return _diffs(new_config, old_config), _diffs(old_config, new_config)
2514-
25152394
@contextlib.contextmanager
25162395
def transaction(
25172396
self,
@@ -3040,6 +2919,127 @@ def _check_identifier_length(self, expression: exp.Expression) -> None:
30402919
f"Identifier name '{name}' (length {name_length}) exceeds {self.dialect.capitalize()}'s max identifier limit of {self.MAX_IDENTIFIER_LENGTH} characters"
30412920
)
30422921

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

30443044
class EngineAdapterWithIndexSupport(EngineAdapter):
30453045
SUPPORTS_INDEXES = True

0 commit comments

Comments
 (0)