@bunyad/orm 0.2.0-beta.3 → 0.2.0-beta.4

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.
@@ -217,9 +217,10 @@ export declare class ModelQuery<T extends Model = Model, TResult extends "model"
217
217
  distinct(value?: boolean): this;
218
218
  orderBy(column: ColumnHint<T>, direction?: "asc" | "desc"): this;
219
219
  orderByDesc(column: ColumnHint<T>): this;
220
- orderByRaw(sql: string): this;
220
+ /** `orderByRaw($sql, $bindings)`. */
221
+ orderByRaw(sql: string, bindings?: unknown[]): this;
221
222
  /** Alias for `orderByRaw`. */
222
- orderBySql(sql: string): this;
223
+ orderBySql(sql: string, bindings?: unknown[]): this;
223
224
  reorder(column?: string, direction?: "asc" | "desc"): this;
224
225
  inRandomOrder(): this;
225
226
  latest(column?: string): this;
@@ -39,6 +39,120 @@ function mqMut(arr) {
39
39
  function mqMutObj(obj) {
40
40
  return obj === MQ_EMPTY_OBJ ? {} : obj;
41
41
  }
42
+ /** Creation order of where conditions, shared across every kind (plain, IN, null, …). */
43
+ let mqWhereSeq = 0;
44
+ function nextWhereSeq() {
45
+ return ++mqWhereSeq;
46
+ }
47
+ /**
48
+ * Apply every kind of where condition onto a QueryBuilder in the order the caller
49
+ * wrote them, so `whereIn(...).orWhereNull(...)` stays `IN … OR NULL`. Conditions
50
+ * without a sequence number keep the old per-kind order.
51
+ */
52
+ function applyWhereLists(q, lists) {
53
+ const steps = [];
54
+ for (const w of lists.wheres ?? []) {
55
+ steps.push({
56
+ seq: w.seq ?? 0,
57
+ run: (q) => {
58
+ if (w.op === "__null__") {
59
+ return w.boolean === "or" ? q.orWhereNull(w.column) : q.whereNull(w.column);
60
+ }
61
+ if (w.op === "__notnull__") {
62
+ return w.boolean === "or"
63
+ ? q.orWhereNotNull(w.column)
64
+ : q.whereNotNull(w.column);
65
+ }
66
+ return w.boolean === "or"
67
+ ? q.orWhere(w.column, w.op, w.value)
68
+ : q.where(w.column, w.op, w.value);
69
+ },
70
+ });
71
+ }
72
+ for (const w of lists.whereIns ?? []) {
73
+ steps.push({
74
+ seq: w.seq ?? 0,
75
+ run: (q) => w.boolean === "or"
76
+ ? w.not
77
+ ? q.orWhereNotIn(w.column, w.values)
78
+ : q.orWhereIn(w.column, w.values)
79
+ : w.not
80
+ ? q.whereNotIn(w.column, w.values)
81
+ : q.whereIn(w.column, w.values),
82
+ });
83
+ }
84
+ for (const w of lists.whereNulls ?? []) {
85
+ steps.push({
86
+ seq: w.seq ?? 0,
87
+ run: (q) => w.boolean === "or"
88
+ ? w.not
89
+ ? q.orWhereNotNull(w.column)
90
+ : q.orWhereNull(w.column)
91
+ : w.not
92
+ ? q.whereNotNull(w.column)
93
+ : q.whereNull(w.column),
94
+ });
95
+ }
96
+ for (const w of lists.whereBetweens ?? []) {
97
+ steps.push({
98
+ seq: w.seq ?? 0,
99
+ run: (q) => w.boolean === "or"
100
+ ? w.not
101
+ ? q.orWhereNotBetween(w.column, w.values)
102
+ : q.orWhereBetween(w.column, w.values)
103
+ : w.not
104
+ ? q.whereNotBetween(w.column, w.values)
105
+ : q.whereBetween(w.column, w.values),
106
+ });
107
+ }
108
+ for (const w of lists.whereColumns ?? []) {
109
+ steps.push({
110
+ seq: w.seq ?? 0,
111
+ run: (q) => w.boolean === "or"
112
+ ? q.orWhereColumn(w.first, w.op, w.second)
113
+ : q.whereColumn(w.first, w.op, w.second),
114
+ });
115
+ }
116
+ for (const w of lists.whereRaws ?? []) {
117
+ steps.push({
118
+ seq: w.seq ?? 0,
119
+ run: (q) => w.boolean === "or"
120
+ ? q.orWhereRaw(w.sql, w.bindings)
121
+ : q.whereRaw(w.sql, w.bindings),
122
+ });
123
+ }
124
+ for (const w of lists.whereLikes ?? []) {
125
+ steps.push({
126
+ seq: w.seq ?? 0,
127
+ run: (q) => w.boolean === "or"
128
+ ? w.not
129
+ ? q.orWhereNotLike(w.column, w.value, w.caseSensitive)
130
+ : q.orWhereLike(w.column, w.value, w.caseSensitive)
131
+ : w.not
132
+ ? q.whereNotLike(w.column, w.value, w.caseSensitive)
133
+ : q.whereLike(w.column, w.value, w.caseSensitive),
134
+ });
135
+ }
136
+ for (const w of lists.dateWheres ?? []) {
137
+ steps.push({
138
+ seq: w.seq ?? 0,
139
+ run: (q) => {
140
+ if (w.kind === "date")
141
+ return q.whereDate(w.column, w.op, w.value);
142
+ if (w.kind === "year")
143
+ return q.whereYear(w.column, w.op, Number(w.value));
144
+ if (w.kind === "month")
145
+ return q.whereMonth(w.column, w.op, Number(w.value));
146
+ return q.whereDay(w.column, w.op, Number(w.value));
147
+ },
148
+ });
149
+ }
150
+ // Array.prototype.sort is stable: equal (or missing) sequence numbers keep list order.
151
+ steps.sort((a, b) => a.seq - b.seq);
152
+ for (const step of steps)
153
+ q = step.run(q);
154
+ return q;
155
+ }
42
156
  /** Compiled simple-SELECT SQL keyed by constraint fingerprint (per model). */
43
157
  const simpleSelectSqlCache = new WeakMap();
44
158
  /** Compiled parent+EXISTS SELECT SQL (whereHas fast path). */
@@ -753,7 +867,7 @@ export class ModelQuery {
753
867
  return this;
754
868
  }
755
869
  if (value === undefined) {
756
- (this.#wheres = mqMut(this.#wheres)).push({
870
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
757
871
  column: columnOrCallback,
758
872
  op: "=",
759
873
  value: opOrValue,
@@ -775,7 +889,7 @@ export class ModelQuery {
775
889
  op !== "NOT LIKE") {
776
890
  this.#simple = false;
777
891
  }
778
- (this.#wheres = mqMut(this.#wheres)).push({
892
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
779
893
  column: columnOrCallback,
780
894
  op,
781
895
  value,
@@ -795,7 +909,7 @@ export class ModelQuery {
795
909
  return this;
796
910
  }
797
911
  if (value === undefined) {
798
- (this.#wheres = mqMut(this.#wheres)).push({
912
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
799
913
  column: columnOrCallback,
800
914
  op: "=",
801
915
  value: opOrValue,
@@ -817,7 +931,7 @@ export class ModelQuery {
817
931
  op !== "NOT LIKE") {
818
932
  this.#simple = false;
819
933
  }
820
- (this.#wheres = mqMut(this.#wheres)).push({
934
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
821
935
  column: columnOrCallback,
822
936
  op,
823
937
  value,
@@ -828,26 +942,26 @@ export class ModelQuery {
828
942
  }
829
943
  whereIn(column, values) {
830
944
  this.#simple = false;
831
- (this.#whereIns = mqMut(this.#whereIns)).push({ column, values, not: false, boolean: "and" });
945
+ (this.#whereIns = mqMut(this.#whereIns)).push({ seq: nextWhereSeq(), column, values, not: false, boolean: "and" });
832
946
  return this;
833
947
  }
834
948
  orWhereIn(column, values) {
835
949
  this.#simple = false;
836
- (this.#whereIns = mqMut(this.#whereIns)).push({ column, values, not: false, boolean: "or" });
950
+ (this.#whereIns = mqMut(this.#whereIns)).push({ seq: nextWhereSeq(), column, values, not: false, boolean: "or" });
837
951
  return this;
838
952
  }
839
953
  whereNotIn(column, values) {
840
954
  this.#simple = false;
841
- (this.#whereIns = mqMut(this.#whereIns)).push({ column, values, not: true, boolean: "and" });
955
+ (this.#whereIns = mqMut(this.#whereIns)).push({ seq: nextWhereSeq(), column, values, not: true, boolean: "and" });
842
956
  return this;
843
957
  }
844
958
  orWhereNotIn(column, values) {
845
959
  this.#simple = false;
846
- (this.#whereIns = mqMut(this.#whereIns)).push({ column, values, not: true, boolean: "or" });
960
+ (this.#whereIns = mqMut(this.#whereIns)).push({ seq: nextWhereSeq(), column, values, not: true, boolean: "or" });
847
961
  return this;
848
962
  }
849
963
  whereNull(column) {
850
- (this.#wheres = mqMut(this.#wheres)).push({
964
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
851
965
  column,
852
966
  op: "__null__",
853
967
  value: null,
@@ -856,7 +970,7 @@ export class ModelQuery {
856
970
  return this;
857
971
  }
858
972
  orWhereNull(column) {
859
- (this.#wheres = mqMut(this.#wheres)).push({
973
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
860
974
  column,
861
975
  op: "__null__",
862
976
  value: null,
@@ -865,7 +979,7 @@ export class ModelQuery {
865
979
  return this;
866
980
  }
867
981
  whereNotNull(column) {
868
- (this.#wheres = mqMut(this.#wheres)).push({
982
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
869
983
  column,
870
984
  op: "__notnull__",
871
985
  value: null,
@@ -874,7 +988,7 @@ export class ModelQuery {
874
988
  return this;
875
989
  }
876
990
  orWhereNotNull(column) {
877
- (this.#wheres = mqMut(this.#wheres)).push({
991
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
878
992
  column,
879
993
  op: "__notnull__",
880
994
  value: null,
@@ -884,7 +998,7 @@ export class ModelQuery {
884
998
  }
885
999
  whereBetween(column, values) {
886
1000
  this.#simple = false;
887
- (this.#whereBetweens = mqMut(this.#whereBetweens)).push({
1001
+ (this.#whereBetweens = mqMut(this.#whereBetweens)).push({ seq: nextWhereSeq(),
888
1002
  column,
889
1003
  values,
890
1004
  not: false,
@@ -894,7 +1008,7 @@ export class ModelQuery {
894
1008
  }
895
1009
  orWhereBetween(column, values) {
896
1010
  this.#simple = false;
897
- (this.#whereBetweens = mqMut(this.#whereBetweens)).push({
1011
+ (this.#whereBetweens = mqMut(this.#whereBetweens)).push({ seq: nextWhereSeq(),
898
1012
  column,
899
1013
  values,
900
1014
  not: false,
@@ -904,7 +1018,7 @@ export class ModelQuery {
904
1018
  }
905
1019
  whereNotBetween(column, values) {
906
1020
  this.#simple = false;
907
- (this.#whereBetweens = mqMut(this.#whereBetweens)).push({
1021
+ (this.#whereBetweens = mqMut(this.#whereBetweens)).push({ seq: nextWhereSeq(),
908
1022
  column,
909
1023
  values,
910
1024
  not: true,
@@ -914,7 +1028,7 @@ export class ModelQuery {
914
1028
  }
915
1029
  orWhereNotBetween(column, values) {
916
1030
  this.#simple = false;
917
- (this.#whereBetweens = mqMut(this.#whereBetweens)).push({
1031
+ (this.#whereBetweens = mqMut(this.#whereBetweens)).push({ seq: nextWhereSeq(),
918
1032
  column,
919
1033
  values,
920
1034
  not: true,
@@ -925,7 +1039,7 @@ export class ModelQuery {
925
1039
  whereColumn(first, opOrSecond, second) {
926
1040
  if (second === undefined) {
927
1041
  this.#simple = false;
928
- (this.#whereColumns = mqMut(this.#whereColumns)).push({
1042
+ (this.#whereColumns = mqMut(this.#whereColumns)).push({ seq: nextWhereSeq(),
929
1043
  first,
930
1044
  op: "=",
931
1045
  second: opOrSecond,
@@ -934,7 +1048,7 @@ export class ModelQuery {
934
1048
  }
935
1049
  else {
936
1050
  this.#simple = false;
937
- (this.#whereColumns = mqMut(this.#whereColumns)).push({
1051
+ (this.#whereColumns = mqMut(this.#whereColumns)).push({ seq: nextWhereSeq(),
938
1052
  first,
939
1053
  op: opOrSecond,
940
1054
  second,
@@ -946,7 +1060,7 @@ export class ModelQuery {
946
1060
  orWhereColumn(first, opOrSecond, second) {
947
1061
  if (second === undefined) {
948
1062
  this.#simple = false;
949
- (this.#whereColumns = mqMut(this.#whereColumns)).push({
1063
+ (this.#whereColumns = mqMut(this.#whereColumns)).push({ seq: nextWhereSeq(),
950
1064
  first,
951
1065
  op: "=",
952
1066
  second: opOrSecond,
@@ -955,7 +1069,7 @@ export class ModelQuery {
955
1069
  }
956
1070
  else {
957
1071
  this.#simple = false;
958
- (this.#whereColumns = mqMut(this.#whereColumns)).push({
1072
+ (this.#whereColumns = mqMut(this.#whereColumns)).push({ seq: nextWhereSeq(),
959
1073
  first,
960
1074
  op: opOrSecond,
961
1075
  second,
@@ -966,17 +1080,17 @@ export class ModelQuery {
966
1080
  }
967
1081
  whereRaw(sql, bindings = []) {
968
1082
  this.#simple = false;
969
- (this.#whereRaws = mqMut(this.#whereRaws)).push({ sql, bindings, boolean: "and" });
1083
+ (this.#whereRaws = mqMut(this.#whereRaws)).push({ seq: nextWhereSeq(), sql, bindings, boolean: "and" });
970
1084
  return this;
971
1085
  }
972
1086
  orWhereRaw(sql, bindings = []) {
973
1087
  this.#simple = false;
974
- (this.#whereRaws = mqMut(this.#whereRaws)).push({ sql, bindings, boolean: "or" });
1088
+ (this.#whereRaws = mqMut(this.#whereRaws)).push({ seq: nextWhereSeq(), sql, bindings, boolean: "or" });
975
1089
  return this;
976
1090
  }
977
1091
  whereLike(column, value, caseSensitive = false) {
978
1092
  this.#simple = false;
979
- (this.#whereLikes = mqMut(this.#whereLikes)).push({
1093
+ (this.#whereLikes = mqMut(this.#whereLikes)).push({ seq: nextWhereSeq(),
980
1094
  column,
981
1095
  value,
982
1096
  not: false,
@@ -987,7 +1101,7 @@ export class ModelQuery {
987
1101
  }
988
1102
  orWhereLike(column, value, caseSensitive = false) {
989
1103
  this.#simple = false;
990
- (this.#whereLikes = mqMut(this.#whereLikes)).push({
1104
+ (this.#whereLikes = mqMut(this.#whereLikes)).push({ seq: nextWhereSeq(),
991
1105
  column,
992
1106
  value,
993
1107
  not: false,
@@ -998,7 +1112,7 @@ export class ModelQuery {
998
1112
  }
999
1113
  whereNotLike(column, value, caseSensitive = false) {
1000
1114
  this.#simple = false;
1001
- (this.#whereLikes = mqMut(this.#whereLikes)).push({
1115
+ (this.#whereLikes = mqMut(this.#whereLikes)).push({ seq: nextWhereSeq(),
1002
1116
  column,
1003
1117
  value,
1004
1118
  not: true,
@@ -1009,7 +1123,7 @@ export class ModelQuery {
1009
1123
  }
1010
1124
  orWhereNotLike(column, value, caseSensitive = false) {
1011
1125
  this.#simple = false;
1012
- (this.#whereLikes = mqMut(this.#whereLikes)).push({
1126
+ (this.#whereLikes = mqMut(this.#whereLikes)).push({ seq: nextWhereSeq(),
1013
1127
  column,
1014
1128
  value,
1015
1129
  not: true,
@@ -1022,12 +1136,12 @@ export class ModelQuery {
1022
1136
  const op = value === undefined ? "=" : String(opOrValue);
1023
1137
  const raw = (value === undefined ? opOrValue : value);
1024
1138
  this.#simple = false;
1025
- (this.#dateWheres = mqMut(this.#dateWheres)).push({ column, op, value: raw, kind: "date" });
1139
+ (this.#dateWheres = mqMut(this.#dateWheres)).push({ seq: nextWhereSeq(), column, op, value: raw, kind: "date" });
1026
1140
  return this;
1027
1141
  }
1028
1142
  whereYear(column, value) {
1029
1143
  this.#simple = false;
1030
- (this.#dateWheres = mqMut(this.#dateWheres)).push({
1144
+ (this.#dateWheres = mqMut(this.#dateWheres)).push({ seq: nextWhereSeq(),
1031
1145
  column,
1032
1146
  op: "=",
1033
1147
  value: String(value),
@@ -1037,7 +1151,7 @@ export class ModelQuery {
1037
1151
  }
1038
1152
  whereMonth(column, value) {
1039
1153
  this.#simple = false;
1040
- (this.#dateWheres = mqMut(this.#dateWheres)).push({
1154
+ (this.#dateWheres = mqMut(this.#dateWheres)).push({ seq: nextWhereSeq(),
1041
1155
  column,
1042
1156
  op: "=",
1043
1157
  value: String(value),
@@ -1047,7 +1161,7 @@ export class ModelQuery {
1047
1161
  }
1048
1162
  whereDay(column, value) {
1049
1163
  this.#simple = false;
1050
- (this.#dateWheres = mqMut(this.#dateWheres)).push({
1164
+ (this.#dateWheres = mqMut(this.#dateWheres)).push({ seq: nextWhereSeq(),
1051
1165
  column,
1052
1166
  op: "=",
1053
1167
  value: String(value),
@@ -1083,14 +1197,15 @@ export class ModelQuery {
1083
1197
  orderByDesc(column) {
1084
1198
  return this.orderBy(column, "desc");
1085
1199
  }
1086
- orderByRaw(sql) {
1200
+ /** `orderByRaw($sql, $bindings)`. */
1201
+ orderByRaw(sql, bindings = []) {
1087
1202
  this.#simple = false;
1088
- (this.#orders = mqMut(this.#orders)).push({ raw: sql });
1203
+ (this.#orders = mqMut(this.#orders)).push(bindings.length > 0 ? { raw: sql, bindings } : { raw: sql });
1089
1204
  return this;
1090
1205
  }
1091
1206
  /** Alias for `orderByRaw`. */
1092
- orderBySql(sql) {
1093
- return this.orderByRaw(sql);
1207
+ orderBySql(sql, bindings = []) {
1208
+ return this.orderByRaw(sql, bindings);
1094
1209
  }
1095
1210
  reorder(column, direction = "asc") {
1096
1211
  this.#orders = [];
@@ -1541,6 +1656,13 @@ export class ModelQuery {
1541
1656
  #canHasExistsSelect() {
1542
1657
  if (this.#hasConstraints.length === 0)
1543
1658
  return false;
1659
+ // This path compiles its own statement and has no place for values bound in an ORDER BY.
1660
+ for (const o of this.#orders) {
1661
+ if ("raw" in o && o.raw === "__inRandomOrder__")
1662
+ continue;
1663
+ if ("bindings" in o && o.bindings !== undefined && o.bindings.length > 0)
1664
+ return false;
1665
+ }
1544
1666
  for (const c of this.#hasConstraints) {
1545
1667
  if (c.existsSql === undefined)
1546
1668
  return false;
@@ -1713,7 +1835,7 @@ export class ModelQuery {
1713
1835
  q =
1714
1836
  o.raw === "__inRandomOrder__"
1715
1837
  ? q.inRandomOrder()
1716
- : q.orderByRaw(o.raw);
1838
+ : q.orderByRaw(o.raw, o.bindings ?? []);
1717
1839
  }
1718
1840
  else
1719
1841
  q = q.orderBy(o.column, o.direction);
@@ -1846,90 +1968,16 @@ export class ModelQuery {
1846
1968
  }
1847
1969
  /** Apply this query's wheres onto a QueryBuilder (exists subqueries). */
1848
1970
  applyConstraintsTo(q) {
1849
- for (const w of this.#wheres) {
1850
- if (w.op === "__null__") {
1851
- q =
1852
- w.boolean === "or" ? q.orWhereNull(w.column) : q.whereNull(w.column);
1853
- continue;
1854
- }
1855
- if (w.op === "__notnull__") {
1856
- q =
1857
- w.boolean === "or"
1858
- ? q.orWhereNotNull(w.column)
1859
- : q.whereNotNull(w.column);
1860
- continue;
1861
- }
1862
- q =
1863
- w.boolean === "or"
1864
- ? q.orWhere(w.column, w.op, w.value)
1865
- : q.where(w.column, w.op, w.value);
1866
- }
1867
- for (const w of this.#whereIns) {
1868
- if (w.boolean === "or") {
1869
- q = w.not
1870
- ? q.orWhereNotIn(w.column, w.values)
1871
- : q.orWhereIn(w.column, w.values);
1872
- }
1873
- else {
1874
- q = w.not
1875
- ? q.whereNotIn(w.column, w.values)
1876
- : q.whereIn(w.column, w.values);
1877
- }
1878
- }
1879
- for (const w of this.#whereNulls) {
1880
- if (w.boolean === "or") {
1881
- q = w.not ? q.orWhereNotNull(w.column) : q.orWhereNull(w.column);
1882
- }
1883
- else {
1884
- q = w.not ? q.whereNotNull(w.column) : q.whereNull(w.column);
1885
- }
1886
- }
1887
- for (const w of this.#whereBetweens) {
1888
- if (w.boolean === "or") {
1889
- q = w.not
1890
- ? q.orWhereNotBetween(w.column, w.values)
1891
- : q.orWhereBetween(w.column, w.values);
1892
- }
1893
- else {
1894
- q = w.not
1895
- ? q.whereNotBetween(w.column, w.values)
1896
- : q.whereBetween(w.column, w.values);
1897
- }
1898
- }
1899
- for (const w of this.#whereColumns) {
1900
- q =
1901
- w.boolean === "or"
1902
- ? q.orWhereColumn(w.first, w.op, w.second)
1903
- : q.whereColumn(w.first, w.op, w.second);
1904
- }
1905
- for (const w of this.#whereRaws) {
1906
- q =
1907
- w.boolean === "or"
1908
- ? q.orWhereRaw(w.sql, w.bindings)
1909
- : q.whereRaw(w.sql, w.bindings);
1910
- }
1911
- for (const w of this.#whereLikes) {
1912
- if (w.boolean === "or") {
1913
- q = w.not
1914
- ? q.orWhereNotLike(w.column, w.value, w.caseSensitive)
1915
- : q.orWhereLike(w.column, w.value, w.caseSensitive);
1916
- }
1917
- else {
1918
- q = w.not
1919
- ? q.whereNotLike(w.column, w.value, w.caseSensitive)
1920
- : q.whereLike(w.column, w.value, w.caseSensitive);
1921
- }
1922
- }
1923
- for (const w of this.#dateWheres) {
1924
- if (w.kind === "date")
1925
- q = q.whereDate(w.column, w.op, w.value);
1926
- else if (w.kind === "year")
1927
- q = q.whereYear(w.column, w.op, Number(w.value));
1928
- else if (w.kind === "month")
1929
- q = q.whereMonth(w.column, w.op, Number(w.value));
1930
- else
1931
- q = q.whereDay(w.column, w.op, Number(w.value));
1932
- }
1971
+ q = applyWhereLists(q, {
1972
+ wheres: this.#wheres,
1973
+ whereIns: this.#whereIns,
1974
+ whereNulls: this.#whereNulls,
1975
+ whereBetweens: this.#whereBetweens,
1976
+ whereColumns: this.#whereColumns,
1977
+ whereRaws: this.#whereRaws,
1978
+ whereLikes: this.#whereLikes,
1979
+ dateWheres: this.#dateWheres,
1980
+ });
1933
1981
  for (const constraint of this.#hasConstraints) {
1934
1982
  q = this.#applyHasConstraint(q, constraint);
1935
1983
  }
@@ -2154,106 +2202,16 @@ export class ModelQuery {
2154
2202
  return () => { };
2155
2203
  }
2156
2204
  return (q) => {
2157
- if (wheres) {
2158
- for (const w of wheres) {
2159
- if (w.op === "__null__") {
2160
- q =
2161
- w.boolean === "or" ? q.orWhereNull(w.column) : q.whereNull(w.column);
2162
- continue;
2163
- }
2164
- if (w.op === "__notnull__") {
2165
- q =
2166
- w.boolean === "or"
2167
- ? q.orWhereNotNull(w.column)
2168
- : q.whereNotNull(w.column);
2169
- continue;
2170
- }
2171
- q =
2172
- w.boolean === "or"
2173
- ? q.orWhere(w.column, w.op, w.value)
2174
- : q.where(w.column, w.op, w.value);
2175
- }
2176
- }
2177
- if (whereIns) {
2178
- for (const w of whereIns) {
2179
- if (w.boolean === "or") {
2180
- q = w.not
2181
- ? q.orWhereNotIn(w.column, w.values)
2182
- : q.orWhereIn(w.column, w.values);
2183
- }
2184
- else {
2185
- q = w.not
2186
- ? q.whereNotIn(w.column, w.values)
2187
- : q.whereIn(w.column, w.values);
2188
- }
2189
- }
2190
- }
2191
- if (whereNulls) {
2192
- for (const w of whereNulls) {
2193
- if (w.boolean === "or") {
2194
- q = w.not ? q.orWhereNotNull(w.column) : q.orWhereNull(w.column);
2195
- }
2196
- else {
2197
- q = w.not ? q.whereNotNull(w.column) : q.whereNull(w.column);
2198
- }
2199
- }
2200
- }
2201
- if (whereBetweens) {
2202
- for (const w of whereBetweens) {
2203
- if (w.boolean === "or") {
2204
- q = w.not
2205
- ? q.orWhereNotBetween(w.column, w.values)
2206
- : q.orWhereBetween(w.column, w.values);
2207
- }
2208
- else {
2209
- q = w.not
2210
- ? q.whereNotBetween(w.column, w.values)
2211
- : q.whereBetween(w.column, w.values);
2212
- }
2213
- }
2214
- }
2215
- if (whereColumns) {
2216
- for (const w of whereColumns) {
2217
- q =
2218
- w.boolean === "or"
2219
- ? q.orWhereColumn(w.first, w.op, w.second)
2220
- : q.whereColumn(w.first, w.op, w.second);
2221
- }
2222
- }
2223
- if (whereRaws) {
2224
- for (const w of whereRaws) {
2225
- q =
2226
- w.boolean === "or"
2227
- ? q.orWhereRaw(w.sql, w.bindings)
2228
- : q.whereRaw(w.sql, w.bindings);
2229
- }
2230
- }
2231
- if (whereLikes) {
2232
- for (const w of whereLikes) {
2233
- if (w.boolean === "or") {
2234
- q = w.not
2235
- ? q.orWhereNotLike(w.column, w.value, w.caseSensitive)
2236
- : q.orWhereLike(w.column, w.value, w.caseSensitive);
2237
- }
2238
- else {
2239
- q = w.not
2240
- ? q.whereNotLike(w.column, w.value, w.caseSensitive)
2241
- : q.whereLike(w.column, w.value, w.caseSensitive);
2242
- }
2243
- }
2244
- }
2245
- if (dateWheres) {
2246
- for (const w of dateWheres) {
2247
- if (w.kind === "date")
2248
- q = q.whereDate(w.column, w.op, w.value);
2249
- else if (w.kind === "year")
2250
- q = q.whereYear(w.column, w.op, Number(w.value));
2251
- else if (w.kind === "month")
2252
- q = q.whereMonth(w.column, w.op, Number(w.value));
2253
- else
2254
- q = q.whereDay(w.column, w.op, Number(w.value));
2255
- }
2256
- }
2205
+ applyWhereLists(q, {
2206
+ wheres,
2207
+ whereIns,
2208
+ whereNulls,
2209
+ whereBetweens,
2210
+ whereColumns,
2211
+ whereRaws,
2212
+ whereLikes,
2213
+ dateWheres,
2214
+ });
2257
2215
  };
2258
2216
  }
2259
2217
  /**
@@ -2279,7 +2237,7 @@ export class ModelQuery {
2279
2237
  });
2280
2238
  if (usesSoftDeletes(meta.related)) {
2281
2239
  const delCol = deletedAtColumn(meta.related);
2282
- (this.#wheres = mqMut(this.#wheres)).push({
2240
+ (this.#wheres = mqMut(this.#wheres)).push({ seq: nextWhereSeq(),
2283
2241
  column: `${relatedAlias}.${delCol}`,
2284
2242
  op: "__null__",
2285
2243
  value: null,
package/dist/model.d.ts CHANGED
@@ -398,9 +398,9 @@ export declare class Model {
398
398
  static whereNotNull<T extends typeof Model>(this: T, column: ColumnHint<InstanceType<T>>): ModelQuery<InstanceType<T>>;
399
399
  static orderBy<T extends typeof Model>(this: T, column: ColumnHint<InstanceType<T>>, direction?: "asc" | "desc"): ModelQuery<InstanceType<T>>;
400
400
  static orderByDesc<T extends typeof Model>(this: T, column: ColumnHint<InstanceType<T>>): ModelQuery<InstanceType<T>>;
401
- static orderByRaw<T extends typeof Model>(this: T, sql: string): ModelQuery<InstanceType<T>>;
401
+ static orderByRaw<T extends typeof Model>(this: T, ...args: Parameters<ModelQuery<InstanceType<T>>["orderByRaw"]>): ModelQuery<InstanceType<T>>;
402
402
  /** Alias for `orderByRaw`. */
403
- static orderBySql<T extends typeof Model>(this: T, sql: string): ModelQuery<InstanceType<T>>;
403
+ static orderBySql<T extends typeof Model>(this: T, ...args: Parameters<ModelQuery<InstanceType<T>>["orderByRaw"]>): ModelQuery<InstanceType<T>>;
404
404
  static latest<T extends typeof Model>(this: T, column?: string): ModelQuery<InstanceType<T>>;
405
405
  static oldest<T extends typeof Model>(this: T, column?: string): ModelQuery<InstanceType<T>>;
406
406
  static limit<T extends typeof Model>(this: T, value: number): ModelQuery<InstanceType<T>>;
package/dist/model.js CHANGED
@@ -1525,13 +1525,13 @@ export class Model {
1525
1525
  static orderByDesc(column) {
1526
1526
  return this.orderBy(column, "desc");
1527
1527
  }
1528
- static orderByRaw(sql) {
1528
+ static orderByRaw(...args) {
1529
1529
  this.bootIfNotBooted();
1530
- return this.newQuery().orderByRaw(sql);
1530
+ return this.newQuery().orderByRaw(...args);
1531
1531
  }
1532
1532
  /** Alias for `orderByRaw`. */
1533
- static orderBySql(sql) {
1534
- return this.orderByRaw(sql);
1533
+ static orderBySql(...args) {
1534
+ return this.orderByRaw(...args);
1535
1535
  }
1536
1536
  static latest(column = "created_at") {
1537
1537
  this.bootIfNotBooted();
@@ -32,7 +32,9 @@ export async function testDrivers() {
32
32
  }
33
33
  const my = Bun.env.BUNYAD_TEST_MYSQL_URL;
34
34
  if (my && /^mysql:\/\//i.test(my)) {
35
- const connection = connectMysql({ url: my, tls: { rejectUnauthorized: false } });
35
+ // Every test file opens its own connection and none closes it, so keep each pool small:
36
+ // with the default of 10 the run exhausts MySQL's 151 connections and later tests fail.
37
+ const connection = connectMysql({ url: my, tls: { rejectUnauthorized: false }, max: 2 });
36
38
  if (await reachable(connection))
37
39
  drivers.push({ name: "mysql", connection });
38
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunyad/orm",
3
- "version": "0.2.0-beta.3",
3
+ "version": "0.2.0-beta.4",
4
4
  "description": "Active-record ORM for Bunyad: models, relations, casts, scopes, events, factories.",
5
5
  "license": "MIT",
6
6
  "author": "Shah Khalid",
@@ -36,8 +36,8 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@bunyad/common": "^0.2.0-beta.3",
40
- "@bunyad/database": "^0.2.0-beta.3"
39
+ "@bunyad/common": "^0.2.0-beta.4",
40
+ "@bunyad/database": "^0.2.0-beta.4"
41
41
  },
42
42
  "publishConfig": {
43
43
  "access": "public"