feat(opengauss): support A-compatibility packages
This commit is contained in:
1 parent
760cad6d1b
commit
deb47df2eb
28 files changed
+1706
-139
No files matched your search
@@ -130,6 +130,15 @@ describe("databaseObjectCapabilities", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("exposes packages only for openGauss A compatibility mode", () => {
|
||||
expect(sidebarObjectKindsForDatabase("opengauss", "A")).toEqual(expect.arrayContaining(["PACKAGE", "PACKAGE_BODY"]));
|
||||
expect(sidebarObjectKindsForDatabase("opengauss", "a")).toContain("PACKAGE");
|
||||
for (const mode of ["B", "C", "PG", undefined]) {
|
||||
expect(sidebarObjectKindsForDatabase("opengauss", mode), String(mode)).not.toContain("PACKAGE");
|
||||
}
|
||||
expect(databaseObjectCapabilities("opengauss", "A").sourceReadable).toEqual(expect.arrayContaining(["PACKAGE", "PACKAGE_BODY"]));
|
||||
});
|
||||
|
||||
it("enables custom type details only for verified PG-family databases", () => {
|
||||
for (const dbType of ["postgres", "opengauss", "gaussdb", "kingbase", "vastbase"] as const) {
|
||||
expect(customTypeCapabilities(dbType), dbType).toEqual({ details: true, members: true, ddl: true });
|
||||
|
||||
@@ -17,6 +17,11 @@ describe("buildDatabaseTreeNodes", () => {
|
||||
expect(node.id).toBe("conn-1:analytics");
|
||||
});
|
||||
|
||||
it("carries database compatibility mode into database nodes", () => {
|
||||
const [node] = buildDatabaseTreeNodes("conn-1", [{ name: "oracle_mode", compatibility_mode: "A" }]);
|
||||
expect(node.compatibilityMode).toBe("A");
|
||||
});
|
||||
|
||||
it("shortens the Cloud Spanner label but keeps the resource path as the node identity", () => {
|
||||
const [node] = buildDatabaseTreeNodes("conn-1", databases(SPANNER_PATH), { displayLabel: spannerDisplayDatabase });
|
||||
|
||||
|
||||
@@ -25,6 +25,13 @@ describe("queryTimeout", () => {
|
||||
expect(frontendQueryTimeoutSecsForSql("UPDATE sample_records SET state = 'ready' RETURNING id", "postgres", 30)).toBe(0);
|
||||
});
|
||||
|
||||
it("uses conservative package splitting for an unresolved openGauss mode", () => {
|
||||
const packageSpec = `CREATE OR REPLACE PACKAGE pkg_utils AS
|
||||
FUNCTION get_version RETURN VARCHAR2;
|
||||
END pkg_utils;`;
|
||||
expect(frontendQueryTimeoutSecsForSql(`${packageSpec}\n/\nSELECT 1;`, "opengauss", 30)).toBe(120);
|
||||
});
|
||||
|
||||
it("keeps the frontend guard for non-row PostgreSQL statements", () => {
|
||||
expect(frontendQueryTimeoutSecsForSql("UPDATE sample_records SET state = 'ready'", "postgres", 30)).toBe(60);
|
||||
expect(frontendQueryTimeoutSecsForSql("INSERT INTO sample_records(note) VALUES ('RETURNING is text')", "postgres", 30)).toBe(60);
|
||||
|
||||
@@ -616,6 +616,27 @@ END pkg_utils_without_replace;`;
|
||||
expect(rangeSqlTexts(splitSqlStatementRanges(`${packageSpecWithoutReplace}\nSELECT 1;`, "xugu"))).toEqual([packageSpecWithoutReplace, "SELECT 1"]);
|
||||
});
|
||||
|
||||
it("keeps openGauss packages together while compatibility metadata is unknown", () => {
|
||||
const packageSpec = `CREATE OR REPLACE PACKAGE pkg_utils AS
|
||||
FUNCTION get_version RETURN VARCHAR2;
|
||||
PROCEDURE log_message(msg VARCHAR2);
|
||||
END pkg_utils;`;
|
||||
const script = `${packageSpec}\n/\nSELECT 1;`;
|
||||
|
||||
expect(rangeSqlTexts(splitSqlStatementRanges(script, "opengauss"))).toEqual([packageSpec, "SELECT 1"]);
|
||||
});
|
||||
|
||||
it("splits openGauss A-mode packages without changing PG mode", () => {
|
||||
const packageSpec = `CREATE OR REPLACE PACKAGE pkg_utils AS
|
||||
FUNCTION get_version RETURN VARCHAR2;
|
||||
PROCEDURE log_message(msg VARCHAR2);
|
||||
END pkg_utils;`;
|
||||
const script = `${packageSpec}\n/\nSELECT 1;`;
|
||||
|
||||
expect(rangeSqlTexts(splitSqlStatementRanges(script, "opengauss", { compatibilityMode: "A" }))).toEqual([packageSpec, "SELECT 1"]);
|
||||
expect(rangeSqlTexts(splitSqlStatementRanges(script, "opengauss", { compatibilityMode: "PG" }))).not.toEqual([packageSpec, "SELECT 1"]);
|
||||
});
|
||||
|
||||
it("splits a declaration-only Oracle package body before following DML", () => {
|
||||
const packageBody = `CREATE OR REPLACE PACKAGE BODY packageName IS
|
||||
null;
|
||||
|
||||
@@ -18,6 +18,7 @@ const MYSQL_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW", "PROCEDURE", "FUNCT
|
||||
// covers user-created types (enum/domain/composite/range/multirange/base);
|
||||
// relation auto-generated row types stay hidden.
|
||||
const POSTGRES_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW", "MATERIALIZED_VIEW", "PROCEDURE", "FUNCTION", "SEQUENCE", "TYPE"];
|
||||
const OPENGAUSS_A_OBJECTS: SidebarObjectKind[] = [...POSTGRES_OBJECTS, "PACKAGE", "PACKAGE_BODY"];
|
||||
|
||||
// KWDB is routed through the PostgreSQL pool but its pg_type catalog
|
||||
// compatibility is not verified yet, so it stays on the pre-TYPE object set.
|
||||
@@ -114,8 +115,8 @@ function isSourceReadableObjectKind(kind: SidebarObjectKind, dbType?: DatabaseTy
|
||||
return true;
|
||||
}
|
||||
|
||||
export function databaseObjectCapabilities(dbType?: DatabaseType): DatabaseObjectCapabilities {
|
||||
const sidebarObjects = sidebarObjectKindsForDatabase(dbType);
|
||||
export function databaseObjectCapabilities(dbType?: DatabaseType, compatibilityMode?: string): DatabaseObjectCapabilities {
|
||||
const sidebarObjects = sidebarObjectKindsForDatabase(dbType, compatibilityMode);
|
||||
return {
|
||||
sidebarObjects,
|
||||
sourceReadable: sidebarObjects.filter((kind) => isSourceReadableObjectKind(kind, dbType)),
|
||||
@@ -166,8 +167,9 @@ export function schemaDiffRoutineObjectTypesIntersection(sourceDbType?: Database
|
||||
return schemaDiffRoutineObjectTypes(targetDbType).filter((kind) => sourceTypes.has(kind));
|
||||
}
|
||||
|
||||
export function sidebarObjectKindsForDatabase(dbType?: DatabaseType): SidebarObjectKind[] {
|
||||
export function sidebarObjectKindsForDatabase(dbType?: DatabaseType, compatibilityMode?: string): SidebarObjectKind[] {
|
||||
if (!dbType) return [...TABLE_VIEW_OBJECTS];
|
||||
if (dbType === "opengauss" && compatibilityMode?.trim().toUpperCase() === "A") return [...OPENGAUSS_A_OBJECTS];
|
||||
return DATABASE_TYPE_OBJECTS.get(dbType) ?? [...ROUTINE_OBJECTS];
|
||||
}
|
||||
|
||||
@@ -202,8 +204,8 @@ export function customTypeCapabilities(dbType?: DatabaseType): CustomTypeCapabil
|
||||
return { details: supported, members: supported, ddl: supported };
|
||||
}
|
||||
|
||||
export function supportsPackageMemberExpansion(dbType?: DatabaseType): boolean {
|
||||
return !!dbType && PACKAGE_MEMBER_EXPANSION_DATABASES.has(dbType);
|
||||
export function supportsPackageMemberExpansion(dbType?: DatabaseType, compatibilityMode?: string): boolean {
|
||||
return !!dbType && (PACKAGE_MEMBER_EXPANSION_DATABASES.has(dbType) || (dbType === "opengauss" && compatibilityMode?.trim().toUpperCase() === "A"));
|
||||
}
|
||||
|
||||
export function normalizeSidebarObjectKind(type: string): SidebarObjectKind {
|
||||
|
||||
@@ -38,6 +38,7 @@ export function buildDatabaseTreeNodes(
|
||||
type: "database" as const,
|
||||
connectionId,
|
||||
database: name,
|
||||
compatibilityMode: db.compatibility_mode?.trim() || undefined,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
},
|
||||
@@ -87,6 +88,7 @@ export function buildDuckDbConnectionTreeNodes(connectionId: string, databases:
|
||||
type: "database" as const,
|
||||
connectionId,
|
||||
database: name,
|
||||
compatibilityMode: db.compatibility_mode?.trim() || undefined,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@ export function executableStatementRangeCacheForDoc(
|
||||
): ExecutableStatementRangeCache {
|
||||
const parameterOptions = typeof parameterOptionsOrParse === "function" ? undefined : parameterOptionsOrParse;
|
||||
const parse = typeof parameterOptionsOrParse === "function" ? parameterOptionsOrParse : customParse;
|
||||
const parameterSyntaxKey = parameterOptions?.enabledSyntaxes ? parameterOptions.enabledSyntaxes.join(",") : "*";
|
||||
const parameterSyntaxKey = `${parameterOptions?.enabledSyntaxes ? parameterOptions.enabledSyntaxes.join(",") : "*"}|compat=${parameterOptions?.compatibilityMode?.trim().toUpperCase() ?? ""}`;
|
||||
if (cache?.doc === doc && cache.databaseType === databaseType && cache.parameterSyntaxKey === parameterSyntaxKey) return cache;
|
||||
|
||||
const byStart = new Map<number, SqlTextRange>();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { splitSqlStatementRanges } from "@/lib/sql/sqlStatementRanges";
|
||||
import { splitSqlStatementRanges, sqlStatementParameterOptionsForCompatibility } from "@/lib/sql/sqlStatementRanges";
|
||||
import type { SqlParameterOptions } from "@/lib/sql/sqlParameters";
|
||||
import { tokenizeSqlSemantic } from "@/lib/sql/semantic/tokens";
|
||||
import { DEFAULT_QUERY_TIMEOUT_SECS } from "@/lib/connection/timeoutLimits";
|
||||
import type { ConnectionConfig, DatabaseType } from "@/types/database";
|
||||
@@ -46,7 +47,7 @@ export function queryTimeoutSecsForConcurrentIndex(configuredTimeoutSecs: number
|
||||
return Math.max(configuredTimeoutSecs, CONCURRENT_INDEX_QUERY_TIMEOUT_SECS);
|
||||
}
|
||||
|
||||
export function frontendQueryTimeoutSecsForSql(sql: string, databaseType: DatabaseType | undefined, queryTimeoutSecs: number): number {
|
||||
export function frontendQueryTimeoutSecsForSql(sql: string, databaseType: DatabaseType | undefined, queryTimeoutSecs: number, parameterOptions?: SqlParameterOptions): number {
|
||||
if (queryTimeoutSecs === 0) return 0;
|
||||
|
||||
// PostgreSQL applies the configured timeout while the backend receives rows
|
||||
@@ -56,7 +57,7 @@ export function frontendQueryTimeoutSecsForSql(sql: string, databaseType: Databa
|
||||
if (databaseType === "postgres" && postgresQueryMayReturnRows(sql, databaseType)) return 0;
|
||||
|
||||
const baseTimeoutSecs = Math.max(queryTimeoutSecs * 2, 60);
|
||||
const statementCount = Math.max(splitSqlStatementRanges(sql, databaseType).length, 1);
|
||||
const statementCount = Math.max(splitSqlStatementRanges(sql, databaseType, parameterOptions ?? sqlStatementParameterOptionsForCompatibility(databaseType)).length, 1);
|
||||
return baseTimeoutSecs * statementCount;
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ export function frontendQueryTimeoutDelayMs(timeoutSecs: number): number | undef
|
||||
}
|
||||
|
||||
function postgresQueryMayReturnRows(sql: string, databaseType: DatabaseType): boolean {
|
||||
return splitSqlStatementRanges(sql, databaseType).some(({ sql: statement }) => {
|
||||
return splitSqlStatementRanges(sql, databaseType, sqlStatementParameterOptionsForCompatibility(databaseType)).some(({ sql: statement }) => {
|
||||
const tokens = tokenizeSqlSemantic(statement, "postgres");
|
||||
const firstKeyword = tokens.find((token) => token.kind === "word" && token.depth === 0)?.normalized;
|
||||
if (!firstKeyword) return false;
|
||||
|
||||
@@ -24,14 +24,14 @@ export interface SqlSemanticDiagnosticVisibleRange {
|
||||
to: number;
|
||||
}
|
||||
|
||||
export function sqlSemanticDiagnosticRangesForViewport(sql: string, visibleRanges: readonly SqlSemanticDiagnosticVisibleRange[], databaseType?: DatabaseType, cachedStatements?: readonly SqlTextRange[]): SqlTextRange[] {
|
||||
const statements = databaseType === "sqlserver" ? sqlServerSemanticDiagnosticRanges(sql) : (cachedStatements ?? executableStatementRanges(sql, databaseType));
|
||||
export function sqlSemanticDiagnosticRangesForViewport(sql: string, visibleRanges: readonly SqlSemanticDiagnosticVisibleRange[], databaseType?: DatabaseType, cachedStatements?: readonly SqlTextRange[], parameterOptions?: { compatibilityMode?: string }): SqlTextRange[] {
|
||||
const statements = databaseType === "sqlserver" ? sqlServerSemanticDiagnosticRanges(sql) : (cachedStatements ?? executableStatementRanges(sql, databaseType, parameterOptions));
|
||||
if (statements.length === 0 || visibleRanges.length === 0) return [];
|
||||
|
||||
const selected: SqlTextRange[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const statement of statements) {
|
||||
if (isOraclePlSqlStatement(statement.sql, databaseType)) continue;
|
||||
if (isOraclePlSqlStatement(statement.sql, databaseType, parameterOptions)) continue;
|
||||
if (!visibleRanges.some((visibleRange) => rangesIntersect(statement, visibleRange))) continue;
|
||||
const key = `${statement.from}:${statement.to}`;
|
||||
if (seen.has(key)) continue;
|
||||
|
||||
@@ -55,6 +55,8 @@ type TriggerPseudoRecordName = "new" | "old" | "parent" | "eventinfo";
|
||||
|
||||
export interface SqlParameterOptions {
|
||||
databaseType?: DatabaseType;
|
||||
/** Database-level compatibility mode, for example openGauss A/B/C/PG. */
|
||||
compatibilityMode?: string;
|
||||
// Which placeholder syntaxes are recognized. Undefined enables all of them.
|
||||
enabledSyntaxes?: readonly SqlParameterSyntax[];
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ export function splitSqlStatementRanges(sql: string, databaseType?: DatabaseType
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (isOracleLikeDatabase(databaseType) && isAtLineStart(sql, i) && isSlashLine(sql, i)) {
|
||||
if (isOracleLikeDatabase(databaseType, parameterOptions) && isAtLineStart(sql, i) && isSlashLine(sql, i)) {
|
||||
const lineEnd = findLineEnd(sql, i);
|
||||
flush(i);
|
||||
i = nextLineStart(sql, lineEnd);
|
||||
@@ -579,7 +579,7 @@ export function splitSqlStatementRanges(sql: string, databaseType?: DatabaseType
|
||||
const tagMatch = /^\$[A-Za-z_0-9]*\$/.exec(sql.slice(i));
|
||||
if (tagMatch) {
|
||||
markContent(i);
|
||||
if (databaseType === "gaussdb" && statementStart !== -1 && startsWithPostgresDollarQuotedRoutinePrefix(sql.slice(statementStart, i))) {
|
||||
if ((databaseType === "gaussdb" || isOpenGaussOracleCompatibility(databaseType, parameterOptions)) && statementStart !== -1 && startsWithPostgresDollarQuotedRoutinePrefix(sql.slice(statementStart, i))) {
|
||||
postgresDollarQuotedRoutine = true;
|
||||
}
|
||||
dollarTag = tagMatch[0].slice(1, -1);
|
||||
@@ -609,7 +609,7 @@ export function splitSqlStatementRanges(sql: string, databaseType?: DatabaseType
|
||||
// Internal semicolons remain part of the routine body.
|
||||
flush();
|
||||
} else {
|
||||
if (oraclePlSqlStatementEnd === undefined && isOracleLikeDatabase(databaseType) && !postgresDollarQuotedRoutine && statementStart !== -1) {
|
||||
if (oraclePlSqlStatementEnd === undefined && isOracleLikeDatabase(databaseType, parameterOptions) && !postgresDollarQuotedRoutine && statementStart !== -1) {
|
||||
const statementSoFar = sql.slice(statementStart, i);
|
||||
oraclePlSqlStatementEnd = startsWithOraclePlSqlBlock(statementSoFar) ? statementStart + (oraclePlSqlBlockEnd(sql.slice(statementStart)) ?? sql.length - statementStart) : null;
|
||||
}
|
||||
@@ -740,7 +740,7 @@ function rangeForCursorInSoftRanges(sql: string, ranges: RawStatement[], pos: nu
|
||||
}
|
||||
|
||||
function splitStatementRangeAtSoftStarts(sql: string, statement: RawStatement, databaseType?: DatabaseType, parameterOptions?: SqlParameterOptions): RawStatement[] {
|
||||
if (isOraclePlSqlStatement(statement.sql, databaseType)) return [statement];
|
||||
if (isOraclePlSqlStatement(statement.sql, databaseType, parameterOptions)) return [statement];
|
||||
if (isSapHanaScriptBlockStatement(statement.sql, databaseType)) return [statement];
|
||||
// Routine bodies contain top-level-looking SET/INSERT/SELECT lines that are not independent statements.
|
||||
if (isMysqlRoutineBlockDatabase(databaseType) && startsWithMysqlRoutineBlock(statement.sql, parameterOptions)) return [statement];
|
||||
@@ -1575,12 +1575,27 @@ function isSqlWhitespace(ch: string): boolean {
|
||||
return ch === " " || ch === "\t" || ch === "\r" || ch === "\n";
|
||||
}
|
||||
|
||||
export function isOracleLikeDatabase(databaseType?: DatabaseType): boolean {
|
||||
return !!databaseType && ORACLE_LIKE_PL_SQL_DATABASES.has(databaseType);
|
||||
function isOpenGaussOracleCompatibility(databaseType?: DatabaseType, options?: SqlParameterOptions): boolean {
|
||||
if (databaseType !== "opengauss") return false;
|
||||
const mode = options?.compatibilityMode?.trim().toUpperCase();
|
||||
// Unknown mode is handled conservatively so an A-mode package is never
|
||||
// split into executable fragments before metadata loading finishes.
|
||||
return mode === undefined || mode === "A";
|
||||
}
|
||||
|
||||
export function isOraclePlSqlStatement(sql: string, databaseType?: DatabaseType): boolean {
|
||||
return isOracleLikeDatabase(databaseType) && startsWithOraclePlSqlBlock(sql);
|
||||
export function sqlStatementParameterOptionsForCompatibility(databaseType?: DatabaseType, compatibilityMode?: string): SqlParameterOptions | undefined {
|
||||
if (databaseType !== "opengauss") return undefined;
|
||||
// Keep the browser-side splitter aligned with the backend's conservative
|
||||
// behavior while the compatibility probe is still cold or unavailable.
|
||||
return { compatibilityMode: compatibilityMode?.trim() || "A" };
|
||||
}
|
||||
|
||||
export function isOracleLikeDatabase(databaseType?: DatabaseType, options?: SqlParameterOptions): boolean {
|
||||
return !!databaseType && (ORACLE_LIKE_PL_SQL_DATABASES.has(databaseType) || isOpenGaussOracleCompatibility(databaseType, options));
|
||||
}
|
||||
|
||||
export function isOraclePlSqlStatement(sql: string, databaseType?: DatabaseType, options?: SqlParameterOptions): boolean {
|
||||
return isOracleLikeDatabase(databaseType, options) && startsWithOraclePlSqlBlock(sql);
|
||||
}
|
||||
|
||||
function isSapHanaScriptBlockDatabase(databaseType?: DatabaseType): boolean {
|
||||
|
||||
@@ -4,7 +4,8 @@ import { hexToRgba } from "@/lib/common/color";
|
||||
import type { CSSProperties } from "vue";
|
||||
import { findConnectionGroupPath } from "@/lib/sidebar/sidebarLayout";
|
||||
import { splitMongoCommandRanges } from "@/lib/mongo/mongoShellCommand";
|
||||
import { executableStatementRanges, splitSqlStatementRanges, type SqlTextRange } from "@/lib/sql/sqlStatementRanges";
|
||||
import { executableStatementRanges, splitSqlStatementRanges, sqlStatementParameterOptionsForCompatibility, type SqlTextRange } from "@/lib/sql/sqlStatementRanges";
|
||||
import type { SqlParameterOptions } from "@/lib/sql/sqlParameters";
|
||||
import { sqlTextFingerprint } from "@/lib/sql/sqlTextFingerprint";
|
||||
import { isQueryExecutionErrorResult } from "@/lib/query/queryResultError";
|
||||
import type { BatchSqlExecution, ConnectionConfig, DatabaseType, QueryResult, QueryTab } from "@/types/database";
|
||||
@@ -240,14 +241,14 @@ export function resultSqlForGrid(tab: Pick<QueryTab, "result" | "resultBaseSql"
|
||||
* A stale or ambiguous source is ignored instead of highlighting a different
|
||||
* statement that happens to have the same text.
|
||||
*/
|
||||
export function resultSourceRange(editorSql: string, result: Pick<QueryResult, "sourceStatement" | "sourceFrom" | "sourceTo"> | undefined, resultIndex: number | undefined, databaseType?: DatabaseType): SqlTextRange | undefined {
|
||||
export function resultSourceRange(editorSql: string, result: Pick<QueryResult, "sourceStatement" | "sourceFrom" | "sourceTo"> | undefined, resultIndex: number | undefined, databaseType?: DatabaseType, parameterOptions?: SqlParameterOptions): SqlTextRange | undefined {
|
||||
const sourceStatement = result?.sourceStatement;
|
||||
if (!sourceStatement) return undefined;
|
||||
if (typeof result.sourceFrom === "number" && typeof result.sourceTo === "number" && editorSql.slice(result.sourceFrom, result.sourceTo) === sourceStatement) {
|
||||
return { from: result.sourceFrom, to: result.sourceTo, sql: sourceStatement };
|
||||
}
|
||||
|
||||
const statements = statementRanges(editorSql, databaseType);
|
||||
const statements = statementRanges(editorSql, databaseType, parameterOptions);
|
||||
const indexed = typeof resultIndex === "number" ? statements[resultIndex] : undefined;
|
||||
if (indexed?.sql === sourceStatement) {
|
||||
return { from: indexed.from, to: indexed.to, sql: indexed.sql };
|
||||
@@ -273,10 +274,10 @@ function lineStartOffset(sql: string, from: number): number {
|
||||
return sql.lastIndexOf("\n", Math.max(0, from - 1)) + 1;
|
||||
}
|
||||
|
||||
function statementRanges(sql: string, databaseType?: DatabaseType): SqlTextRange[] {
|
||||
function statementRanges(sql: string, databaseType?: DatabaseType, parameterOptions?: SqlParameterOptions): SqlTextRange[] {
|
||||
if (databaseType === "redis") return executableStatementRanges(sql, databaseType);
|
||||
if (databaseType === "mongodb") return splitMongoCommandRanges(sql).map(({ from, to, text }) => ({ from, to, sql: text }));
|
||||
return splitSqlStatementRanges(sql, databaseType);
|
||||
return splitSqlStatementRanges(sql, databaseType, parameterOptions ?? sqlStatementParameterOptionsForCompatibility(databaseType));
|
||||
}
|
||||
|
||||
function liveStatementExecutionMarkers(editorSql: string, batch: BatchSqlExecution): StatementExecutionMarker[] {
|
||||
@@ -301,12 +302,20 @@ function liveStatementExecutionMarkers(editorSql: string, batch: BatchSqlExecuti
|
||||
}));
|
||||
}
|
||||
|
||||
export function statementExecutionMarkers(editorSql: string, results: QueryResult[] | undefined, databaseType?: DatabaseType, submittedSql = editorSql, executionEditorFingerprint = sqlTextFingerprint(editorSql), batch?: BatchSqlExecution): StatementExecutionMarker[] {
|
||||
export function statementExecutionMarkers(
|
||||
editorSql: string,
|
||||
results: QueryResult[] | undefined,
|
||||
databaseType?: DatabaseType,
|
||||
submittedSql = editorSql,
|
||||
executionEditorFingerprint = sqlTextFingerprint(editorSql),
|
||||
batch?: BatchSqlExecution,
|
||||
parameterOptions?: SqlParameterOptions,
|
||||
): StatementExecutionMarker[] {
|
||||
if (batch?.items.length) return liveStatementExecutionMarkers(editorSql, batch);
|
||||
if (!results?.length || sqlTextFingerprint(editorSql) !== executionEditorFingerprint) return [];
|
||||
const submittedStatements = statementRanges(submittedSql, databaseType);
|
||||
const submittedStatements = statementRanges(submittedSql, databaseType, parameterOptions);
|
||||
if (submittedStatements.length <= 1) return [];
|
||||
const editorStatements = submittedSql === editorSql ? submittedStatements : statementRanges(editorSql, databaseType);
|
||||
const editorStatements = submittedSql === editorSql ? submittedStatements : statementRanges(editorSql, databaseType, parameterOptions);
|
||||
|
||||
const byLine = new Map<number, { success: number; error: number }>();
|
||||
for (const result of results) {
|
||||
|
||||
Reference in new issue
Block a user