relq 1.0.86 → 1.0.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -25,7 +25,12 @@ function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
|
|
|
25
25
|
const rightProxy = (0, table_proxy_1.createTableProxy)(rightTableName, rightAlias, rightTableDef);
|
|
26
26
|
const conditionBuilder = new join_condition_builder_1.JoinConditionBuilder();
|
|
27
27
|
if (callback) {
|
|
28
|
-
|
|
28
|
+
if (joinType === 'RIGHT JOIN') {
|
|
29
|
+
callback(conditionBuilder, leftProxy, rightProxy);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
callback(conditionBuilder, rightProxy, leftProxy);
|
|
33
|
+
}
|
|
29
34
|
}
|
|
30
35
|
const conditionInternals = conditionBuilder[join_internals_1.JOIN_INTERNAL];
|
|
31
36
|
if (!conditionInternals.hasConditions() && schema && relations) {
|
|
@@ -37,7 +42,7 @@ function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
|
|
|
37
42
|
}
|
|
38
43
|
else {
|
|
39
44
|
throw new relq_errors_1.RelqQueryError(`Cannot auto-resolve FK relationship between "${ctx.schemaKey || ctx.tableName}" and "${rightTableKey}". ` +
|
|
40
|
-
`Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on,
|
|
45
|
+
`Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on, ${rightTableKey}, source) => on.equal(${rightTableKey}.id, source.columnName))` });
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
const selectedProps = conditionInternals.getSelectedColumns();
|
|
@@ -93,7 +98,7 @@ function executeTypeSafeJoinMany(ctx, joinType, tableOrAlias, callback) {
|
|
|
93
98
|
};
|
|
94
99
|
};
|
|
95
100
|
conditionBuilder[join_internals_1.JOIN_SETUP](proxyCreator, rightProxy);
|
|
96
|
-
callback(conditionBuilder,
|
|
101
|
+
callback(conditionBuilder, rightProxy, leftProxy);
|
|
97
102
|
const lateralSQL = buildLateralSubquery(rightTableName, rightAlias, conditionBuilder, rightTableDef);
|
|
98
103
|
const lateralJoinType = joinType === 'LEFT JOIN' ? 'LEFT JOIN LATERAL' : 'JOIN LATERAL';
|
|
99
104
|
const joinClause = {
|
|
@@ -21,7 +21,12 @@ export function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
|
|
|
21
21
|
const rightProxy = createTableProxy(rightTableName, rightAlias, rightTableDef);
|
|
22
22
|
const conditionBuilder = new JoinConditionBuilder();
|
|
23
23
|
if (callback) {
|
|
24
|
-
|
|
24
|
+
if (joinType === 'RIGHT JOIN') {
|
|
25
|
+
callback(conditionBuilder, leftProxy, rightProxy);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
callback(conditionBuilder, rightProxy, leftProxy);
|
|
29
|
+
}
|
|
25
30
|
}
|
|
26
31
|
const conditionInternals = conditionBuilder[JOIN_INTERNAL];
|
|
27
32
|
if (!conditionInternals.hasConditions() && schema && relations) {
|
|
@@ -33,7 +38,7 @@ export function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
|
|
|
33
38
|
}
|
|
34
39
|
else {
|
|
35
40
|
throw new RelqQueryError(`Cannot auto-resolve FK relationship between "${ctx.schemaKey || ctx.tableName}" and "${rightTableKey}". ` +
|
|
36
|
-
`Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on,
|
|
41
|
+
`Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on, ${rightTableKey}, source) => on.equal(${rightTableKey}.id, source.columnName))` });
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
const selectedProps = conditionInternals.getSelectedColumns();
|
|
@@ -89,7 +94,7 @@ export function executeTypeSafeJoinMany(ctx, joinType, tableOrAlias, callback) {
|
|
|
89
94
|
};
|
|
90
95
|
};
|
|
91
96
|
conditionBuilder[JOIN_SETUP](proxyCreator, rightProxy);
|
|
92
|
-
callback(conditionBuilder,
|
|
97
|
+
callback(conditionBuilder, rightProxy, leftProxy);
|
|
93
98
|
const lateralSQL = buildLateralSubquery(rightTableName, rightAlias, conditionBuilder, rightTableDef);
|
|
94
99
|
const lateralJoinType = joinType === 'LEFT JOIN' ? 'LEFT JOIN LATERAL' : 'JOIN LATERAL';
|
|
95
100
|
const joinClause = {
|
package/dist/index.d.ts
CHANGED
|
@@ -8502,45 +8502,63 @@ export type InferResultType<TSchema, TTable, TColumns> = TColumns extends [
|
|
|
8502
8502
|
} ? TColumns extends readonly string[] ? Simplify$1<Pick<TSelect, Extract<TColumns[number], keyof TSelect>>> : TSelect : SelectResult<TTable, TColumns extends readonly any[] ? TColumns : [
|
|
8503
8503
|
]>;
|
|
8504
8504
|
/**
|
|
8505
|
-
* Join callback function type
|
|
8506
|
-
*
|
|
8505
|
+
* Join callback function type for join/innerJoin/leftJoin.
|
|
8506
|
+
* The joined table proxy comes FIRST for natural DX:
|
|
8507
|
+
* when you write `.join('orders', ...)`, `orders` is what you think about first.
|
|
8507
8508
|
*
|
|
8508
8509
|
* @param on - The condition builder for ON clause
|
|
8509
|
-
* @param
|
|
8510
|
-
* @param
|
|
8510
|
+
* @param joined - Table proxy for the joined table (the one in .join('tableName'))
|
|
8511
|
+
* @param source - Table proxy for the source table (the one .join() is called on)
|
|
8511
8512
|
*
|
|
8512
8513
|
* @example
|
|
8513
8514
|
* ```typescript
|
|
8514
|
-
*
|
|
8515
|
-
*
|
|
8516
|
-
*
|
|
8517
|
-
*
|
|
8518
|
-
*
|
|
8515
|
+
* db.table.users.select()
|
|
8516
|
+
* .join('orders', (on, orders, users) =>
|
|
8517
|
+
* on.equal(orders.userId, users.id)
|
|
8518
|
+
* .select(['id', 'total'])
|
|
8519
|
+
* )
|
|
8519
8520
|
* ```
|
|
8520
8521
|
*/
|
|
8521
|
-
export type JoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>,
|
|
8522
|
+
export type JoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>, joined: TableProxy<TRight>, source: TableProxy<TLeft>) => JoinConditionBuilder<TLeft, TResult>;
|
|
8523
|
+
/**
|
|
8524
|
+
* Right join callback — reversed parameter order from JoinCallback.
|
|
8525
|
+
* For rightJoin, the source table comes first since the right (joined) table
|
|
8526
|
+
* is the primary table in a RIGHT JOIN.
|
|
8527
|
+
*
|
|
8528
|
+
* @param on - The condition builder for ON clause
|
|
8529
|
+
* @param source - Table proxy for the source table
|
|
8530
|
+
* @param joined - Table proxy for the joined (right/primary) table
|
|
8531
|
+
*
|
|
8532
|
+
* @example
|
|
8533
|
+
* ```typescript
|
|
8534
|
+
* db.table.users.select()
|
|
8535
|
+
* .rightJoin('orders', (on, users, orders) =>
|
|
8536
|
+
* on.equal(users.id, orders.userId)
|
|
8537
|
+
* )
|
|
8538
|
+
* ```
|
|
8539
|
+
*/
|
|
8540
|
+
export type RightJoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>, source: TableProxy<TLeft>, joined: TableProxy<TRight>) => JoinConditionBuilder<TLeft, TResult>;
|
|
8522
8541
|
/**
|
|
8523
8542
|
* JoinMany callback function type for LATERAL subqueries.
|
|
8524
|
-
*
|
|
8525
|
-
* Includes schema for type-safe inner joins with autocomplete.
|
|
8526
|
-
* TResult allows the callback to return a narrowed type (e.g., after .select())
|
|
8543
|
+
* Same parameter order as JoinCallback: joined table first, source second.
|
|
8527
8544
|
*
|
|
8528
8545
|
* @param on - The condition builder for LATERAL subquery
|
|
8529
|
-
* @param
|
|
8530
|
-
* @param
|
|
8546
|
+
* @param joined - Table proxy for the joined table
|
|
8547
|
+
* @param source - Table proxy for the source (outer) table
|
|
8531
8548
|
*
|
|
8532
8549
|
* @example
|
|
8533
8550
|
* ```typescript
|
|
8534
8551
|
* // Get top 5 orders per user
|
|
8535
|
-
* .
|
|
8536
|
-
*
|
|
8537
|
-
* .
|
|
8538
|
-
*
|
|
8539
|
-
*
|
|
8540
|
-
*
|
|
8552
|
+
* db.table.users.select()
|
|
8553
|
+
* .joinMany('orders', (on, orders, users) =>
|
|
8554
|
+
* on.equal(orders.userId, users.id)
|
|
8555
|
+
* .where(q => q.equal('status', 'completed'))
|
|
8556
|
+
* .orderBy(orders.createdAt, 'DESC')
|
|
8557
|
+
* .limit(5)
|
|
8558
|
+
* )
|
|
8541
8559
|
* ```
|
|
8542
8560
|
*/
|
|
8543
|
-
export type JoinManyCallback<TSchema, TLeft, TRight, TRightKey extends string, TResult = TRight> = (on: JoinManyConditionBuilder<TSchema, TLeft, TRight, TRightKey>,
|
|
8561
|
+
export type JoinManyCallback<TSchema, TLeft, TRight, TRightKey extends string, TResult = TRight> = (on: JoinManyConditionBuilder<TSchema, TLeft, TRight, TRightKey>, joined: TableProxy<TRight>, source: TableProxy<TLeft>) => JoinManyConditionBuilder<TSchema, TLeft, TResult, TRightKey>;
|
|
8544
8562
|
/**
|
|
8545
8563
|
* Internal interface for query builders
|
|
8546
8564
|
* This interface exposes execution methods that are hidden from the public API
|
|
@@ -8794,16 +8812,16 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8794
8812
|
* .join('users') // Auto-detects orders.userId → users.id
|
|
8795
8813
|
* // Result: { ...order, users: { id, name, ... } }
|
|
8796
8814
|
*
|
|
8797
|
-
* // With explicit callback
|
|
8815
|
+
* // With explicit callback — joined table first, source second
|
|
8798
8816
|
* db.table.orders.select()
|
|
8799
|
-
* .join('users', (on,
|
|
8800
|
-
* on.equal(
|
|
8817
|
+
* .join('users', (on, users, orders) =>
|
|
8818
|
+
* on.equal(users.id, orders.userId)
|
|
8801
8819
|
* )
|
|
8802
8820
|
*
|
|
8803
8821
|
* // With alias
|
|
8804
8822
|
* db.table.orders.select()
|
|
8805
|
-
* .join(['users', 'user'], (on,
|
|
8806
|
-
* on.equal(
|
|
8823
|
+
* .join(['users', 'user'], (on, user, orders) =>
|
|
8824
|
+
* on.equal(user.id, orders.userId)
|
|
8807
8825
|
* )
|
|
8808
8826
|
* // Result: { ...order, user: { id, name, ... } }
|
|
8809
8827
|
* ```
|
|
@@ -8829,10 +8847,10 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8829
8847
|
* .leftJoin('users')
|
|
8830
8848
|
* // Result: { ...order, users: { ... } | null }
|
|
8831
8849
|
*
|
|
8832
|
-
* // With callback
|
|
8850
|
+
* // With callback — joined table first, source second
|
|
8833
8851
|
* db.table.orders.select()
|
|
8834
|
-
* .leftJoin(['users', 'user'], (on,
|
|
8835
|
-
* on.equal(
|
|
8852
|
+
* .leftJoin(['users', 'user'], (on, user, orders) =>
|
|
8853
|
+
* on.equal(user.id, orders.userId)
|
|
8836
8854
|
* )
|
|
8837
8855
|
* ```
|
|
8838
8856
|
*/
|
|
@@ -8848,12 +8866,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8848
8866
|
leftJoin<TRightKey extends keyof TSchema & string, TResult>(table: TRightKey, callback: JoinCallback<TTable, TSchema[TRightKey], TResult>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedLeftJoin<TRightKey, TResult>>;
|
|
8849
8867
|
/**
|
|
8850
8868
|
* Type-safe RIGHT JOIN.
|
|
8869
|
+
* Callback order is (on, source, joined) — reversed from join/leftJoin
|
|
8870
|
+
* because in a RIGHT JOIN the joined table is the primary table.
|
|
8851
8871
|
*
|
|
8852
8872
|
* @example
|
|
8853
8873
|
* ```typescript
|
|
8854
8874
|
* db.table.orders.select()
|
|
8855
|
-
* .rightJoin('users')
|
|
8856
|
-
*
|
|
8875
|
+
* .rightJoin('users', (on, orders, users) =>
|
|
8876
|
+
* on.equal(orders.userId, users.id)
|
|
8877
|
+
* )
|
|
8857
8878
|
* ```
|
|
8858
8879
|
*/
|
|
8859
8880
|
rightJoin<TRightKey extends keyof TSchema & string, TAlias extends string>(tableAndAlias: [
|
|
@@ -8864,8 +8885,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8864
8885
|
rightJoin<TRightKey extends keyof TSchema & string, TAlias extends string>(tableAndAlias: [
|
|
8865
8886
|
TRightKey,
|
|
8866
8887
|
TAlias
|
|
8867
|
-
], callback:
|
|
8868
|
-
rightJoin<TRightKey extends keyof TSchema & string>(table: TRightKey, callback:
|
|
8888
|
+
], callback: RightJoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TAlias, TSchema[TRightKey]>>;
|
|
8889
|
+
rightJoin<TRightKey extends keyof TSchema & string>(table: TRightKey, callback: RightJoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TRightKey, TSchema[TRightKey]>>;
|
|
8869
8890
|
/**
|
|
8870
8891
|
* Type-safe INNER JOIN (alias for join()).
|
|
8871
8892
|
*/
|
|
@@ -8893,8 +8914,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8893
8914
|
* db.table.users.select()
|
|
8894
8915
|
* .joinSubquery(
|
|
8895
8916
|
* 'recent_orders',
|
|
8896
|
-
* db.table.orders.select().join('payments', (on,
|
|
8897
|
-
* on.equal(
|
|
8917
|
+
* db.table.orders.select().join('payments', (on, p, o) =>
|
|
8918
|
+
* on.equal(p.orderId, o.id)
|
|
8898
8919
|
* ),
|
|
8899
8920
|
* `"recent_orders"."user_id" = "users"."id"`
|
|
8900
8921
|
* )
|
|
@@ -8944,15 +8965,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8944
8965
|
* | SQLite | ❌ | Use separate queries |
|
|
8945
8966
|
*
|
|
8946
8967
|
* @param tableOrAlias - Table name or [tableName, alias] tuple
|
|
8947
|
-
* @param callback - Join condition callback: `(on,
|
|
8968
|
+
* @param callback - Join condition callback: `(on, joined, source) => on.equal(...)`
|
|
8948
8969
|
* @throws {RelqConfigError} If dialect doesn't support LATERAL joins
|
|
8949
8970
|
*
|
|
8950
8971
|
* @example
|
|
8951
8972
|
* ```typescript
|
|
8952
|
-
* // Get top 5 orders per user
|
|
8973
|
+
* // Get top 5 orders per user — joined table first, source second
|
|
8953
8974
|
* db.table.users.select()
|
|
8954
|
-
* .joinMany('orders', (on,
|
|
8955
|
-
* on.equal(
|
|
8975
|
+
* .joinMany('orders', (on, orders, users) =>
|
|
8976
|
+
* on.equal(orders.userId, users.id)
|
|
8956
8977
|
* .where(q => q.equal('status', 'completed'))
|
|
8957
8978
|
* .orderBy('createdAt', 'DESC')
|
|
8958
8979
|
* .limit(5)
|
|
@@ -8962,8 +8983,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8962
8983
|
*
|
|
8963
8984
|
* // With alias
|
|
8964
8985
|
* db.table.users.select()
|
|
8965
|
-
* .joinMany(['orders', 'recentOrders'], (on,
|
|
8966
|
-
* on.equal(
|
|
8986
|
+
* .joinMany(['orders', 'recentOrders'], (on, orders, users) =>
|
|
8987
|
+
* on.equal(orders.userId, users.id)
|
|
8967
8988
|
* .orderBy('createdAt', 'DESC')
|
|
8968
8989
|
* .limit(3)
|
|
8969
8990
|
* )
|
|
@@ -8990,15 +9011,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8990
9011
|
* | SQLite | ❌ | Use separate queries |
|
|
8991
9012
|
*
|
|
8992
9013
|
* @param tableOrAlias - Table name or [tableName, alias] tuple
|
|
8993
|
-
* @param callback - Join condition callback: `(on,
|
|
9014
|
+
* @param callback - Join condition callback: `(on, joined, source) => on.equal(...)`
|
|
8994
9015
|
* @throws {RelqConfigError} If dialect doesn't support LATERAL joins
|
|
8995
9016
|
*
|
|
8996
9017
|
* @example
|
|
8997
9018
|
* ```typescript
|
|
8998
9019
|
* // Get all users with their orders (empty array if no orders)
|
|
8999
9020
|
* db.table.users.select()
|
|
9000
|
-
* .leftJoinMany('orders', (on,
|
|
9001
|
-
* on.equal(
|
|
9021
|
+
* .leftJoinMany('orders', (on, orders, users) =>
|
|
9022
|
+
* on.equal(orders.userId, users.id)
|
|
9002
9023
|
* .where(q => q.equal('status', 'completed'))
|
|
9003
9024
|
* )
|
|
9004
9025
|
* .all()
|