fix(generate): emit JSON literals for JSON columns
This commit is contained in:
3 files changed
+70
-2
No files matched your search
@@ -607,8 +607,11 @@ function sqlStatementsForTable(r: GeneratedTableResult): string[] {
|
||||
stmts.push(...r.statements);
|
||||
} else {
|
||||
const colList = r.columns.map((c) => quoteTableIdentifier(dbType.value, c)).join(", ");
|
||||
// Match by column name: rows may carry a leading tbname (TDengine stable),
|
||||
// so positional indexes into resolvedColumns would drift.
|
||||
const dataTypeByName = new Map(r.resolvedColumns.map((c) => [c.columnName.toLowerCase(), c.dataType]));
|
||||
for (const row of r.rows) {
|
||||
const vals = row.map((value) => formatGeneratedValue(value)).join(", ");
|
||||
const vals = row.map((value, index) => formatGeneratedValue(value, dbType.value, dataTypeByName.get(r.columns[index]?.toLowerCase() ?? ""))).join(", ");
|
||||
stmts.push(`INSERT INTO ${targetTable} (${colList}) VALUES (${vals});`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1758,9 +1758,37 @@ export function formatGeneratedValue(value: unknown, databaseType?: DatabaseType
|
||||
const temporalValue = formatOracleTemporalValue(stringValue, dataType);
|
||||
if (temporalValue) return temporalValue;
|
||||
}
|
||||
if (isJsonType(dataType)) {
|
||||
// MySQL (and MariaDB) reject any non-JSON text in a JSON column, so free
|
||||
// text from a string generator must land as a JSON string scalar; values
|
||||
// that are already valid JSON pass through untouched.
|
||||
const jsonText = isWellFormedJson(stringValue) ? stringValue : JSON.stringify(stringValue);
|
||||
// MySQL's lexer consumes backslash escapes inside '...' literals, so the
|
||||
// JSON escape sequences must double their backslashes to survive the trip.
|
||||
if (databaseType === "mysql") return quoteGeneratedString(jsonText.replace(/\\/g, "\\\\"));
|
||||
return quoteGeneratedString(jsonText);
|
||||
}
|
||||
return quoteGeneratedString(stringValue);
|
||||
}
|
||||
|
||||
function isJsonType(dataType: string | undefined): boolean {
|
||||
return !!dataType && dataType.toLowerCase().includes("json");
|
||||
}
|
||||
|
||||
function isWellFormedJson(value: string): boolean {
|
||||
// Cheap pre-filter: plain prose (the common case from string generators)
|
||||
// can't be JSON, so skip the parse for it.
|
||||
if (!/^".*"$/.test(value) && !/^\{.*\}$/.test(value) && !/^\[.*\]$/.test(value) && !/^(true|false|null|-?\d+(\.\d+)?([eE][+-]?\d+)?)$/.test(value)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
JSON.parse(value);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function displayGeneratedValue(value: unknown): string {
|
||||
if (isGeneratedSqlExpression(value)) return value.display;
|
||||
if (value === null || value === undefined) return "NULL";
|
||||
|
||||
Reference in new issue
Block a user