mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
@@ -1,5 +1,14 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildPostgresSequenceLiteralCompletionItems, buildSelectStarExpansion, buildSqlCompletionItems, getPostgresSequenceLiteralCompletionContext, getSqlCompletionContext, selectStarResultColumnsMatch, shouldAutoOpenSqlCompletion } from "@/lib/sql/sqlCompletion";
|
||||
import {
|
||||
buildPostgresSequenceLiteralCompletionItems,
|
||||
buildSelectStarExpansion,
|
||||
buildSqlCompletionItems,
|
||||
buildSqlCompletionItemsFromContext,
|
||||
getPostgresSequenceLiteralCompletionContext,
|
||||
getSqlCompletionContext,
|
||||
selectStarResultColumnsMatch,
|
||||
shouldAutoOpenSqlCompletion,
|
||||
} from "@/lib/sql/sqlCompletion";
|
||||
import { sqlCompletionContextFromSemantic } from "@/lib/sql/semantic/completion";
|
||||
import { buildSqlSemanticModel } from "@/lib/sql/semantic/model";
|
||||
import { originForSqlCompletionProvider, originForTypedSqlCompletionStart, shouldAllowSqlCompletionTrigger, type SqlCompletionTriggerFacts } from "@/lib/sql/sqlCompletionTriggerPolicy";
|
||||
@@ -17,6 +26,38 @@ describe("sqlCompletion keyword snippets", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("MySQL DESCRIBE table completion", () => {
|
||||
it.each(["DESC", "DESCRIBE"])("treats %s as a table-name context", (keyword) => {
|
||||
const sql = `${keyword} ord`;
|
||||
const options = { databaseType: "mysql", dialect: "mysql" } as const;
|
||||
const context = sqlCompletionContextFromSemantic(buildSqlSemanticModel(sql, sql.length, options), getSqlCompletionContext(sql, sql.length, options));
|
||||
expect(context.suggestTables).toBe(true);
|
||||
expect(shouldAutoOpenSqlCompletion(sql, sql.length, options)).toBe(true);
|
||||
expect(
|
||||
buildSqlCompletionItemsFromContext(context, {
|
||||
tables: [{ name: "orders" }],
|
||||
columnsByTable: new Map(),
|
||||
...options,
|
||||
}),
|
||||
).toEqual(expect.arrayContaining([expect.objectContaining({ label: "orders", type: "table" })]));
|
||||
});
|
||||
|
||||
it("does not treat PostgreSQL ORDER BY DESC as a table-name context", () => {
|
||||
const sql = "SELECT * FROM users ORDER BY name DESC ord";
|
||||
const options = { databaseType: "postgres", dialect: "postgres" } as const;
|
||||
const context = sqlCompletionContextFromSemantic(buildSqlSemanticModel(sql, sql.length, options), getSqlCompletionContext(sql, sql.length, options));
|
||||
|
||||
expect(context.suggestTables).toBe(false);
|
||||
expect(
|
||||
buildSqlCompletionItemsFromContext(context, {
|
||||
tables: [{ name: "orders" }],
|
||||
columnsByTable: new Map(),
|
||||
...options,
|
||||
}).some((item) => item.type === "table"),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("PostgreSQL sequence literal completion", () => {
|
||||
it.each(["nextval", "currval", "setval"])("recognizes the first %s regclass literal", (functionName) => {
|
||||
const sql = `SELECT ${functionName}('public.order_`;
|
||||
|
||||
@@ -624,6 +624,10 @@ const JOIN_MODIFIER_KEYWORD_PHRASES = ["LEFT JOIN", "RIGHT JOIN", "INNER JOIN",
|
||||
const MAX_TABLE_COMPLETION_ITEMS = 200;
|
||||
const EXACT_LABEL_MATCH_BOOST = 10000;
|
||||
|
||||
function isTableTriggerKeyword(keyword: string, options: SqlSemanticBuildOptions): boolean {
|
||||
return TABLE_TRIGGER_KEYWORDS.has(keyword) || (keyword === "desc" && resolveSqlDialectId(options) === "mysql");
|
||||
}
|
||||
|
||||
// Keywords that only make sense in DDL / statement-start contexts (not inside SELECT/INSERT/UPDATE/DELETE)
|
||||
const DDL_ONLY_KEYWORDS = new Set([
|
||||
"CREATE",
|
||||
@@ -2136,7 +2140,7 @@ export function getSqlCompletionContext(sql: string, cursor: number, options: Sq
|
||||
const deleteInfo = detectDeleteCompletionContext(beforeCursor);
|
||||
const oracleTableFunctionContext = detectOracleTableFunctionContext(beforeCursor);
|
||||
|
||||
const afterTableTrigger = TABLE_TRIGGER_KEYWORDS.has(lastWord) || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken);
|
||||
const afterTableTrigger = isTableTriggerKeyword(lastWord, options) || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken);
|
||||
const exclusiveTableSuggestions = EXCLUSIVE_TABLE_TRIGGER_KEYWORDS.has(lastWord) || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken);
|
||||
const tableAliasAfterCursor = hasTableAliasAfterCursor(sql, cursor);
|
||||
const autoAliasTableCompletions = (lastWord === "from" || lastWord === "join" || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken)) && !tableAliasAfterCursor;
|
||||
|
||||
Reference in New Issue
Block a user