Skip to content

Commit 24ea896

Browse files
committed
refactor: grants validations and _apply_grants logic
1 parent 90a6818 commit 24ea896

File tree

2 files changed

+41
-51
lines changed

2 files changed

+41
-51
lines changed

sqlmesh/core/model/meta.py

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -522,48 +522,11 @@ def grants(self) -> t.Optional[GrantsConfig]:
522522
if not self.grants_.expressions:
523523
return {}
524524

525-
def expr_to_string(expr: exp.Expression, context: str) -> str:
526-
if isinstance(expr, (d.MacroFunc, d.MacroVar)):
527-
raise ConfigError(
528-
f"Unresolved macro in {context}: {expr.sql(dialect=self.dialect)}"
529-
)
530-
531-
if isinstance(expr, exp.Null):
532-
raise ConfigError(f"NULL value in {context}")
533-
534-
if isinstance(expr, exp.Literal):
535-
return str(expr.this).strip()
536-
if isinstance(expr, exp.Identifier):
537-
return expr.name
538-
if isinstance(expr, exp.Column):
539-
return expr.name
540-
return expr.sql(dialect=self.dialect).strip()
541-
542-
def normalize_to_string_list(value_expr: exp.Expression) -> t.List[str]:
543-
result = []
544-
545-
def process_expression(expr: exp.Expression) -> None:
546-
if isinstance(expr, exp.Array):
547-
for elem in expr.expressions:
548-
process_expression(elem)
549-
550-
elif isinstance(expr, (exp.Tuple, exp.Paren)):
551-
expressions = (
552-
[expr.unnest()] if isinstance(expr, exp.Paren) else expr.expressions
553-
)
554-
for elem in expressions:
555-
process_expression(elem)
556-
else:
557-
result.append(expr_to_string(expr, "grant value"))
558-
559-
process_expression(value_expr)
560-
return result
561-
562525
grants_dict = {}
563526
for eq_expr in self.grants_.expressions:
564527
try:
565-
permission_name = expr_to_string(eq_expr.left, "permission name")
566-
grantee_list = normalize_to_string_list(eq_expr.expression)
528+
permission_name = self._validate_config_expression(eq_expr.left)
529+
grantee_list = self._validate_nested_config_values(eq_expr.expression)
567530
grants_dict[permission_name] = grantee_list
568531
except ConfigError as e:
569532
permission_name = (
@@ -637,3 +600,33 @@ def on_additive_change(self) -> OnAdditiveChange:
637600
@property
638601
def ignored_rules(self) -> t.Set[str]:
639602
return self.ignored_rules_ or set()
603+
604+
def _validate_config_expression(self, expr: exp.Expression) -> str:
605+
if isinstance(expr, (d.MacroFunc, d.MacroVar)):
606+
raise ConfigError(f"Unresolved macro: {expr.sql(dialect=self.dialect)}")
607+
608+
if isinstance(expr, exp.Null):
609+
raise ConfigError("NULL value")
610+
611+
if isinstance(expr, exp.Literal):
612+
return str(expr.this).strip()
613+
if isinstance(expr, (exp.Column, exp.Identifier)):
614+
return expr.name
615+
return expr.sql(dialect=self.dialect).strip()
616+
617+
def _validate_nested_config_values(self, value_expr: exp.Expression) -> t.List[str]:
618+
result = []
619+
620+
def flatten_expr(expr: exp.Expression) -> None:
621+
if isinstance(expr, exp.Array):
622+
for elem in expr.expressions:
623+
flatten_expr(elem)
624+
elif isinstance(expr, (exp.Tuple, exp.Paren)):
625+
expressions = [expr.unnest()] if isinstance(expr, exp.Paren) else expr.expressions
626+
for elem in expressions:
627+
flatten_expr(elem)
628+
else:
629+
result.append(self._validate_config_expression(expr))
630+
631+
flatten_expr(value_expr)
632+
return result

sqlmesh/core/snapshot/evaluator.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,26 +1722,23 @@ def _apply_grants(
17221722

17231723
model_grants_target_layer = model.grants_target_layer
17241724

1725-
is_prod_and_dev_only = is_snapshot_deployable and model.virtual_environment_mode.is_dev_only
1726-
1727-
if not (
1725+
if (
17281726
model_grants_target_layer.is_all
17291727
or model_grants_target_layer == target_layer
17301728
# Always apply grants in production when VDE is dev_only regardless of target_layer
17311729
# since only physical tables are created in production
1732-
or is_prod_and_dev_only
1730+
or (is_snapshot_deployable and model.virtual_environment_mode.is_dev_only)
17331731
):
1732+
logger.info(f"Applying grants for model {model.name} to table {table_name}")
1733+
self.adapter.sync_grants_config(
1734+
exp.to_table(table_name, dialect=self.adapter.dialect),
1735+
grants_config,
1736+
model.grants_table_type,
1737+
)
1738+
else:
17341739
logger.debug(
17351740
f"Skipping grants application for model {model.name} in {target_layer} layer"
17361741
)
1737-
return
1738-
1739-
logger.info(f"Applying grants for model {model.name} to table {table_name}")
1740-
self.adapter.sync_grants_config(
1741-
exp.to_table(table_name, dialect=self.adapter.dialect),
1742-
grants_config,
1743-
model.grants_table_type,
1744-
)
17451742

17461743

17471744
class SymbolicStrategy(EvaluationStrategy):

0 commit comments

Comments
 (0)