drizzle-kit 0.30.1-e6823b4 → 0.30.1-f2d266c

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.
Files changed (4) hide show
  1. package/api.js +216 -50
  2. package/api.mjs +216 -50
  3. package/bin.cjs +1 -1
  4. package/package.json +1 -1
package/api.js CHANGED
@@ -24837,24 +24837,33 @@ var init_primary_keys = __esm({
24837
24837
  function getOrderByOperators() {
24838
24838
  return orderByOperators;
24839
24839
  }
24840
- function mapRelationalRow(row, buildQueryResultSelection, mapColumnValue = (value) => value, parseJson = false) {
24840
+ function mapRelationalRow(row, buildQueryResultSelection, mapColumnValue = (value) => value, parseJson = false, path2) {
24841
24841
  for (const selectionItem of buildQueryResultSelection) {
24842
24842
  const field = selectionItem.field;
24843
24843
  if (is(field, Table2)) {
24844
+ const currentPath = `${path2 ? `${path2}.` : ""}${selectionItem.key}`;
24844
24845
  if (row[selectionItem.key] === null)
24845
24846
  continue;
24846
24847
  if (parseJson)
24847
24848
  row[selectionItem.key] = JSON.parse(row[selectionItem.key]);
24848
24849
  if (selectionItem.isArray) {
24849
24850
  for (const item of row[selectionItem.key]) {
24850
- mapRelationalRow(item, selectionItem.selection, mapColumnValue);
24851
+ mapRelationalRow(
24852
+ item,
24853
+ selectionItem.selection,
24854
+ mapColumnValue,
24855
+ false,
24856
+ currentPath
24857
+ );
24851
24858
  }
24852
24859
  continue;
24853
24860
  }
24854
24861
  mapRelationalRow(
24855
24862
  row[selectionItem.key],
24856
24863
  selectionItem.selection,
24857
- mapColumnValue
24864
+ mapColumnValue,
24865
+ false,
24866
+ currentPath
24858
24867
  );
24859
24868
  continue;
24860
24869
  }
@@ -24905,7 +24914,7 @@ function defineRelations(schema5, relations) {
24905
24914
  );
24906
24915
  }
24907
24916
  function relationsFieldFilterToSQL(column5, filter2) {
24908
- if (typeof filter2 !== "object" || is(filter2, Placeholder))
24917
+ if (typeof filter2 !== "object")
24909
24918
  return eq(column5, filter2);
24910
24919
  const entries = Object.entries(filter2);
24911
24920
  if (!entries.length)
@@ -24932,6 +24941,21 @@ function relationsFieldFilterToSQL(column5, filter2) {
24932
24941
  );
24933
24942
  continue;
24934
24943
  }
24944
+ case "isNotNull":
24945
+ case "isNull": {
24946
+ if (!value)
24947
+ continue;
24948
+ parts.push(operators[target](column5));
24949
+ continue;
24950
+ }
24951
+ case "in": {
24952
+ parts.push(operators.inArray(column5, value));
24953
+ continue;
24954
+ }
24955
+ case "notIn": {
24956
+ parts.push(operators.notInArray(column5, value));
24957
+ continue;
24958
+ }
24935
24959
  default: {
24936
24960
  parts.push(
24937
24961
  operators[target](
@@ -25029,18 +25053,49 @@ function relationExtrasToSQL(table5, extras) {
25029
25053
  selection
25030
25054
  };
25031
25055
  }
25032
- function relationToSQL(relation, sourceTable, targetTable) {
25056
+ function getTableSql(table5) {
25057
+ return sql`${sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(!table5[IsAlias] && table5[Schema])}`}${table5}`;
25058
+ }
25059
+ function relationToSQL(relation, sourceTable, targetTable, throughTable) {
25060
+ if (relation.through) {
25061
+ const outerColumnWhere = relation.sourceColumns.map((s, i) => {
25062
+ const t = relation.through.source[i];
25063
+ return eq(
25064
+ sql`${getTableSql(sourceTable)}.${sql.identifier(s.name)}`,
25065
+ sql`${getTableSql(throughTable)}.${sql.identifier(t.name)}`
25066
+ );
25067
+ });
25068
+ const innerColumnWhere = relation.targetColumns.map((s, i) => {
25069
+ const t = relation.through.target[i];
25070
+ return eq(
25071
+ sql`${getTableSql(throughTable)}.${sql.identifier(t.name)}`,
25072
+ sql`${getTableSql(targetTable)}.${sql.identifier(s.name)}`
25073
+ );
25074
+ });
25075
+ return {
25076
+ filter: and(
25077
+ relation.where ? relation.isReversed ? relationsFilterToSQL(targetTable, relation.where) : relationsFilterToSQL(sourceTable, relation.where) : void 0
25078
+ ),
25079
+ joinCondition: and(
25080
+ ...outerColumnWhere,
25081
+ ...innerColumnWhere
25082
+ )
25083
+ };
25084
+ }
25033
25085
  const columnWhere = relation.sourceColumns.map((s, i) => {
25034
25086
  const t = relation.targetColumns[i];
25035
25087
  return eq(
25036
- sql`${sql`${sql`${sql.identifier(sourceTable[Schema] ?? "")}.`.if(sourceTable[Schema] && !sourceTable[IsAlias])}`}${sourceTable}.${sql.identifier(s.name)}`,
25037
- sql`${sql`${sql`${sql.identifier(targetTable[Schema] ?? "")}.`.if(targetTable[Schema] && !targetTable[IsAlias])}`}${targetTable}.${sql.identifier(t.name)}`
25088
+ sql`${getTableSql(sourceTable)}.${sql.identifier(s.name)}`,
25089
+ sql`${getTableSql(targetTable)}.${sql.identifier(t.name)}`
25038
25090
  );
25039
25091
  });
25040
- const targetWhere = relation.where ? and(...columnWhere, relationsFilterToSQL(sourceTable, relation.where)) : and(...columnWhere);
25041
- return targetWhere;
25092
+ const fullWhere = and(
25093
+ ...columnWhere,
25094
+ relation.where ? relation.isReversed ? relationsFilterToSQL(targetTable, relation.where) : relationsFilterToSQL(sourceTable, relation.where) : void 0
25095
+ );
25096
+ return { filter: fullWhere };
25042
25097
  }
25043
- var _a118, Relations, _a119, Relation, _a120, _b95, One, _a121, _b96, Many, _a122, AggregatedField, _a123, _b97, Count, operators, orderByOperators, _a124, RelationsBuilderTable, _a125, RelationsBuilderColumn, _a126, RelationsHelperStatic;
25098
+ var _a118, Relations, _a119, Relation, _a120, _b95, One, _a121, _b96, Many, _a122, AggregatedField, _a123, _b97, Count, operators, orderByOperators, _a124, RelationsBuilderTable, _a125, _RelationsBuilderColumn, RelationsBuilderColumn, _a126, RelationsHelperStatic;
25044
25099
  var init_relations = __esm({
25045
25100
  "../drizzle-orm/dist/relations.js"() {
25046
25101
  "use strict";
@@ -25115,9 +25170,30 @@ var init_relations = __esm({
25115
25170
  if (relation.sourceColumns && relation.targetColumns) {
25116
25171
  if (relation.sourceColumns.length !== relation.targetColumns.length) {
25117
25172
  throw new Error(
25118
- `${relationPrintName}: "from" and "to" arrays must have the same length`
25173
+ `${relationPrintName}: "from" and "to" fields must have the same length`
25119
25174
  );
25120
25175
  }
25176
+ if (relation.through) {
25177
+ if (relation.through.source.length !== relation.through.target.length || relation.through.source.length !== relation.sourceColumns.length || relation.through.target.length !== relation.targetColumns.length) {
25178
+ throw new Error(
25179
+ `${relationPrintName}: ".through(column)" must be used either on all columns in "from" and "to" or not defined on any of them`
25180
+ );
25181
+ }
25182
+ for (const column5 of relation.through.source) {
25183
+ if (column5.table !== relation.throughTable) {
25184
+ throw new Error(
25185
+ `${relationPrintName}: ".through(column)" must be used on the same table by all columns of the relation`
25186
+ );
25187
+ }
25188
+ }
25189
+ for (const column5 of relation.through.target) {
25190
+ if (column5.table !== relation.throughTable) {
25191
+ throw new Error(
25192
+ `${relationPrintName}: ".through(column)" must be used on the same table by all columns of the relation`
25193
+ );
25194
+ }
25195
+ }
25196
+ }
25121
25197
  continue;
25122
25198
  }
25123
25199
  if (relation.sourceColumns || relation.targetColumns) {
@@ -25177,7 +25253,13 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25177
25253
  }
25178
25254
  relation.sourceColumns = reverseRelation.targetColumns;
25179
25255
  relation.targetColumns = reverseRelation.sourceColumns;
25180
- relation.where = reverseRelation.where;
25256
+ relation.through = reverseRelation.through ? {
25257
+ source: reverseRelation.through.target,
25258
+ target: reverseRelation.through.source
25259
+ } : void 0;
25260
+ relation.throughTable = reverseRelation.throughTable;
25261
+ relation.isReversed = !relation.where;
25262
+ relation.where = relation.where ?? reverseRelation.where;
25181
25263
  }
25182
25264
  }
25183
25265
  }
@@ -25192,6 +25274,9 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25192
25274
  __publicField(this, "alias");
25193
25275
  __publicField(this, "where");
25194
25276
  __publicField(this, "sourceTable");
25277
+ __publicField(this, "through");
25278
+ __publicField(this, "throughTable");
25279
+ __publicField(this, "isReversed");
25195
25280
  this.targetTable = targetTable;
25196
25281
  }
25197
25282
  };
@@ -25203,12 +25288,30 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25203
25288
  this.alias = config?.alias;
25204
25289
  this.where = config?.where;
25205
25290
  if (config?.from) {
25206
- this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) => it._.column) : [config.from._.column];
25291
+ this.sourceColumns = (Array.isArray(config.from) ? config.from : [config.from]).map((it) => {
25292
+ this.throughTable ??= it._.through?._.column.table;
25293
+ return it._.column;
25294
+ });
25207
25295
  }
25208
25296
  if (config?.to) {
25209
- this.targetColumns = Array.isArray(config.to) ? config.to.map((it) => it._.column) : [config.to._.column];
25297
+ this.targetColumns = (Array.isArray(config.to) ? config.to : [config.to]).map((it) => {
25298
+ this.throughTable ??= it._.through?._.column.table;
25299
+ return it._.column;
25300
+ });
25210
25301
  }
25211
- this.optional = config?.optional ?? false;
25302
+ if (this.throughTable) {
25303
+ this.through = Array.isArray(config?.from) ? {
25304
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25305
+ source: config.from.map((e) => e._.through?._.column),
25306
+ target: (config.to ?? []).map((e) => e._.column)
25307
+ } : {
25308
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25309
+ source: [config?.from?._.through?._.column],
25310
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
25311
+ target: [config?.to?._.through?._.column]
25312
+ };
25313
+ }
25314
+ this.optional = config?.optional ?? true;
25212
25315
  }
25213
25316
  };
25214
25317
  __publicField(One, _a120, "OneV2");
@@ -25219,10 +25322,28 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25219
25322
  this.alias = config?.alias;
25220
25323
  this.where = config?.where;
25221
25324
  if (config?.from) {
25222
- this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) => it._.column) : [config.from._.column];
25325
+ this.sourceColumns = (Array.isArray(config.from) ? config.from : [config.from]).map((it) => {
25326
+ this.throughTable ??= it._.through?._.column.table;
25327
+ return it._.column;
25328
+ });
25223
25329
  }
25224
25330
  if (config?.to) {
25225
- this.targetColumns = Array.isArray(config.to) ? config.to.map((it) => it._.column) : [config.to._.column];
25331
+ this.targetColumns = (Array.isArray(config.to) ? config.to : [config.to]).map((it) => {
25332
+ this.throughTable ??= it._.through?._.column.table;
25333
+ return it._.column;
25334
+ });
25335
+ }
25336
+ if (this.throughTable) {
25337
+ this.through = Array.isArray(config?.from) ? {
25338
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25339
+ source: config.from.map((e) => e._.through?._.column),
25340
+ target: (config.to ?? []).map((e) => e._.column)
25341
+ } : {
25342
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25343
+ source: [config?.from?._.through?._.column],
25344
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
25345
+ target: [config?.to?._.through?._.column]
25346
+ };
25226
25347
  }
25227
25348
  }
25228
25349
  };
@@ -25247,7 +25368,8 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25247
25368
  if (!this.query) {
25248
25369
  if (!this.table)
25249
25370
  throw new Error("Table must be set before building aggregate field");
25250
- this.query = sql`select count(*) as ${sql.identifier("r")} from ${this.table}`.mapWith(Number);
25371
+ const table5 = this.table;
25372
+ this.query = sql`select count(*) as ${sql.identifier("r")} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}`.mapWith(Number);
25251
25373
  }
25252
25374
  return this.query;
25253
25375
  }
@@ -25297,24 +25419,25 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25297
25419
  };
25298
25420
  __publicField(RelationsBuilderTable, _a124, "RelationsBuilderTable");
25299
25421
  _a125 = entityKind;
25300
- RelationsBuilderColumn = class {
25301
- constructor(column5) {
25422
+ _RelationsBuilderColumn = class _RelationsBuilderColumn {
25423
+ constructor(column5, through) {
25302
25424
  __publicField(this, "_");
25303
25425
  this._ = {
25304
25426
  tableName: getTableName(column5.table),
25305
25427
  data: void 0,
25306
- column: column5
25428
+ column: column5,
25429
+ through
25307
25430
  };
25308
25431
  }
25309
25432
  through(column5) {
25310
- this._.through = column5;
25311
- return this;
25433
+ return new _RelationsBuilderColumn(this._.column, column5);
25312
25434
  }
25313
25435
  getSQL() {
25314
25436
  return this._.column.getSQL();
25315
25437
  }
25316
25438
  };
25317
- __publicField(RelationsBuilderColumn, _a125, "RelationsBuilderColumn");
25439
+ __publicField(_RelationsBuilderColumn, _a125, "RelationsBuilderColumn");
25440
+ RelationsBuilderColumn = _RelationsBuilderColumn;
25318
25441
  _a126 = entityKind;
25319
25442
  RelationsHelperStatic = class {
25320
25443
  constructor(tables) {
@@ -26071,7 +26194,7 @@ var init_dialect = __esm({
26071
26194
  sql`, `
26072
26195
  );
26073
26196
  });
26074
- __publicField(this, "buildColumns", (table5, tableConfig, selection, config) => config?.columns ? (() => {
26197
+ __publicField(this, "buildColumns", (table5, selection, config) => config?.columns ? (() => {
26075
26198
  const entries = Object.entries(config.columns);
26076
26199
  const columnIdentifiers = [];
26077
26200
  let colSelectionMode;
@@ -26718,7 +26841,8 @@ var init_dialect = __esm({
26718
26841
  relationWhere,
26719
26842
  mode,
26720
26843
  errorPath,
26721
- depth
26844
+ depth,
26845
+ throughJoin
26722
26846
  }) {
26723
26847
  const selection = [];
26724
26848
  const isSingle = mode === "first";
@@ -26729,7 +26853,7 @@ var init_dialect = __esm({
26729
26853
  const offset = params?.offset;
26730
26854
  const where = params?.where && relationWhere ? and(relationsFilterToSQL(table5, params.where), relationWhere) : params?.where ? relationsFilterToSQL(table5, params.where) : relationWhere;
26731
26855
  const order = params?.orderBy ? relationsOrderToSQL(table5, params.orderBy) : void 0;
26732
- const columns = this.buildColumns(table5, tableConfig, selection, params);
26856
+ const columns = this.buildColumns(table5, selection, params);
26733
26857
  const extras = params?.extras ? relationExtrasToSQL(table5, params.extras) : void 0;
26734
26858
  if (extras)
26735
26859
  selection.push(...extras.selection);
@@ -26757,10 +26881,15 @@ var init_dialect = __esm({
26757
26881
  const relation = tableConfig.relations[k];
26758
26882
  const isSingle2 = is(relation, One);
26759
26883
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
26760
- const relationFilter = relationToSQL(relation, table5, targetTable);
26761
- selectionArr.push(
26762
- isSingle2 ? sql`${sql.identifier(k)}.${sql.identifier("r")} as ${sql.identifier(k)}` : sql`coalesce(${sql.identifier(k)}.${sql.identifier("r")}, '[]') as ${sql.identifier(k)}`
26884
+ const throughTable = relation.throughTable ? aliasedTable(relation.throughTable, `tr${currentDepth}`) : void 0;
26885
+ const { filter: filter2, joinCondition } = relationToSQL(
26886
+ relation,
26887
+ table5,
26888
+ targetTable,
26889
+ throughTable
26763
26890
  );
26891
+ selectionArr.push(sql`${sql.identifier(k)}.${sql.identifier("r")} as ${sql.identifier(k)}`);
26892
+ const throughJoin2 = throughTable ? sql` inner join ${sql`${sql.identifier(throughTable[Schema] ?? "")}.`.if(throughTable[Schema])}${sql.identifier(throughTable[OriginalName])} as ${throughTable} on ${joinCondition}` : void 0;
26764
26893
  const innerQuery = this.buildRelationalQuery({
26765
26894
  table: targetTable,
26766
26895
  mode: isSingle2 ? "first" : "many",
@@ -26769,17 +26898,20 @@ var init_dialect = __esm({
26769
26898
  tableConfig: schema5[tableNamesMap[getTableUniqueName(relation.targetTable)]],
26770
26899
  tableNamesMap,
26771
26900
  tables,
26772
- relationWhere: relationFilter,
26901
+ relationWhere: filter2,
26773
26902
  errorPath: `${currentPath.length ? `${currentPath}.` : ""}${k}`,
26774
- depth: currentDepth + 1
26903
+ depth: currentDepth + 1,
26904
+ throughJoin: throughJoin2
26775
26905
  });
26776
26906
  selection.push({
26777
26907
  field: targetTable,
26778
26908
  key: k,
26779
26909
  selection: innerQuery.selection,
26780
- isArray: !isSingle2
26910
+ isArray: !isSingle2,
26911
+ isOptional: (relation.optional ?? false) || join !== true && !!join.where
26781
26912
  });
26782
- return sql`left join lateral(select ${isSingle2 ? sql`row_to_json(${sql.identifier("t")}.*) ${sql.identifier("r")}` : sql`json_agg(row_to_json(${sql.identifier("t")}.*)) ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)} on true`;
26913
+ const joinQuery = sql`left join lateral(select ${isSingle2 ? sql`row_to_json(${sql.identifier("t")}.*) ${sql.identifier("r")}` : sql`coalesce(json_agg(row_to_json(${sql.identifier("t")}.*)), '[]') as ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)} on true`;
26914
+ return joinQuery;
26783
26915
  }),
26784
26916
  sql` `
26785
26917
  );
@@ -26792,7 +26924,7 @@ var init_dialect = __esm({
26792
26924
  });
26793
26925
  }
26794
26926
  const selectionSet = sql.join(selectionArr.filter((e) => e !== void 0), sql`, `);
26795
- const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${sql` ${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
26927
+ const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${throughJoin}${sql` ${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
26796
26928
  return {
26797
26929
  sql: query,
26798
26930
  selection
@@ -32797,7 +32929,8 @@ var init_dialect2 = __esm({
32797
32929
  mode,
32798
32930
  isNested,
32799
32931
  errorPath,
32800
- depth
32932
+ depth,
32933
+ throughJoin
32801
32934
  }) {
32802
32935
  const selection = [];
32803
32936
  const isSingle = mode === "first";
@@ -32834,7 +32967,14 @@ var init_dialect2 = __esm({
32834
32967
  const relation = tableConfig.relations[k];
32835
32968
  const isSingle2 = is(relation, One);
32836
32969
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
32837
- const relationFilter = relationToSQL(relation, table5, targetTable);
32970
+ const throughTable = relation.throughTable ? aliasedTable(relation.throughTable, `tr${currentDepth}`) : void 0;
32971
+ const { filter: filter2, joinCondition } = relationToSQL(
32972
+ relation,
32973
+ table5,
32974
+ targetTable,
32975
+ throughTable
32976
+ );
32977
+ const throughJoin2 = throughTable ? sql` inner join ${sql`${sql.identifier(throughTable[Schema] ?? "")}.`.if(throughTable[Schema])}${sql.identifier(throughTable[OriginalName])} as ${throughTable} on ${joinCondition}` : void 0;
32838
32978
  const innerQuery = this.buildRelationalQuery({
32839
32979
  table: targetTable,
32840
32980
  mode: isSingle2 ? "first" : "many",
@@ -32843,16 +32983,18 @@ var init_dialect2 = __esm({
32843
32983
  tableConfig: schema5[tableNamesMap[getTableUniqueName(relation.targetTable)]],
32844
32984
  tableNamesMap,
32845
32985
  tables,
32846
- relationWhere: relationFilter,
32986
+ relationWhere: filter2,
32847
32987
  isNested: true,
32848
32988
  errorPath: `${currentPath.length ? `${currentPath}.` : ""}${k}`,
32849
- depth: currentDepth + 1
32989
+ depth: currentDepth + 1,
32990
+ throughJoin: throughJoin2
32850
32991
  });
32851
32992
  selection.push({
32852
32993
  field: targetTable,
32853
32994
  key: k,
32854
32995
  selection: innerQuery.selection,
32855
- isArray: !isSingle2
32996
+ isArray: !isSingle2,
32997
+ isOptional: (relation.optional ?? false) || join !== true && !!join.where
32856
32998
  });
32857
32999
  const jsonColumns = sql.join(
32858
33000
  innerQuery.selection.map((s) => {
@@ -32860,7 +33002,9 @@ var init_dialect2 = __esm({
32860
33002
  }),
32861
33003
  sql`, `
32862
33004
  );
32863
- return isNested ? isSingle2 ? sql`(select jsonb_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select jsonb_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}` : isSingle2 ? sql`(select json_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select json_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}`;
33005
+ const json4 = isNested ? sql`jsonb` : sql`json`;
33006
+ const joinQuery = isSingle2 ? sql`(select ${json4}_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select ${json4}_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}`;
33007
+ return joinQuery;
32864
33008
  }),
32865
33009
  sql`, `
32866
33010
  );
@@ -32872,7 +33016,7 @@ var init_dialect2 = __esm({
32872
33016
  });
32873
33017
  }
32874
33018
  const selectionSet = sql.join(selectionArr, sql`, `);
32875
- const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
33019
+ const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${throughJoin}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
32876
33020
  return {
32877
33021
  sql: query,
32878
33022
  selection
@@ -37744,6 +37888,12 @@ var init_dialect3 = __esm({
37744
37888
  columnIdentifiers.push(
37745
37889
  sql`${table5[column5.tsName]} as ${sql.identifier(column5.tsName)}`
37746
37890
  );
37891
+ selection.push(
37892
+ {
37893
+ key: column5.tsName,
37894
+ field: column5.column
37895
+ }
37896
+ );
37747
37897
  }
37748
37898
  return columnIdentifiers.length ? sql.join(columnIdentifiers, sql`, `) : void 0;
37749
37899
  })() : this.unwrapAllColumns(table5, selection));
@@ -38565,7 +38715,9 @@ var init_dialect3 = __esm({
38565
38715
  relationWhere,
38566
38716
  mode,
38567
38717
  errorPath,
38568
- depth
38718
+ depth,
38719
+ isNested,
38720
+ throughJoin
38569
38721
  }) {
38570
38722
  const selection = [];
38571
38723
  const isSingle = mode === "first";
@@ -38599,12 +38751,19 @@ var init_dialect3 = __esm({
38599
38751
  key: k,
38600
38752
  field: relation2
38601
38753
  });
38602
- return sql`, lateral(${query2}) as ${sql.identifier(k)}`;
38754
+ return sql` left join lateral (${query2}) as ${sql.identifier(k)} on true`;
38603
38755
  }
38604
38756
  const relation = tableConfig.relations[k];
38605
38757
  const isSingle2 = is(relation, One);
38606
38758
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
38607
- const relationFilter = relationToSQL(relation, table5, targetTable);
38759
+ const throughTable = relation.throughTable ? aliasedTable(relation.throughTable, `tr${currentDepth}`) : void 0;
38760
+ const { filter: filter2, joinCondition } = relationToSQL(
38761
+ relation,
38762
+ table5,
38763
+ targetTable,
38764
+ throughTable
38765
+ );
38766
+ const throughJoin2 = throughTable ? sql` inner join ${sql`${sql.identifier(throughTable[Schema] ?? "")}.`.if(throughTable[Schema])}${sql.identifier(throughTable[OriginalName])} as ${throughTable} on ${joinCondition}` : void 0;
38608
38767
  const innerQuery = this.buildRelationalQuery({
38609
38768
  table: targetTable,
38610
38769
  mode: isSingle2 ? "first" : "many",
@@ -38613,21 +38772,25 @@ var init_dialect3 = __esm({
38613
38772
  tableConfig: schema5[tableNamesMap[getTableUniqueName(relation.targetTable)]],
38614
38773
  tableNamesMap,
38615
38774
  tables,
38616
- relationWhere: relationFilter,
38775
+ relationWhere: filter2,
38617
38776
  errorPath: `${currentPath.length ? `${currentPath}.` : ""}${k}`,
38618
- depth: currentDepth + 1
38777
+ depth: currentDepth + 1,
38778
+ isNested: true,
38779
+ throughJoin: throughJoin2
38619
38780
  });
38620
38781
  selection.push({
38621
38782
  field: targetTable,
38622
38783
  key: k,
38623
38784
  selection: innerQuery.selection,
38624
- isArray: !isSingle2
38785
+ isArray: !isSingle2,
38786
+ isOptional: (relation.optional ?? false) || join !== true && !!join.where
38625
38787
  });
38626
38788
  const jsonColumns = sql.join(
38627
38789
  innerQuery.selection.map((s) => sql`${sql.raw(this.escapeString(s.key))}, ${sql.identifier(s.key)}`),
38628
38790
  sql`, `
38629
38791
  );
38630
- return sql`, lateral(select ${isSingle2 ? sql`json_object(${jsonColumns}) as ${sql.identifier("r")}` : sql`coalesce(json_arrayagg(json_object(${jsonColumns})), json_array()) as ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}`;
38792
+ const joinQuery = sql` left join lateral(select ${sql`${isSingle2 ? sql`json_object(${jsonColumns})` : sql`coalesce(json_arrayagg(json_object(${jsonColumns})), json_array())`} as ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)} on true`;
38793
+ return joinQuery;
38631
38794
  })
38632
38795
  );
38633
38796
  })() : void 0;
@@ -38638,8 +38801,11 @@ var init_dialect3 = __esm({
38638
38801
  message: `No fields selected for table "${tableConfig.tsName}"${currentPath ? ` ("${currentPath}")` : ""}`
38639
38802
  });
38640
38803
  }
38804
+ if (isNested && order) {
38805
+ selectionArr.push(sql`row_number() over (order by ${order})`);
38806
+ }
38641
38807
  const selectionSet = sql.join(selectionArr, sql`, `);
38642
- const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${sql`${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
38808
+ const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${throughJoin}${sql`${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
38643
38809
  return {
38644
38810
  sql: query,
38645
38811
  selection
package/api.mjs CHANGED
@@ -24842,24 +24842,33 @@ var init_primary_keys = __esm({
24842
24842
  function getOrderByOperators() {
24843
24843
  return orderByOperators;
24844
24844
  }
24845
- function mapRelationalRow(row, buildQueryResultSelection, mapColumnValue = (value) => value, parseJson = false) {
24845
+ function mapRelationalRow(row, buildQueryResultSelection, mapColumnValue = (value) => value, parseJson = false, path2) {
24846
24846
  for (const selectionItem of buildQueryResultSelection) {
24847
24847
  const field = selectionItem.field;
24848
24848
  if (is(field, Table2)) {
24849
+ const currentPath = `${path2 ? `${path2}.` : ""}${selectionItem.key}`;
24849
24850
  if (row[selectionItem.key] === null)
24850
24851
  continue;
24851
24852
  if (parseJson)
24852
24853
  row[selectionItem.key] = JSON.parse(row[selectionItem.key]);
24853
24854
  if (selectionItem.isArray) {
24854
24855
  for (const item of row[selectionItem.key]) {
24855
- mapRelationalRow(item, selectionItem.selection, mapColumnValue);
24856
+ mapRelationalRow(
24857
+ item,
24858
+ selectionItem.selection,
24859
+ mapColumnValue,
24860
+ false,
24861
+ currentPath
24862
+ );
24856
24863
  }
24857
24864
  continue;
24858
24865
  }
24859
24866
  mapRelationalRow(
24860
24867
  row[selectionItem.key],
24861
24868
  selectionItem.selection,
24862
- mapColumnValue
24869
+ mapColumnValue,
24870
+ false,
24871
+ currentPath
24863
24872
  );
24864
24873
  continue;
24865
24874
  }
@@ -24910,7 +24919,7 @@ function defineRelations(schema5, relations) {
24910
24919
  );
24911
24920
  }
24912
24921
  function relationsFieldFilterToSQL(column5, filter2) {
24913
- if (typeof filter2 !== "object" || is(filter2, Placeholder))
24922
+ if (typeof filter2 !== "object")
24914
24923
  return eq(column5, filter2);
24915
24924
  const entries = Object.entries(filter2);
24916
24925
  if (!entries.length)
@@ -24937,6 +24946,21 @@ function relationsFieldFilterToSQL(column5, filter2) {
24937
24946
  );
24938
24947
  continue;
24939
24948
  }
24949
+ case "isNotNull":
24950
+ case "isNull": {
24951
+ if (!value)
24952
+ continue;
24953
+ parts.push(operators[target](column5));
24954
+ continue;
24955
+ }
24956
+ case "in": {
24957
+ parts.push(operators.inArray(column5, value));
24958
+ continue;
24959
+ }
24960
+ case "notIn": {
24961
+ parts.push(operators.notInArray(column5, value));
24962
+ continue;
24963
+ }
24940
24964
  default: {
24941
24965
  parts.push(
24942
24966
  operators[target](
@@ -25034,18 +25058,49 @@ function relationExtrasToSQL(table5, extras) {
25034
25058
  selection
25035
25059
  };
25036
25060
  }
25037
- function relationToSQL(relation, sourceTable, targetTable) {
25061
+ function getTableSql(table5) {
25062
+ return sql`${sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(!table5[IsAlias] && table5[Schema])}`}${table5}`;
25063
+ }
25064
+ function relationToSQL(relation, sourceTable, targetTable, throughTable) {
25065
+ if (relation.through) {
25066
+ const outerColumnWhere = relation.sourceColumns.map((s, i) => {
25067
+ const t = relation.through.source[i];
25068
+ return eq(
25069
+ sql`${getTableSql(sourceTable)}.${sql.identifier(s.name)}`,
25070
+ sql`${getTableSql(throughTable)}.${sql.identifier(t.name)}`
25071
+ );
25072
+ });
25073
+ const innerColumnWhere = relation.targetColumns.map((s, i) => {
25074
+ const t = relation.through.target[i];
25075
+ return eq(
25076
+ sql`${getTableSql(throughTable)}.${sql.identifier(t.name)}`,
25077
+ sql`${getTableSql(targetTable)}.${sql.identifier(s.name)}`
25078
+ );
25079
+ });
25080
+ return {
25081
+ filter: and(
25082
+ relation.where ? relation.isReversed ? relationsFilterToSQL(targetTable, relation.where) : relationsFilterToSQL(sourceTable, relation.where) : void 0
25083
+ ),
25084
+ joinCondition: and(
25085
+ ...outerColumnWhere,
25086
+ ...innerColumnWhere
25087
+ )
25088
+ };
25089
+ }
25038
25090
  const columnWhere = relation.sourceColumns.map((s, i) => {
25039
25091
  const t = relation.targetColumns[i];
25040
25092
  return eq(
25041
- sql`${sql`${sql`${sql.identifier(sourceTable[Schema] ?? "")}.`.if(sourceTable[Schema] && !sourceTable[IsAlias])}`}${sourceTable}.${sql.identifier(s.name)}`,
25042
- sql`${sql`${sql`${sql.identifier(targetTable[Schema] ?? "")}.`.if(targetTable[Schema] && !targetTable[IsAlias])}`}${targetTable}.${sql.identifier(t.name)}`
25093
+ sql`${getTableSql(sourceTable)}.${sql.identifier(s.name)}`,
25094
+ sql`${getTableSql(targetTable)}.${sql.identifier(t.name)}`
25043
25095
  );
25044
25096
  });
25045
- const targetWhere = relation.where ? and(...columnWhere, relationsFilterToSQL(sourceTable, relation.where)) : and(...columnWhere);
25046
- return targetWhere;
25097
+ const fullWhere = and(
25098
+ ...columnWhere,
25099
+ relation.where ? relation.isReversed ? relationsFilterToSQL(targetTable, relation.where) : relationsFilterToSQL(sourceTable, relation.where) : void 0
25100
+ );
25101
+ return { filter: fullWhere };
25047
25102
  }
25048
- var _a118, Relations, _a119, Relation, _a120, _b95, One, _a121, _b96, Many, _a122, AggregatedField, _a123, _b97, Count, operators, orderByOperators, _a124, RelationsBuilderTable, _a125, RelationsBuilderColumn, _a126, RelationsHelperStatic;
25103
+ var _a118, Relations, _a119, Relation, _a120, _b95, One, _a121, _b96, Many, _a122, AggregatedField, _a123, _b97, Count, operators, orderByOperators, _a124, RelationsBuilderTable, _a125, _RelationsBuilderColumn, RelationsBuilderColumn, _a126, RelationsHelperStatic;
25049
25104
  var init_relations = __esm({
25050
25105
  "../drizzle-orm/dist/relations.js"() {
25051
25106
  "use strict";
@@ -25120,9 +25175,30 @@ var init_relations = __esm({
25120
25175
  if (relation.sourceColumns && relation.targetColumns) {
25121
25176
  if (relation.sourceColumns.length !== relation.targetColumns.length) {
25122
25177
  throw new Error(
25123
- `${relationPrintName}: "from" and "to" arrays must have the same length`
25178
+ `${relationPrintName}: "from" and "to" fields must have the same length`
25124
25179
  );
25125
25180
  }
25181
+ if (relation.through) {
25182
+ if (relation.through.source.length !== relation.through.target.length || relation.through.source.length !== relation.sourceColumns.length || relation.through.target.length !== relation.targetColumns.length) {
25183
+ throw new Error(
25184
+ `${relationPrintName}: ".through(column)" must be used either on all columns in "from" and "to" or not defined on any of them`
25185
+ );
25186
+ }
25187
+ for (const column5 of relation.through.source) {
25188
+ if (column5.table !== relation.throughTable) {
25189
+ throw new Error(
25190
+ `${relationPrintName}: ".through(column)" must be used on the same table by all columns of the relation`
25191
+ );
25192
+ }
25193
+ }
25194
+ for (const column5 of relation.through.target) {
25195
+ if (column5.table !== relation.throughTable) {
25196
+ throw new Error(
25197
+ `${relationPrintName}: ".through(column)" must be used on the same table by all columns of the relation`
25198
+ );
25199
+ }
25200
+ }
25201
+ }
25126
25202
  continue;
25127
25203
  }
25128
25204
  if (relation.sourceColumns || relation.targetColumns) {
@@ -25182,7 +25258,13 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25182
25258
  }
25183
25259
  relation.sourceColumns = reverseRelation.targetColumns;
25184
25260
  relation.targetColumns = reverseRelation.sourceColumns;
25185
- relation.where = reverseRelation.where;
25261
+ relation.through = reverseRelation.through ? {
25262
+ source: reverseRelation.through.target,
25263
+ target: reverseRelation.through.source
25264
+ } : void 0;
25265
+ relation.throughTable = reverseRelation.throughTable;
25266
+ relation.isReversed = !relation.where;
25267
+ relation.where = relation.where ?? reverseRelation.where;
25186
25268
  }
25187
25269
  }
25188
25270
  }
@@ -25197,6 +25279,9 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25197
25279
  __publicField(this, "alias");
25198
25280
  __publicField(this, "where");
25199
25281
  __publicField(this, "sourceTable");
25282
+ __publicField(this, "through");
25283
+ __publicField(this, "throughTable");
25284
+ __publicField(this, "isReversed");
25200
25285
  this.targetTable = targetTable;
25201
25286
  }
25202
25287
  };
@@ -25208,12 +25293,30 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25208
25293
  this.alias = config?.alias;
25209
25294
  this.where = config?.where;
25210
25295
  if (config?.from) {
25211
- this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) => it._.column) : [config.from._.column];
25296
+ this.sourceColumns = (Array.isArray(config.from) ? config.from : [config.from]).map((it) => {
25297
+ this.throughTable ??= it._.through?._.column.table;
25298
+ return it._.column;
25299
+ });
25212
25300
  }
25213
25301
  if (config?.to) {
25214
- this.targetColumns = Array.isArray(config.to) ? config.to.map((it) => it._.column) : [config.to._.column];
25302
+ this.targetColumns = (Array.isArray(config.to) ? config.to : [config.to]).map((it) => {
25303
+ this.throughTable ??= it._.through?._.column.table;
25304
+ return it._.column;
25305
+ });
25215
25306
  }
25216
- this.optional = config?.optional ?? false;
25307
+ if (this.throughTable) {
25308
+ this.through = Array.isArray(config?.from) ? {
25309
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25310
+ source: config.from.map((e) => e._.through?._.column),
25311
+ target: (config.to ?? []).map((e) => e._.column)
25312
+ } : {
25313
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25314
+ source: [config?.from?._.through?._.column],
25315
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
25316
+ target: [config?.to?._.through?._.column]
25317
+ };
25318
+ }
25319
+ this.optional = config?.optional ?? true;
25217
25320
  }
25218
25321
  };
25219
25322
  __publicField(One, _a120, "OneV2");
@@ -25224,10 +25327,28 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25224
25327
  this.alias = config?.alias;
25225
25328
  this.where = config?.where;
25226
25329
  if (config?.from) {
25227
- this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) => it._.column) : [config.from._.column];
25330
+ this.sourceColumns = (Array.isArray(config.from) ? config.from : [config.from]).map((it) => {
25331
+ this.throughTable ??= it._.through?._.column.table;
25332
+ return it._.column;
25333
+ });
25228
25334
  }
25229
25335
  if (config?.to) {
25230
- this.targetColumns = Array.isArray(config.to) ? config.to.map((it) => it._.column) : [config.to._.column];
25336
+ this.targetColumns = (Array.isArray(config.to) ? config.to : [config.to]).map((it) => {
25337
+ this.throughTable ??= it._.through?._.column.table;
25338
+ return it._.column;
25339
+ });
25340
+ }
25341
+ if (this.throughTable) {
25342
+ this.through = Array.isArray(config?.from) ? {
25343
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25344
+ source: config.from.map((e) => e._.through?._.column),
25345
+ target: (config.to ?? []).map((e) => e._.column)
25346
+ } : {
25347
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
25348
+ source: [config?.from?._.through?._.column],
25349
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
25350
+ target: [config?.to?._.through?._.column]
25351
+ };
25231
25352
  }
25232
25353
  }
25233
25354
  };
@@ -25252,7 +25373,8 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25252
25373
  if (!this.query) {
25253
25374
  if (!this.table)
25254
25375
  throw new Error("Table must be set before building aggregate field");
25255
- this.query = sql`select count(*) as ${sql.identifier("r")} from ${this.table}`.mapWith(Number);
25376
+ const table5 = this.table;
25377
+ this.query = sql`select count(*) as ${sql.identifier("r")} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}`.mapWith(Number);
25256
25378
  }
25257
25379
  return this.query;
25258
25380
  }
