#SQL completion: scope, settings, and verification
The JustyBase SQL editor provides SQL completion through the language server. The server combines the active dialect's keyword and function catalog with parser-derived statement scope, local definitions, and database metadata. The editor can complete table and column names without asking the live database catalog while you type.
#What completion covers
#SQL structure and identifiers
- Dialect-aware keywords, built-in functions, types, and special values.
- Object targets after statements such as
SELECT ... FROM,INSERT INTO,UPDATE,DELETE,CREATE,ALTER,DROP,CALL,EXEC, andEXECUTEwhere the active dialect provides the corresponding path. - Database, schema, and table paths, including Netezza
DATABASE..TABLEpaths and dialect-specific two- or three-part names. - Tables, views, and other relation-like sources provided by the active dialect.
- Columns for a table or view, qualified columns after
alias., and partial qualified names such asalias.CUST. - Table aliases and projected names resolved from the current statement, visible CTEs, nested queries, local definitions, and local or temporary tables tracked by the editor.
SELECTandINSERTcontext suggestions, wildcard expansion, and scope-aware filtering. The parser keeps nested query scopes separate and only exposes CTEs that are visible at the cursor.- Identifier matching by direct prefix, compact spelling,
snake_case/camelCaseword starts, delimited initials, and multi-character name fragments. Direct matches rank first; fuzzy matches are lower in the list. One-character fragments do not create broad substring matches.
Quoted CTE names remain limited by the SQL grammar. Other quoted table, schema, alias, and column identifiers are supported where the active dialect parser accepts them.
#JOIN completion
Type JOIN after a table source to see related-table suggestions. A suggestion can insert a dialect-qualified table path, a unique alias, and an ON predicate. Type ON at an empty condition to see available predicates for the tables already in the statement.
The relation sources are ranked as follows:
- Workspace
justybase.sql.joinRelationsentries. These are exact, explicit mappings, support composite keys and different column names, and work for dialects without catalog FK metadata (including virtual Netezza relationships). - Declared catalog foreign keys, when the active dialect's metadata provider exposes them and the relationship is present in the refreshed cache. Composite constraints remain grouped together in catalog order. Exact FK targets in another cached schema are included by their endpoint identity; name/key heuristics remain limited to the source schema.
- Optional name/key heuristics from cached columns. These compare normalized column names and cached PK/FK flags; they are suggestions, not proof of a database constraint.
Exact configured or declared pairs rank before heuristics. joinNameHeuristics controls only heuristic suggestions; turning it off keeps exact workspace and catalog relationships. Completion reads this data from metadata cache and does not query system catalogs while typing. Catalog FK adapters currently populate exact endpoint pairs for Netezza, Db2, MSSQL, MySQL, Oracle, PostgreSQL, and Vertica. Other dialects can use workspace relationships and any cached heuristic matches available to them.
Generated aliases are unique within the current statement. By default the editor uses a table-name initial (or initials for a multi-part name) and adds numeric suffixes for collisions. A workspace alias override takes priority. Disabling automatic aliases removes the generated alias; it does not change source aliases already present in the SQL.
#Function and window-function completion
Function items show available parameter signatures. Accepting a function inserts a snippet with argument tab stops. Window-required functions such as ROW_NUMBER, RANK, DENSE_RANK, LAG, and LEAD insert OVER (...) automatically. The cursor lands inside the OVER parentheses; for LAG and LEAD, argument stops come first.
Functions that support both ordinary aggregate and window use show separate items. SUM and COUNT keep their normal aggregate item and also offer a window variant such as SUM(expression) OVER (...). A window item is inserted only when it is accepted. The completion edit replaces the typed prefix and preserves text to the right of the cursor. Window snippets add one OVER clause; signature examples are not inserted as extra clauses.
The available functions and keywords follow the active DatabaseSqlAuthoring profile, so dialect catalogs can differ.
#JOIN workspace settings
These examples can go in the workspace .vscode/settings.json or the VS Code workspace settings UI. Table identity fields are case-insensitive. Configured database and schema values act as exact identity constraints. When SQL names a table without a schema, a schema-qualified setting matches only if the active schema is known and matches; otherwise qualify the SQL source or omit schema from the setting when that table name is unique in the searched scope. An omitted setting component with no active context is a wildcard, so avoid it when names can collide.
{
"justybase.sql.joinNameHeuristics": true,
"justybase.sql.autoJoinAliases": true,
"justybase.sql.joinAliases": [
{
"table": { "database": "ANALYTICS", "schema": "PUBLIC", "table": "ORDERS" },
"alias": "ord"
}
],
"justybase.sql.joinRelations": [
{
"left": { "database": "ANALYTICS", "schema": "PUBLIC", "table": "CUSTOMER" },
"right": { "database": "ANALYTICS", "schema": "PUBLIC", "table": "ORDERS" },
"columns": [
{ "left": "TENANT_KEY", "right": "TENANT_ID" },
{ "left": "CUSTOMER_KEY", "right": "CUSTOMER_ID" }
]
}
]
}The example produces both predicates, in the declared order. The relationship works in either table order. For Netezza, use the database and schema from the metadata browser; use a virtual relationship when Netezza objects have no declared FK constraint. Malformed entries and empty column pairs are ignored.
#Manual verification
#Prepare metadata
- Configure a connection in the JustyBase connection view and connect to the intended database.
- Refresh schema metadata. For exact FK suggestions, make sure the selected tables' column metadata has been loaded. Metadata is retained in the disk cache when supported by the current connection/cache configuration.
- Open a SQL file associated with that connection. Use
Ctrl+Spaceto request completion. The LSP's cache-only completion path must not run catalog queries while you type.
#Verify ordinary completion
- Type
SELECT * FROMand request completion. Expect visible tables and relation-like objects from the active database/schema. - Type
INSERT INTOandUPDATEin separate statements. Expect valid object targets for the active dialect. - Type
SELECT u.afterFROM USERS u. Expect columns forUSERS, not columns from unrelated tables. - Type a partial form such as
u.CUST,customerName,customer_name, oraiforACCOUNT_ID. Expect case-insensitive acronym matches below exact-prefix results. A one-letter fragment should not flood the list with arbitrary substring matches. - Add a CTE and a nested query. Expect only definitions visible at the cursor and aliases from the current query scope.
- In schemas that require qualification, start from an unqualified table source and accept an object completion. Confirm the insertion uses the active dialect's normal database/schema path. For Netezza also check
DATABASE..TABLEand schema-qualified paths.
#Verify JOIN targets, aliases, and predicates
- Type
SELECT * FROM CUSTOMER c JOINand request completion. With a configured virtual relationship, expectORDERS, its unique alias, and the two mapped predicates in the candidate. With catalog FK metadata, expect the exact FK columns. A matching-name heuristic may appear lower in the list. - Accept the candidate. Expect one table path, one alias, and one
ONclause. Add another table that would produce the same default alias; expect a suffix such asO2rather than a duplicate alias. - Type
SELECT * FROM CUSTOMER c JOIN ORDERS o ONand request completion. Expect the configured/catalog composite predicate as one item withANDbetween pairs. Reverse the source/target table order and confirm the equality direction is reversed correctly. - Set
"justybase.sql.joinNameHeuristics": false. Expect name/key-only matches to disappear while configured and declared FK relationships remain. - Set
"justybase.sql.autoJoinAliases": false. Expect the target path and predicate with no generated target alias. Add ajoinAliasesoverride and confirm that alias is used when automatic aliasing is enabled. - For a schema-qualified dialect, verify the accepted target keeps the required schema/database qualification. For Netezza, verify default-schema targets retain the supported double-dot form where appropriate.
- Repeat for a Netezza virtual relation, then repeat after changing a workspace relationship. The next completion request should use the new workspace setting without requiring a catalog query.
- For a declared cross-schema FK, put the source table in one schema and its referenced table in another. Expect the exact target and FK predicate with target schema qualification; same-name/key heuristics from other schemas should not appear.
#Verify function snippets and cursor behavior
- Type
SELECT ROW_NUMand acceptROW_NUMBER. ExpectROW_NUMBER() OVER (...)with the caret inside the parentheses. - Accept
LAGandLEAD. Expect argument tab stops before theOVERtab stop. - Request
SUMandCOUNT. Confirm there is a plain aggregate item and a separate window item. Accept each variant and confirm only the window variant insertsOVER (...). - Repeat with a partial function prefix and SQL text after the cursor, for example
SELECT ROW| + 1. AcceptROW_NUMBER; expect the suffix+ 1to remain and exactly oneOVERin the inserted snippet.
#Verify cache after restart
- Refresh metadata and run the
JOINand emptyONchecks once so columns and relation endpoint metadata are cached. - Close and reopen VS Code, reconnect, and repeat completion without manually forcing a new schema refresh.
- Expect the same table, column, and exact FK suggestions from disk-backed metadata. Completion must not perform a live catalog query while typing.
#Automated checks
Focused completion and cache checks:
npm run test -- --runInBand --testPathPatterns="completionEngine.test.ts|completionRenderer.test.ts|completionJoinConditions.test.ts|joinCompletionSettings.test.ts|columnMetadataService.test.ts|metadataColumnCodec.test.ts"
npm run test:metadata-cache:integration
npm run benchmark:lsp
LSP_BENCHMARK_ENFORCE=1 npm run benchmark:lspThe LSP benchmark includes ordinary and JOIN completion with 200 and 1000 cached tables, for cold and warm cache. It reports median and p95 request time, metadata reads per request, and maximum read concurrency. Completion uses the existing limits: median at most 150 ms and p95 at most 300 ms.
Live catalog completion/relationship checks:
npm run test:netezza:integration
npm run test:mssql:integration
npm run test:mysql:integration
npm run test:oracle:integration
npm run test:postgres:integration
npm run test:db2:integration
npm run test:vertica:integrationThe suites use their dialect-specific *_LIVE_TEST_* variables; Netezza uses NZ_DEV_HOST, NZ_DEV_PORT, NZ_DEV_USER, NZ_DEV_PASSWORD, and NZ_DEV_DATABASE for the main integration gate. A configured test must connect and execute the catalog query with the test user's permissions. Missing configuration is reported as unavailable rather than treated as a passing live test.
Live fixtures use unique table names in a scratch schema, create only their own tables, avoid inserts and existing user objects, and are removed in finally. The FK suites create parent/child tables with PK/FK constraints. The Netezza live suite creates parent/child tables without an FK and verifies the workspace-style virtual composite mapping. For a manual Netezza check, add the joinRelations entry only to the test workspace and remove it afterward. If a process is interrupted, inspect and drop only the uniquely named fixture tables created by that run.