|
28 | 28 | # Sufficient to store any value up to 2^63
|
29 | 29 | DEFAULT_ORDERING_ID_LENGTH: int = math.ceil(63 * math.log(2, ORDERING_ID_STRING_BASE))
|
30 | 30 |
|
31 |
| -STABLE_SORTS = ["mergesort", "stable"] |
32 |
| - |
33 | 31 |
|
34 | 32 | class OrderingDirection(Enum):
|
35 | 33 | ASC = 1
|
@@ -113,47 +111,46 @@ def with_non_sequential(self):
|
113 | 111 | def with_ordering_columns(
|
114 | 112 | self,
|
115 | 113 | ordering_value_columns: Sequence[OrderingColumnReference] = (),
|
116 |
| - stable: bool = False, |
117 | 114 | ) -> ExpressionOrdering:
|
118 | 115 | """Creates a new ordering that reorders by the given columns.
|
119 | 116 |
|
120 | 117 | Args:
|
121 | 118 | ordering_value_columns:
|
122 | 119 | In decreasing precedence order, the values used to sort the ordering
|
123 |
| - stable: |
124 |
| - If True, will use apply a stable sorting, using the old ordering where |
125 |
| - the new ordering produces ties. Otherwise, ties will be resolved in |
126 |
| - a performance maximizing way, |
127 | 120 |
|
128 | 121 | Returns:
|
129 | 122 | Modified ExpressionOrdering
|
130 | 123 | """
|
131 | 124 | col_ids_new = [
|
132 | 125 | ordering_ref.column_id for ordering_ref in ordering_value_columns
|
133 | 126 | ]
|
134 |
| - if stable: |
135 |
| - # Only reference each column once, so discard old referenc if there is a new reference |
136 |
| - old_ordering_keep = [ |
137 |
| - ordering_ref |
138 |
| - for ordering_ref in self.ordering_value_columns |
139 |
| - if ordering_ref.column_id not in col_ids_new |
140 |
| - ] |
141 |
| - else: |
142 |
| - # New ordering needs to keep all total ordering columns no matter what. |
143 |
| - # All other old ordering references can be discarded as does not need |
144 |
| - # to be a stable sort. |
145 |
| - old_ordering_keep = [ |
146 |
| - ordering_ref |
147 |
| - for ordering_ref in self.ordering_value_columns |
148 |
| - if (ordering_ref.column_id not in col_ids_new) |
149 |
| - and (ordering_ref.column_id in self.total_ordering_columns) |
150 |
| - ] |
151 |
| - new_ordering = (*ordering_value_columns, *old_ordering_keep) |
| 127 | + old_ordering_keep = [ |
| 128 | + ordering_ref |
| 129 | + for ordering_ref in self.ordering_value_columns |
| 130 | + if ordering_ref.column_id not in col_ids_new |
| 131 | + ] |
| 132 | + |
| 133 | + # Truncate to remove any unneded col references after all total order cols included |
| 134 | + new_ordering = self._truncate_ordering( |
| 135 | + (*ordering_value_columns, *old_ordering_keep) |
| 136 | + ) |
152 | 137 | return ExpressionOrdering(
|
153 | 138 | new_ordering,
|
154 | 139 | total_ordering_columns=self.total_ordering_columns,
|
155 | 140 | )
|
156 | 141 |
|
| 142 | + def _truncate_ordering( |
| 143 | + self, order_refs: tuple[OrderingColumnReference, ...] |
| 144 | + ) -> tuple[OrderingColumnReference, ...]: |
| 145 | + total_order_cols_remaining = set(self.total_ordering_columns) |
| 146 | + for i in range(len(order_refs)): |
| 147 | + column = order_refs[i].column_id |
| 148 | + if column in total_order_cols_remaining: |
| 149 | + total_order_cols_remaining.remove(column) |
| 150 | + if len(total_order_cols_remaining) == 0: |
| 151 | + return order_refs[: i + 1] |
| 152 | + raise ValueError("Ordering did not contain all total_order_cols") |
| 153 | + |
157 | 154 | def with_reverse(self):
|
158 | 155 | """Reverses the ordering."""
|
159 | 156 | return ExpressionOrdering(
|
|
0 commit comments