@@ -25302,24 +25424,25 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
25302
25424
  };
25303
25425
  __publicField(RelationsBuilderTable, _a124, "RelationsBuilderTable");
25304
25426
  _a125 = entityKind;
25305
- RelationsBuilderColumn = class {
25306
- constructor(column5) {
25427
+ _RelationsBuilderColumn = class _RelationsBuilderColumn {
25428
+ constructor(column5, through) {
25307
25429
  __publicField(this, "_");
25308
25430
  this._ = {
25309
25431
  tableName: getTableName(column5.table),
25310
25432
  data: void 0,
25311
- column: column5
25433
+ column: column5,
25434
+ through
25312
25435
  };
25313
25436
  }
25314
25437
  through(column5) {
25315
- this._.through = column5;
25316
- return this;
25438
+ return new _RelationsBuilderColumn(this._.column, column5);
25317
25439
  }
25318
25440
  getSQL() {
25319
25441
  return this._.column.getSQL();
25320
25442
  }
25321
25443
  };
25322
- __publicField(RelationsBuilderColumn, _a125, "RelationsBuilderColumn");
25444
+ __publicField(_RelationsBuilderColumn, _a125, "RelationsBuilderColumn");
25445
+ RelationsBuilderColumn = _RelationsBuilderColumn;
25323
25446
  _a126 = entityKind;
25324
25447
  RelationsHelperStatic = class {
25325
25448
  constructor(tables) {
@@ -26076,7 +26199,7 @@ var init_dialect = __esm({
26076
26199
  sql`, `
26077
26200
  );
26078
26201
  });
26079
- __publicField(this, "buildColumns", (table5, tableConfig, selection, config) => config?.columns ? (() => {
26202
+ __publicField(this, "buildColumns", (table5, selection, config) => config?.columns ? (() => {
26080
26203
  const entries = Object.entries(config.columns);
26081
26204
  const columnIdentifiers = [];
26082
26205
  let colSelectionMode;
@@ -26723,7 +26846,8 @@ var init_dialect = __esm({
26723
26846
  relationWhere,
26724
26847
  mode,
26725
26848
  errorPath,
26726
- depth
26849
+ depth,
26850
+ throughJoin
26727
26851
  }) {
26728
26852
  const selection = [];
26729
26853
  const isSingle = mode === "first";
@@ -26734,7 +26858,7 @@ var init_dialect = __esm({
26734
26858
  const offset = params?.offset;
26735
26859
  const where = params?.where && relationWhere ? and(relationsFilterToSQL(table5, params.where), relationWhere) : params?.where ? relationsFilterToSQL(table5, params.where) : relationWhere;
26736
26860
  const order = params?.orderBy ? relationsOrderToSQL(table5, params.orderBy) : void 0;
26737
- const columns = this.buildColumns(table5, tableConfig, selection, params);
26861
+ const columns = this.buildColumns(table5, selection, params);
26738
26862
  const extras = params?.extras ? relationExtrasToSQL(table5, params.extras) : void 0;
26739
26863
  if (extras)
26740
26864
  selection.push(...extras.selection);
@@ -26762,10 +26886,15 @@ var init_dialect = __esm({
26762
26886
  const relation = tableConfig.relations[k];
26763
26887
  const isSingle2 = is(relation, One);
26764
26888
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
26765
- const relationFilter = relationToSQL(relation, table5, targetTable);
26766
- selectionArr.push(
26767
- isSingle2 ? sql`${sql.identifier(k)}.${sql.identifier("r")} as ${sql.identifier(k)}` : sql`coalesce(${sql.identifier(k)}.${sql.identifier("r")}, '[]') as ${sql.identifier(k)}`
26889
+ const throughTable = relation.throughTable ? aliasedTable(relation.throughTable, `tr${currentDepth}`) : void 0;
26890
+ const { filter: filter2, joinCondition } = relationToSQL(
26891
+ relation,
26892
+ table5,
26893
+ targetTable,
26894
+ throughTable
26768
26895
  );
26896
+ selectionArr.push(sql`${sql.identifier(k)}.${sql.identifier("r")} as ${sql.identifier(k)}`);
26897
+ const throughJoin2 = throughTable ? sql` inner join ${sql`${sql.identifier(throughTable[Schema] ?? "")}.`.if(throughTable[Schema])}${sql.identifier(throughTable[OriginalName])} as ${throughTable} on ${joinCondition}` : void 0;
26769
26898
  const innerQuery = this.buildRelationalQuery({
26770
26899
  table: targetTable,
26771
26900
  mode: isSingle2 ? "first" : "many",
@@ -26774,17 +26903,20 @@ var init_dialect = __esm({
26774
26903
  tableConfig: schema5[tableNamesMap[getTableUniqueName(relation.targetTable)]],
26775
26904
  tableNamesMap,
26776
26905
  tables,
26777
- relationWhere: relationFilter,
26906
+ relationWhere: filter2,
26778
26907
  errorPath: `${currentPath.length ? `${currentPath}.` : ""}${k}`,
26779
- depth: currentDepth + 1
26908
+ depth: currentDepth + 1,
26909
+ throughJoin: throughJoin2
26780
26910
  });
26781
26911
  selection.push({
26782
26912
  field: targetTable,
26783
26913
  key: k,
26784
26914
  selection: innerQuery.selection,
26785
- isArray: !isSingle2
26915
+ isArray: !isSingle2,
26916
+ isOptional: (relation.optional ?? false) || join !== true && !!join.where
26786
26917
  });
26787
- return sql`left join lateral(select ${isSingle2 ? sql`row_to_json(${sql.identifier("t")}.*) ${sql.identifier("r")}` : sql`json_agg(row_to_json(${sql.identifier("t")}.*)) ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)} on true`;
26918
+ const joinQuery = sql`left join lateral(select ${isSingle2 ? sql`row_to_json(${sql.identifier("t")}.*) ${sql.identifier("r")}` : sql`coalesce(json_agg(row_to_json(${sql.identifier("t")}.*)), '[]') as ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)} on true`;
26919
+ return joinQuery;
26788
26920
  }),
26789
26921
  sql` `
26790
26922
  );
@@ -26797,7 +26929,7 @@ var init_dialect = __esm({
26797
26929
  });
26798
26930
  }
26799
26931
  const selectionSet = sql.join(selectionArr.filter((e) => e !== void 0), sql`, `);
26800
- const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${sql` ${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
26932
+ const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${throughJoin}${sql` ${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
26801
26933
  return {
26802
26934
  sql: query,
26803
26935
  selection
@@ -32802,7 +32934,8 @@ var init_dialect2 = __esm({
32802
32934
  mode,
32803
32935
  isNested,
32804
32936
  errorPath,
32805
- depth
32937
+ depth,
32938
+ throughJoin
32806
32939
  }) {
32807
32940
  const selection = [];
32808
32941
  const isSingle = mode === "first";
@@ -32839,7 +32972,14 @@ var init_dialect2 = __esm({
32839
32972
  const relation = tableConfig.relations[k];
32840
32973
  const isSingle2 = is(relation, One);
32841
32974
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
32842
- const relationFilter = relationToSQL(relation, table5, targetTable);
32975
+ const throughTable = relation.throughTable ? aliasedTable(relation.throughTable, `tr${currentDepth}`) : void 0;
32976
+ const { filter: filter2, joinCondition } = relationToSQL(
32977
+ relation,
32978
+ table5,
32979
+ targetTable,
32980
+ throughTable
32981
+ );
32982
+ const throughJoin2 = throughTable ? sql` inner join ${sql`${sql.identifier(throughTable[Schema] ?? "")}.`.if(throughTable[Schema])}${sql.identifier(throughTable[OriginalName])} as ${throughTable} on ${joinCondition}` : void 0;
32843
32983
  const innerQuery = this.buildRelationalQuery({
32844
32984
  table: targetTable,
32845
32985
  mode: isSingle2 ? "first" : "many",
@@ -32848,16 +32988,18 @@ var init_dialect2 = __esm({
32848
32988
  tableConfig: schema5[tableNamesMap[getTableUniqueName(relation.targetTable)]],
32849
32989
  tableNamesMap,
32850
32990
  tables,
32851
- relationWhere: relationFilter,
32991
+ relationWhere: filter2,
32852
32992
  isNested: true,
32853
32993
  errorPath: `${currentPath.length ? `${currentPath}.` : ""}${k}`,
32854
- depth: currentDepth + 1
32994
+ depth: currentDepth + 1,
32995
+ throughJoin: throughJoin2
32855
32996
  });
32856
32997
  selection.push({
32857
32998
  field: targetTable,
32858
32999
  key: k,
32859
33000
  selection: innerQuery.selection,
32860
- isArray: !isSingle2
33001
+ isArray: !isSingle2,
33002
+ isOptional: (relation.optional ?? false) || join !== true && !!join.where
32861
33003
  });
32862
33004
  const jsonColumns = sql.join(
32863
33005
  innerQuery.selection.map((s) => {
@@ -32865,7 +33007,9 @@ var init_dialect2 = __esm({
32865
33007
  }),
32866
33008
  sql`, `
32867
33009
  );
32868
- return isNested ? isSingle2 ? sql`(select jsonb_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select jsonb_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}` : isSingle2 ? sql`(select json_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select json_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}`;
33010
+ const json4 = isNested ? sql`jsonb` : sql`json`;
33011
+ const joinQuery = isSingle2 ? sql`(select ${json4}_object(${jsonColumns}) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}` : sql`coalesce((select ${json4}_group_array(json_object(${jsonColumns})) as ${sql.identifier("r")} from (${innerQuery.sql}) as ${sql.identifier("t")}), jsonb_array()) as ${sql.identifier(k)}`;
33012
+ return joinQuery;
32869
33013
  }),
32870
33014
  sql`, `
32871
33015
  );
@@ -32877,7 +33021,7 @@ var init_dialect2 = __esm({
32877
33021
  });
32878
33022
  }
32879
33023
  const selectionSet = sql.join(selectionArr, sql`, `);
32880
- const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
33024
+ const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${throughJoin}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
32881
33025
  return {
32882
33026
  sql: query,
32883
33027
  selection
@@ -37749,6 +37893,12 @@ var init_dialect3 = __esm({
37749
37893
  columnIdentifiers.push(
37750
37894
  sql`${table5[column5.tsName]} as ${sql.identifier(column5.tsName)}`
37751
37895
  );
37896
+ selection.push(
37897
+ {
37898
+ key: column5.tsName,
37899
+ field: column5.column
37900
+ }
37901
+ );
37752
37902
  }
37753
37903
  return columnIdentifiers.length ? sql.join(columnIdentifiers, sql`, `) : void 0;
37754
37904
  })() : this.unwrapAllColumns(table5, selection));
@@ -38570,7 +38720,9 @@ var init_dialect3 = __esm({
38570
38720
  relationWhere,
38571
38721
  mode,
38572
38722
  errorPath,
38573
- depth
38723
+ depth,
38724
+ isNested,
38725
+ throughJoin
38574
38726
  }) {
38575
38727
  const selection = [];
38576
38728
  const isSingle = mode === "first";
@@ -38604,12 +38756,19 @@ var init_dialect3 = __esm({
38604
38756
  key: k,
38605
38757
  field: relation2
38606
38758
  });
38607
- return sql`, lateral(${query2}) as ${sql.identifier(k)}`;
38759
+ return sql` left join lateral (${query2}) as ${sql.identifier(k)} on true`;
38608
38760
  }
38609
38761
  const relation = tableConfig.relations[k];
38610
38762
  const isSingle2 = is(relation, One);
38611
38763
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
38612
- const relationFilter = relationToSQL(relation, table5, targetTable);
38764
+ const throughTable = relation.throughTable ? aliasedTable(relation.throughTable, `tr${currentDepth}`) : void 0;
38765
+ const { filter: filter2, joinCondition } = relationToSQL(
38766
+ relation,
38767
+ table5,
38768
+ targetTable,
38769
+ throughTable
38770
+ );
38771
+ const throughJoin2 = throughTable ? sql` inner join ${sql`${sql.identifier(throughTable[Schema] ?? "")}.`.if(throughTable[Schema])}${sql.identifier(throughTable[OriginalName])} as ${throughTable} on ${joinCondition}` : void 0;
38613
38772
  const innerQuery = this.buildRelationalQuery({
38614
38773
  table: targetTable,
38615
38774
  mode: isSingle2 ? "first" : "many",
@@ -38618,21 +38777,25 @@ var init_dialect3 = __esm({
38618
38777
  tableConfig: schema5[tableNamesMap[getTableUniqueName(relation.targetTable)]],
38619
38778
  tableNamesMap,
38620
38779
  tables,
38621
- relationWhere: relationFilter,
38780
+ relationWhere: filter2,
38622
38781
  errorPath: `${currentPath.length ? `${currentPath}.` : ""}${k}`,
38623
- depth: currentDepth + 1
38782
+ depth: currentDepth + 1,
38783
+ isNested: true,
38784
+ throughJoin: throughJoin2
38624
38785
  });
38625
38786
  selection.push({
38626
38787
  field: targetTable,
38627
38788
  key: k,
38628
38789
  selection: innerQuery.selection,
38629
- isArray: !isSingle2
38790
+ isArray: !isSingle2,
38791
+ isOptional: (relation.optional ?? false) || join !== true && !!join.where
38630
38792
  });
38631
38793
  const jsonColumns = sql.join(
38632
38794
  innerQuery.selection.map((s) => sql`${sql.raw(this.escapeString(s.key))}, ${sql.identifier(s.key)}`),
38633
38795
  sql`, `
38634
38796
  );
38635
- return sql`, lateral(select ${isSingle2 ? sql`json_object(${jsonColumns}) as ${sql.identifier("r")}` : sql`coalesce(json_arrayagg(json_object(${jsonColumns})), json_array()) as ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)}`;
38797
+ const joinQuery = sql` left join lateral(select ${sql`${isSingle2 ? sql`json_object(${jsonColumns})` : sql`coalesce(json_arrayagg(json_object(${jsonColumns})), json_array())`} as ${sql.identifier("r")}`} from (${innerQuery.sql}) as ${sql.identifier("t")}) as ${sql.identifier(k)} on true`;
38798
+ return joinQuery;
38636
38799
  })
38637
38800
  );
38638
38801
  })() : void 0;
@@ -38643,8 +38806,11 @@ var init_dialect3 = __esm({
38643
38806
  message: `No fields selected for table "${tableConfig.tsName}"${currentPath ? ` ("${currentPath}")` : ""}`
38644
38807
  });
38645
38808
  }
38809
+ if (isNested && order) {
38810
+ selectionArr.push(sql`row_number() over (order by ${order})`);
38811
+ }
38646
38812
  const selectionSet = sql.join(selectionArr, sql`, `);
38647
- const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${sql`${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
38813
+ const query = sql`select ${selectionSet} from ${table5[IsAlias] ? sql`${sql`${sql.identifier(table5[Schema] ?? "")}.`.if(table5[Schema])}${sql.identifier(table5[OriginalName])} as ${table5}` : table5}${throughJoin}${sql`${joins}`.if(joins)}${sql` where ${where}`.if(where)}${sql` order by ${order}`.if(order)}${sql` limit ${limit}`.if(limit !== void 0)}${sql` offset ${offset}`.if(offset !== void 0)}`;
38648
38814
  return {
38649
38815
  sql: query,
38650
38816
  selection
package/bin.cjs CHANGED
@@ -92611,7 +92611,7 @@ init_utils5();
92611
92611
  var version2 = async () => {
92612
92612
  const { npmVersion } = await ormCoreVersions();
92613
92613
  const ormVersion = npmVersion ? `drizzle-orm: v${npmVersion}` : "";
92614
- const envVersion = "0.30.1-e6823b4";
92614
+ const envVersion = "0.30.1-f2d266c";
92615
92615
  const kitVersion = envVersion ? `v${envVersion}` : "--";
92616
92616
  const versions = `drizzle-kit: ${kitVersion}
92617
92617
  ${ormVersion}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-kit",
3
- "version": "0.30.1-e6823b4",
3
+ "version": "0.30.1-f2d266c",
4
4
  "homepage": "https://orm.drizzle.team",
5
5
  "keywords": [
6
6
  "drizzle",