Skip to content

Autocomplete#46

Merged
Maxteabag merged 23 commits intomainfrom
autocomplete
Dec 27, 2025
Merged

Autocomplete#46
Maxteabag merged 23 commits intomainfrom
autocomplete

Conversation

@Maxteabag
Copy link
Owner

@Maxteabag Maxteabag commented Dec 27, 2025

This update introduces a sophisticated SQL completion engine with context-aware DML/DDL suggestions, leveraging schema caching and lazy loading table metadata for autocompletions, and a new idle scheduler for background jobs.

It also adds cross-database query handling with capability detection, adapter improvements for various databases.

If we have not selected a default database, It adds a UI indicator of what database we are connected to.
We will automatically "use" a database when we expand on it using 'Enter' replacing 'u' to use.

Table expansion and querying is now more robust for databases that does not support cross-db queries.

This will fix postgres and D1 tables expanding as (empty) when not having selected a default database, as well as querying errors when connected to an Azure SQL database. For databases such as these, will automatically default to reconnecting behind the scenes, instead of "use," while giving the user the experience of still being connected to the server.

Fixes #43
Highly likely fixes #4

- New SQL completion engine using sqlparse for context detection
- Suggests tables after FROM/JOIN, columns after WHERE/SELECT, operators after column names
- Lazy loading of columns to avoid UI lag during schema indexing
- Scrollable autocomplete dropdown with keyboard navigation
- Auto-hide when cursor moves away from typing position
- Fuzzy matching and alias resolution support

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Previously, an empty string password was treated differently from None,
meaning connections with empty passwords would fail instead of prompting
the user. Now both None and empty string trigger the password prompt.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Azure SQL Database does not support cross-database queries or USE
statements. This fix:

- Adds _get_cursor_for_database() that tries USE first (fast for
  regular SQL Server), then falls back to creating a new connection
  with the target database (for Azure SQL)
- Stores config and driver on connection object for reconnection
- Removes all cross-database reference syntax ([Database].schema.table)
- Updates all adapter methods to use the new approach

Also adds unit tests verifying no cross-database references are used,
and integration tests for Azure SQL Database.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reorganizes sql_completion.py into a package with separate modules:
- core.py: base classes and utilities
- completion.py: main SQLCompletion class
- alter_table.py, create_table.py, create_index.py, create_view.py,
  delete.py, drop.py, insert.py, truncate.py, update.py: statement handlers

Also introduces QueryTextArea widget that wraps TextArea with SQL
autocomplete functionality, simplifying the integration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Return empty completions when there's no SQL content yet (just
  whitespace). This prevents showing irrelevant keywords when pressing
  space/enter on an empty query.
- Add handlers for IN ( and EXISTS ( patterns to suggest SELECT for
  subqueries.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
For Azure SQL Database, clicking a table from a different database now
correctly executes the query against that database:

- build_select_query no longer includes [database] prefix (breaks Azure)
- Added _query_target_database to track which database to query
- Query execution uses apply_database_override when target differs
- Target database is cleared after use to not affect user-typed queries

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…database

When connected without a default database (multiple databases visible),
autocomplete now suggests fully qualified names like [db].[schema].[table]
instead of just table names. This allows queries to work correctly.

Uses adapter.quote_identifier() for proper quoting (brackets for SQL Server).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Idle Scheduler:
- Add idle scheduler inspired by browser's requestIdleCallback API
- Execute background work during user idle periods (500ms threshold)
- Queue schema loading (tables/views/procedures) as idle jobs
- Add --debug-idle-scheduler flag to show scheduler status bar
- Preload columns for tables found in query editor during idle

Shared Cache:
- Tree and autocomplete now share _db_object_cache for tables/views/procedures
- Expanding tree nodes populates autocomplete cache and vice versa
- Refresh ('f') clears both object cache and column cache

Azure SQL:
- Add separate AzureSQLAdapter with required database field
- Simplify MSSQL adapter by removing Azure-specific fallback logic

Autocomplete UX:
- Add *, DISTINCT, TOP, ALL to SELECT clause completions
- Remove table names from SELECT suggestions (belong after FROM)
- Dropdown stays visible when window loses focus
- Dropdown constrained to stay within bounds (no right-edge cutoff)
- Enter now hides the autocomplete dropdown and inserts a newline
- Only Tab accepts autocomplete suggestions
- Added suppress flag to prevent autocomplete from re-triggering
  after Enter dismisses it (newline text change was re-showing dropdown)
Introduces _active_database separate from current_config.database to
preserve tree structure while allowing users to set a preferred database.

- Added get/set_database_preference() to config.py for persistence
- On connect: load cached preference into _active_database
- On 'u' press: save preference and reload schema for new database
- On disconnect: clear _active_database
- Star display in tree now uses _active_database
- Autocomplete schema loading now respects _active_database

The connection config (and tree structure) remains unchanged - only the
user's runtime preference is cached in settings.json.
- Add system_databases property to DatabaseAdapter base class
- Define system databases for each adapter:
  - MSSQL: master, tempdb, model, msdb
  - PostgreSQL: template0, template1
  - MySQL/MariaDB: mysql, information_schema, performance_schema, sys
  - ClickHouse: system, information_schema
  - Snowflake: SNOWFLAKE
- Update autocomplete to filter using adapter.system_databases
- ESC key now closes autocomplete AND exits to normal mode
- Add unit tests for system_databases property
Add priority=True to escape bindings on all modal screens to ensure
ESC key is handled correctly when other bindings are active.
Flatten multi-line error messages to single line since DataTable cells
only display one line. Replaces textwrap with regex whitespace collapse.
- Add supports_cross_database_queries property to DatabaseAdapter
  - Returns True for MSSQL, MySQL, ClickHouse, Snowflake (support USE)
  - Returns False for PostgreSQL, CockroachDB, D1 (require reconnection)
- Add switch_database() method to ConnectionSession for reconnecting
  to a different database while reusing SSH tunnel
- Auto-switch database when expanding database nodes or their contents
  - For cross-db adapters: sets active database (USE approach)
  - For non-cross-db adapters: reconnects to the database
  - Falls back to reconnection if USE fails (e.g., Azure SQL)
- Remove 'u' keybinding - Enter on database node now sets it active
- Apply active database to query execution context
- Add helper functions in providers.py for database requirement checks
- Update tests with new mock attributes
Azure SQL is now handled by the MSSQL adapter with automatic fallback:
- If USE statement fails, automatically reconnect to target database
- Retry the operation after reconnection
- Show original error only if reconnection also fails

This makes Azure SQL work transparently without a separate adapter.
Previously, typing a semicolon after a complete statement would show
irrelevant suggestions (tables or keywords). Now the autocomplete
popup hides when the cursor is immediately after a semicolon.
- Only prompt for password when password is None (not set), not when
  it's an empty string (explicitly set to empty)
- Some databases allow passwordless connections, so "" should be valid
- Remove Azure SQL adapter tests (adapter was removed)
@Maxteabag Maxteabag merged commit 4831ded into main Dec 27, 2025
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Postgres tables are empty in multi-database view not able to fetch tables with connection without DB name

1 participant