Skip to content

Incremental autocomplete keeps stale candidate ordering after an exact match #2444

Description

@devy1540

What happened?

When the autocomplete popup opens for a short prefix and the user continues typing, the visible list can keep the ranking from the earlier prefix. An exact keyword can remain below a longer function candidate, and the stale first row stays selected for Return or Tab.

For example, after the popup opens for t, completing the token to true can leave the numeric function TRUNCATE(n, decimals) above the exact keyword TRUE:

SELECT * FROM GT_USER
WHERE true

The same problem is reproducible with other candidate pairs, including:

  • n -> null: NULLIF() can remain above NULL
  • i -> in: INSTR() can remain above IN
  • i -> is: ISNULL() can remain above IS
  • r -> regexp: REGEXP_REPLACE() can remain above REGEXP

This is not specific to TRUE. It occurs whenever the correct order changes as the prefix grows while both candidates survive filtering.

Steps to reproduce

  1. Open a SQL query editor.
  2. Enter a query ending in WHERE t.
  3. Wait for the autocomplete popup to open for t.
  4. Continue typing rue without closing the popup.
  5. Observe that TRUNCATE(n, decimals) can remain above TRUE and stays selected.
  6. Close the popup, remove the last character, and type it again so a fresh popup opens for the complete true prefix.
  7. Observe that the fresh ranking places TRUE above TRUNCATE.

The n -> null and i -> in sequences provide additional reproductions.

Expected behavior

The visible completion list should be filtered and ranked for the current full prefix on every incremental update. Exact matches such as TRUE, NULL, and IN should move ahead of longer prefix or fuzzy matches before the first row is selected.

Confirmed cause

QueryCompletionAdapter.completionOnCursorMove immediately returns synchronousRefilter, which calls service.filter and preserves the previous order. scheduleRefilter calculates the correct ranking after a 30 ms debounce, but stores it only in lastRefilterItems; it does not update the visible SuggestionViewModel.items.

Relevant code:

  • TablePro/Views/Editor/QueryCompletionAdapter.swift
  • TablePro/Core/Autocomplete/SQLCompletionService.swift
  • TablePro/Core/Autocomplete/SQLCompletionProvider.swift
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionViewModel.swift

A fresh completion request already performs getCandidates -> filterByPrefix -> rankResults. The stale order is specific to the open-popup cursor-update path.

Acceptance criteria

  • Incremental completion updates return candidates ranked for the current prefix.
  • t -> true places TRUE before TRUNCATE().
  • n -> null places NULL before NULLIF().
  • i -> in places IN before INSTR().
  • The first selected row matches the newly ranked first item.
  • SQL and MongoDB completion behavior remains covered by targeted tests.

Environment

  • TablePro: 0.68.0
  • macOS: 26.6.2
  • Architecture: Apple Silicon
  • Database type: SQL completion path; the ranking code is shared across SQL dialects

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions