sqlglot.optimizer.lower_identities
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):
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