ReviewOS

stacks/bun-query-builder

belongsToMany buildSelect uses 'related.*, pivot.*' — column-name collisions overwrite related fields

#1036
Closed glennmichael123 opened this 2 months ago ·
2 months ago

Summary

The per-instance BelongsToManyRelationBuilder.buildSelect() selects ${relatedTable}.*, ${pivotTable}.* into one flat row. When pivot and related tables share a column name (id, created_at, updated_at, deleted_at, or any user pivot column matching a related attribute), the second .* overwrites the first in the driver's row object, corrupting hydrated related models. The eager-load path queries pivot and related separately and avoids this — so the per-instance builder and eager-load can disagree.

Status

Suspected — reasoned from code; worth a repro with an overlapping pivot column (e.g. a pivot id).

Location

src/orm.ts:~1319 (buildSelect) + ~1346 (hydrateRows).

Suggested fix

Alias columns explicitly (e.g. pivot.col AS pivot__col) or split into two queries like the eager-load path.

Severity: medium. Found via internal code audit.

9 days ago

Fixed in 44daffd. The belongsToMany builder now aliases the related columns (related.col AS __btm_rel__col) and keeps pivot.*, so a same-named pivot column (or the pivot's own id) can no longer overwrite the related value. Aliasing the related side (known from the model def) rather than the pivot side avoids depending on the pivot's declared columns, which are empty for through: models. Regression test added; full suite green (incl. existing Option A/B BTM tests).

Sign in to comment on this issue.