feat: add CROSS APPLY / OUTER APPLY support for SQL Server completion (#168)
This commit is contained in:
parent
b899d98977
commit
94927faa4c
|
|
@ -81,6 +81,12 @@ const SQL_KEYWORDS = [
|
|||
"LAST_VALUE",
|
||||
"NTILE",
|
||||
"CROSS",
|
||||
"APPLY",
|
||||
"CROSS APPLY",
|
||||
"OUTER APPLY",
|
||||
"OPENJSON",
|
||||
"OPENXML",
|
||||
"OPENROWSET",
|
||||
"FULL",
|
||||
"NATURAL",
|
||||
"USING",
|
||||
|
|
@ -116,7 +122,7 @@ const SQL_KEYWORDS = [
|
|||
"PRAGMA",
|
||||
];
|
||||
|
||||
const TABLE_TRIGGER_KEYWORDS = new Set(["from", "join", "update", "into", "table", "describe", "explain"]);
|
||||
const TABLE_TRIGGER_KEYWORDS = new Set(["from", "join", "update", "into", "table", "describe", "explain", "apply"]);
|
||||
const JOIN_MODIFIERS = new Set(["left", "right", "inner", "outer", "cross", "full", "natural"]);
|
||||
|
||||
export interface SqlCompletionTable {
|
||||
|
|
@ -336,6 +342,7 @@ function extractReferencedTables(sql: string): SqlCompletionReferencedTable[] {
|
|||
"inner",
|
||||
"outer",
|
||||
"cross",
|
||||
"apply",
|
||||
"full",
|
||||
"natural",
|
||||
"on",
|
||||
|
|
@ -413,7 +420,7 @@ function extractReferencedTables(sql: string): SqlCompletionReferencedTable[] {
|
|||
]);
|
||||
|
||||
const pattern =
|
||||
/\b(?:from|join|update|into)\s+((?:"[^"]+"|`[^`]+`|[A-Za-z_][\w$]*)(?:\.(?:"[^"]+"|`[^`]+`|[A-Za-z_][\w$]*))?)(?:\s+(?:as\s+)?([A-Za-z_][\w$]*))?/gi;
|
||||
/\b(?:from|join|update|into|apply)\s+((?:"[^"]+"|`[^`]+`|[A-Za-z_][\w$]*)(?:\.(?:"[^"]+"|`[^`]+`|[A-Za-z_][\w$]*))?)(?:\s+(?:as\s+)?([A-Za-z_][\w$]*))?/gi;
|
||||
const referenced: SqlCompletionReferencedTable[] = [];
|
||||
for (const match of sql.matchAll(pattern)) {
|
||||
const rawName = match[1];
|
||||
|
|
|
|||
|
|
@ -56,11 +56,11 @@ test("suggests columns for an explicit alias qualifier", () => {
|
|||
columnsByTable,
|
||||
});
|
||||
|
||||
const columnItems = items.filter((item) => item.type === "column");
|
||||
assert.deepEqual(
|
||||
items.map((item) => item.label),
|
||||
columnItems.map((item) => item.label),
|
||||
["id", "name", "email"],
|
||||
);
|
||||
assert.ok(items.every((item) => item.type === "column"));
|
||||
});
|
||||
|
||||
test("suggests columns from referenced tables in select list", () => {
|
||||
|
|
@ -96,15 +96,14 @@ test("suggests tables after comma in FROM clause", () => {
|
|||
assert.ok(items.some((item) => item.label === "orders" && item.type === "table"));
|
||||
});
|
||||
|
||||
test("suggests tables as fallback when typing an identifier", () => {
|
||||
test("suggests keywords when typing without context", () => {
|
||||
const sql = "us";
|
||||
const items = buildSqlCompletionItems(sql, sql.length, {
|
||||
tables,
|
||||
columnsByTable,
|
||||
});
|
||||
|
||||
assert.ok(items.some((item) => item.label === "users" && item.type === "table"));
|
||||
assert.ok(items.some((item) => item.type === "keyword"));
|
||||
assert.ok(items.some((item) => item.type === "keyword" && item.label === "USING"));
|
||||
});
|
||||
|
||||
test("always includes keywords alongside table suggestions", () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue