relq 1.0.86 → 1.0.88
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.
- package/dist/cjs/core/helpers/select-joins.cjs +19 -6
- package/dist/cjs/select/join-condition-builder.cjs +4 -4
- package/dist/cjs/select/join-many-condition-builder.cjs +16 -10
- package/dist/esm/core/helpers/select-joins.js +19 -6
- package/dist/esm/select/join-condition-builder.js +4 -4
- package/dist/esm/select/join-many-condition-builder.js +16 -10
- package/dist/index.d.ts +85 -55
- package/package.json +1 -1
|
@@ -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 = {
|
|
@@ -113,12 +118,21 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
|
|
|
113
118
|
const internals = builder[join_internals_1.JOIN_INTERNAL];
|
|
114
119
|
parts.push('SELECT');
|
|
115
120
|
const selectedProps = internals.getSelectedColumns();
|
|
121
|
+
const innerJoins = internals.getInnerJoins();
|
|
122
|
+
const hasInnerJoins = innerJoins.length > 0;
|
|
123
|
+
const toSnake = (s) => s.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`);
|
|
116
124
|
if (selectedProps && selectedProps.length > 0) {
|
|
117
125
|
const tableColumns = tableDef?.$columns || tableDef;
|
|
118
126
|
const selectCols = selectedProps.map(prop => {
|
|
119
127
|
const columnDef = tableColumns?.[prop];
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
if (columnDef || !hasInnerJoins) {
|
|
129
|
+
const sqlName = columnDef?.$columnName || toSnake(prop);
|
|
130
|
+
return `"${alias}"."${sqlName}" AS "${prop}"`;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
const sqlName = toSnake(prop);
|
|
134
|
+
return `"${sqlName}" AS "${prop}"`;
|
|
135
|
+
}
|
|
122
136
|
}).join(', ');
|
|
123
137
|
parts.push(selectCols);
|
|
124
138
|
}
|
|
@@ -126,7 +140,6 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
|
|
|
126
140
|
parts.push(`"${alias}".*`);
|
|
127
141
|
}
|
|
128
142
|
parts.push(`FROM "${tableName}" AS "${alias}"`);
|
|
129
|
-
const innerJoins = internals.getInnerJoins();
|
|
130
143
|
for (const join of innerJoins) {
|
|
131
144
|
parts.push(`${join.type} "${join.table}" AS "${join.alias}" ON ${join.onClause}`);
|
|
132
145
|
}
|
|
@@ -98,12 +98,12 @@ class JoinConditionBuilder {
|
|
|
98
98
|
this.whereConditions.push(...collector.getConditions());
|
|
99
99
|
return this;
|
|
100
100
|
}
|
|
101
|
-
select(
|
|
102
|
-
if (
|
|
103
|
-
this.selectedColumns =
|
|
101
|
+
select(...args) {
|
|
102
|
+
if (args.length === 1 && Array.isArray(args[0])) {
|
|
103
|
+
this.selectedColumns = args[0];
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
106
|
-
this.selectedColumns =
|
|
106
|
+
this.selectedColumns = args;
|
|
107
107
|
}
|
|
108
108
|
return this;
|
|
109
109
|
}
|
|
@@ -34,28 +34,34 @@ class JoinManyConditionBuilder extends join_condition_builder_1.JoinConditionBui
|
|
|
34
34
|
this.rightProxy = rightProxy;
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
innerJoin(
|
|
37
|
+
innerJoin(tableOrAlias, callback) {
|
|
38
38
|
if (!this.proxyCreator) {
|
|
39
39
|
throw new Error('innerJoin requires proxy creator - use raw innerJoinRaw() instead');
|
|
40
40
|
}
|
|
41
|
-
const
|
|
41
|
+
const [tableKey, alias] = Array.isArray(tableOrAlias)
|
|
42
|
+
? tableOrAlias
|
|
43
|
+
: [tableOrAlias, tableOrAlias];
|
|
44
|
+
const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
|
|
42
45
|
const conditionBuilder = new join_condition_builder_1.JoinConditionBuilder();
|
|
43
46
|
callback(conditionBuilder, innerProxy);
|
|
44
47
|
const internals = conditionBuilder[join_internals_1.JOIN_INTERNAL];
|
|
45
48
|
const onClause = internals.toSQL();
|
|
46
|
-
this.innerJoins.push({ type: 'JOIN', table: tableName, alias
|
|
49
|
+
this.innerJoins.push({ type: 'JOIN', table: tableName, alias, onClause });
|
|
47
50
|
return this;
|
|
48
51
|
}
|
|
49
|
-
leftInnerJoin(
|
|
52
|
+
leftInnerJoin(tableOrAlias, callback) {
|
|
50
53
|
if (!this.proxyCreator) {
|
|
51
54
|
throw new Error('leftInnerJoin requires proxy creator - use raw leftInnerJoinRaw() instead');
|
|
52
55
|
}
|
|
53
|
-
const
|
|
56
|
+
const [tableKey, alias] = Array.isArray(tableOrAlias)
|
|
57
|
+
? tableOrAlias
|
|
58
|
+
: [tableOrAlias, tableOrAlias];
|
|
59
|
+
const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
|
|
54
60
|
const conditionBuilder = new join_condition_builder_1.JoinConditionBuilder();
|
|
55
61
|
callback(conditionBuilder, innerProxy);
|
|
56
62
|
const internals = conditionBuilder[join_internals_1.JOIN_INTERNAL];
|
|
57
63
|
const onClause = internals.toSQL();
|
|
58
|
-
this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias
|
|
64
|
+
this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias, onClause });
|
|
59
65
|
return this;
|
|
60
66
|
}
|
|
61
67
|
innerJoinRaw(table, alias, onClause) {
|
|
@@ -66,12 +72,12 @@ class JoinManyConditionBuilder extends join_condition_builder_1.JoinConditionBui
|
|
|
66
72
|
this.innerJoins.push({ type: 'LEFT JOIN', table, alias, onClause });
|
|
67
73
|
return this;
|
|
68
74
|
}
|
|
69
|
-
select(
|
|
70
|
-
if (
|
|
71
|
-
this.selectedColumns =
|
|
75
|
+
select(...args) {
|
|
76
|
+
if (args.length === 1 && Array.isArray(args[0])) {
|
|
77
|
+
this.selectedColumns = args[0];
|
|
72
78
|
}
|
|
73
79
|
else {
|
|
74
|
-
this.selectedColumns =
|
|
80
|
+
this.selectedColumns = args;
|
|
75
81
|
}
|
|
76
82
|
return this;
|
|
77
83
|
}
|
|
@@ -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 = {
|
|
@@ -109,12 +114,21 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
|
|
|
109
114
|
const internals = builder[JOIN_INTERNAL];
|
|
110
115
|
parts.push('SELECT');
|
|
111
116
|
const selectedProps = internals.getSelectedColumns();
|
|
117
|
+
const innerJoins = internals.getInnerJoins();
|
|
118
|
+
const hasInnerJoins = innerJoins.length > 0;
|
|
119
|
+
const toSnake = (s) => s.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`);
|
|
112
120
|
if (selectedProps && selectedProps.length > 0) {
|
|
113
121
|
const tableColumns = tableDef?.$columns || tableDef;
|
|
114
122
|
const selectCols = selectedProps.map(prop => {
|
|
115
123
|
const columnDef = tableColumns?.[prop];
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
if (columnDef || !hasInnerJoins) {
|
|
125
|
+
const sqlName = columnDef?.$columnName || toSnake(prop);
|
|
126
|
+
return `"${alias}"."${sqlName}" AS "${prop}"`;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
const sqlName = toSnake(prop);
|
|
130
|
+
return `"${sqlName}" AS "${prop}"`;
|
|
131
|
+
}
|
|
118
132
|
}).join(', ');
|
|
119
133
|
parts.push(selectCols);
|
|
120
134
|
}
|
|
@@ -122,7 +136,6 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
|
|
|
122
136
|
parts.push(`"${alias}".*`);
|
|
123
137
|
}
|
|
124
138
|
parts.push(`FROM "${tableName}" AS "${alias}"`);
|
|
125
|
-
const innerJoins = internals.getInnerJoins();
|
|
126
139
|
for (const join of innerJoins) {
|
|
127
140
|
parts.push(`${join.type} "${join.table}" AS "${join.alias}" ON ${join.onClause}`);
|
|
128
141
|
}
|
|
@@ -91,12 +91,12 @@ export class JoinConditionBuilder {
|
|
|
91
91
|
this.whereConditions.push(...collector.getConditions());
|
|
92
92
|
return this;
|
|
93
93
|
}
|
|
94
|
-
select(
|
|
95
|
-
if (
|
|
96
|
-
this.selectedColumns =
|
|
94
|
+
select(...args) {
|
|
95
|
+
if (args.length === 1 && Array.isArray(args[0])) {
|
|
96
|
+
this.selectedColumns = args[0];
|
|
97
97
|
}
|
|
98
98
|
else {
|
|
99
|
-
this.selectedColumns =
|
|
99
|
+
this.selectedColumns = args;
|
|
100
100
|
}
|
|
101
101
|
return this;
|
|
102
102
|
}
|
|
@@ -27,28 +27,34 @@ export class JoinManyConditionBuilder extends JoinConditionBuilder {
|
|
|
27
27
|
this.rightProxy = rightProxy;
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
-
innerJoin(
|
|
30
|
+
innerJoin(tableOrAlias, callback) {
|
|
31
31
|
if (!this.proxyCreator) {
|
|
32
32
|
throw new Error('innerJoin requires proxy creator - use raw innerJoinRaw() instead');
|
|
33
33
|
}
|
|
34
|
-
const
|
|
34
|
+
const [tableKey, alias] = Array.isArray(tableOrAlias)
|
|
35
|
+
? tableOrAlias
|
|
36
|
+
: [tableOrAlias, tableOrAlias];
|
|
37
|
+
const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
|
|
35
38
|
const conditionBuilder = new JoinConditionBuilder();
|
|
36
39
|
callback(conditionBuilder, innerProxy);
|
|
37
40
|
const internals = conditionBuilder[JOIN_INTERNAL];
|
|
38
41
|
const onClause = internals.toSQL();
|
|
39
|
-
this.innerJoins.push({ type: 'JOIN', table: tableName, alias
|
|
42
|
+
this.innerJoins.push({ type: 'JOIN', table: tableName, alias, onClause });
|
|
40
43
|
return this;
|
|
41
44
|
}
|
|
42
|
-
leftInnerJoin(
|
|
45
|
+
leftInnerJoin(tableOrAlias, callback) {
|
|
43
46
|
if (!this.proxyCreator) {
|
|
44
47
|
throw new Error('leftInnerJoin requires proxy creator - use raw leftInnerJoinRaw() instead');
|
|
45
48
|
}
|
|
46
|
-
const
|
|
49
|
+
const [tableKey, alias] = Array.isArray(tableOrAlias)
|
|
50
|
+
? tableOrAlias
|
|
51
|
+
: [tableOrAlias, tableOrAlias];
|
|
52
|
+
const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
|
|
47
53
|
const conditionBuilder = new JoinConditionBuilder();
|
|
48
54
|
callback(conditionBuilder, innerProxy);
|
|
49
55
|
const internals = conditionBuilder[JOIN_INTERNAL];
|
|
50
56
|
const onClause = internals.toSQL();
|
|
51
|
-
this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias
|
|
57
|
+
this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias, onClause });
|
|
52
58
|
return this;
|
|
53
59
|
}
|
|
54
60
|
innerJoinRaw(table, alias, onClause) {
|
|
@@ -59,12 +65,12 @@ export class JoinManyConditionBuilder extends JoinConditionBuilder {
|
|
|
59
65
|
this.innerJoins.push({ type: 'LEFT JOIN', table, alias, onClause });
|
|
60
66
|
return this;
|
|
61
67
|
}
|
|
62
|
-
select(
|
|
63
|
-
if (
|
|
64
|
-
this.selectedColumns =
|
|
68
|
+
select(...args) {
|
|
69
|
+
if (args.length === 1 && Array.isArray(args[0])) {
|
|
70
|
+
this.selectedColumns = args[0];
|
|
65
71
|
}
|
|
66
72
|
else {
|
|
67
|
-
this.selectedColumns =
|
|
73
|
+
this.selectedColumns = args;
|
|
68
74
|
}
|
|
69
75
|
return this;
|
|
70
76
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -7644,17 +7644,17 @@ declare class JoinConditionBuilder<TLeft = any, TRight = any> {
|
|
|
7644
7644
|
where(callback: (q: TypedConditionBuilder<TRight>) => TypedConditionBuilder<TRight>): this;
|
|
7645
7645
|
/**
|
|
7646
7646
|
* Select specific columns from the joined table.
|
|
7647
|
-
* If not called
|
|
7647
|
+
* If not called, all columns are selected.
|
|
7648
7648
|
* The return type narrows TRight to only the selected columns.
|
|
7649
7649
|
*
|
|
7650
|
-
* @param columns - Array of column names to select, or '*' for all columns
|
|
7651
|
-
*
|
|
7652
7650
|
* @example
|
|
7653
7651
|
* on.equal(orders.userId, users.id)
|
|
7654
|
-
* .select(['id', 'name', 'email'])
|
|
7655
|
-
* on.
|
|
7652
|
+
* .select(['id', 'name', 'email']) // array syntax
|
|
7653
|
+
* on.equal(orders.userId, users.id)
|
|
7654
|
+
* .select('id', 'name', 'email') // spread syntax
|
|
7656
7655
|
*/
|
|
7657
|
-
select<K extends ColumnKeys<TRight>>(columns: K[]
|
|
7656
|
+
select<K extends ColumnKeys<TRight>>(columns: K[]): JoinConditionBuilder<TLeft, PickColumns<TRight, K>>;
|
|
7657
|
+
select<K extends ColumnKeys<TRight>>(...columns: K[]): JoinConditionBuilder<TLeft, PickColumns<TRight, K>>;
|
|
7658
7658
|
/** @internal */
|
|
7659
7659
|
get [JOIN_INTERNAL](): JoinConditionInternals;
|
|
7660
7660
|
/**
|
|
@@ -7786,7 +7786,10 @@ declare class JoinManyConditionBuilder<TSchema = any, TLeft = any, TRight = any,
|
|
|
7786
7786
|
* // JOIN LATERAL (SELECT ... FROM purchases JOIN products ON ... WHERE ...) ...
|
|
7787
7787
|
* ```
|
|
7788
7788
|
*/
|
|
7789
|
-
innerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(
|
|
7789
|
+
innerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(tableOrAlias: TInnerKey | [
|
|
7790
|
+
TInnerKey,
|
|
7791
|
+
string
|
|
7792
|
+
], callback: InnerJoinCallback<TRight, TSchema[TInnerKey]>): this;
|
|
7790
7793
|
/**
|
|
7791
7794
|
* Add a LEFT JOIN within the LATERAL subquery.
|
|
7792
7795
|
* Autocomplete excludes parent tables already in scope.
|
|
@@ -7794,7 +7797,10 @@ declare class JoinManyConditionBuilder<TSchema = any, TLeft = any, TRight = any,
|
|
|
7794
7797
|
* @param table - Table name (schema key) to join
|
|
7795
7798
|
* @param callback - Join callback receiving (on, innerTable)
|
|
7796
7799
|
*/
|
|
7797
|
-
leftInnerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(
|
|
7800
|
+
leftInnerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(tableOrAlias: TInnerKey | [
|
|
7801
|
+
TInnerKey,
|
|
7802
|
+
string
|
|
7803
|
+
], callback: InnerJoinCallback<TRight, TSchema[TInnerKey]>): this;
|
|
7798
7804
|
/**
|
|
7799
7805
|
* Add a raw inner JOIN with SQL string (no type safety).
|
|
7800
7806
|
* Use when you don't have schema access.
|
|
@@ -7812,9 +7818,12 @@ declare class JoinManyConditionBuilder<TSchema = any, TLeft = any, TRight = any,
|
|
|
7812
7818
|
* Select specific columns from the joined table.
|
|
7813
7819
|
* The return type narrows TRight to only the selected columns.
|
|
7814
7820
|
*
|
|
7815
|
-
* @
|
|
7821
|
+
* @example
|
|
7822
|
+
* on.select(['id', 'name']) // array syntax
|
|
7823
|
+
* on.select('id', 'name') // spread syntax
|
|
7816
7824
|
*/
|
|
7817
|
-
select<K extends ColumnKeys<TRight>>(columns: K[]
|
|
7825
|
+
select<K extends ColumnKeys<TRight>>(columns: K[]): JoinManyConditionBuilder<TSchema, TLeft, PickColumns<TRight, K>, TRightKey>;
|
|
7826
|
+
select<K extends ColumnKeys<TRight>>(...columns: K[]): JoinManyConditionBuilder<TSchema, TLeft, PickColumns<TRight, K>, TRightKey>;
|
|
7818
7827
|
/** @internal */
|
|
7819
7828
|
get [JOIN_INTERNAL](): JoinManyInternals;
|
|
7820
7829
|
/**
|
|
@@ -8502,45 +8511,63 @@ export type InferResultType<TSchema, TTable, TColumns> = TColumns extends [
|
|
|
8502
8511
|
} ? TColumns extends readonly string[] ? Simplify$1<Pick<TSelect, Extract<TColumns[number], keyof TSelect>>> : TSelect : SelectResult<TTable, TColumns extends readonly any[] ? TColumns : [
|
|
8503
8512
|
]>;
|
|
8504
8513
|
/**
|
|
8505
|
-
* Join callback function type
|
|
8506
|
-
*
|
|
8514
|
+
* Join callback function type for join/innerJoin/leftJoin.
|
|
8515
|
+
* The joined table proxy comes FIRST for natural DX:
|
|
8516
|
+
* when you write `.join('orders', ...)`, `orders` is what you think about first.
|
|
8517
|
+
*
|
|
8518
|
+
* @param on - The condition builder for ON clause
|
|
8519
|
+
* @param joined - Table proxy for the joined table (the one in .join('tableName'))
|
|
8520
|
+
* @param source - Table proxy for the source table (the one .join() is called on)
|
|
8521
|
+
*
|
|
8522
|
+
* @example
|
|
8523
|
+
* ```typescript
|
|
8524
|
+
* db.table.users.select()
|
|
8525
|
+
* .join('orders', (on, orders, users) =>
|
|
8526
|
+
* on.equal(orders.userId, users.id)
|
|
8527
|
+
* .select(['id', 'total'])
|
|
8528
|
+
* )
|
|
8529
|
+
* ```
|
|
8530
|
+
*/
|
|
8531
|
+
export type JoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>, joined: TableProxy<TRight>, source: TableProxy<TLeft>) => JoinConditionBuilder<TLeft, TResult>;
|
|
8532
|
+
/**
|
|
8533
|
+
* Right join callback — reversed parameter order from JoinCallback.
|
|
8534
|
+
* For rightJoin, the source table comes first since the right (joined) table
|
|
8535
|
+
* is the primary table in a RIGHT JOIN.
|
|
8507
8536
|
*
|
|
8508
8537
|
* @param on - The condition builder for ON clause
|
|
8509
|
-
* @param
|
|
8510
|
-
* @param
|
|
8538
|
+
* @param source - Table proxy for the source table
|
|
8539
|
+
* @param joined - Table proxy for the joined (right/primary) table
|
|
8511
8540
|
*
|
|
8512
8541
|
* @example
|
|
8513
8542
|
* ```typescript
|
|
8514
|
-
*
|
|
8515
|
-
*
|
|
8516
|
-
*
|
|
8517
|
-
*
|
|
8518
|
-
* )
|
|
8543
|
+
* db.table.users.select()
|
|
8544
|
+
* .rightJoin('orders', (on, users, orders) =>
|
|
8545
|
+
* on.equal(users.id, orders.userId)
|
|
8546
|
+
* )
|
|
8519
8547
|
* ```
|
|
8520
8548
|
*/
|
|
8521
|
-
export type
|
|
8549
|
+
export type RightJoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>, source: TableProxy<TLeft>, joined: TableProxy<TRight>) => JoinConditionBuilder<TLeft, TResult>;
|
|
8522
8550
|
/**
|
|
8523
8551
|
* 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())
|
|
8552
|
+
* Same parameter order as JoinCallback: joined table first, source second.
|
|
8527
8553
|
*
|
|
8528
8554
|
* @param on - The condition builder for LATERAL subquery
|
|
8529
|
-
* @param
|
|
8530
|
-
* @param
|
|
8555
|
+
* @param joined - Table proxy for the joined table
|
|
8556
|
+
* @param source - Table proxy for the source (outer) table
|
|
8531
8557
|
*
|
|
8532
8558
|
* @example
|
|
8533
8559
|
* ```typescript
|
|
8534
8560
|
* // Get top 5 orders per user
|
|
8535
|
-
* .
|
|
8536
|
-
*
|
|
8537
|
-
* .
|
|
8538
|
-
*
|
|
8539
|
-
*
|
|
8540
|
-
*
|
|
8561
|
+
* db.table.users.select()
|
|
8562
|
+
* .joinMany('orders', (on, orders, users) =>
|
|
8563
|
+
* on.equal(orders.userId, users.id)
|
|
8564
|
+
* .where(q => q.equal('status', 'completed'))
|
|
8565
|
+
* .orderBy(orders.createdAt, 'DESC')
|
|
8566
|
+
* .limit(5)
|
|
8567
|
+
* )
|
|
8541
8568
|
* ```
|
|
8542
8569
|
*/
|
|
8543
|
-
export type JoinManyCallback<TSchema, TLeft, TRight, TRightKey extends string, TResult = TRight> = (on: JoinManyConditionBuilder<TSchema, TLeft, TRight, TRightKey>,
|
|
8570
|
+
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
8571
|
/**
|
|
8545
8572
|
* Internal interface for query builders
|
|
8546
8573
|
* This interface exposes execution methods that are hidden from the public API
|
|
@@ -8794,16 +8821,16 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8794
8821
|
* .join('users') // Auto-detects orders.userId → users.id
|
|
8795
8822
|
* // Result: { ...order, users: { id, name, ... } }
|
|
8796
8823
|
*
|
|
8797
|
-
* // With explicit callback
|
|
8824
|
+
* // With explicit callback — joined table first, source second
|
|
8798
8825
|
* db.table.orders.select()
|
|
8799
|
-
* .join('users', (on,
|
|
8800
|
-
* on.equal(
|
|
8826
|
+
* .join('users', (on, users, orders) =>
|
|
8827
|
+
* on.equal(users.id, orders.userId)
|
|
8801
8828
|
* )
|
|
8802
8829
|
*
|
|
8803
8830
|
* // With alias
|
|
8804
8831
|
* db.table.orders.select()
|
|
8805
|
-
* .join(['users', 'user'], (on,
|
|
8806
|
-
* on.equal(
|
|
8832
|
+
* .join(['users', 'user'], (on, user, orders) =>
|
|
8833
|
+
* on.equal(user.id, orders.userId)
|
|
8807
8834
|
* )
|
|
8808
8835
|
* // Result: { ...order, user: { id, name, ... } }
|
|
8809
8836
|
* ```
|
|
@@ -8829,10 +8856,10 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8829
8856
|
* .leftJoin('users')
|
|
8830
8857
|
* // Result: { ...order, users: { ... } | null }
|
|
8831
8858
|
*
|
|
8832
|
-
* // With callback
|
|
8859
|
+
* // With callback — joined table first, source second
|
|
8833
8860
|
* db.table.orders.select()
|
|
8834
|
-
* .leftJoin(['users', 'user'], (on,
|
|
8835
|
-
* on.equal(
|
|
8861
|
+
* .leftJoin(['users', 'user'], (on, user, orders) =>
|
|
8862
|
+
* on.equal(user.id, orders.userId)
|
|
8836
8863
|
* )
|
|
8837
8864
|
* ```
|
|
8838
8865
|
*/
|
|
@@ -8848,12 +8875,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8848
8875
|
leftJoin<TRightKey extends keyof TSchema & string, TResult>(table: TRightKey, callback: JoinCallback<TTable, TSchema[TRightKey], TResult>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedLeftJoin<TRightKey, TResult>>;
|
|
8849
8876
|
/**
|
|
8850
8877
|
* Type-safe RIGHT JOIN.
|
|
8878
|
+
* Callback order is (on, source, joined) — reversed from join/leftJoin
|
|
8879
|
+
* because in a RIGHT JOIN the joined table is the primary table.
|
|
8851
8880
|
*
|
|
8852
8881
|
* @example
|
|
8853
8882
|
* ```typescript
|
|
8854
8883
|
* db.table.orders.select()
|
|
8855
|
-
* .rightJoin('users')
|
|
8856
|
-
*
|
|
8884
|
+
* .rightJoin('users', (on, orders, users) =>
|
|
8885
|
+
* on.equal(orders.userId, users.id)
|
|
8886
|
+
* )
|
|
8857
8887
|
* ```
|
|
8858
8888
|
*/
|
|
8859
8889
|
rightJoin<TRightKey extends keyof TSchema & string, TAlias extends string>(tableAndAlias: [
|
|
@@ -8864,8 +8894,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8864
8894
|
rightJoin<TRightKey extends keyof TSchema & string, TAlias extends string>(tableAndAlias: [
|
|
8865
8895
|
TRightKey,
|
|
8866
8896
|
TAlias
|
|
8867
|
-
], callback:
|
|
8868
|
-
rightJoin<TRightKey extends keyof TSchema & string>(table: TRightKey, callback:
|
|
8897
|
+
], callback: RightJoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TAlias, TSchema[TRightKey]>>;
|
|
8898
|
+
rightJoin<TRightKey extends keyof TSchema & string>(table: TRightKey, callback: RightJoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TRightKey, TSchema[TRightKey]>>;
|
|
8869
8899
|
/**
|
|
8870
8900
|
* Type-safe INNER JOIN (alias for join()).
|
|
8871
8901
|
*/
|
|
@@ -8893,8 +8923,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8893
8923
|
* db.table.users.select()
|
|
8894
8924
|
* .joinSubquery(
|
|
8895
8925
|
* 'recent_orders',
|
|
8896
|
-
* db.table.orders.select().join('payments', (on,
|
|
8897
|
-
* on.equal(
|
|
8926
|
+
* db.table.orders.select().join('payments', (on, p, o) =>
|
|
8927
|
+
* on.equal(p.orderId, o.id)
|
|
8898
8928
|
* ),
|
|
8899
8929
|
* `"recent_orders"."user_id" = "users"."id"`
|
|
8900
8930
|
* )
|
|
@@ -8944,15 +8974,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8944
8974
|
* | SQLite | ❌ | Use separate queries |
|
|
8945
8975
|
*
|
|
8946
8976
|
* @param tableOrAlias - Table name or [tableName, alias] tuple
|
|
8947
|
-
* @param callback - Join condition callback: `(on,
|
|
8977
|
+
* @param callback - Join condition callback: `(on, joined, source) => on.equal(...)`
|
|
8948
8978
|
* @throws {RelqConfigError} If dialect doesn't support LATERAL joins
|
|
8949
8979
|
*
|
|
8950
8980
|
* @example
|
|
8951
8981
|
* ```typescript
|
|
8952
|
-
* // Get top 5 orders per user
|
|
8982
|
+
* // Get top 5 orders per user — joined table first, source second
|
|
8953
8983
|
* db.table.users.select()
|
|
8954
|
-
* .joinMany('orders', (on,
|
|
8955
|
-
* on.equal(
|
|
8984
|
+
* .joinMany('orders', (on, orders, users) =>
|
|
8985
|
+
* on.equal(orders.userId, users.id)
|
|
8956
8986
|
* .where(q => q.equal('status', 'completed'))
|
|
8957
8987
|
* .orderBy('createdAt', 'DESC')
|
|
8958
8988
|
* .limit(5)
|
|
@@ -8962,8 +8992,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8962
8992
|
*
|
|
8963
8993
|
* // With alias
|
|
8964
8994
|
* db.table.users.select()
|
|
8965
|
-
* .joinMany(['orders', 'recentOrders'], (on,
|
|
8966
|
-
* on.equal(
|
|
8995
|
+
* .joinMany(['orders', 'recentOrders'], (on, orders, users) =>
|
|
8996
|
+
* on.equal(orders.userId, users.id)
|
|
8967
8997
|
* .orderBy('createdAt', 'DESC')
|
|
8968
8998
|
* .limit(3)
|
|
8969
8999
|
* )
|
|
@@ -8990,15 +9020,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
8990
9020
|
* | SQLite | ❌ | Use separate queries |
|
|
8991
9021
|
*
|
|
8992
9022
|
* @param tableOrAlias - Table name or [tableName, alias] tuple
|
|
8993
|
-
* @param callback - Join condition callback: `(on,
|
|
9023
|
+
* @param callback - Join condition callback: `(on, joined, source) => on.equal(...)`
|
|
8994
9024
|
* @throws {RelqConfigError} If dialect doesn't support LATERAL joins
|
|
8995
9025
|
*
|
|
8996
9026
|
* @example
|
|
8997
9027
|
* ```typescript
|
|
8998
9028
|
* // Get all users with their orders (empty array if no orders)
|
|
8999
9029
|
* db.table.users.select()
|
|
9000
|
-
* .leftJoinMany('orders', (on,
|
|
9001
|
-
* on.equal(
|
|
9030
|
+
* .leftJoinMany('orders', (on, orders, users) =>
|
|
9031
|
+
* on.equal(orders.userId, users.id)
|
|
9002
9032
|
* .where(q => q.equal('status', 'completed'))
|
|
9003
9033
|
* )
|
|
9004
9034
|
* .all()
|