feat(dolt): add native profile, branch database discovery, and SQL completion
This commit is contained in:
1 parent
56edbd3656
commit
681c6f35c5
19 files changed
+304
-23
No files matched your search
@@ -13,6 +13,7 @@ import { requiresPostgresIdentifierQuote } from "@/lib/sql/sqlIdentifier";
|
||||
import { identifierMatchScore, matchesIdentifierSearch } from "@/lib/sql/identifierSearch";
|
||||
import { containsHan, orderedSubsequenceSpan, pinyinFirstLetters } from "@/lib/common/pinyin";
|
||||
import { quoteTableIdentifier } from "@/lib/table/tableSelectSql";
|
||||
import { DOLT_SQL_ROUTINES, doltSqlRoutineSignatures, isDoltDriverProfile } from "@/lib/database/doltProfile";
|
||||
|
||||
export { DEFAULT_SQL_SNIPPETS, resolveSqlSnippetBodyForDatabase } from "@/lib/sql/sqlSnippetTemplates";
|
||||
|
||||
@@ -1304,6 +1305,7 @@ export interface SqlCompletionProviderInput {
|
||||
snippets?: SqlSnippet[];
|
||||
dialect?: "mysql" | "postgres" | "sqlserver";
|
||||
databaseType?: DatabaseType;
|
||||
driverProfile?: string;
|
||||
currentSchema?: string;
|
||||
keywordCase?: SqlKeywordCase;
|
||||
functionCase?: SqlKeywordCase;
|
||||
@@ -1322,6 +1324,7 @@ export function buildSqlCompletionItems(
|
||||
translations?: SqlCompletionTranslations;
|
||||
dialect?: "mysql" | "postgres" | "sqlserver";
|
||||
databaseType?: DatabaseType;
|
||||
driverProfile?: string;
|
||||
currentSchema?: string;
|
||||
keywordCase?: SqlKeywordCase;
|
||||
functionCase?: SqlKeywordCase;
|
||||
@@ -1367,7 +1370,7 @@ class SqlCompletionProvider {
|
||||
this.items.push(...buildSnippetItems(context.prefix, snippets, this.input.keywordCase, this.databaseType));
|
||||
}
|
||||
if (!preferReferencedColumns || context.suggestRoutines) {
|
||||
const functionItems = context.dataTypeContext ? [] : buildFunctionSnippetItems(context.prefix, getFunctionDescriptions(this.t), this.databaseType, context.openingParenAfterCursor, this.input.keywordCase, this.input.functionCase);
|
||||
const functionItems = context.dataTypeContext ? [] : buildFunctionSnippetItems(context.prefix, getFunctionDescriptions(this.t), this.databaseType, this.input.driverProfile, context.openingParenAfterCursor, this.input.keywordCase, this.input.functionCase);
|
||||
this.items.push(...(preferReferencedColumns ? functionItems.filter((item) => item.label.toLowerCase().startsWith(context.prefix.toLowerCase())) : functionItems));
|
||||
if (isOracleLikeDatabase(this.databaseType)) {
|
||||
this.items.push(...buildOracleSystemValueItems(context.prefix, this.input.keywordCase));
|
||||
@@ -1435,7 +1438,8 @@ class SqlCompletionProvider {
|
||||
}
|
||||
|
||||
if (context.suggestRoutines || context.exclusiveRoutineSuggestions || context.oracleTableFunctionContext) {
|
||||
this.items.push(...buildObjectItems(context, this.input.objects ?? [], this.dialect, this.databaseType, this.input.currentSchema));
|
||||
const profileObjects = isDoltDriverProfile(this.input.driverProfile) ? DOLT_SQL_ROUTINES : [];
|
||||
this.items.push(...buildObjectItems(context, [...(this.input.objects ?? []), ...profileObjects], this.dialect, this.databaseType, this.input.currentSchema));
|
||||
}
|
||||
|
||||
if (context.comparisonLeftColumn && context.suggestKeywords) {
|
||||
@@ -1654,7 +1658,7 @@ export function getSqlCompletionResultValidFor(sql: string, cursor: number): Reg
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getSqlFunctionSignatureHelp(sql: string, cursor: number, databaseType?: DatabaseType): SqlFunctionSignatureHelp | null {
|
||||
export function getSqlFunctionSignatureHelp(sql: string, cursor: number, databaseType?: DatabaseType, driverProfile?: string): SqlFunctionSignatureHelp | null {
|
||||
const beforeCursor = sql.slice(0, cursor);
|
||||
const call = findActiveFunctionCall(beforeCursor);
|
||||
if (!call) return null;
|
||||
@@ -1662,7 +1666,7 @@ export function getSqlFunctionSignatureHelp(sql: string, cursor: number, databas
|
||||
const observedParameter = countTopLevelCommas(call.groupText);
|
||||
if (databaseType !== "clickhouse") {
|
||||
const lookupName = call.name.toUpperCase();
|
||||
const parameters = (databaseType ? DATABASE_FUNCTION_SIGNATURES[databaseType]?.get(lookupName) : undefined) ?? SQL_FUNCTION_SIGNATURES.get(lookupName);
|
||||
const parameters = activeFunctionSignatures(databaseType, driverProfile).get(lookupName);
|
||||
if (!parameters) return null;
|
||||
const activeParameter = Math.min(observedParameter, Math.max(0, parameters.length - 1));
|
||||
const signature = `${lookupName}(${parameters.join(", ")})`;
|
||||
@@ -4167,13 +4171,14 @@ function buildSnippetItems(prefix: string, snippets: SqlSnippet[], keywordCase?:
|
||||
});
|
||||
}
|
||||
|
||||
function activeFunctionSignatures(databaseType?: DatabaseType): Map<string, string[]> {
|
||||
function activeFunctionSignatures(databaseType?: DatabaseType, driverProfile?: string): Map<string, string[]> {
|
||||
const commonFunctionNames = databaseType === "cloudflare-d1" ? CLOUDFLARE_D1_COMMON_FUNCTION_NAMES : COMMON_SQL_FUNCTION_NAMES;
|
||||
const signatures = databaseType ? new Map(Array.from(SQL_FUNCTION_SIGNATURES.entries()).filter(([name]) => commonFunctionNames.has(name))) : new Map(SQL_FUNCTION_SIGNATURES);
|
||||
const databaseSignatures = databaseType ? DATABASE_FUNCTION_SIGNATURES[databaseType] : undefined;
|
||||
if (databaseSignatures) {
|
||||
for (const [name, parameters] of databaseSignatures) signatures.set(name, parameters);
|
||||
}
|
||||
for (const [name, parameters] of doltSqlRoutineSignatures(driverProfile)) signatures.set(name, parameters);
|
||||
return signatures;
|
||||
}
|
||||
|
||||
@@ -4215,11 +4220,11 @@ function buildClickHouseFunctionItems(prefix: string, omitOpeningParen: boolean,
|
||||
});
|
||||
}
|
||||
|
||||
function buildFunctionSnippetItems(prefix: string, functionDescriptions: Map<string, string>, databaseType?: DatabaseType, omitOpeningParen = false, keywordCase?: SqlKeywordCase, functionCase?: SqlKeywordCase): SqlCompletionItem[] {
|
||||
function buildFunctionSnippetItems(prefix: string, functionDescriptions: Map<string, string>, databaseType?: DatabaseType, driverProfile?: string, omitOpeningParen = false, keywordCase?: SqlKeywordCase, functionCase?: SqlKeywordCase): SqlCompletionItem[] {
|
||||
if (databaseType === "clickhouse") return buildClickHouseFunctionItems(prefix, omitOpeningParen);
|
||||
const items: SqlCompletionItem[] = [];
|
||||
|
||||
for (const [name, parameters] of activeFunctionSignatures(databaseType).entries()) {
|
||||
for (const [name, parameters] of activeFunctionSignatures(databaseType, driverProfile).entries()) {
|
||||
if (!matchesPrefix(name, prefix)) continue;
|
||||
const functionName = applySqlFunctionCase(name, functionCase);
|
||||
const paramStr = parameters.length > 0 ? parameters.map((p) => `\${${applyGeneratedSqlTemplateKeywordCase(p, keywordCase)}}`).join(", ") : "";
|
||||
@@ -4227,7 +4232,7 @@ function buildFunctionSnippetItems(prefix: string, functionDescriptions: Map<str
|
||||
items.push({
|
||||
label: functionName,
|
||||
type: "function" as const,
|
||||
detail: functionDescriptions.get(name) ?? "function",
|
||||
detail: functionDescriptions.get(name) ?? (isDoltDriverProfile(driverProfile) && name.startsWith("DOLT_") ? "Dolt routine" : "function"),
|
||||
apply: mysqlApply ? `${functionName}${applyGeneratedSqlTemplateKeywordCase(mysqlApply.slice(name.length), keywordCase)}` : `${functionName}(${paramStr})`,
|
||||
boost: computeBoost(name, prefix) + 300,
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user