Edit on GitHub

sqlglot.optimizer.qualify

  1from __future__ import annotations
  2
  3import typing as t
  4
  5from sqlglot import exp
  6from sqlglot.dialects.dialect import Dialect, DialectType
  7from sqlglot.optimizer.isolate_table_selects import isolate_table_selects
  8from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
  9from sqlglot.optimizer.qualify_columns import (
 10    qualify_columns as qualify_columns_func,
 11    quote_identifiers as quote_identifiers_func,
 12    validate_qualify_columns as validate_qualify_columns_func,
 13)
 14from sqlglot.optimizer.qualify_tables import qualify_tables
 15from sqlglot.schema import Schema, ensure_schema
 16
 17
 18def qualify(
 19    expression: exp.Expression,
 20    dialect: DialectType = None,
 21    db: t.Optional[str] = None,
 22    catalog: t.Optional[str] = None,
 23    schema: t.Optional[dict | Schema] = None,
 24    expand_alias_refs: bool = True,
 25    expand_stars: bool = True,
 26    infer_schema: t.Optional[bool] = None,
 27    isolate_tables: bool = False,
 28    qualify_columns: bool = True,
 29    allow_partial_qualification: bool = False,
 30    validate_qualify_columns: bool = True,
 31    quote_identifiers: bool = True,
 32    identify: bool = True,
 33    canonicalize_table_aliases: bool = False,
 34    on_qualify: t.Optional[t.Callable[[exp.Expression], None]] = None,
 35    sql: t.Optional[str] = None,
 36) -> exp.Expression:
 37    """
 38    Rewrite sqlglot AST to have normalized and qualified tables and columns.
 39
 40    This step is necessary for all further SQLGlot optimizations.
 41
 42    Example:
 43        >>> import sqlglot
 44        >>> schema = {"tbl": {"col": "INT"}}
 45        >>> expression = sqlglot.parse_one("SELECT col FROM tbl")
 46        >>> qualify(expression, schema=schema).sql()
 47        'SELECT "tbl"."col" AS "col" FROM "tbl" AS "tbl"'
 48
 49    Args:
 50        expression: Expression to qualify.
 51        db: Default database name for tables.
 52        catalog: Default catalog name for tables.
 53        schema: Schema to infer column names and types.
 54        expand_alias_refs: Whether to expand references to aliases.
 55        expand_stars: Whether to expand star queries. This is a necessary step
 56            for most of the optimizer's rules to work; do not set to False unless you
 57            know what you're doing!
 58        infer_schema: Whether to infer the schema if missing.
 59        isolate_tables: Whether to isolate table selects.
 60        qualify_columns: Whether to qualify columns.
 61        allow_partial_qualification: Whether to allow partial qualification.
 62        validate_qualify_columns: Whether to validate columns.
 63        quote_identifiers: Whether to run the quote_identifiers step.
 64            This step is necessary to ensure correctness for case sensitive queries.
 65            But this flag is provided in case this step is performed at a later time.
 66        identify: If True, quote all identifiers, else only necessary ones.
 67        canonicalize_table_aliases: Whether to use canonical aliases (_0, _1, ...) for all sources
 68            instead of preserving table names.
 69        on_qualify: Callback after a table has been qualified.
 70        sql: Original SQL string for error highlighting. If not provided, errors will not include
 71            highlighting. Requires that the expression has position metadata from parsing.
 72
 73    Returns:
 74        The qualified expression.
 75    """
 76    schema = ensure_schema(schema, dialect=dialect)
 77    dialect = Dialect.get_or_raise(dialect)
 78
 79    expression = normalize_identifiers(
 80        expression,
 81        dialect=dialect,
 82        store_original_column_identifiers=True,
 83    )
 84    expression = qualify_tables(
 85        expression,
 86        db=db,
 87        catalog=catalog,
 88        dialect=dialect,
 89        on_qualify=on_qualify,
 90        canonicalize_table_aliases=canonicalize_table_aliases,
 91    )
 92
 93    if isolate_tables:
 94        expression = isolate_table_selects(expression, schema=schema)
 95
 96    if qualify_columns:
 97        expression = qualify_columns_func(
 98            expression,
 99            schema,
100            expand_alias_refs=expand_alias_refs,
101            expand_stars=expand_stars,
102            infer_schema=infer_schema,
103            allow_partial_qualification=allow_partial_qualification,
104        )
105
106    if quote_identifiers:
107        expression = quote_identifiers_func(expression, dialect=dialect, identify=identify)
108
109    if validate_qualify_columns:
110        validate_qualify_columns_func(expression, sql=sql)
111
112    return expression
def qualify( expression: sqlglot.expressions.Expression, dialect: Union[str, sqlglot.dialects.Dialect, Type[sqlglot.dialects.Dialect], NoneType] = None, db: Optional[str] = None, catalog: Optional[str] = None, schema: Union[dict, sqlglot.schema.Schema, NoneType] = None, expand_alias_refs: bool = True, expand_stars: bool = True, infer_schema: Optional[bool] = None, isolate_tables: bool = False, qualify_columns: bool = True, allow_partial_qualification: bool = False, validate_qualify_columns: bool = True, quote_identifiers: bool = True, identify: bool = True, canonicalize_table_aliases: bool = False, on_qualify: Optional[Callable[[sqlglot.expressions.Expression], NoneType]] = None, sql: Optional[str] = None) -> sqlglot.expressions.Expression:
 19def qualify(
 20    expression: exp.Expression,
 21    dialect: DialectType = None,
 22    db: t.Optional[str] = None,
 23    catalog: t.Optional[str] = None,
 24    schema: t.Optional[dict | Schema] = None,
 25    expand_alias_refs: bool = True,
 26    expand_stars: bool = True,
 27    infer_schema: t.Optional[bool] = None,
 28    isolate_tables: bool = False,
 29    qualify_columns: bool = True,
 30    allow_partial_qualification: bool = False,
 31    validate_qualify_columns: bool = True,
 32    quote_identifiers: bool = True,
 33    identify: bool = True,
 34    canonicalize_table_aliases: bool = False,
 35    on_qualify: t.Optional[t.Callable[[exp.Expression], None]] = None,
 36    sql: t.Optional[str] = None,
 37) -> exp.Expression:
 38    """
 39    Rewrite sqlglot AST to have normalized and qualified tables and columns.
 40
 41    This step is necessary for all further SQLGlot optimizations.
 42
 43    Example:
 44        >>> import sqlglot
 45        >>> schema = {"tbl": {"col": "INT"}}
 46        >>> expression = sqlglot.parse_one("SELECT col FROM tbl")
 47        >>> qualify(expression, schema=schema).sql()
 48        'SELECT "tbl"."col" AS "col" FROM "tbl" AS "tbl"'
 49
 50    Args:
 51        expression: Expression to qualify.
 52        db: Default database name for tables.
 53        catalog: Default catalog name for tables.
 54        schema: Schema to infer column names and types.
 55        expand_alias_refs: Whether to expand references to aliases.
 56        expand_stars: Whether to expand star queries. This is a necessary step
 57            for most of the optimizer's rules to work; do not set to False unless you
 58            know what you're doing!
 59        infer_schema: Whether to infer the schema if missing.
 60        isolate_tables: Whether to isolate table selects.
 61        qualify_columns: Whether to qualify columns.
 62        allow_partial_qualification: Whether to allow partial qualification.
 63        validate_qualify_columns: Whether to validate columns.
 64        quote_identifiers: Whether to run the quote_identifiers step.
 65            This step is necessary to ensure correctness for case sensitive queries.
 66            But this flag is provided in case this step is performed at a later time.
 67        identify: If True, quote all identifiers, else only necessary ones.
 68        canonicalize_table_aliases: Whether to use canonical aliases (_0, _1, ...) for all sources
 69            instead of preserving table names.
 70        on_qualify: Callback after a table has been qualified.
 71        sql: Original SQL string for error highlighting. If not provided, errors will not include
 72            highlighting. Requires that the expression has position metadata from parsing.
 73
 74    Returns:
 75        The qualified expression.
 76    """
 77    schema = ensure_schema(schema, dialect=dialect)
 78    dialect = Dialect.get_or_raise(dialect)
 79
 80    expression = normalize_identifiers(
 81        expression,
 82        dialect=dialect,
 83        store_original_column_identifiers=True,
 84    )
 85    expression = qualify_tables(
 86        expression,
 87        db=db,
 88        catalog=catalog,
 89        dialect=dialect,
 90        on_qualify=on_qualify,
 91        canonicalize_table_aliases=canonicalize_table_aliases,
 92    )
 93
 94    if isolate_tables:
 95        expression = isolate_table_selects(expression, schema=schema)
 96
 97    if qualify_columns:
 98        expression = qualify_columns_func(
 99            expression,
100            schema,
101            expand_alias_refs=expand_alias_refs,
102            expand_stars=expand_stars,
103            infer_schema=infer_schema,
104            allow_partial_qualification=allow_partial_qualification,
105        )
106
107    if quote_identifiers:
108        expression = quote_identifiers_func(expression, dialect=dialect, identify=identify)
109
110    if validate_qualify_columns:
111        validate_qualify_columns_func(expression, sql=sql)
112
113    return expression

