Edit on GitHub

# sqlglot.optimizer.lower_identities

View Source

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

def lower_identities(expression): View Source

     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.iter_expressions():
    44        if k in traversed:
    45            continue
    46        v.transform(_lower, copy=False)
    47
    48    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