@stamhoofd/sql 2.119.0 → 2.120.1

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 (272) hide show
  1. package/dist/{src/ModelCache.d.ts → ModelCache.d.ts} +1 -1
  2. package/dist/ModelCache.d.ts.map +1 -0
  3. package/{src/ModelCache.ts → dist/ModelCache.js} +8 -16
  4. package/dist/ModelCache.js.map +1 -0
  5. package/dist/{src/QueryableModel.d.ts → QueryableModel.d.ts} +7 -6
  6. package/dist/QueryableModel.d.ts.map +1 -0
  7. package/dist/{src/QueryableModel.js → QueryableModel.js} +9 -13
  8. package/dist/QueryableModel.js.map +1 -0
  9. package/dist/{src/SQL.d.ts → SQL.d.ts} +7 -5
  10. package/dist/SQL.d.ts.map +1 -0
  11. package/dist/SQL.js +100 -0
  12. package/dist/SQL.js.map +1 -0
  13. package/dist/{src/SQLDelete.d.ts → SQLDelete.d.ts} +2 -2
  14. package/dist/SQLDelete.d.ts.map +1 -0
  15. package/dist/{src/SQLDelete.js → SQLDelete.js} +8 -12
  16. package/dist/SQLDelete.js.map +1 -0
  17. package/dist/SQLExpression.d.ts.map +1 -0
  18. package/dist/{src/SQLExpression.js → SQLExpression.js} +3 -8
  19. package/dist/SQLExpression.js.map +1 -0
  20. package/dist/{src/SQLExpressions.d.ts → SQLExpressions.d.ts} +2 -2
  21. package/dist/SQLExpressions.d.ts.map +1 -0
  22. package/dist/{src/SQLExpressions.js → SQLExpressions.js} +78 -115
  23. package/dist/SQLExpressions.js.map +1 -0
  24. package/dist/{src/SQLInsert.d.ts → SQLInsert.d.ts} +3 -2
  25. package/dist/SQLInsert.d.ts.map +1 -0
  26. package/dist/{src/SQLInsert.js → SQLInsert.js} +17 -21
  27. package/dist/SQLInsert.js.map +1 -0
  28. package/dist/{src/SQLJoin.d.ts → SQLJoin.d.ts} +1 -1
  29. package/dist/SQLJoin.d.ts.map +1 -0
  30. package/{src/SQLJoin.ts → dist/SQLJoin.js} +15 -18
  31. package/dist/SQLJoin.js.map +1 -0
  32. package/dist/{src/SQLJsonExpressions.d.ts → SQLJsonExpressions.d.ts} +2 -2
  33. package/dist/SQLJsonExpressions.d.ts.map +1 -0
  34. package/dist/{src/SQLJsonExpressions.js → SQLJsonExpressions.js} +31 -44
  35. package/dist/SQLJsonExpressions.js.map +1 -0
  36. package/dist/SQLLogger.d.ts.map +1 -0
  37. package/dist/{src/SQLLogger.js → SQLLogger.js} +5 -8
  38. package/dist/SQLLogger.js.map +1 -0
  39. package/dist/{src/SQLOrderBy.d.ts → SQLOrderBy.d.ts} +1 -1
  40. package/dist/SQLOrderBy.d.ts.map +1 -0
  41. package/dist/{src/SQLOrderBy.js → SQLOrderBy.js} +8 -13
  42. package/dist/SQLOrderBy.js.map +1 -0
  43. package/dist/{src/SQLSelect.d.ts → SQLSelect.d.ts} +3 -3
  44. package/dist/SQLSelect.d.ts.map +1 -0
  45. package/dist/{src/SQLSelect.js → SQLSelect.js} +24 -29
  46. package/dist/SQLSelect.js.map +1 -0
  47. package/dist/{src/SQLTranslatedStringHelper.d.ts → SQLTranslatedStringHelper.d.ts} +3 -2
  48. package/dist/SQLTranslatedStringHelper.d.ts.map +1 -0
  49. package/dist/SQLTranslatedStringHelper.js +33 -0
  50. package/dist/SQLTranslatedStringHelper.js.map +1 -0
  51. package/dist/{src/SQLUpdate.d.ts → SQLUpdate.d.ts} +3 -2
  52. package/dist/SQLUpdate.d.ts.map +1 -0
  53. package/{src/SQLUpdate.ts → dist/SQLUpdate.js} +18 -35
  54. package/dist/SQLUpdate.js.map +1 -0
  55. package/dist/{src/SQLWhere.d.ts → SQLWhere.d.ts} +3 -3
  56. package/dist/SQLWhere.d.ts.map +1 -0
  57. package/dist/{src/SQLWhere.js → SQLWhere.js} +42 -56
  58. package/dist/SQLWhere.js.map +1 -0
  59. package/dist/{src/filters → filters}/SQLFilter.d.ts +5 -5
  60. package/dist/filters/SQLFilter.d.ts.map +1 -0
  61. package/{src/filters/SQLFilter.ts → dist/filters/SQLFilter.js} +55 -121
  62. package/dist/filters/SQLFilter.js.map +1 -0
  63. package/dist/{src/filters → filters}/SQLSorter.d.ts +6 -6
  64. package/dist/filters/SQLSorter.d.ts.map +1 -0
  65. package/dist/{src/filters → filters}/SQLSorter.js +4 -7
  66. package/dist/filters/SQLSorter.js.map +1 -0
  67. package/dist/filters/compilers/contains.d.ts +4 -0
  68. package/dist/filters/compilers/contains.d.ts.map +1 -0
  69. package/{src/filters/compilers/contains.ts → dist/filters/compilers/contains.js} +7 -25
  70. package/dist/filters/compilers/contains.js.map +1 -0
  71. package/dist/filters/compilers/equals.d.ts +4 -0
  72. package/dist/filters/compilers/equals.d.ts.map +1 -0
  73. package/dist/filters/compilers/equals.js +44 -0
  74. package/dist/filters/compilers/equals.js.map +1 -0
  75. package/dist/filters/compilers/greater.d.ts +4 -0
  76. package/dist/filters/compilers/greater.d.ts.map +1 -0
  77. package/dist/filters/compilers/greater.js +15 -0
  78. package/dist/filters/compilers/greater.js.map +1 -0
  79. package/dist/filters/compilers/in.d.ts +4 -0
  80. package/dist/filters/compilers/in.d.ts.map +1 -0
  81. package/{src/filters/compilers/in.ts → dist/filters/compilers/in.js} +7 -21
  82. package/dist/filters/compilers/in.js.map +1 -0
  83. package/dist/filters/compilers/index.d.ts.map +1 -0
  84. package/{src/filters/compilers/index.ts → dist/filters/compilers/index.js} +1 -0
  85. package/dist/filters/compilers/index.js.map +1 -0
  86. package/dist/filters/compilers/less.d.ts +4 -0
  87. package/dist/filters/compilers/less.d.ts.map +1 -0
  88. package/dist/filters/compilers/less.js +15 -0
  89. package/dist/filters/compilers/less.js.map +1 -0
  90. package/dist/filters/helpers/isJSONColumn.d.ts +5 -0
  91. package/dist/filters/helpers/isJSONColumn.d.ts.map +1 -0
  92. package/{src/filters/helpers/isJSONColumn.ts → dist/filters/helpers/isJSONColumn.js} +4 -5
  93. package/dist/filters/helpers/isJSONColumn.js.map +1 -0
  94. package/dist/{src/filters → filters}/helpers/normalizeCompareValue.d.ts +1 -1
  95. package/dist/filters/helpers/normalizeCompareValue.d.ts.map +1 -0
  96. package/{src/filters/helpers/normalizeCompareValue.ts → dist/filters/helpers/normalizeCompareValue.js} +2 -20
  97. package/dist/filters/helpers/normalizeCompareValue.js.map +1 -0
  98. package/dist/index.d.ts +14 -14
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +14 -25
  101. package/dist/index.js.map +1 -1
  102. package/package.json +6 -6
  103. package/dist/src/ModelCache.d.ts.map +0 -1
  104. package/dist/src/ModelCache.js +0 -57
  105. package/dist/src/ModelCache.js.map +0 -1
  106. package/dist/src/QueryableModel.d.ts.map +0 -1
  107. package/dist/src/QueryableModel.js.map +0 -1
  108. package/dist/src/SQL.d.ts.map +0 -1
  109. package/dist/src/SQL.js +0 -103
  110. package/dist/src/SQL.js.map +0 -1
  111. package/dist/src/SQLDelete.d.ts.map +0 -1
  112. package/dist/src/SQLDelete.js.map +0 -1
  113. package/dist/src/SQLExpression.d.ts.map +0 -1
  114. package/dist/src/SQLExpression.js.map +0 -1
  115. package/dist/src/SQLExpressions.d.ts.map +0 -1
  116. package/dist/src/SQLExpressions.js.map +0 -1
  117. package/dist/src/SQLInsert.d.ts.map +0 -1
  118. package/dist/src/SQLInsert.js.map +0 -1
  119. package/dist/src/SQLJoin.d.ts.map +0 -1
  120. package/dist/src/SQLJoin.js +0 -61
  121. package/dist/src/SQLJoin.js.map +0 -1
  122. package/dist/src/SQLJsonExpressions.d.ts.map +0 -1
  123. package/dist/src/SQLJsonExpressions.js.map +0 -1
  124. package/dist/src/SQLLogger.d.ts.map +0 -1
  125. package/dist/src/SQLLogger.js.map +0 -1
  126. package/dist/src/SQLOrderBy.d.ts.map +0 -1
  127. package/dist/src/SQLOrderBy.js.map +0 -1
  128. package/dist/src/SQLSelect.d.ts.map +0 -1
  129. package/dist/src/SQLSelect.js.map +0 -1
  130. package/dist/src/SQLTranslatedStringHelper.d.ts.map +0 -1
  131. package/dist/src/SQLTranslatedStringHelper.js +0 -37
  132. package/dist/src/SQLTranslatedStringHelper.js.map +0 -1
  133. package/dist/src/SQLUpdate.d.ts.map +0 -1
  134. package/dist/src/SQLUpdate.js +0 -60
  135. package/dist/src/SQLUpdate.js.map +0 -1
  136. package/dist/src/SQLWhere.d.ts.map +0 -1
  137. package/dist/src/SQLWhere.js.map +0 -1
  138. package/dist/src/filters/SQLFilter.d.ts.map +0 -1
  139. package/dist/src/filters/SQLFilter.js +0 -220
  140. package/dist/src/filters/SQLFilter.js.map +0 -1
  141. package/dist/src/filters/SQLSorter.d.ts.map +0 -1
  142. package/dist/src/filters/SQLSorter.js.map +0 -1
  143. package/dist/src/filters/compilers/contains.d.ts +0 -4
  144. package/dist/src/filters/compilers/contains.d.ts.map +0 -1
  145. package/dist/src/filters/compilers/contains.js +0 -29
  146. package/dist/src/filters/compilers/contains.js.map +0 -1
  147. package/dist/src/filters/compilers/equals.d.ts +0 -4
  148. package/dist/src/filters/compilers/equals.d.ts.map +0 -1
  149. package/dist/src/filters/compilers/equals.js +0 -47
  150. package/dist/src/filters/compilers/equals.js.map +0 -1
  151. package/dist/src/filters/compilers/greater.d.ts +0 -4
  152. package/dist/src/filters/compilers/greater.d.ts.map +0 -1
  153. package/dist/src/filters/compilers/greater.js +0 -18
  154. package/dist/src/filters/compilers/greater.js.map +0 -1
  155. package/dist/src/filters/compilers/in.d.ts +0 -4
  156. package/dist/src/filters/compilers/in.d.ts.map +0 -1
  157. package/dist/src/filters/compilers/in.js +0 -51
  158. package/dist/src/filters/compilers/in.js.map +0 -1
  159. package/dist/src/filters/compilers/index.d.ts.map +0 -1
  160. package/dist/src/filters/compilers/index.js +0 -8
  161. package/dist/src/filters/compilers/index.js.map +0 -1
  162. package/dist/src/filters/compilers/less.d.ts +0 -4
  163. package/dist/src/filters/compilers/less.d.ts.map +0 -1
  164. package/dist/src/filters/compilers/less.js +0 -18
  165. package/dist/src/filters/compilers/less.js.map +0 -1
  166. package/dist/src/filters/helpers/isJSONColumn.d.ts +0 -4
  167. package/dist/src/filters/helpers/isJSONColumn.d.ts.map +0 -1
  168. package/dist/src/filters/helpers/isJSONColumn.js +0 -17
  169. package/dist/src/filters/helpers/isJSONColumn.js.map +0 -1
  170. package/dist/src/filters/helpers/normalizeCompareValue.d.ts.map +0 -1
  171. package/dist/src/filters/helpers/normalizeCompareValue.js +0 -87
  172. package/dist/src/filters/helpers/normalizeCompareValue.js.map +0 -1
  173. package/dist/tests/filters/$and.test.d.ts +0 -2
  174. package/dist/tests/filters/$and.test.d.ts.map +0 -1
  175. package/dist/tests/filters/$and.test.js +0 -216
  176. package/dist/tests/filters/$and.test.js.map +0 -1
  177. package/dist/tests/filters/$contains.test.d.ts +0 -2
  178. package/dist/tests/filters/$contains.test.d.ts.map +0 -1
  179. package/dist/tests/filters/$contains.test.js +0 -917
  180. package/dist/tests/filters/$contains.test.js.map +0 -1
  181. package/dist/tests/filters/$eq.test.d.ts +0 -2
  182. package/dist/tests/filters/$eq.test.d.ts.map +0 -1
  183. package/dist/tests/filters/$eq.test.js +0 -1464
  184. package/dist/tests/filters/$eq.test.js.map +0 -1
  185. package/dist/tests/filters/$gt.test.d.ts +0 -2
  186. package/dist/tests/filters/$gt.test.d.ts.map +0 -1
  187. package/dist/tests/filters/$gt.test.js +0 -641
  188. package/dist/tests/filters/$gt.test.js.map +0 -1
  189. package/dist/tests/filters/$gte.test.d.ts +0 -2
  190. package/dist/tests/filters/$gte.test.d.ts.map +0 -1
  191. package/dist/tests/filters/$gte.test.js +0 -433
  192. package/dist/tests/filters/$gte.test.js.map +0 -1
  193. package/dist/tests/filters/$in.test.d.ts +0 -2
  194. package/dist/tests/filters/$in.test.d.ts.map +0 -1
  195. package/dist/tests/filters/$in.test.js +0 -773
  196. package/dist/tests/filters/$in.test.js.map +0 -1
  197. package/dist/tests/filters/$lt.test.d.ts +0 -2
  198. package/dist/tests/filters/$lt.test.d.ts.map +0 -1
  199. package/dist/tests/filters/$lt.test.js +0 -433
  200. package/dist/tests/filters/$lt.test.js.map +0 -1
  201. package/dist/tests/filters/$lte.test.d.ts +0 -2
  202. package/dist/tests/filters/$lte.test.d.ts.map +0 -1
  203. package/dist/tests/filters/$lte.test.js +0 -472
  204. package/dist/tests/filters/$lte.test.js.map +0 -1
  205. package/dist/tests/filters/$neq.test.d.ts +0 -2
  206. package/dist/tests/filters/$neq.test.d.ts.map +0 -1
  207. package/dist/tests/filters/$neq.test.js +0 -32
  208. package/dist/tests/filters/$neq.test.js.map +0 -1
  209. package/dist/tests/filters/$not.test.d.ts +0 -2
  210. package/dist/tests/filters/$not.test.d.ts.map +0 -1
  211. package/dist/tests/filters/$not.test.js +0 -50
  212. package/dist/tests/filters/$not.test.js.map +0 -1
  213. package/dist/tests/filters/$or.test.d.ts +0 -2
  214. package/dist/tests/filters/$or.test.d.ts.map +0 -1
  215. package/dist/tests/filters/$or.test.js +0 -185
  216. package/dist/tests/filters/$or.test.js.map +0 -1
  217. package/dist/tests/filters/SQLTranslatedStringHelper.test.d.ts +0 -2
  218. package/dist/tests/filters/SQLTranslatedStringHelper.test.d.ts.map +0 -1
  219. package/dist/tests/filters/SQLTranslatedStringHelper.test.js +0 -491
  220. package/dist/tests/filters/SQLTranslatedStringHelper.test.js.map +0 -1
  221. package/dist/tests/filters/dot-syntax.test.d.ts +0 -2
  222. package/dist/tests/filters/dot-syntax.test.d.ts.map +0 -1
  223. package/dist/tests/filters/dot-syntax.test.js +0 -210
  224. package/dist/tests/filters/dot-syntax.test.js.map +0 -1
  225. package/dist/tests/filters/exists.test.d.ts +0 -2
  226. package/dist/tests/filters/exists.test.d.ts.map +0 -1
  227. package/dist/tests/filters/exists.test.js +0 -96
  228. package/dist/tests/filters/exists.test.js.map +0 -1
  229. package/dist/tests/filters/joined-relations.test.d.ts +0 -2
  230. package/dist/tests/filters/joined-relations.test.d.ts.map +0 -1
  231. package/dist/tests/filters/joined-relations.test.js +0 -167
  232. package/dist/tests/filters/joined-relations.test.js.map +0 -1
  233. package/dist/tests/filters/special-cases.test.d.ts +0 -2
  234. package/dist/tests/filters/special-cases.test.d.ts.map +0 -1
  235. package/dist/tests/filters/special-cases.test.js +0 -114
  236. package/dist/tests/filters/special-cases.test.js.map +0 -1
  237. package/dist/tests/filters/wildcard.test.d.ts +0 -2
  238. package/dist/tests/filters/wildcard.test.d.ts.map +0 -1
  239. package/dist/tests/filters/wildcard.test.js +0 -67
  240. package/dist/tests/filters/wildcard.test.js.map +0 -1
  241. package/dist/tests/jest.global.setup.d.ts +0 -3
  242. package/dist/tests/jest.global.setup.d.ts.map +0 -1
  243. package/dist/tests/jest.global.setup.js +0 -7
  244. package/dist/tests/jest.global.setup.js.map +0 -1
  245. package/dist/tests/jest.setup.d.ts +0 -2
  246. package/dist/tests/jest.setup.d.ts.map +0 -1
  247. package/dist/tests/jest.setup.js +0 -5
  248. package/dist/tests/jest.setup.js.map +0 -1
  249. package/dist/tests/utils/index.d.ts +0 -57
  250. package/dist/tests/utils/index.d.ts.map +0 -1
  251. package/dist/tests/utils/index.js +0 -206
  252. package/dist/tests/utils/index.js.map +0 -1
  253. package/dist/tsconfig.tsbuildinfo +0 -1
  254. package/src/QueryableModel.ts +0 -134
  255. package/src/SQL.ts +0 -128
  256. package/src/SQLDelete.ts +0 -73
  257. package/src/SQLExpression.ts +0 -34
  258. package/src/SQLExpressions.ts +0 -587
  259. package/src/SQLInsert.ts +0 -113
  260. package/src/SQLJsonExpressions.ts +0 -283
  261. package/src/SQLLogger.ts +0 -82
  262. package/src/SQLOrderBy.ts +0 -69
  263. package/src/SQLSelect.ts +0 -520
  264. package/src/SQLTranslatedStringHelper.ts +0 -40
  265. package/src/SQLWhere.ts +0 -744
  266. package/src/filters/SQLSorter.ts +0 -60
  267. package/src/filters/compilers/equals.ts +0 -73
  268. package/src/filters/compilers/greater.ts +0 -21
  269. package/src/filters/compilers/less.ts +0 -20
  270. /package/dist/{src/SQLExpression.d.ts → SQLExpression.d.ts} +0 -0
  271. /package/dist/{src/SQLLogger.d.ts → SQLLogger.d.ts} +0 -0
  272. /package/dist/{src/filters → filters}/compilers/index.d.ts +0 -0
