Skip to content

Commit aa08c29

Browse files
committed
<<< add column names from all tables present after the from keyword
1 parent 0bd70ef commit aa08c29

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

larray_editor/editor.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ class SQLWidget(QTextEdit):
445445
"LIMIT", "OFFSET", "UNION", "ALL",
446446
"VALUES", "SET", "CASE", "WHEN", "THEN", "ELSE", "END"
447447
]
448+
SQL_KEYWORDS_SET = set(SQL_KEYWORDS)
448449

449450
def __init__(self, editor_window):
450451
import polars as pl
@@ -477,15 +478,42 @@ def __init__(self, editor_window):
477478
self.sql_context = pl.SQLContext(eager=False)
478479
self.update_completer_options({})
479480

480-
def update_completer_options(self, data, selected=None):
481-
data = self._filter_data_for_sql(data)
482-
if selected is not None and self._handled_by_polars_sql(selected):
483-
data['self'] = selected
484-
col_names = selected.collect_schema().names()
481+
def update_completer_options(self, data=None, selected=None):
482+
if data is not None:
483+
data = self._filter_data_for_sql(data)
484+
if selected is not None and self._handled_by_polars_sql(selected):
485+
data['self'] = selected
486+
self.data = data
487+
self.sql_context.register_many(data)
485488
else:
486-
col_names = []
487-
self.sql_context.register_many(data)
489+
data = self.data
490+
491+
if 'self' in data:
492+
table_names_to_fetch_columns = ['self']
493+
else:
494+
table_names_to_fetch_columns = []
495+
488496
table_names = [k for k, v in data.items()]
497+
498+
# extract table names from the current FROM clause
499+
query_text = self.toPlainText()
500+
m = re.search(r'\s+FROM\s+(\S+)', query_text, re.IGNORECASE)
501+
if m:
502+
after_from = m.group(1)
503+
# try any identifier found in the query after the FROM keyword
504+
# there will probably be false positives if a column has the same
505+
# name as another table but that should be rare
506+
from_tables = [word for word in after_from.split()
507+
if word not in self.SQL_KEYWORDS_SET and word in data]
508+
if from_tables:
509+
table_names_to_fetch_columns = from_tables
510+
511+
# add column names from all the used tables or self, if present
512+
col_names_set = set()
513+
for table_name in table_names_to_fetch_columns:
514+
col_names_set.update(set(data[table_name].collect_schema().names()))
515+
col_names = sorted(col_names_set)
516+
489517
logger.debug(f"available tables for SQL queries: {table_names}")
490518
logger.debug(f"available columns for SQL queries: {col_names}")
491519
completions = table_names + col_names + self.SQL_KEYWORDS
@@ -520,6 +548,7 @@ def insert_completion(self, completion):
520548
at_end = cursor.position() == len(self.toPlainText())
521549
cursor.insertText(completion + (' ' if at_end else ''))
522550
self.setTextCursor(cursor)
551+
self.update_completer_options()
523552

524553
def keyPressEvent(self, event):
525554
completer_popup = self.completer.popup()
@@ -574,14 +603,17 @@ def keyPressEvent(self, event):
574603
self.clear()
575604
return
576605
super().keyPressEvent(event)
606+
self.update_completer_options()
577607
# we need to compute the prefix *after* the keypress event has been
578-
# handled so that the prefix contains the last key stroke
608+
# handled so that the prefix contains the last keystroke
579609
prefix = self.get_word_prefix()
580610
if prefix:
581611
self.completer.setCompletionPrefix(prefix)
582612
num_completion = self.completer.completionCount()
583-
if (0 < num_completion <= self.completer.maxVisibleItems() and
584-
not completer_popup.isVisible()):
613+
# we must show the popup even if it is already visible, because
614+
# the number of completions might have changed and the popup size
615+
# needs to be updated
616+
if 0 < num_completion <= self.completer.maxVisibleItems():
585617
self.show_autocomplete_popup()
586618
elif num_completion == 0 and completer_popup.isVisible():
587619
completer_popup.hide()
@@ -625,6 +657,7 @@ def search_and_recall_history(self, direction: int):
625657
if self.history[index].startswith(prefix):
626658
self.history_index = index
627659
self.setPlainText(self.history[self.history_index])
660+
self.update_completer_options()
628661
cursor.setPosition(cursor_pos)
629662
self.setTextCursor(cursor)
630663
return True

0 commit comments

Comments
 (0)