|
1 | 1 | import io |
2 | 2 | import logging |
3 | | -import threading |
4 | 3 | import tkinter as tk |
5 | 4 | from functools import partial |
6 | 5 | from math import ceil, floor, isinf, isnan |
|
15 | 14 | duckdb_dtype_is_numeric, |
16 | 15 | duckdb_dtype_to_datatype_choice, |
17 | 16 | duckdb_escape_identifier, |
18 | | - duckdb_escape_literal, |
19 | 17 | ) |
20 | 18 |
|
21 | 19 | logger = logging.getLogger(__name__) |
@@ -239,71 +237,37 @@ def set_sort_order(self, column_num: int, descending: Optional[bool] = None): |
239 | 237 | self.sort_ascending = not descending |
240 | 238 | self.sort_by_col = column_num |
241 | 239 |
|
242 | | - # Include all column names for a stable sort order. |
| 240 | + # Create an index for whatever column we're sorting by, followed by |
| 241 | + # all other column names for a stable sort order. |
| 242 | + |
243 | 243 | column_name = self.table.columns[column_num] |
244 | 244 | escaped_column_names = [ |
245 | 245 | duckdb_escape_identifier(c) for c in [column_name] + [c for c in self.table.columns if c != column_name] |
246 | 246 | ] |
247 | 247 |
|
248 | | - # We add an index for whatever column we're sorting by, |
249 | | - # if it doesn't already exist. |
250 | | - # XXX could do this in a thread? |
251 | | - index_name = f"{self.table.alias}__{column_name}__idx" |
252 | | - index_identifier = duckdb_escape_identifier(index_name) |
253 | | - index_literal = duckdb_escape_literal(index_name) |
| 248 | + index_identifier = f"{self.table.alias}_{column_num}_idx" |
254 | 249 |
|
255 | | - def _create_index_continue(): |
256 | | - direction = "ASC" if self.sort_ascending else "DESC" |
257 | | - self.table_order = ",".join(f"{c} {direction}" for c in escaped_column_names) |
| 250 | + # XXX I did have some code here which built the index in a separate thread / cursor but it |
| 251 | + # was mad with race conditions so I've scrapped it for now and the GUI will just have to |
| 252 | + # awkwardly pause. |
258 | 253 |
|
259 | | - logger.debug("TabularDataFrame set_sort_order %s %s", column_name, self.table_order) |
| 254 | + sql = ( |
| 255 | + f"CREATE INDEX IF NOT EXISTS {index_identifier} ON {self.table.alias} (" |
| 256 | + + ",".join(escaped_column_names) |
| 257 | + + ")" |
| 258 | + ) |
| 259 | + self.ddbc.sql(sql) |
260 | 260 |
|
261 | | - for n, label in enumerate(self.labels): |
262 | | - icon = "sort_un" if n != column_num else "sort_up" if self.sort_ascending else "sort_dn" |
263 | | - label.configure(image=get_icon(self, icon)) |
| 261 | + direction = "ASC" if self.sort_ascending else "DESC" |
| 262 | + self.table_order = ",".join(f"{c} {direction}" for c in escaped_column_names) |
264 | 263 |
|
265 | | - self.refresh() |
| 264 | + logger.debug("TabularDataFrame set_sort_order %s %s", column_name, self.table_order) |
266 | 265 |
|
267 | | - # XXX workaround for https://github.com/duckdb/duckdb/issues/16086 |
268 | | - if not self.ddbc.sql(f"select 1 from duckdb_indexes() where index_name = {index_literal}"): |
269 | | - cursor = self.ddbc.cursor() |
270 | | - cursor.sql("set enable_progress_bar_print=false") |
271 | | - cursor.sql("set progress_bar_time=0") |
272 | | - |
273 | | - if self._set_sort_order_thread and self._set_sort_order_thread.is_alive(): |
274 | | - logger.debug("TabularDataFrame set_sort_order thread already running") |
275 | | - self._set_sort_order_thread.join() |
276 | | - |
277 | | - def _create_index_thread(): |
278 | | - sql = ( |
279 | | - f"CREATE INDEX IF NOT EXISTS {index_identifier} ON {self.table.alias} (" |
280 | | - + ",".join(escaped_column_names) |
281 | | - + ")" |
282 | | - ) |
283 | | - logger.debug("TabularDataFrame set_sort_order index sql %s", sql) |
284 | | - cursor.sql(sql) |
285 | | - |
286 | | - self._set_sort_order_thread = threading.Thread(target=_create_index_thread) |
287 | | - self._set_sort_order_thread.start() |
288 | | - |
289 | | - def _create_index_monitor(): |
290 | | - if self._set_sort_order_thread.is_alive(): |
291 | | - try: |
292 | | - qp = cursor.query_progress() |
293 | | - except AttributeError: |
294 | | - qp = 50 |
295 | | - |
296 | | - if qp >= 0: |
297 | | - logger.info("Indexing: %d%%", qp) |
298 | | - self.after(50, _create_index_monitor) |
299 | | - else: |
300 | | - self._set_sort_order_thread.join() |
301 | | - logger.info("Indexing: 100%") |
302 | | - _create_index_continue() |
303 | | - |
304 | | - self.after(50, _create_index_monitor) |
305 | | - else: |
306 | | - _create_index_continue() |
| 266 | + for n, label in enumerate(self.labels): |
| 267 | + icon = "sort_un" if n != column_num else "sort_up" if self.sort_ascending else "sort_dn" |
| 268 | + label.configure(image=get_icon(self, icon)) |
| 269 | + |
| 270 | + self.refresh() |
307 | 271 |
|
308 | 272 | def _label_button_1(self, num, event): |
309 | 273 | """Click on column labels to set sort order""" |
|
0 commit comments