Area: Ingestion
Sub-Area: SQL Parsing
Issue
SQL queries from data warehouse logs are failing to parse correctly, resulting in missing or incorrect lineage. This commonly occurs with complex SQL queries, non-standard SQL dialects, or unsupported SQL features.
Common Error Messages:
SQL parsing failed for queryUnable to extract table referencesUnsupported SQL syntaxParseException at line X
You Might Be Asking:
- Why isn't my SQL query parsing correctly?
- Which SQL dialects are supported?
- Can I improve SQL parsing accuracy?
Solution
- Configure SQL parser in ingestion:
Example for Snowflake. This can be adapted for other data sources/connectors like BigQuery, Redshift, or other SQL-based platforms.
source:
type: snowflake
config:
include_table_lineage: true
# Choose SQL parser
sql_parser: "sqlglot" # Recommended (default)
# Alternative: "sql-metadata" (faster, less comprehensive)
# SQL parsing options
sql_parser_config:
use_external_process: true
timeout_seconds: 30
- Handle complex SQL patterns:
source:
config:
# For queries with CTEs, temp tables, etc.
parse_queries_with_ctes: true
# Handle dialect-specific features
sql_dialect: "snowflake" # or "bigquery", "postgres", etc.
# Fallback for unparseable queries
sql_parsing_fallback: "skip" # or "log_warning"
- Pre-process queries before parsing:
from datahub.utilities.sql_parser import SQLParser
def preprocess_query(sql):
# Remove comments
sql = re.sub(r'--.*?$', '', sql, flags=re.MULTILINE)
sql = re.sub(r'/\*.*?\*/', '', sql, flags=re.DOTALL)
# Normalize whitespace
sql = ' '.join(sql.split())
# Handle dialect-specific syntax
sql = sql.replace('`', '"') # BigQuery to standard
return sql
# Use in custom ingestion
parser = SQLParser(preprocess_query(raw_sql))
tables = parser.get_tables()
- Debug SQL parsing issues:
from datahub.utilities.sql_parser import SQLParser
import logging
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
# Test specific query
sql = """
INSERT INTO target_table
SELECT t1.*, t2.amount
FROM source_table_1 t1
JOIN source_table_2 t2 ON t1.id = t2.id
"""
try:
parser = SQLParser(sql, dialect="snowflake")
tables = parser.get_tables()
print(f"Source tables: {tables}")
except Exception as e:
print(f"Parsing failed: {e}")
# Log the problematic query
with open("failed_queries.log", "a") as f:
f.write(f"\n\nFailed query:\n{sql}\nError: {e}\n")
- Use manual lineage for unparseable queries:
Example for Snowflake. This can be adapted for other data sources/connectors.
# For queries that can't be parsed, emit manual lineage
from datahub.emitter.mce_builder import make_dataset_urn
from datahub.metadata.schema_classes import UpstreamLineageClass, UpstreamClass
# If SQL parsing fails, define lineage explicitly
upstream_lineage = UpstreamLineageClass(
upstreams=[
UpstreamClass(
dataset=make_dataset_urn("snowflake", "db.schema.source1"),
type="TRANSFORMED"
),
UpstreamClass(
dataset=make_dataset_urn("snowflake", "db.schema.source2"),
type="TRANSFORMED"
)
]
)
emitter.emit_mcp(
entity_urn=make_dataset_urn("snowflake", "db.schema.target"),
aspect_name="upstreamLineage",
aspect=upstream_lineage
)
Additional Notes
SQLglot parser handles most standard SQL and many dialect-specific features. For very complex queries or proprietary SQL extensions, consider using manual lineage. Log failed queries for analysis and parser improvement.
Related Documentation
Tags:
sql-parsing, lineage, sqlglot, query-parsing, sql-dialects, parsing-errors, query-analysis, cte