fix(editor): 修复 Kingbase 反引号 SQL 诊断误报
This commit is contained in:
parent
71ce46e5fd
commit
1e76d60f16
|
|
@ -73,6 +73,7 @@ import { usesLocalOnlyEditorCompletionMetadata, usesOnDemandOnlyEditorColumnMeta
|
|||
import { queryContextObjectActions, queryContextObjectRoute, queryTableCandidateAtSqlPosition, resolveQueryContextCandidateDatabase, resolveQueryContextObjectTarget, type QueryContextObjectAction } from "@/lib/sql/queryCursorTableTarget";
|
||||
import * as api from "@/lib/backend/api";
|
||||
import { areSqlSemanticDiagnosticsEqual, buildSqlParserErrorDiagnostic, buildSqlSemanticDiagnostics, isSqlSemanticDiagnosticInputContext, shouldRunSqlSemanticDiagnostics, sqlSemanticDiagnosticRangesForViewport, tableReferenceKey, type SqlSemanticDiagnostic } from "@/lib/sql/semantic/diagnostics";
|
||||
import { sqlReferenceAnalysisDialectFor } from "@/lib/sql/semantic/dialect";
|
||||
import { buildRedisSyntaxDiagnostics, shouldRunRedisDiagnostics } from "@/lib/redis/redisSyntaxDiagnostics";
|
||||
import { buildRedisCompletionItemsFromContext, getRedisCompletionContext, getRedisCompletionResultValidFor, shouldAutoOpenRedisCompletion, takesKeyArgument, type RedisCompletionItem } from "@/lib/redis/redisCompletion";
|
||||
import type { SqlCompletionColumn, SqlCompletionForeignKey, SqlCompletionItem, SqlCompletionObject, SqlCompletionReferencedTable, SqlCompletionTable } from "@/lib/sql/sqlCompletion";
|
||||
|
|
@ -1860,7 +1861,14 @@ async function refreshSemanticDiagnostics(options: { preserveOutsideRanges?: boo
|
|||
const nextDiagnostics: SqlSemanticDiagnostic[] = [];
|
||||
for (const range of diagnosticRanges) {
|
||||
try {
|
||||
const analysis = await api.analyzeSqlReferences(range.sql, props.formatDialect ?? props.dialect ?? "generic");
|
||||
const analysis = await api.analyzeSqlReferences(
|
||||
range.sql,
|
||||
sqlReferenceAnalysisDialectFor({
|
||||
databaseType: props.databaseType,
|
||||
identifierQuote: connectionStore.connectionIdentifierQuote(props.connectionId),
|
||||
fallbackDialect: props.formatDialect ?? props.dialect ?? "generic",
|
||||
}),
|
||||
);
|
||||
if (runId !== semanticDiagnosticRunId) return;
|
||||
|
||||
const semanticCursor = Math.max(0, Math.min(currentView.state.selection.main.head - range.from, range.sql.length));
|
||||
|
|
|
|||
|
|
@ -137,6 +137,11 @@ export const SQL_SEMANTIC_DIALECTS: Record<string, SqlSemanticDialectAdapter> =
|
|||
},
|
||||
};
|
||||
|
||||
export function sqlReferenceAnalysisDialectFor(options: { databaseType?: DatabaseType; identifierQuote?: string; fallbackDialect: string }): string {
|
||||
if (options.databaseType === "kingbase" && options.identifierQuote === "`") return "mysql";
|
||||
return options.fallbackDialect;
|
||||
}
|
||||
|
||||
export function sqlSemanticDialectFor(options: { databaseType?: DatabaseType; dialect?: "mysql" | "postgres" | "sqlserver" }): SqlSemanticDialectAdapter {
|
||||
if (options.dialect && SQL_SEMANTIC_DIALECTS[options.dialect]) return SQL_SEMANTIC_DIALECTS[options.dialect];
|
||||
switch (options.databaseType) {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,15 @@ fn extracts_mysql_quoted_table_references() {
|
|||
assert_eq!(analysis.tables[0].span.end_column, 24);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_mysql_qualified_backtick_table_references() {
|
||||
let analysis = analyze_sql_references("SELECT * FROM `core`.`products` LIMIT 100;", Some("mysql")).unwrap();
|
||||
|
||||
assert_eq!(analysis.tables.len(), 1);
|
||||
assert_eq!(analysis.tables[0].schema.as_deref(), Some("core"));
|
||||
assert_eq!(analysis.tables[0].name, "products");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_mysql_single_quoted_table_references() {
|
||||
let analysis = analyze_sql_references("SELECT * FROM 't_10001' LIMIT 100", Some("mysql")).unwrap();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { strict as assert } from "node:assert";
|
||||
import { test } from "vitest";
|
||||
import { buildSqlParserErrorDiagnostic, buildSqlSemanticDiagnostics, areSqlSemanticDiagnosticsEqual, isSqlSemanticDiagnosticInputContext, shouldRunSqlSemanticDiagnostics, sqlSemanticDiagnosticRangesForViewport } from "../../apps/desktop/src/lib/sql/semantic/diagnostics.ts";
|
||||
import { sqlReferenceAnalysisDialectFor } from "../../apps/desktop/src/lib/sql/semantic/dialect.ts";
|
||||
import type { SqlReferenceAnalysis } from "../../apps/desktop/src/types/database.ts";
|
||||
|
||||
const span = (startColumn: number, endColumn: number) => ({
|
||||
|
|
@ -290,6 +291,13 @@ test("builds a syntax diagnostic from parser errors with line and column", () =>
|
|||
assert.deepEqual(diagnostic?.span, span(10, 12));
|
||||
});
|
||||
|
||||
test("uses MySQL reference parsing only for Kingbase connections that report backtick identifiers", () => {
|
||||
assert.equal(sqlReferenceAnalysisDialectFor({ databaseType: "kingbase", identifierQuote: "`", fallbackDialect: "postgres" }), "mysql");
|
||||
assert.equal(sqlReferenceAnalysisDialectFor({ databaseType: "kingbase", identifierQuote: '"', fallbackDialect: "postgres" }), "postgres");
|
||||
assert.equal(sqlReferenceAnalysisDialectFor({ databaseType: "kingbase", fallbackDialect: "postgres" }), "postgres");
|
||||
assert.equal(sqlReferenceAnalysisDialectFor({ databaseType: "postgres", identifierQuote: "`", fallbackDialect: "postgres" }), "postgres");
|
||||
});
|
||||
|
||||
test("compares diagnostics by severity message and span", () => {
|
||||
const diagnostics = [
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue