ReviewOS

stacks/bun-query-builder

returningAll() emits RETURNING * on MySQL, so every write using it fails with a syntax error

#1153
Closed glennmichael123 opened this 8 days ago ·
8 days ago

returningAll() on an INSERT, UPDATE or DELETE appends RETURNING * for every dialect. MySQL has no RETURNING clause, so the statement fails with a syntax error and the write never happens. returning(columns) already has a MySQL path (for an UPDATE it selects the matching ids, runs the UPDATE, then selects those rows back) and works.

Version 0.2.69, Bun 1.4.2, MySQL 8.4.5.

Reproduction

import { createQueryBuilder, setConfig } from 'bun-query-builder'

process.env.DB_CONNECTION = 'mysql'
process.env.DB_DIALECT = 'mysql'
process.env.DB_DATABASE = name
setConfig({ dialect: 'mysql', database: { name, host: '127.0.0.1', port: 55440, username: 'root', password: '' } })

const db = createQueryBuilder()
await db.unsafe('CREATE TABLE notes (id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(64))').execute()
await db.unsafe(`INSERT INTO notes (id, title) VALUES (1, 'before')`).execute()

await db.updateTable('notes').set({ title: 'after' }).where('id', '=', 1).returningAll().executeTakeFirst()
await db.updateTable('notes').set({ title: 'after' }).where('id', '=', 1).returning('id').executeTakeFirst()
await db.insertInto('notes').values({ title: 'inserted' }).returningAll().executeTakeFirst()
await db.deleteFrom('notes').where('id', '=', 1).returningAll().executeTakeFirst()

Output:

update + returningAll() -> MySQLError: You have an error in your SQL syntax; ... near 'RETURNING *' at line 1
update + returning('id') -> {"id":1}
insert + returningAll() -> MySQLError: ... near 'RETURNING *' at line 1
delete + returningAll() -> MySQLError: ... near 'RETURNING *' at line 1
rows now: [{"id":1,"title":"after"}]

The only write that landed is the returning('id') update. The insert and the delete did not run, and neither did the first update.

Expected

returningAll() behaves like returning(columns) on MySQL: emulate it, or document it as unsupported there and throw a clear error instead of sending invalid SQL.

Impact

This is not a rare call. In stacksjs/stacks (which pins 0.2.69) returningAll() appears in 63 write calls across 40 files in commerce, CMS and the ORM traits, including the update() behind four dashboard PATCH routes, so those writes fail on MySQL: https://github.com/stacksjs/stacks/issues/2637

Sign in to comment on this issue.