porsager / postgres

Postgres.js - The Fastest full featured PostgreSQL client for Node.js, Deno, Bun and CloudFlare
The Unlicense
7.03k stars 255 forks source link

BUG: inconsistent behaviour inserting multiple records with implicit column names and some properties undefined. #889

Open ddembo opened 1 month ago

ddembo commented 1 month ago

When inserting records with some properties undefined, and no transformation config to handle this, the expected result is:

UNDEFINED_VALUE: Undefined values are not allowed.

However, when allowing postgres.js to implicitly derive the inserted records' columns, and the insertion contains a mix of records where some properties are undefined, the order of these records changes the results.

For example, given a postgres connection instance without any transform config for undefined values:

await sql.unsafe(/* SQL */ `
  CREATE TABLE test (
    title VARCHAR(255) NOT NULL,
    foo BOOLEAN NOT NULL DEFAULT FALSE
  );
`);

function insertTest(sql, records) {
  return await sql`
    INSERT INTO test ${sql(records)}
    RETURNING *;
  `;
}

await insertTest([{ title: 'fizz' }, { title: 'buzz', foo: true }]);  ❌ 
// Expected:
//   Error: UNDEFINED_VALUE: Undefined values are not allowed
// Actual:
//   Error [PostgresError]: null value in column "foo" of relation "test" violates not-null constraint

await insertTest([{ title: 'buzz', foo: true }, { title: 'fizz' }]); ✅ 
// Expected & Actual: Error: UNDEFINED_VALUE: Undefined values are not allowed

This is a simplified example that happens to also return a different error, however in more complex scenarios, if the first record has undefined properties, the insert can succeed, but the records' data will be incorrect.