Return the dictionary with the values of the existing aggregations.
(self, using, aggregate_exprs)
| 455 | return target.get_col(alias, field) |
| 456 | |
| 457 | def get_aggregation(self, using, aggregate_exprs): |
| 458 | """ |
| 459 | Return the dictionary with the values of the existing aggregations. |
| 460 | """ |
| 461 | if not aggregate_exprs: |
| 462 | return {} |
| 463 | # Store annotation mask prior to temporarily adding aggregations for |
| 464 | # resolving purpose to facilitate their subsequent removal. |
| 465 | refs_subquery = False |
| 466 | refs_window = False |
| 467 | replacements = {} |
| 468 | annotation_select_mask = self.annotation_select_mask |
| 469 | for alias, aggregate_expr in aggregate_exprs.items(): |
| 470 | self.check_alias(alias) |
| 471 | aggregate = aggregate_expr.resolve_expression( |
| 472 | self, allow_joins=True, reuse=None, summarize=True |
| 473 | ) |
| 474 | if not aggregate.contains_aggregate: |
| 475 | raise TypeError("%s is not an aggregate expression" % alias) |
| 476 | # Temporarily add aggregate to annotations to allow remaining |
| 477 | # members of `aggregates` to resolve against each others. |
| 478 | self.append_annotation_mask([alias]) |
| 479 | aggregate_refs = aggregate.get_refs() |
| 480 | refs_subquery |= any( |
| 481 | getattr(self.annotations[ref], "contains_subquery", False) |
| 482 | for ref in aggregate_refs |
| 483 | ) |
| 484 | refs_window |= any( |
| 485 | getattr(self.annotations[ref], "contains_over_clause", True) |
| 486 | for ref in aggregate_refs |
| 487 | ) |
| 488 | aggregate = aggregate.replace_expressions(replacements) |
| 489 | self.annotations[alias] = aggregate |
| 490 | replacements[Ref(alias, aggregate)] = aggregate |
| 491 | # Stash resolved aggregates now that they have been allowed to resolve |
| 492 | # against each other. |
| 493 | aggregates = {alias: self.annotations.pop(alias) for alias in aggregate_exprs} |
| 494 | self.set_annotation_mask(annotation_select_mask) |
| 495 | # Existing usage of aggregation can be determined by the presence of |
| 496 | # selected aggregates but also by filters against aliased aggregates. |
| 497 | _, having, qualify = self.where.split_having_qualify() |
| 498 | has_existing_aggregation = ( |
| 499 | any( |
| 500 | getattr(annotation, "contains_aggregate", True) |
| 501 | for annotation in self.annotations.values() |
| 502 | ) |
| 503 | or having |
| 504 | ) |
| 505 | set_returning_annotations = { |
| 506 | alias |
| 507 | for alias, annotation in self.annotation_select.items() |
| 508 | if getattr(annotation, "set_returning", False) |
| 509 | } |
| 510 | # Decide if we need to use a subquery. |
| 511 | # |
| 512 | # Existing aggregations would cause incorrect results as |
| 513 | # get_aggregation() must produce just one result and thus must not use |
| 514 | # GROUP BY. |
no test coverage detected