fix: parse PG brace-style array text in cell coercion to prevent false dirty
coercePostgresArrayValue() only handled JSON [...] format but editor
outputs PG {...} format. When the user entered and exited edit mode
without changes, the string "{1,2,3}" failed to parse back to an
array, creating a false dirty detection via strict equality.
Add parsePostgresArrayText() recursive descent parser and return
oldValue reference when parsed result is equivalent.
This commit is contained in:
1 parent
619573a69d
commit
45a6bb8a58
2 files changed
+199
-6
No files matched your search
@@ -56,13 +56,33 @@ function coercePostgresArrayValue(options: CoerceDataGridCellValueOptions): unkn
|
||||
if (options.databaseType !== "postgres") return undefined;
|
||||
if (!isPostgresArrayColumn(options.columnInfo, options.oldValue)) return undefined;
|
||||
const trimmed = options.value.trim();
|
||||
if (!trimmed.startsWith("[")) return undefined;
|
||||
try {
|
||||
const parsed = JSON.parse(normalizeSmartQuotes(trimmed));
|
||||
return Array.isArray(parsed) ? parsed : undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
|
||||
if (trimmed.startsWith("[")) {
|
||||
try {
|
||||
const parsed = JSON.parse(normalizeSmartQuotes(trimmed));
|
||||
return Array.isArray(parsed) ? parsed : undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (trimmed.startsWith("{")) {
|
||||
try {
|
||||
const parsed = parsePostgresArrayText(trimmed);
|
||||
if (Array.isArray(options.oldValue) && deepEqual(parsed, options.oldValue)) {
|
||||
return options.oldValue;
|
||||
}
|
||||
return parsed;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function deepEqual(a: unknown, b: unknown): boolean {
|
||||
return JSON.stringify(a) === JSON.stringify(b);
|
||||
}
|
||||
|
||||
function isPostgresArrayColumn(
|
||||
@@ -115,3 +135,74 @@ function formatPostgresArrayElement(value: unknown): string {
|
||||
function needsQuotedPostgresArrayElement(value: string): boolean {
|
||||
return value === "" || /[\s,"{}\\]/.test(value) || value.toUpperCase() === "NULL";
|
||||
}
|
||||
|
||||
function parsePostgresArrayText(value: string): unknown[] {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) {
|
||||
throw new Error("Invalid PG array literal");
|
||||
}
|
||||
const inner = trimmed.slice(1, -1);
|
||||
if (inner.length === 0) return [];
|
||||
|
||||
const elements: unknown[] = [];
|
||||
let i = 0;
|
||||
while (i < inner.length) {
|
||||
while (i < inner.length && inner[i] === " ") i++;
|
||||
if (i >= inner.length) break;
|
||||
|
||||
let element: unknown;
|
||||
if (inner[i] === '"') {
|
||||
i++;
|
||||
let str = "";
|
||||
while (i < inner.length) {
|
||||
if (inner[i] === "\\" && i + 1 < inner.length) {
|
||||
i++;
|
||||
str += inner[i];
|
||||
i++;
|
||||
} else if (inner[i] === '"') {
|
||||
i++;
|
||||
break;
|
||||
} else {
|
||||
str += inner[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
element = str;
|
||||
} else if (inner[i] === "{") {
|
||||
let depth = 0;
|
||||
const start = i;
|
||||
while (i < inner.length) {
|
||||
if (inner[i] === "{") depth++;
|
||||
else if (inner[i] === "}") {
|
||||
depth--;
|
||||
if (depth === 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
element = parsePostgresArrayText(inner.slice(start, i));
|
||||
} else {
|
||||
let start = i;
|
||||
while (i < inner.length && inner[i] !== "," && inner[i] !== "}") i++;
|
||||
const token = inner.slice(start, i).trim();
|
||||
if (token.toUpperCase() === "NULL") {
|
||||
element = null;
|
||||
} else if (/^(true|false)$/i.test(token)) {
|
||||
element = token.toLowerCase() === "true";
|
||||
} else if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(token)) {
|
||||
element = Number(token);
|
||||
} else {
|
||||
element = token;
|
||||
}
|
||||
}
|
||||
|
||||
elements.push(element);
|
||||
|
||||
while (i < inner.length && inner[i] === " ") i++;
|
||||
if (i < inner.length && inner[i] === ",") i++;
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
Reference in new issue
Block a user