Return a list of 2-tuples of the form (expr, (sql, params, is_ref)) for the ORDER BY clause. The order_by clause can alter the select clause (for example it can add aliases to clauses that do not yet have one, or it can add totally new select clauses).
(self)
| 477 | ) |
| 478 | |
| 479 | def get_order_by(self): |
| 480 | """ |
| 481 | Return a list of 2-tuples of the form (expr, (sql, params, is_ref)) for |
| 482 | the ORDER BY clause. |
| 483 | |
| 484 | The order_by clause can alter the select clause (for example it can add |
| 485 | aliases to clauses that do not yet have one, or it can add totally new |
| 486 | select clauses). |
| 487 | """ |
| 488 | result = [] |
| 489 | seen = set() |
| 490 | for expr, is_ref in self._order_by_pairs(): |
| 491 | resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None) |
| 492 | if not is_ref and self.query.combinator and self.select: |
| 493 | src = resolved.expression |
| 494 | expr_src = expr.expression |
| 495 | for sel_expr, _, col_alias in self.select: |
| 496 | if src == sel_expr: |
| 497 | # When values() is used the exact alias must be used to |
| 498 | # reference annotations. |
| 499 | if ( |
| 500 | self.query.has_select_fields |
| 501 | and col_alias in self.query.annotation_select |
| 502 | and not ( |
| 503 | isinstance(expr_src, F) and col_alias == expr_src.name |
| 504 | ) |
| 505 | ): |
| 506 | continue |
| 507 | resolved.set_source_expressions( |
| 508 | [Ref(col_alias if col_alias else src.target.column, src)] |
| 509 | ) |
| 510 | break |
| 511 | else: |
| 512 | # Add column used in ORDER BY clause to the selected |
| 513 | # columns and to each combined query. |
| 514 | order_by_idx = len(self.query.select) + 1 |
| 515 | col_alias = f"__orderbycol{order_by_idx}" |
| 516 | for q in self.query.combined_queries: |
| 517 | # If fields were explicitly selected through values() |
| 518 | # combined queries cannot be augmented. |
| 519 | if q.has_select_fields: |
| 520 | raise DatabaseError( |
| 521 | "ORDER BY term does not match any column in " |
| 522 | "the result set." |
| 523 | ) |
| 524 | q.add_annotation(expr_src, col_alias) |
| 525 | self.query.add_select_col(resolved, col_alias) |
| 526 | resolved.set_source_expressions([Ref(col_alias, src)]) |
| 527 | sql, params = self.compile(resolved) |
| 528 | # Don't add the same column twice, but the order direction is |
| 529 | # not taken into account so we strip it. When this entire method |
| 530 | # is refactored into expressions, then we can check each part as we |
| 531 | # generate it. |
| 532 | without_ordering = self.ordering_parts.search(sql)[1] |
| 533 | params_hash = make_hashable(params) |
| 534 | if (without_ordering, params_hash) in seen: |
| 535 | continue |
| 536 | seen.add((without_ordering, params_hash)) |
no test coverage detected