orchid-orm 1.47.0 → 1.48.0

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/index.d.ts CHANGED
@@ -43,6 +43,7 @@ type HasOneQuery<T extends RelationConfigSelf, Name extends string, TableQuery e
43
43
  } : K extends 'join' ? RelJoin : TableQuery[K];
44
44
  };
45
45
  interface HasOneInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasOne, Q extends Query, CD = T['relations'][Name]['options'] extends RelationThroughOptions ? CreateData<Q, CreateBelongsToData<Q>> : CreateData<AddQueryDefaults<Q, HasOnePopulate<T, Name>>, CreateBelongsToData<Q>>> extends RelationConfigBase {
46
+ returnsOne: true;
46
47
  query: Q;
47
48
  params: HasOneParams<T, Rel>;
48
49
  maybeSingle: T['relations'][Name]['options']['required'] extends true ? QueryTake<Q> : QueryTakeOptional<Q>;
@@ -84,6 +85,7 @@ interface HasMany extends RelationThunkBase {
84
85
  options: HasOneOptions;
85
86
  }
86
87
  interface HasManyInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasMany, Q extends Query> extends RelationConfigBase {
88
+ returnsOne: false;
87
89
  query: Q;
88
90
  params: HasOneParams<T, Rel>;
89
91
  maybeSingle: Q;
@@ -142,6 +144,7 @@ type BelongsToQuery<T extends Query, Name extends string> = {
142
144
  } : P extends 'join' ? RelJoin : P extends CreateMethodsNames | DeleteMethodsNames ? never : T[P];
143
145
  };
144
146
  interface BelongsToInfo<T extends RelationConfigSelf, Name extends string, Rel extends BelongsTo, FK extends string, Required, Q extends Query> extends RelationConfigBase {
147
+ returnsOne: true;
145
148
  query: Q;
146
149
  params: BelongsToParams<T, Rel>;
147
150
  maybeSingle: Required extends true ? QueryTake<Q> : QueryTakeOptional<Q>;
@@ -315,6 +318,7 @@ type HasAndBelongsToManyQuery<Name extends string, TableQuery extends Query> = {
315
318
  } : K extends 'join' ? RelJoin : TableQuery[K];
316
319
  };
317
320
  interface HasAndBelongsToManyInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasAndBelongsToMany, Q extends Query> extends RelationConfigBase {
321
+ returnsOne: false;
318
322
  query: Q;
319
323
  params: HasAndBelongsToManyParams<T, Rel>;
320
324
  maybeSingle: Q;
package/dist/index.js CHANGED
@@ -206,7 +206,10 @@ const selectIfNotSelected = (q, columns) => {
206
206
  };
207
207
  function joinHasThrough(q, baseQuery, joiningQuery, throughRelation, sourceRelation) {
208
208
  return q.whereExists(
209
- throughRelation.joinQuery(throughRelation.query, baseQuery),
209
+ throughRelation.joinQuery(
210
+ throughRelation.query,
211
+ baseQuery
212
+ ),
210
213
  () => {
211
214
  const as = pqb.getQueryAs(joiningQuery);
212
215
  return sourceRelation.joinQuery(
@@ -231,17 +234,6 @@ function joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)
231
234
  }
232
235
  return q;
233
236
  }
234
- const joinQueryChainingHOF = (reverseJoin, joinQuery) => (joiningQuery, baseQuery) => {
235
- const chain = joiningQuery.q.relChain;
236
- if (!chain || chain.length === 1) {
237
- return joinQuery(joiningQuery, baseQuery);
238
- }
239
- const last = chain[chain.length - 1];
240
- const query = "relationConfig" in last ? last.relationConfig.joinQuery(last, baseQuery) : last;
241
- return joiningQuery.where({
242
- EXISTS: { q: reverseJoin(query, joiningQuery) }
243
- });
244
- };
245
237
  const addAutoForeignKey = (tableConfig, from, to, primaryKeys, foreignKeys, options) => {
246
238
  var _a;
247
239
  const toTable = to.table;
@@ -298,6 +290,66 @@ const getColumnKeyFromDbName = (query, name) => {
298
290
  return name;
299
291
  };
300
292
 
293
+ const joinQueryChainHOF = (relPKeys, reverseJoin, joinQuery) => (joiningQuery, baseQuery) => {
294
+ const jq = joiningQuery;
295
+ const chain = jq.q.relChain;
296
+ if (!chain || chain.length === 1) {
297
+ return joinQuery(jq, baseQuery);
298
+ }
299
+ const last = chain[chain.length - 1];
300
+ const query = "relationConfig" in last ? last.relationConfig.joinQuery(last, baseQuery) : last;
301
+ const result = jq.join(
302
+ { _internalJoin: reverseJoin(query, jq) },
303
+ void 0
304
+ );
305
+ if (!query.q.chainMultiple) {
306
+ return result;
307
+ }
308
+ const item = selectRowNumber(result, relPKeys);
309
+ combineOrdering(result, query);
310
+ return wrapQuery(jq, result, item);
311
+ };
312
+ const selectRowNumber = (result, relPKeys) => {
313
+ const hookSelect = result.q.hookSelect = new Map(
314
+ result.q.hookSelect && [...result.q.hookSelect]
315
+ );
316
+ const as = `"${pqb.getQueryAs(result)}"`;
317
+ const partitionColumns = relPKeys.map(
318
+ (key) => `${as}."${result.shape[key]?.data.name || key}"`
319
+ );
320
+ const item = {
321
+ select: {
322
+ sql: `row_number() OVER (PARTITION BY ${partitionColumns.join(", ")})`
323
+ }
324
+ };
325
+ hookSelect.set("r", item);
326
+ return item;
327
+ };
328
+ const combineOrdering = (result, joined) => {
329
+ const { order } = joined.q;
330
+ if (order) {
331
+ const as = pqb.getQueryAs(joined);
332
+ const add = order.map(
333
+ (o) => typeof o === "string" ? `${as}.${o}` : orchidCore.isExpression(o) ? o : Object.fromEntries(
334
+ Object.entries(o).map(([key, value]) => [`${as}.${key}`, value])
335
+ )
336
+ );
337
+ const arr = result.q.order;
338
+ result.q.order = arr ? [...add, ...arr] : add;
339
+ }
340
+ };
341
+ const wrapQuery = (joiningQuery, result, item) => {
342
+ const baseOuterQuery = pqb.cloneQueryBaseUnscoped(joiningQuery);
343
+ const outer = baseOuterQuery.clone();
344
+ outer.q.and = [new pqb.DynamicRawSQL(() => new pqb.RawSQL(`${item.as || "r"} = 1`))];
345
+ outer.q.useFromLimitOffset = true;
346
+ outer.shape = pqb.getShapeFromSelect(result, true);
347
+ outer.q.select = Object.keys(outer.shape);
348
+ outer.q.returnType = result.q.returnType;
349
+ result.q.returnsOne = true;
350
+ return result.wrap(outer);
351
+ };
352
+
301
353
  class BelongsToVirtualColumn extends pqb.VirtualColumn {
302
354
  constructor(schema, key, state) {
303
355
  super(schema);
@@ -404,9 +456,15 @@ const makeBelongsToMethod = (tableConfig, table, relation, relationName, query)
404
456
  relationName,
405
457
  state
406
458
  ),
407
- joinQuery: joinQueryChainingHOF(
459
+ joinQuery: joinQueryChainHOF(
460
+ pqb.getPrimaryKeys(query),
408
461
  reverseJoin,
409
- (joiningQuery, baseQuery) => join(baseQuery, joiningQuery, primaryKeys, foreignKeys)
462
+ (joiningQuery, baseQuery) => join(
463
+ baseQuery,
464
+ joiningQuery,
465
+ primaryKeys,
466
+ foreignKeys
467
+ )
410
468
  ),
411
469
  reverseJoin
412
470
  };
@@ -643,6 +701,7 @@ class HasOneVirtualColumn extends pqb.VirtualColumn {
643
701
  }
644
702
  }
645
703
  const makeHasOneMethod = (tableConfig, table, relation, relationName, query) => {
704
+ const relPKeys = pqb.getPrimaryKeys(query);
646
705
  if ("through" in relation.options) {
647
706
  const { through, source } = relation.options;
648
707
  const throughRelation = getThroughRelation(table, through);
@@ -670,7 +729,8 @@ const makeHasOneMethod = (tableConfig, table, relation, relationName, query) =>
670
729
  const throughQuery = table.queryRelated(through, params);
671
730
  return query.whereExists(throughQuery, whereExistsCallback);
672
731
  },
673
- joinQuery: joinQueryChainingHOF(
732
+ joinQuery: joinQueryChainHOF(
733
+ relPKeys,
674
734
  reverseJoin2,
675
735
  (joiningQuery, baseQuery) => joinHasThrough(
676
736
  joiningQuery,
@@ -728,7 +788,8 @@ const makeHasOneMethod = (tableConfig, table, relation, relationName, query) =>
728
788
  relationName,
729
789
  state
730
790
  ),
731
- joinQuery: joinQueryChainingHOF(
791
+ joinQuery: joinQueryChainHOF(
792
+ relPKeys,
732
793
  reverseJoin,
733
794
  (joiningQuery, baseQuery) => joinHasRelation(
734
795
  baseQuery,
@@ -911,6 +972,7 @@ class HasManyVirtualColumn extends pqb.VirtualColumn {
911
972
  }
912
973
  }
913
974
  const makeHasManyMethod = (tableConfig, table, relation, relationName, query) => {
975
+ const relPKeys = pqb.getPrimaryKeys(query);
914
976
  if ("through" in relation.options) {
915
977
  const { through, source } = relation.options;
916
978
  const throughRelation = getThroughRelation(table, through);
@@ -941,7 +1003,8 @@ const makeHasManyMethod = (tableConfig, table, relation, relationName, query) =>
941
1003
  whereExistsCallback
942
1004
  );
943
1005
  },
944
- joinQuery: joinQueryChainingHOF(
1006
+ joinQuery: joinQueryChainHOF(
1007
+ relPKeys,
945
1008
  reverseJoin2,
946
1009
  (joiningQuery, baseQuery) => joinHasThrough(
947
1010
  joiningQuery,
@@ -999,7 +1062,8 @@ const makeHasManyMethod = (tableConfig, table, relation, relationName, query) =>
999
1062
  relationName,
1000
1063
  state
1001
1064
  ),
1002
- joinQuery: joinQueryChainingHOF(
1065
+ joinQuery: joinQueryChainHOF(
1066
+ relPKeys,
1003
1067
  reverseJoin,
1004
1068
  (joiningQuery, baseQuery) => joinHasRelation(
1005
1069
  baseQuery,
@@ -1388,7 +1452,8 @@ const makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relatio
1388
1452
  relationName,
1389
1453
  state
1390
1454
  ),
1391
- joinQuery: joinQueryChainingHOF(
1455
+ joinQuery: joinQueryChainHOF(
1456
+ pqb.getPrimaryKeys(query),
1392
1457
  reverseJoin,
1393
1458
  (joiningQuery, baseQuery2) => joinQuery(
1394
1459
  joiningQuery,