Source code for sqlspec.dialects.spanner._spanner

"""Google Cloud Spanner SQL dialect (GoogleSQL variant).

Extends the BigQuery dialect with Spanner-only DDL features: ``INTERLEAVE IN
[PARENT]`` for interleaved tables and ``ROW DELETION POLICY`` for row-level
time-to-live policies. The PostgreSQL-interface ``TTL INTERVAL ... ON`` form
is accepted on parse and normalized to the canonical row deletion policy so
generation always emits valid GoogleSQL.
"""

from typing import TYPE_CHECKING, Any

from sqlglot.dialects.bigquery import BigQuery
from sqlglot.tokenizer_core import TokenType

from sqlspec.dialects.spanner._generators import SpannerGenerator
from sqlspec.dialects.spanner._parsers import SpannerParser, attach_hints, normalize_spanner_tokens

if TYPE_CHECKING:
    from sqlglot import exp
    from sqlglot.tokenizer_core import Token

__all__ = ("Spanner",)


class SpannerTokenizer(BigQuery.Tokenizer):
    """Tokenizer for Spanner GoogleSQL string literal escapes and brace hints."""

    STRING_ESCAPES = ["'", "\\"]
    KEYWORDS = {**BigQuery.Tokenizer.KEYWORDS, "FLOAT32": TokenType.FLOAT, "TOKENLIST": TokenType.USERDEFINED}

    def tokenize(self, sql: str) -> "list[Token]":
        """Tokenize Spanner SQL and normalize ``@{...}`` hints into token comments."""
        return normalize_spanner_tokens(super().tokenize(sql), sql)


[docs] class Spanner(BigQuery): """Google Cloud Spanner SQL dialect.""" Tokenizer = SpannerTokenizer Parser = SpannerParser Generator = SpannerGenerator
[docs] def parse(self, sql: str, **opts: Any) -> "list[exp.Expr | None]": """Parse Spanner SQL statements and attach hints.""" expressions = super().parse(sql, **opts) for expression in expressions: if expression is not None: attach_hints(expression) return expressions
[docs] def parse_into(self, expression_type: Any, sql: str, **opts: Any) -> "list[exp.Expr | None]": """Parse into specific expression type with attached hints.""" expressions = super().parse_into(expression_type, sql, **opts) for expression in expressions: if expression is not None: attach_hints(expression) return expressions