fix(hana): improve metadata fallback and SQLScript parameters

This commit is contained in:
LRcoding authored and GitHub committed 2026-07-08 17:25:34 +08:00
1 parent fd80464cb2
commit 430f097602
6 files changed
+57 -22

No files matched your search

@@ -176,6 +176,11 @@ describe("extractSqlParameters", () => {
const sql = "select value::int, value := 1, :actual_value";
expect(extractSqlParameters(sql)).toEqual(["actual_value"]);
});
it("ignores HANA SQLScript variable references", () => {
const sql = "DO BEGIN Dummy1 = SELECT 1 FROM DUMMY; SELECT * FROM :Dummy1; END";
expect(extractSqlParameters(sql, { databaseType: "saphana" })).toEqual([]);
});
});
describe("substituteSqlParameters", () => {
@@ -264,6 +269,11 @@ DEALLOCATE PREPARE stmt;`;
}),
).toBe("exec dbo.search_orders @date_start = '2026-07-04', @status = 'paid', @tenant_id = 7");
});
it("keeps HANA SQLScript variable references while replacing template parameters", () => {
const sql = "DO BEGIN Dummy1 = SELECT * FROM ORDERS WHERE TENANT_ID = ${tenant_id}; SELECT * FROM :Dummy1; END";
expect(substituteSqlParameters(sql, { tenant_id: { kind: "number", value: "42" } }, { databaseType: "saphana" })).toBe("DO BEGIN Dummy1 = SELECT * FROM ORDERS WHERE TENANT_ID = 42; SELECT * FROM :Dummy1; END");
});
});
describe("sqlParameterLiteral", () => {
+15 -8
View File
@@ -1,3 +1,5 @@
import type { DatabaseType } from "@/types/database";
export type SqlParameterValueKind = "string" | "number" | "boolean" | "null" | "raw";
export interface SqlParameterInput {
@@ -19,19 +21,23 @@ interface ParameterOccurrence extends SqlParameterDescriptor {
end: number;
}
export interface SqlParameterOptions {
databaseType?: DatabaseType;
}
const PARAMETER_NAME_RE = /^[\p{L}_][\p{L}\p{N}_]*$/u;
const PARAMETER_NAME_START_RE = /[\p{L}_]/u;
const PARAMETER_NAME_CHAR_RE = /[\p{L}\p{N}_]/u;
const SQL_SERVER_TEMP_TABLE_CONTEXT_KEYWORDS = new Set(["table", "from", "join", "into", "update", "truncate"]);
export function extractSqlParameters(sql: string): string[] {
return extractSqlParameterDescriptors(sql).map((descriptor) => descriptor.key);
export function extractSqlParameters(sql: string, options?: SqlParameterOptions): string[] {
return extractSqlParameterDescriptors(sql, options).map((descriptor) => descriptor.key);
}
export function extractSqlParameterDescriptors(sql: string): SqlParameterDescriptor[] {
export function extractSqlParameterDescriptors(sql: string, options?: SqlParameterOptions): SqlParameterDescriptor[] {
const names = new Set<string>();
const descriptors: SqlParameterDescriptor[] = [];
for (const occurrence of findSqlParameterOccurrences(sql)) {
for (const occurrence of findSqlParameterOccurrences(sql, options)) {
if (names.has(occurrence.key)) continue;
names.add(occurrence.key);
descriptors.push({
@@ -44,8 +50,8 @@ export function extractSqlParameterDescriptors(sql: string): SqlParameterDescrip
return descriptors;
}
export function substituteSqlParameters(sql: string, values: Record<string, SqlParameterInput>): string {
const occurrences = findSqlParameterOccurrences(sql);
export function substituteSqlParameters(sql: string, values: Record<string, SqlParameterInput>, options?: SqlParameterOptions): string {
const occurrences = findSqlParameterOccurrences(sql, options);
if (!occurrences.length) return sql;
let result = "";
@@ -68,9 +74,10 @@ export function sqlParameterLiteral(input: SqlParameterInput): string {
return quoteSqlString(raw);
}
function findSqlParameterOccurrences(sql: string): ParameterOccurrence[] {
function findSqlParameterOccurrences(sql: string, options?: SqlParameterOptions): ParameterOccurrence[] {
const occurrences: ParameterOccurrence[] = [];
const nativeSqlServerParameters = collectNativeSqlServerParameters(sql);
const supportsNamedParameters = options?.databaseType !== "saphana";
let i = 0;
let dollarQuoteEnd = "";
let positionalIndex = 0;
@@ -110,7 +117,7 @@ function findSqlParameterOccurrences(sql: string): ParameterOccurrence[] {
i += 1;
continue;
}
if (ch === ":") {
if (ch === ":" && supportsNamedParameters) {
const name = readParameterName(sql, i + 1);
if (name && sql[i - 1] !== ":" && sql[i + 1] !== "=") {
occurrences.push({