(self)
| 658 | return part_sql, part_args |
| 659 | |
| 660 | def get_qualify_sql(self): |
| 661 | where_parts = [] |
| 662 | if self.where: |
| 663 | where_parts.append(self.where) |
| 664 | if self.having: |
| 665 | where_parts.append(self.having) |
| 666 | inner_query = self.query.clone() |
| 667 | inner_query.subquery = True |
| 668 | inner_query.where = inner_query.where.__class__(where_parts) |
| 669 | # Augment the inner query with any window function references that |
| 670 | # might have been masked via values() and alias(). If any masked |
| 671 | # aliases are added they'll be masked again to avoid fetching |
| 672 | # the data in the `if qual_aliases` branch below. |
| 673 | select = { |
| 674 | expr: alias for expr, _, alias in self.get_select(with_col_aliases=True)[0] |
| 675 | } |
| 676 | select_aliases = set(select.values()) |
| 677 | qual_aliases = set() |
| 678 | replacements = {} |
| 679 | |
| 680 | def collect_replacements(expressions): |
| 681 | while expressions: |
| 682 | expr = expressions.pop() |
| 683 | if expr in replacements: |
| 684 | continue |
| 685 | elif select_alias := select.get(expr): |
| 686 | replacements[expr] = select_alias |
| 687 | elif isinstance(expr, Lookup): |
| 688 | expressions.extend(expr.get_source_expressions()) |
| 689 | elif isinstance(expr, Ref): |
| 690 | if expr.refs not in select_aliases: |
| 691 | expressions.extend(expr.get_source_expressions()) |
| 692 | else: |
| 693 | num_qual_alias = len(qual_aliases) |
| 694 | select_alias = f"qual{num_qual_alias}" |
| 695 | qual_aliases.add(select_alias) |
| 696 | inner_query.add_annotation(expr, select_alias) |
| 697 | replacements[expr] = select_alias |
| 698 | |
| 699 | collect_replacements(list(self.qualify.leaves())) |
| 700 | self.qualify = self.qualify.replace_expressions( |
| 701 | {expr: Ref(alias, expr) for expr, alias in replacements.items()} |
| 702 | ) |
| 703 | order_by = [] |
| 704 | for order_by_expr, *_ in self.get_order_by(): |
| 705 | collect_replacements(order_by_expr.get_source_expressions()) |
| 706 | order_by.append( |
| 707 | order_by_expr.replace_expressions( |
| 708 | {expr: Ref(alias, expr) for expr, alias in replacements.items()} |
| 709 | ) |
| 710 | ) |
| 711 | inner_query_compiler = inner_query.get_compiler( |
| 712 | self.using, connection=self.connection, elide_empty=self.elide_empty |
| 713 | ) |
| 714 | inner_sql, inner_params = inner_query_compiler.as_sql( |
| 715 | # The limits must be applied to the outer query to avoid pruning |
| 716 | # results too eagerly. |
| 717 | with_limits=False, |
no test coverage detected