diff --git a/core/dbt/clients/jinja_static.py b/core/dbt/clients/jinja_static.py index 16ebd2044fc..a57c96642a1 100644 --- a/core/dbt/clients/jinja_static.py +++ b/core/dbt/clients/jinja_static.py @@ -173,12 +173,10 @@ def statically_parse_ref(input: str) -> RefArgs: try: statically_parsed = py_extract_from_source(f"{{{{ {input} }}}}") except ExtractionError: - # TODO: more precise error - raise ParsingError(f"Invalid jinja expression: {input}.") + raise ParsingError(f"Invalid jinja expression: {input}") - if not statically_parsed["refs"]: - # TODO: more precise error class - raise ParsingError("not a ref") + if not statically_parsed.get("refs"): + raise ParsingError(f"Invalid ref expression: {input}") ref = list(statically_parsed["refs"])[0] return RefArgs(package=ref.get("package"), name=ref.get("name"), version=ref.get("version")) @@ -198,12 +196,10 @@ def statically_parse_source(input: str) -> Tuple[str, str]: try: statically_parsed = py_extract_from_source(f"{{{{ {input} }}}}") except ExtractionError: - # TODO: more precise error - raise ParsingError(f"Invalid jinja expression: {input}.") + raise ParsingError(f"Invalid jinja expression: {input}") - if not statically_parsed["sources"]: - # TODO: more precise error class - raise ParsingError("not a ref") + if not statically_parsed.get("sources"): + raise ParsingError(f"Invalid source expression: {input}") source = list(statically_parsed["sources"])[0] source_name, source_table_name = source diff --git a/core/dbt/compilation.py b/core/dbt/compilation.py index d662d9c8e49..5c20f7fd641 100644 --- a/core/dbt/compilation.py +++ b/core/dbt/compilation.py @@ -29,7 +29,9 @@ from dbt.exceptions import ( DbtInternalError, DbtRuntimeError, + ForeignKeyConstraintToSyntaxError, GraphDependencyNotFoundError, + ParsingError, ) from dbt.flags import get_flags from dbt.graph import Graph @@ -465,7 +467,11 @@ def _compile_code( def _compile_relation_for_foreign_key_constraint_to( self, manifest: Manifest, node: ManifestSQLNode, to_expression: str ) -> str: - foreign_key_node = manifest.find_node_from_ref_or_source(to_expression) + try: + foreign_key_node = manifest.find_node_from_ref_or_source(to_expression) + except ParsingError: + raise ForeignKeyConstraintToSyntaxError(node, to_expression) + if not foreign_key_node: raise GraphDependencyNotFoundError(node, to_expression) adapter = get_adapter(self.config) diff --git a/core/dbt/contracts/graph/manifest.py b/core/dbt/contracts/graph/manifest.py index b6d445ce05d..587c14a8046 100644 --- a/core/dbt/contracts/graph/manifest.py +++ b/core/dbt/contracts/graph/manifest.py @@ -70,6 +70,7 @@ AmbiguousResourceNameRefError, CompilationError, DuplicateResourceNameError, + ParsingError, ) from dbt.flags import get_flags from dbt.mp_context import get_mp_context @@ -1643,17 +1644,15 @@ def find_node_from_ref_or_source( valid_source = True try: ref = statically_parse_ref(expression) - # TODO: better error handling - except Exception: + except ParsingError: valid_ref = False try: source_name, source_table_name = statically_parse_source(expression) - # TODO: better error handling - except Exception: + except ParsingError: valid_source = False if not valid_ref and not valid_ref: - raise CompilationError(f"Invalid ref or source expression: {expression}") + raise ParsingError(f"Invalid ref or source syntax: {expression}.") if valid_ref: node = self.ref_lookup.find(ref.name, ref.package, ref.version, self) diff --git a/core/dbt/exceptions.py b/core/dbt/exceptions.py index aec2b5e3826..27aa863fd17 100644 --- a/core/dbt/exceptions.py +++ b/core/dbt/exceptions.py @@ -136,6 +136,18 @@ def get_message(self) -> str: return msg +class ForeignKeyConstraintToSyntaxError(CompilationError): + def __init__(self, node, expression: str) -> None: + self.expression = expression + self.node = node + super().__init__(msg=self.get_message()) + + def get_message(self) -> str: + msg = f"'{self.node.unique_id}' defines a foreign key constraint 'to' expression which is not valid 'ref' or 'source' syntax: {self.expression}." + + return msg + + # client level exceptions