Edit on GitHub

# sqlglot.optimizer.lower_identities

View Source

     1from sqlglot import exp
     2from sqlglot.helper import ensure_collection
     3
     4
     5def lower_identities(expression):
     6    """
     7    Convert all unquoted identifiers to lower case.
     8
     9    Assuming the schema is all lower case, this essentially makes identifiers case-insensitive.
    10
    11    Example:
    12        >>> import sqlglot
    13        >>> expression = sqlglot.parse_one('SELECT Bar.A AS A FROM "Foo".Bar')
    14        >>> lower_identities(expression).sql()
    15        'SELECT bar.a AS A FROM "Foo".bar'
    16
    17    Args:
    18        expression (sqlglot.Expression): expression to quote
    19    Returns:
    20        sqlglot.Expression: quoted expression
    21    """
    22    # We need to leave the output aliases unchanged, so the selects need special handling
    23    _lower_selects(expression)
    24
    25    # These clauses can reference output aliases and also need special handling
    26    _lower_order(expression)
    27    _lower_having(expression)
    28
    29    # We've already handled these args, so don't traverse into them
    30    traversed = {"expressions", "order", "having"}
    31
    32    if isinstance(expression, exp.Subquery):
    33        # Root subquery, e.g. (SELECT A AS A FROM X) LIMIT 1
    34        lower_identities(expression.this)
    35        traversed |= {"this"}
    36
    37    if isinstance(expression, exp.Union):
    38        # Union, e.g. SELECT A AS A FROM X UNION SELECT A AS A FROM X
    39        lower_identities(expression.left)
    40        lower_identities(expression.right)
    41        traversed |= {"this", "expression"}
    42
    43    for k, v in expression.args.items():
    44        if k in traversed:
    45            continue
    46
    47        for child in ensure_collection(v):
    48            if isinstance(child, exp.Expression):
    49                child.transform(_lower, copy=False)
    50
    51    return expression
    52
    53
    54def _lower_selects(expression):
    55    for e in expression.expressions:
    56        # Leave output aliases as-is
    57        e.unalias().transform(_lower, copy=False)
    58
    59
    60def _lower_order(expression):
    61    order = expression.args.get("order")
    62
    63    if not order:
    64        return
    65
    66    output_aliases = {e.alias for e in expression.expressions if isinstance(e, exp.Alias)}
    67
    68    for ordered in order.expressions:
    69        # Don't lower references to output aliases
    70        if not (
    71            isinstance(ordered.this, exp.Column)
    72            and not ordered.this.table
    73            and ordered.this.name in output_aliases
    74        ):
    75            ordered.transform(_lower, copy=False)
    76
    77
    78def _lower_having(expression):
    79    having = expression.args.get("having")
    80
    81    if not having:
    82        return
    83
    84    # Don't lower references to output aliases
    85    for agg in having.find_all(exp.AggFunc):
    86        agg.transform(_lower, copy=False)
    87
    88
    89def _lower(node):
    90    if isinstance(node, exp.Identifier) and not node.quoted:
    91        node.set("this", node.this.lower())
    92    return node

def lower_identities(expression): View Source

     6def lower_identities(expression):
     7    """
     8    Convert all unquoted identifiers to lower case.
     9
    10    Assuming the schema is all lower case, this essentially makes identifiers case-insensitive.
    11
    12    Example:
    13        >>> import sqlglot
    14        >>> expression = sqlglot.parse_one('SELECT Bar.A AS A FROM "Foo".Bar')
    15        >>> lower_identities(expression).sql()
    16        'SELECT bar.a AS A FROM "Foo".bar'
    17
    18    Args:
    19        expression (sqlglot.Expression): expression to quote
    20    Returns:
    21        sqlglot.Expression: quoted expression
    22    """
    23    # We need to leave the output aliases unchanged, so the selects need special handling
    24    _lower_selects(expression)
    25
    26    # These clauses can reference output aliases and also need special handling
    27    _lower_order(expression)
    28    _lower_having(expression)
    29
    30    # We've already handled these args, so don't traverse into them
    31    traversed = {"expressions", "order", "having"}
    32
    33    if isinstance(expression, exp.Subquery):
    34        # Root subquery, e.g. (SELECT A AS A FROM X) LIMIT 1
    35        lower_identities(expression.this)
    36        traversed |= {"this"}
    37
    38    if isinstance(expression, exp.Union):
    39        # Union, e.g. SELECT A AS A FROM X UNION SELECT A AS A FROM X
    40        lower_identities(expression.left)
    41        lower_identities(expression.right)
    42        traversed |= {"this", "expression"}
    43
    44    for k, v in expression.args.items():
    45        if k in traversed:
    46            continue
    47
    48        for child in ensure_collection(v):
    49            if isinstance(child, exp.Expression):
    50                child.transform(_lower, copy=False)
    51
    52    return expression

Convert all unquoted identifiers to lower case.

Assuming the schema is all lower case, this essentially makes identifiers case-insensitive.

###### Example:

>     >>> import sqlglot
>     >>> expression = sqlglot.parse_one('SELECT Bar.A AS A FROM "Foo".Bar')
>     >>> lower_identities(expression).sql()
>     'SELECT bar.a AS A FROM "Foo".bar'

###### Arguments:

- expression (sqlglot.Expression): expression to quote

###### Returns:

> sqlglot.Expression: quoted expression