|
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