test(storage): integration test for migrate-tier (FED-M1-08) + camelCase column fix (#477)
This commit was merged in pull request #477.
This commit is contained in:
@@ -491,11 +491,24 @@ export class PostgresMigrationTarget implements MigrationTarget {
|
||||
/* Source-row normalisation */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* Convert a camelCase key to snake_case.
|
||||
* e.g. "userId" → "user_id", "emailVerified" → "email_verified".
|
||||
* Keys that are already snake_case (no uppercase letters) are returned as-is.
|
||||
*/
|
||||
function toSnakeCase(key: string): string {
|
||||
return key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drizzle returns rows as camelCase TypeScript objects (e.g. `userId`, not
|
||||
* `user_id`). The PostgresMigrationTarget upserts via raw SQL and uses the
|
||||
* column names as given — the `insights` no-vector path uses snake_case column
|
||||
* aliases in the SELECT, so those rows already arrive as snake_case.
|
||||
* column names as given. We must convert camelCase keys → snake_case before
|
||||
* building the INSERT statement so column names match the PG schema.
|
||||
*
|
||||
* Exception: the `insights` no-vector path already returns snake_case keys
|
||||
* from its raw SQL projection — toSnakeCase() is idempotent for already-
|
||||
* snake_case keys so this conversion is safe in all paths.
|
||||
*
|
||||
* For vector tables (insights), if `embedding` is absent from the source row
|
||||
* (because DrizzleMigrationSource omitted it in the no-vector projection), we
|
||||
@@ -509,7 +522,11 @@ export function normaliseSourceRow(
|
||||
row: Record<string, unknown>,
|
||||
sourceHasVector: boolean,
|
||||
): Record<string, unknown> {
|
||||
const out = { ...row };
|
||||
// Convert all camelCase keys to snake_case for raw-SQL target compatibility.
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const [k, v] of Object.entries(row)) {
|
||||
out[toSnakeCase(k)] = v;
|
||||
}
|
||||
|
||||
if (VECTOR_TABLES.has(tableName) && !sourceHasVector) {
|
||||
// Source cannot have embeddings — explicitly null them so ON CONFLICT
|
||||
|
||||
Reference in New Issue
Block a user