feat(RQBv2): add custom SQL builder functions for relation columns #5284
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds support for custom SQL builder functions in relation
from/toconfiguration. This enables type casting, JSON extraction, and other SQL transformations when joining columns of incompatible types.Problem
When relations join columns of different types (e.g.,
biginttovarcharin polymorphic associations), PostgreSQL throws:This is common in systems with mixed ID formats (bigint, UUID, external string IDs) or legacy databases.
Solution
Allow passing a builder function to
from/tothat receives the aliased table and returns custom SQL:Also works for other transformations:
Changes
drizzle-orm/src/relations.tsintegration-tests/tests/pg/common-rqb.tsImplementation details
New types:
RelationColumnBuilder = (table: SQL) => SQL- Builder function typeRelationColumnValue = Column<any> \| RelationColumnBuilder- Union type for columnsRelationConfigValue = RelationsBuilderColumnBase \| RelationColumnBuilder- Config value typeUpdated types:
Relation.sourceColumns/targetColumns:Column<any>[]→RelationColumnValue[]OneConfig.from/to: Now acceptsRelationConfigValueManyConfig.from/to: Now acceptsRelationConfigValueNew helpers:
isRelationsBuilderColumnBase(): Type guard to distinguish column refs from functionsbuildColumnSQL(): Builds SQL for a column, calling the function if providedUpdated functions:
One/Manyconstructors: Detect and pass through functionsrelationToSQL(): UsesbuildColumnSQL()to handle both casesTest plan
Added test:
RQB v2 relation with custom SQL builder function (type casting)findFirstwith nested relations and reverse lookupsAdded test:
RQB v2 relation with custom SQL builder for JSON extraction->>'field'extraction for product/category relationTo run tests: