Skip to content

Commit 27be0df

Browse files
committed
refactor: grants validations and _apply_grants logic
1 parent 3bbcff9 commit 27be0df

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
@@ -1724,26 +1724,23 @@ def _apply_grants(
17241724

17251725
model_grants_target_layer = model.grants_target_layer
17261726

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

17481745

17491746
class SymbolicStrategy(EvaluationStrategy):

0 commit comments

Comments
 (0)