feat(postgres): complete sequence names in regclass literals

Closes #4005
This commit is contained in:
t8y2 committed 2026-08-13 02:54:18 +00:00
1 parent a67bcb09db
commit 91e7463ee5
11 files changed
+580 -24

No files matched your search

@@ -34,8 +34,10 @@ import { useToast } from "@/composables/useToast";
import {
buildSelectStarExpansion,
buildSqlCompletionItemsFromContext,
buildPostgresSequenceLiteralCompletionItems,
getSqlFunctionSignatureHelp,
getSqlCompletionContext,
getPostgresSequenceLiteralCompletionContext,
getSqlCompletionResultValidFor,
isSqlCompletionSuppressedContext,
isSqlLikeCompletionStatement,
@@ -3296,12 +3298,13 @@ async function provideSqlCompletions(context: CompletionContext) {
}
if (props.databaseType === "victoriametrics") return null;
const hasDatabase = props.database != null;
const sequenceLiteralContext = getPostgresSequenceLiteralCompletionContext(fullDoc, position, props.databaseType);
const epoch = ++completionEpoch;
try {
// 1. Suppressed context (comment / string literal) rejects everything, including explicit.
if (isSqlCompletionSuppressedContext(fullDoc, position)) return null;
if (isSqlCompletionSuppressedContext(fullDoc, position) && !sequenceLiteralContext) return null;
// 2. Determine completion origin (session-level marker).
activeCompletionOrigin = originForSqlCompletionProvider(activeCompletionOrigin, context.explicit);
@@ -3324,12 +3327,12 @@ async function provideSqlCompletions(context: CompletionContext) {
// require-prefix: only compute local facts (no positionalEligible).
if (mode === "require-prefix") {
const ctx = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const ctx = sequenceLiteralContext ?? getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const prevChar = fullDoc[position - 1] ?? "";
const facts: SqlCompletionTriggerFacts = {
origin,
hasIdentifierPrefix: ctx.prefix.length > 0,
qualifierTriggered: prevChar === "." && ctx.qualifier != null,
qualifierTriggered: prevChar === "." && ("from" in ctx ? ctx.schema != null : ctx.qualifier != null),
useDatabasePrefix,
};
if (!shouldAllowSqlCompletionTrigger(mode, facts)) return null;
@@ -3337,13 +3340,13 @@ async function provideSqlCompletions(context: CompletionContext) {
// positional: compute positionalEligible (lazy).
if (mode === "positional") {
const ctx = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const ctx = sequenceLiteralContext ?? getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const prevChar = fullDoc[position - 1] ?? "";
const positionalEligible = shouldAutoOpenSqlCompletion(fullDoc, position, sqlCompletionDialectOptions());
const facts: SqlCompletionTriggerFacts = {
origin,
hasIdentifierPrefix: ctx.prefix.length > 0,
qualifierTriggered: prevChar === "." && ctx.qualifier != null,
qualifierTriggered: prevChar === "." && ("from" in ctx ? ctx.schema != null : ctx.qualifier != null),
useDatabasePrefix,
positionalEligible,
};
@@ -3379,6 +3382,13 @@ async function provideSqlCompletions(context: CompletionContext) {
return buildCompletionResult(items, useDatabaseCompletion.from, undefined, useDatabaseCompletion.prefix);
}
if (sequenceLiteralContext) {
if (!hasDatabase) return null;
const sequences = await connectionStore.listCompletionObjects(props.connectionId, props.database!, sequenceLiteralContext.prefix, MAX_COMPLETION_TABLES, sequenceLiteralContext.schema, undefined, false, undefined, ["sequence"], sequenceLiteralContext.nameQuoted);
if (epoch !== completionEpoch) return null;
return buildCompletionResult(buildPostgresSequenceLiteralCompletionItems(sequenceLiteralContext, sequences), sequenceLiteralContext.from, undefined, sequenceLiteralContext.prefix);
}
const legacyCompletionContext = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const semanticModel = SEMANTIC_SQL_COMPLETION_ENABLED ? buildSqlSemanticModel(fullDoc, position, sqlCompletionDialectOptions()) : null;
let completionContext = semanticModel ? sqlCompletionContextFromSemantic(semanticModel, legacyCompletionContext) : legacyCompletionContext;
@@ -3546,7 +3556,8 @@ function flushImeComposition() {
* Used by flushImeComposition and shouldStartSqlCompletionAfterInput.
*/
function shouldTriggerSqlCompletionForPosition(fullDoc: string, position: number): boolean {
if (isSqlCompletionSuppressedContext(fullDoc, position)) return false;
const sequenceLiteralContext = getPostgresSequenceLiteralCompletionContext(fullDoc, position, props.databaseType);
if (isSqlCompletionSuppressedContext(fullDoc, position) && !sequenceLiteralContext) return false;
const mode = settingsStore.editorSettings.completionTriggerMode;
if (mode === "manual") return false;
@@ -3558,25 +3569,25 @@ function shouldTriggerSqlCompletionForPosition(fullDoc: string, position: number
const useDatabasePrefix = useDatabaseCompletion?.prefix ?? null;
if (mode === "require-prefix") {
const ctx = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const ctx = sequenceLiteralContext ?? getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const prevChar = fullDoc[position - 1] ?? "";
const facts: SqlCompletionTriggerFacts = {
origin: "typing",
hasIdentifierPrefix: ctx.prefix.length > 0,
qualifierTriggered: prevChar === "." && ctx.qualifier != null,
qualifierTriggered: prevChar === "." && ("from" in ctx ? ctx.schema != null : ctx.qualifier != null),
useDatabasePrefix,
};
return shouldAllowSqlCompletionTrigger(mode, facts);
}
// positional
const ctx = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const ctx = sequenceLiteralContext ?? getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const prevChar = fullDoc[position - 1] ?? "";
const positionalEligible = shouldAutoOpenSqlCompletion(fullDoc, position, sqlCompletionDialectOptions());
const facts: SqlCompletionTriggerFacts = {
origin: "typing",
hasIdentifierPrefix: ctx.prefix.length > 0,
qualifierTriggered: prevChar === "." && ctx.qualifier != null,
qualifierTriggered: prevChar === "." && ("from" in ctx ? ctx.schema != null : ctx.qualifier != null),
useDatabasePrefix,
positionalEligible,
};