package/src/SQLSelect.ts DELETED
@@ -1,520 +0,0 @@
1
- import { Database, SQLResultNamespacedRow } from '@simonbackx/simple-database';
2
- import { Formatter } from '@stamhoofd/utility';
3
- import { SQLExpression, SQLExpressionOptions, SQLNamedExpression, SQLQuery, joinSQLQuery, normalizeSQLQuery } from './SQLExpression.js';
4
- import { SQLAlias, SQLColumnExpression, SQLCount, SQLSelectAs, SQLSum, SQLTableExpression } from './SQLExpressions.js';
5
- import { SQLJoin } from './SQLJoin.js';
6
- import { Orderable } from './SQLOrderBy.js';
7
- import { Whereable } from './SQLWhere.js';
8
- import { SQLLogger } from './SQLLogger.js';
9
-
10
- class EmptyClass {}
11
-
12
- export function parseTable(tableOrExpression: SQLNamedExpression | string, asNamespace?: string): SQLNamedExpression {
13
- if (typeof tableOrExpression === 'string') {
14
- return new SQLTableExpression(tableOrExpression, asNamespace);
15
- }
16
- else {
17
- return tableOrExpression;
18
- }
19
- }
20
-
21
- export type IterableSQLSelect<T extends object = SQLResultNamespacedRow> = AsyncIterableIterator<T, undefined> & {
22
- isDone: boolean;
23
- options: IterableSQLSelectOptions;
24
- maxQueries(maxQueries: number): IterableSQLSelect<T>;
25
- };
26
- export type IterableSQLSelectOptions = {
27
- /**
28
- * The loop will cancel after this amount of queries - but you can continue to loop over the results when starting a new for loop.
29
- */
30
- maxQueries?: number;
31
- };
32
-
33
- export type SQLNamedSelect<T extends object = SQLResultNamespacedRow> = SQLSelect<T> & { getName(): string };
34
-
35
- export class SQLSelect<T extends object = SQLResultNamespacedRow> extends Whereable(Orderable(EmptyClass)) implements SQLExpression {
36
- _columns: SQLExpression[];
37
- _from: SQLNamedExpression;
38
-
39
- _limit: number | null = null;
40
- _offset: number | null = null;
41
- _groupBy: SQLExpression[] = [];
42
- _joins: (InstanceType<typeof SQLJoin>)[] = [];
43
- _max_execution_time: number | null = null;
44
- private _name: string | null = null;
45
- static slowQueryThresholdMs: number | null = null;
46
-
47
- _transformer: ((row: SQLResultNamespacedRow) => T) | null = null;
48
-
49
- constructor(...columns: (SQLExpression | string)[]);
50
- constructor(transformer: ((row: SQLResultNamespacedRow) => T), ...columns: (SQLExpression | string)[]);
51
- constructor(...columns: (SQLExpression | string | ((row: SQLResultNamespacedRow) => T))[]) {
52
- super();
53
-
54
- if (typeof columns[0] === 'function') {
55
- this._transformer = columns.shift() as any;
56
- }
57
- this._columns = columns.map(c => typeof c === 'string' ? new SQLColumnExpression(c) : c) as any;
58
- }
59
-
60
- clone(): this {
61
- const c = new SQLSelect(...this._columns);
62
- Object.assign(c, this);
63
- this._where = this._where ? this._where.clone() : null;
64
- return c as any;
65
- }
66
-
67
- from(table: string, namespace: string): this;
68
- from(table: string): this;
69
- from(expression: SQLNamedExpression): this;
70
- from(tableOrExpression: SQLNamedExpression | string, namespace?: string): this {
71
- this._from = parseTable(tableOrExpression, namespace);
72
-
73
- return this;
74
- }
75
-
76
- select(...columns: (SQLExpression | string)[]): this {
77
- this._columns.push(...columns.map(c => typeof c === 'string' ? new SQLColumnExpression(c) : c));
78
- return this;
79
- }
80
-
81
- join(join: InstanceType<typeof SQLJoin>): this {
82
- // prevent duplicate joins (reference of join should be the same)
83
- if (!this._joins.includes(join)) {
84
- this._joins.push(join);
85
- }
86
-
87
- return this;
88
- }
89
-
90
- groupBy(...columns: SQLExpression[]): this {
91
- this._groupBy.push(...columns);
92
- return this;
93
- }
94
-
95
- setMaxExecutionTime(ms: number): this {
96
- this._max_execution_time = ms;
97
- return this;
98
- }
99
-
100
- getSQL(options?: SQLExpressionOptions): SQLQuery {
101
- if (!this._from) {
102
- throw new Error('Forgot to define .from(...) for SQLSelect');
103
- }
104
-
105
- const query: SQLQuery[] = [
106
- 'SELECT',
107
- ];
108
-
109
- if (this._max_execution_time !== null) {
110
- query.push('/*+ MAX_EXECUTION_TIME(' + this._max_execution_time + ') */');
111
- }
112
-
113
- // Create a clone since we are mutating the default namespaces
114
- const parentOptions = options;
115
- options = options ? { ...options } : {};
116
- options.defaultNamespace = this._from.getName();
117
-
118
- if (parentOptions?.defaultNamespace) {
119
- options.parentNamespace = parentOptions.defaultNamespace;
120
- }
121
-
122
- const columns = this._columns.map(c => c.getSQL(options));
123
- query.push(
124
- joinSQLQuery(columns, ', '),
125
- );
126
-
127
- query.push(
128
- 'FROM',
129
- );
130
-
131
- query.push(this._from.getSQL(options));
132
-
133
- // Joins
134
- query.push(...this._joins.map(j => j.getSQL(options)));
135
- if (this._where) {
136
- const whereJoins = Formatter.uniqueArray(this._where.getJoins()).filter(j => !this._joins.includes(j));
137
- query.push(...whereJoins.map(j => j.getSQL(options)));
138
- }
139
-
140
- // Where
141
- if (this._where) {
142
- const always = this._where.isAlways;
143
- if (always === false) {
144
- throw new Error('Cannot use SQLSelect with a where that is not always true');
145
- }
146
- else if (always === null) {
147
- query.push('WHERE');
148
- query.push(this._where.getSQL(options));
149
- }
150
- }
151
-
152
- if (this._groupBy.length > 0) {
153
- query.push('GROUP BY');
154
- query.push(
155
- joinSQLQuery(
156
- this._groupBy.map(c => c.getSQL(options)),
157
- ', ',
158
- ),
159
- );
160
- }
161
-
162
- if (this._orderBy) {
163
- query.push(this._orderBy.getSQL(options));
164
- }
165
-
166
- if (this._limit !== null) {
167
- query.push('LIMIT ' + this._limit);
168
- if (this._offset !== null && this._offset !== 0) {
169
- query.push('OFFSET ' + this._offset);
170
- }
171
- }
172
-
173
- return joinSQLQuery(query, ' ');
174
- }
175
-
176
- /**
177
- * Returns true when it know all results will be included without filtering.
178
- * Returns false when it knows no single result will be included.
179
- * Null when it does not know.
180
- */
181
- get isAlways() {
182
- return this._where ? this._where.isAlways : true;
183
- }
184
-
185
- limit(limit: number | null, offset: number | null = null): this {
186
- this._limit = limit;
187
- this._offset = offset;
188
- return this;
189
- }
190
-
191
- async fetch(): Promise<T[]> {
192
- if (this._where && this._where.isAlways === false) {
193
- return [];
194
- }
195
-
196
- const { query, params } = normalizeSQLQuery(this.getSQL());
197
-
198
- // when debugging: log all queries
199
- // console.log(query, params);
200
- let rows: SQLResultNamespacedRow[];
201
- try {
202
- const [_rows] = await SQLLogger.log(Database.select(query, params, { nestTables: true }), query, params);
203
- rows = _rows;
204
- }
205
- catch (e) {
206
- console.error('Error executing SQL query', query, params, e);
207
- throw e;
208
- }
209
-
210
- // Now map aggregated queries to the correct namespace
211
- for (const row of rows) {
212
- if (row['']) {
213
- for (const column in row['']) {
214
- const splitted = column.split('__');
215
- if (splitted.length <= 1) {
216
- console.warn('Aggregated column without namespace', column);
217
- continue;
218
- }
219
- const namespace = splitted[0];
220
- const name = splitted[1];
221
- row[namespace] = row[namespace] ?? {};
222
- row[namespace][name] = row[''][column];
223
- }
224
- delete row[''];
225
- }
226
- }
227
-
228
- if (this._transformer) {
229
- return rows.map(this._transformer);
230
- }
231
- return rows as T[];
232
- }
233
-
234
- first(required: false): Promise<T | null>;
235
- first(required: true): Promise<T>;
236
- first(required: boolean): Promise<T | null>;
237
- async first(required = true): Promise<T | null> {
238
- const rows = await this.limit(1).fetch();
239
- if (rows.length === 0) {
240
- if (required) {
241
- throw new Error('Expected at least one result at ' + this._from.getName());
242
- }
243
- return null;
244
- }
245
-
246
- return rows[0];
247
- }
248
-
249
- async count(expression?: SQLExpression): Promise<number> {
250
- if (this._where && this._where.isAlways === false) {
251
- return 0;
252
- }
253
-
254
- this._columns = [
255
- new SQLSelectAs(
256
- new SQLCount(expression ?? null),
257
- new SQLAlias('c'),
258
- ),
259
- ];
260
- this._offset = null;
261
- this._limit = null;
262
- this._orderBy = null;
263
-
264
- const { query, params } = normalizeSQLQuery(this.getSQL());
265
-
266
- const [rows] = await SQLLogger.log(Database.select(query, params, { nestTables: true }), query, params);
267
- if (rows.length === 1) {
268
- const row = rows[0];
269
- if ('' in row) {
270
- const namespaced = row[''];
271
- if ('c' in namespaced) {
272
- const value = namespaced['c'];
273
- if (typeof value === 'number' && Number.isInteger(value)) {
274
- return value;
275
- }
276
- }
277
- }
278
- }
279
- console.warn('Invalid count SQL response', rows);
280
- return 0;
281
- }
282
-
283
- async sum(expression: SQLExpression): Promise<number> {
284
- if (this._where && this._where.isAlways === false) {
285
- return 0;
286
- }
287
-
288
- this._columns = [
289
- new SQLSelectAs(
290
- new SQLSum(expression),
291
- new SQLAlias('c'),
292
- ),
293
- ];
294
- this._offset = null;
295
- this._limit = null;
296
- this._orderBy = null;
297
-
298
- const { query, params } = normalizeSQLQuery(this.getSQL());
299
- // console.log(query, params);
300
-
301
- const [rows] = await SQLLogger.log(Database.select(query, params, { nestTables: true }), query, params);
302
- if (rows.length === 1) {
303
- const row = rows[0];
304
- if ('' in row) {
305
- const namespaced = row[''];
306
- if ('c' in namespaced) {
307
- const value = namespaced['c'];
308
- if (typeof value === 'number' && Number.isInteger(value)) {
309
- return value;
310
- }
311
- }
312
- }
313
- }
314
- console.warn('Invalid sum SQL response', rows);
315
- return 0;
316
- }
317
-
318
- all(options: IterableSQLSelectOptions = {}): T extends { id: string } ? IterableSQLSelect<T> : never {
319
- if (this._orderBy) {
320
- throw new Error('Cannot use async iterator with custom order by. Results should be ordered by ID');
321
- }
322
-
323
- if (this._offset !== null) {
324
- throw new Error('Cannot use async iterator with offset');
325
- }
326
-
327
- if (!this._limit) {
328
- this._limit = 100;
329
- }
330
-
331
- const limit = this._limit;
332
- this.orderBy('id');
333
-
334
- let next: this | null = this.clone();
335
- const base = this;
336
-
337
- let stack: T[] = [];
338
- let stackIndex = 0;
339
-
340
- return {
341
- queryCount: 0,
342
- options,
343
- [Symbol.asyncIterator]() {
344
- return {
345
- ...this,
346
-
347
- // Reset the iterator
348
- queryCount: 0,
349
- };
350
- },
351
- get isDone() {
352
- return !next && (stackIndex + 1) >= stack.length;
353
- },
354
- async next(): Promise<IteratorResult<T, undefined>> {
355
- stackIndex++;
356
-
357
- if (stackIndex < stack.length) {
358
- return {
359
- done: false,
360
- value: stack[stackIndex],
361
- };
362
- }
363
-
364
- if (!next) {
365
- stack = []; // Clean up memory
366
- return {
367
- done: true,
368
- value: undefined,
369
- };
370
- }
371
-
372
- if (this.options.maxQueries !== undefined && this.queryCount >= this.options.maxQueries) {
373
- // Stopping early
374
- return {
375
- done: true,
376
- value: undefined,
377
- };
378
- }
379
-
380
- stack = await next.fetch();
381
- next = null;
382
- this.queryCount += 1;
383
-
384
- if (stack.length === 0) {
385
- return {
386
- done: true,
387
- value: undefined,
388
- };
389
- }
390
- stackIndex = 0;
391
-
392
- if (stack.length >= limit) {
393
- next = base.clone();
394
- const lastResult = stack[stack.length - 1]!;
395
- if (!('id' in lastResult)) {
396
- throw new Error('Cannot use async iterator without ID column');
397
- }
398
-
399
- const lastId = lastResult.id;
400
- if (typeof lastId !== 'string') {
401
- throw new Error('Cannot use async iterator without string ID column');
402
- }
403
-
404
- next.andWhere('id', '>', lastId);
405
- }
406
-
407
- return {
408
- done: false,
409
- value: stack[stackIndex],
410
- };
411
- },
412
- maxQueries(maxQueries: number) {
413
- this.options.maxQueries = maxQueries;
414
- return this;
415
- },
416
- } as IterableSQLSelect<T> as any;
417
- }
418
-
419
- allBatched(options: IterableSQLSelectOptions = {}): T extends { id: string } ? IterableSQLSelect<T[]> : never {
420
- if (this._orderBy) {
421
- throw new Error('Cannot use async iterator with custom order by. Results should be ordered by ID');
422
- }
423
-
424
- if (this._offset !== null) {
425
- throw new Error('Cannot use async iterator with offset');
426
- }
427
-
428
- if (!this._limit) {
429
- this._limit = 100;
430
- }
431
-
432
- const limit = this._limit;
433
- this.orderBy('id');
434
-
435
- let next: this | null = this.clone();
436
- const base = this;
437
-
438
- return {
439
- queryCount: 0,
440
- options,
441
- [Symbol.asyncIterator]() {
442
- return {
443
- ...this,
444
-
445
- // Reset the iterator
446
- queryCount: 0,
447
- };
448
- },
449
- get isDone() {
450
- return !next;
451
- },
452
- async next(): Promise<IteratorResult<T[], undefined>> {
453
- if (!next) {
454
- return {
455
- done: true,
456
- value: undefined,
457
- };
458
- }
459
-
460
- if (this.options.maxQueries !== undefined && this.queryCount >= this.options.maxQueries) {
461
- // Stopping early
462
- return {
463
- done: true,
464
- value: undefined,
465
- };
466
- }
467
-
468
- const stack = await next.fetch();
469
- next = null;
470
- this.queryCount += 1;
471
-
472
- if (stack.length === 0) {
473
- return {
474
- done: true,
475
- value: undefined,
476
- };
477
- }
478
-
479
- if (stack.length >= limit) {
480
- next = base.clone();
481
- const lastResult = stack[stack.length - 1]!;
482
- if (!('id' in lastResult)) {
483
- throw new Error('Cannot use async iterator without ID column');
484
- }
485
-
486
- const lastId = lastResult.id;
487
- if (typeof lastId !== 'string') {
488
- throw new Error('Cannot use async iterator without string ID column');
489
- }
490
-
491
- next.andWhere('id', '>', lastId);
492
- }
493
-
494
- return {
495
- done: false,
496
- value: stack,
497
- };
498
- },
499
- maxQueries(maxQueries: number) {
500
- this.options.maxQueries = maxQueries;
501
- return this;
502
- },
503
- } as IterableSQLSelect<T[]> as any;
504
- }
505
-
506
- getName(): string | null {
507
- return this._name;
508
- }
509
-
510
- /**
511
- * By calling this method we make sure a name is set so we can return an SQLNamedSelect.
512
- * @param name name of the select
513
- * @returns an SQLNamedSelect
514
- */
515
- as(name: string): SQLNamedSelect {
516
- this._name = name;
517
-
518
- return this as SQLNamedSelect;
519
- }
520
- }
@@ -1,40 +0,0 @@
1
- import { SQL, SQLColumnExpression, SQLExpression, SQLExpressionOptions, SQLQuery } from '@stamhoofd/sql';
2
- import { Language } from '@stamhoofd/structures';
3
-
4
- export class SQLTranslatedStringHelper implements SQLExpression {
5
- constructor(private columnExpression: SQLColumnExpression, private path: string, private getLanguage: () => Language) {
6
- }
7
-
8
- getSQL(options?: SQLExpressionOptions): SQLQuery {
9
- const currentLanguage = this.getLanguage();
10
-
11
- const languageOrder: Language[] = [
12
- Language.English,
13
- Language.Dutch,
14
- Language.French,
15
- ];
16
-
17
- const languages = moveToFront(languageOrder, currentLanguage);
18
-
19
- const languageValues: SQLExpression[] = languages.map((language) => {
20
- return SQL.jsonValue(this.columnExpression, `${this.path}.${language}`, 'CHAR');
21
- });
22
-
23
- const type: SQLExpression = SQL.jsonType(SQL.jsonExtract(this.columnExpression, this.path));
24
-
25
- return SQL.if(
26
- type, '=', 'STRING',
27
- ).then(
28
- SQL.jsonValue(this.columnExpression, this.path, 'CHAR'),
29
- ).else(
30
- SQL.coalesce(...languageValues) as SQLExpression,
31
- ).getSQL(options);
32
- }
33
- }
34
-
35
- function moveToFront<T>(arr: T[], value: T): T[] {
36
- const index = arr.indexOf(value);
37
- if (index === -1 || index === 0) return arr;
38
-
39
- return [arr[index], ...arr.slice(0, index), ...arr.slice(index + 1)];
40
- }