Rewrite sqlglot AST to have normalized and qualified tables and columns.

This step is necessary for all further SQLGlot optimizations.

Example:
>>> import sqlglot
>>> schema = {"tbl": {"col": "INT"}}
>>> expression = sqlglot.parse_one("SELECT col FROM tbl")
>>> qualify(expression, schema=schema).sql()
'SELECT "tbl"."col" AS "col" FROM "tbl" AS "tbl"'
Arguments:
  • expression: Expression to qualify.
  • db: Default database name for tables.
  • catalog: Default catalog name for tables.
  • schema: Schema to infer column names and types.
  • expand_alias_refs: Whether to expand references to aliases.
  • expand_stars: Whether to expand star queries. This is a necessary step for most of the optimizer's rules to work; do not set to False unless you know what you're doing!
  • infer_schema: Whether to infer the schema if missing.
  • isolate_tables: Whether to isolate table selects.
  • qualify_columns: Whether to qualify columns.
  • allow_partial_qualification: Whether to allow partial qualification.
  • validate_qualify_columns: Whether to validate columns.
  • quote_identifiers: Whether to run the quote_identifiers step. This step is necessary to ensure correctness for case sensitive queries. But this flag is provided in case this step is performed at a later time.
  • identify: If True, quote all identifiers, else only necessary ones.
  • canonicalize_table_aliases: Whether to use canonical aliases (_0, _1, ...) for all sources instead of preserving table names.
  • on_qualify: Callback after a table has been qualified.
  • sql: Original SQL string for error highlighting. If not provided, errors will not include highlighting. Requires that the expression has position metadata from parsing.
Returns:

The qualified expression.