@grest-ts/sql 0.0.5

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 (146) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +498 -0
  3. package/dist/src/MysqlTable.d.ts +35 -0
  4. package/dist/src/MysqlTable.d.ts.map +1 -0
  5. package/dist/src/MysqlTable.js +70 -0
  6. package/dist/src/MysqlTable.js.map +1 -0
  7. package/dist/src/MysqlTableStructureParser.d.ts +106 -0
  8. package/dist/src/MysqlTableStructureParser.d.ts.map +1 -0
  9. package/dist/src/MysqlTableStructureParser.js +189 -0
  10. package/dist/src/MysqlTableStructureParser.js.map +1 -0
  11. package/dist/src/SQL.d.ts +72 -0
  12. package/dist/src/SQL.d.ts.map +1 -0
  13. package/dist/src/SQL.js +94 -0
  14. package/dist/src/SQL.js.map +1 -0
  15. package/dist/src/SqlExpression.d.ts +49 -0
  16. package/dist/src/SqlExpression.d.ts.map +1 -0
  17. package/dist/src/SqlExpression.js +117 -0
  18. package/dist/src/SqlExpression.js.map +1 -0
  19. package/dist/src/SqlFunctions.d.ts +118 -0
  20. package/dist/src/SqlFunctions.d.ts.map +1 -0
  21. package/dist/src/SqlFunctions.js +331 -0
  22. package/dist/src/SqlFunctions.js.map +1 -0
  23. package/dist/src/Symbols.d.ts +11 -0
  24. package/dist/src/Symbols.d.ts.map +1 -0
  25. package/dist/src/Symbols.js +11 -0
  26. package/dist/src/Symbols.js.map +1 -0
  27. package/dist/src/Types.d.ts +110 -0
  28. package/dist/src/Types.d.ts.map +1 -0
  29. package/dist/src/Types.js +34 -0
  30. package/dist/src/Types.js.map +1 -0
  31. package/dist/src/delete/DeleteBuilder.d.ts +19 -0
  32. package/dist/src/delete/DeleteBuilder.d.ts.map +1 -0
  33. package/dist/src/delete/DeleteBuilder.js +50 -0
  34. package/dist/src/delete/DeleteBuilder.js.map +1 -0
  35. package/dist/src/delete/DeleteInterfaces.d.ts +27 -0
  36. package/dist/src/delete/DeleteInterfaces.d.ts.map +1 -0
  37. package/dist/src/delete/DeleteInterfaces.js +2 -0
  38. package/dist/src/delete/DeleteInterfaces.js.map +1 -0
  39. package/dist/src/escape.d.ts +4 -0
  40. package/dist/src/escape.d.ts.map +1 -0
  41. package/dist/src/escape.js +50 -0
  42. package/dist/src/escape.js.map +1 -0
  43. package/dist/src/index.d.ts +7 -0
  44. package/dist/src/index.d.ts.map +1 -0
  45. package/dist/src/index.js +7 -0
  46. package/dist/src/index.js.map +1 -0
  47. package/dist/src/insert/InsertBuilder.d.ts +19 -0
  48. package/dist/src/insert/InsertBuilder.d.ts.map +1 -0
  49. package/dist/src/insert/InsertBuilder.js +62 -0
  50. package/dist/src/insert/InsertBuilder.js.map +1 -0
  51. package/dist/src/insert/InsertInterfaces.d.ts +11 -0
  52. package/dist/src/insert/InsertInterfaces.d.ts.map +1 -0
  53. package/dist/src/insert/InsertInterfaces.js +2 -0
  54. package/dist/src/insert/InsertInterfaces.js.map +1 -0
  55. package/dist/src/select/SelectBuilder.d.ts +72 -0
  56. package/dist/src/select/SelectBuilder.d.ts.map +1 -0
  57. package/dist/src/select/SelectBuilder.js +315 -0
  58. package/dist/src/select/SelectBuilder.js.map +1 -0
  59. package/dist/src/select/parts/GatewayWhere.d.ts +17 -0
  60. package/dist/src/select/parts/GatewayWhere.d.ts.map +1 -0
  61. package/dist/src/select/parts/GatewayWhere.js +2 -0
  62. package/dist/src/select/parts/GatewayWhere.js.map +1 -0
  63. package/dist/src/select/parts/S0Union.d.ts +20 -0
  64. package/dist/src/select/parts/S0Union.d.ts.map +1 -0
  65. package/dist/src/select/parts/S0Union.js +2 -0
  66. package/dist/src/select/parts/S0Union.js.map +1 -0
  67. package/dist/src/select/parts/S0Uses.d.ts +6 -0
  68. package/dist/src/select/parts/S0Uses.d.ts.map +1 -0
  69. package/dist/src/select/parts/S0Uses.js +2 -0
  70. package/dist/src/select/parts/S0Uses.js.map +1 -0
  71. package/dist/src/select/parts/S0With.d.ts +6 -0
  72. package/dist/src/select/parts/S0With.d.ts.map +1 -0
  73. package/dist/src/select/parts/S0With.js +2 -0
  74. package/dist/src/select/parts/S0With.js.map +1 -0
  75. package/dist/src/select/parts/S1Join.d.ts +12 -0
  76. package/dist/src/select/parts/S1Join.d.ts.map +1 -0
  77. package/dist/src/select/parts/S1Join.js +2 -0
  78. package/dist/src/select/parts/S1Join.js.map +1 -0
  79. package/dist/src/select/parts/S2Columns.d.ts +35 -0
  80. package/dist/src/select/parts/S2Columns.d.ts.map +1 -0
  81. package/dist/src/select/parts/S2Columns.js +3 -0
  82. package/dist/src/select/parts/S2Columns.js.map +1 -0
  83. package/dist/src/select/parts/S2Where.d.ts +13 -0
  84. package/dist/src/select/parts/S2Where.d.ts.map +1 -0
  85. package/dist/src/select/parts/S2Where.js +2 -0
  86. package/dist/src/select/parts/S2Where.js.map +1 -0
  87. package/dist/src/select/parts/S3GroupBy.d.ts +10 -0
  88. package/dist/src/select/parts/S3GroupBy.d.ts.map +1 -0
  89. package/dist/src/select/parts/S3GroupBy.js +2 -0
  90. package/dist/src/select/parts/S3GroupBy.js.map +1 -0
  91. package/dist/src/select/parts/S4Having.d.ts +10 -0
  92. package/dist/src/select/parts/S4Having.d.ts.map +1 -0
  93. package/dist/src/select/parts/S4Having.js +2 -0
  94. package/dist/src/select/parts/S4Having.js.map +1 -0
  95. package/dist/src/select/parts/S5OrderBy.d.ts +9 -0
  96. package/dist/src/select/parts/S5OrderBy.d.ts.map +1 -0
  97. package/dist/src/select/parts/S5OrderBy.js +2 -0
  98. package/dist/src/select/parts/S5OrderBy.js.map +1 -0
  99. package/dist/src/select/parts/S6Limit.d.ts +7 -0
  100. package/dist/src/select/parts/S6Limit.d.ts.map +1 -0
  101. package/dist/src/select/parts/S6Limit.js +2 -0
  102. package/dist/src/select/parts/S6Limit.js.map +1 -0
  103. package/dist/src/select/parts/S7Exec.d.ts +26 -0
  104. package/dist/src/select/parts/S7Exec.d.ts.map +1 -0
  105. package/dist/src/select/parts/S7Exec.js +2 -0
  106. package/dist/src/select/parts/S7Exec.js.map +1 -0
  107. package/dist/src/tsconfig.json +16 -0
  108. package/dist/src/update/UpdateBuilder.d.ts +28 -0
  109. package/dist/src/update/UpdateBuilder.d.ts.map +1 -0
  110. package/dist/src/update/UpdateBuilder.js +77 -0
  111. package/dist/src/update/UpdateBuilder.js.map +1 -0
  112. package/dist/src/update/UpdateInterfaces.d.ts +34 -0
  113. package/dist/src/update/UpdateInterfaces.d.ts.map +1 -0
  114. package/dist/src/update/UpdateInterfaces.js +2 -0
  115. package/dist/src/update/UpdateInterfaces.js.map +1 -0
  116. package/dist/tsconfig.publish.tsbuildinfo +1 -0
  117. package/package.json +54 -0
  118. package/src/MysqlTable.ts +102 -0
  119. package/src/MysqlTableStructureParser.ts +283 -0
  120. package/src/SQL.ts +244 -0
  121. package/src/SqlExpression.ts +172 -0
  122. package/src/SqlFunctions.ts +471 -0
  123. package/src/Symbols.ts +11 -0
  124. package/src/Types.ts +244 -0
  125. package/src/delete/DeleteBuilder.ts +65 -0
  126. package/src/delete/DeleteInterfaces.ts +70 -0
  127. package/src/escape.ts +52 -0
  128. package/src/index.ts +6 -0
  129. package/src/insert/InsertBuilder.ts +76 -0
  130. package/src/insert/InsertInterfaces.ts +16 -0
  131. package/src/select/SelectBuilder.ts +372 -0
  132. package/src/select/parts/GatewayWhere.ts +31 -0
  133. package/src/select/parts/S0Union.ts +43 -0
  134. package/src/select/parts/S0Uses.ts +21 -0
  135. package/src/select/parts/S0With.ts +21 -0
  136. package/src/select/parts/S1Join.ts +39 -0
  137. package/src/select/parts/S2Columns.ts +68 -0
  138. package/src/select/parts/S2Where.ts +51 -0
  139. package/src/select/parts/S3GroupBy.ts +23 -0
  140. package/src/select/parts/S4Having.ts +24 -0
  141. package/src/select/parts/S5OrderBy.ts +21 -0
  142. package/src/select/parts/S6Limit.ts +9 -0
  143. package/src/select/parts/S7Exec.ts +41 -0
  144. package/src/tsconfig.json +16 -0
  145. package/src/update/UpdateBuilder.ts +96 -0
  146. package/src/update/UpdateInterfaces.ts +87 -0
@@ -0,0 +1,372 @@
1
+ import {Over, SqlExpression, Transformer} from "../SqlExpression";
2
+ import {WhereMethods} from "./parts/S2Where";
3
+ import {ColumnsMethods} from "./parts/S2Columns";
4
+ import {JoinMethods} from "./parts/S1Join";
5
+ import {WithMethods} from "./parts/S0With";
6
+ import {UsesMethods} from "./parts/S0Uses";
7
+ import {UnionMethods} from "./parts/S0Union";
8
+ import {GroupByMethods} from "./parts/S3GroupBy";
9
+ import {HavingMethods} from "./parts/S4Having";
10
+ import {OrderByMethods} from "./parts/S5OrderBy";
11
+ import {LimitMethods} from "./parts/S6Limit";
12
+ import {ExecMethods} from "./parts/S7Exec";
13
+ import {MysqlTable} from "../MysqlTable";
14
+ import {SQL_ALIAS, SQL_ENTITY, SQL_EXPRESSION} from "../Symbols";
15
+ import {AliasedTable, AnyAliasedTableDef, DbTableDefinition, SelectExecutor} from "../Types";
16
+ import {escape, escapeId} from "../escape";
17
+ import {ONE, orderByStructureToSqlString} from "../SqlFunctions";
18
+ import {GatewaySelectGroupByMethods, GatewaySelectLimitMethods, GatewaySelectOrderByMethods, GatewayWhereMethods} from "./parts/GatewayWhere";
19
+
20
+ const TAB = " ";
21
+
22
+ export class SelectBuilder<Result, Aliases, AliasesFromWith, Tables> implements UnionMethods<Result>,
23
+ WithMethods<AliasesFromWith>,
24
+ UsesMethods<Aliases, Tables>,
25
+ JoinMethods<Aliases, AliasesFromWith, Tables>,
26
+ ColumnsMethods<Result, Tables>,
27
+ WhereMethods<Result, Tables>,
28
+ GroupByMethods<Result, Tables>,
29
+ HavingMethods<Result, Tables>,
30
+ OrderByMethods<Result, Tables>,
31
+ LimitMethods<Result>,
32
+ ExecMethods<Result>,
33
+ GatewayWhereMethods<Result, Tables>,
34
+ GatewaySelectGroupByMethods<Result, Tables>,
35
+ GatewaySelectOrderByMethods<Result, Tables>,
36
+ GatewaySelectOrderByMethods<Result, Tables>,
37
+ GatewaySelectLimitMethods<Result> {
38
+
39
+ public readonly [SQL_ENTITY]: undefined; // never used
40
+
41
+ private _withQueries: Map<string, string> = new Map()
42
+ private _from: string;
43
+ private readonly _columns: string[] = [];
44
+ private _columnStruct: DbTableDefinition<any> = {} as any;
45
+
46
+ private readonly _joins: string[] = []
47
+ private readonly _windows: string[] = []
48
+ private readonly _where: string[] = []
49
+ private readonly _having: string[] = []
50
+ private readonly _groupBy: string[] = []
51
+ private _orderBy: string[] = []
52
+ private _limit: string = undefined
53
+
54
+ private readonly unions: string[] = []
55
+ private _unionColumnOrder: string[] = []
56
+
57
+ private _distinct: boolean = false;
58
+ private _forUpdate: boolean = false;
59
+
60
+ public readonly transformers: { property: string, transformer: Transformer<any, any> }[] = []
61
+
62
+ public union(table: any | SelectBuilder<any, any, any, any>): SelectBuilder<any, any, any, any> {
63
+ return this._union(table, "DISTINCT") as any
64
+ }
65
+
66
+ public unionAll(table: any | SelectBuilder<any, any, any, any>): SelectBuilder<any, any, any, any> {
67
+ return this._union(table, "ALL")
68
+ }
69
+
70
+ private _union(table: SelectBuilder<any, any, any, any>, type: "ALL" | "DISTINCT" = "DISTINCT"): SelectBuilder<any, any, any, any> {
71
+ if (this.unions.length === 0) {
72
+ const builder = new SelectBuilder()
73
+ builder.unions.push("(\n" + this.toString(1) + ") ")
74
+ builder._columnStruct = this._columnStruct;
75
+ for (const k in this._columnStruct) {
76
+ builder._unionColumnOrder.push(k);
77
+ }
78
+ builder._union(table, type);
79
+ return builder;
80
+ } else {
81
+ const struct = table._columnStruct;
82
+ let i = 0;
83
+ for (const k in struct) {
84
+ if (this._unionColumnOrder[i] !== k) {
85
+ const order: string[] = []
86
+ for (const k in struct) {
87
+ order.push(k);
88
+ }
89
+ throw new Error("Union columns from pos " + i + " do not match! \nFirst call columns: '" + this._unionColumnOrder.join(", ") + "'. \nCurrent call columns: '" + order.join(", ") + "'")
90
+ }
91
+ i++;
92
+ }
93
+ if (i !== this._unionColumnOrder.length) {
94
+ throw new Error("Union columns count do not match! " + this._unionColumnOrder.length + " != " + i + " (Why didn't compiler warn you about this?)");
95
+ }
96
+ this.unions.push("UNION " + (type === "DISTINCT" ? "DISTINCT " : "ALL ") + "(\n" + table.toString(1) + ") ")
97
+ return this;
98
+ }
99
+ }
100
+
101
+ public with(...tables: (any | AnyAliasedTableDef)[]) {
102
+ console.log(tables)
103
+ for (let i = 0; i < tables.length; i++) {
104
+ const table = tables[i];
105
+ const alias = table[SQL_ALIAS]
106
+ this._withQueries.set(alias, escapeId(alias) + " AS " + table[SQL_EXPRESSION])
107
+ }
108
+ return this
109
+ }
110
+
111
+ public uses(table: any | AnyAliasedTableDef) {
112
+ return this
113
+ }
114
+
115
+ public selectFrom(table: any | AnyAliasedTableDef) {
116
+ if (typeof table === "string") {
117
+ this._from = escapeId(table);
118
+ } else {
119
+ this._from = table[SQL_EXPRESSION] + " as " + escapeId(table[SQL_ALIAS]);
120
+ }
121
+
122
+ return this
123
+ }
124
+
125
+ public join(table: any | AnyAliasedTableDef, condition: any) {
126
+ return this._join(table, condition, "JOIN")
127
+ }
128
+
129
+ public leftJoin(table: any | AnyAliasedTableDef, condition: any) {
130
+ return this._join(table, condition, "LEFT JOIN")
131
+ }
132
+
133
+ private _join(table: AnyAliasedTableDef, condition: any, type: "JOIN" | "LEFT JOIN" = "JOIN") {
134
+ const sql = this._withQueries.has(table[SQL_ALIAS]) ? escapeId(table[SQL_ALIAS]) : table[SQL_EXPRESSION] + " as " + escapeId(table[SQL_ALIAS])
135
+ this._joins.push(type + " " + sql + " ON (" + condition.expression + ")")
136
+ return this;
137
+ }
138
+
139
+ public window(name: string, func: (builder: Over<any>) => Over<any>) {
140
+ const builder2 = new Over()
141
+ func(builder2)
142
+ this._windows.push(name + " AS (" + builder2.toString() + ")")
143
+ return this
144
+ }
145
+
146
+ public distinct() {
147
+ this._distinct = true;
148
+ return this
149
+ }
150
+
151
+ public columns(...cols: (any | string | SqlExpression<string, string, any>)[]) {
152
+ for (let i = 0; i < cols.length; i++) {
153
+ const col = cols[i];
154
+ if (col instanceof SqlExpression) {
155
+ this._columns.push(col.expression + (col.nameAs ? " as " + escapeId(col.nameAs) : ""));
156
+ (this._columnStruct as any)[col.nameAs] = true;
157
+ if (col.transformer) {
158
+ this.transformers.push({property: col.nameAs, transformer: col.transformer});
159
+ }
160
+ } else if (typeof col === "string") {
161
+ this._columns.push(escapeId(col));
162
+ (this._columnStruct as any)[col] = true;
163
+ }
164
+ }
165
+ return this
166
+ }
167
+
168
+ public one() {
169
+ this.columns(ONE())
170
+ return this;
171
+ }
172
+
173
+ public allColumnsFrom(table: any | AnyAliasedTableDef) {
174
+ for (const k in table) {
175
+ this.columns(table[k])
176
+ }
177
+ return this
178
+ }
179
+
180
+ public noWhere() {
181
+ return this as any
182
+ }
183
+
184
+ public where(...cols: (any | undefined | null | "" | object | SqlExpression<string, string, any>)[]) {
185
+ for (let i = 0; i < cols.length; i++) {
186
+ const col = cols[i];
187
+ if (col instanceof SqlExpression) {
188
+ this._where.push(col.expression);
189
+ } else if (typeof col === "object") {
190
+ for (const prop in col) {
191
+ this._where.push(escapeId(prop) + " = " + escape(col[prop]));
192
+ }
193
+ } else if (col === undefined || col === null || col === "" || col === false) {
194
+ // skip
195
+ } else {
196
+ throw new Error("Invalid argument to where! Type: '" + (typeof col) + "' String: '" + String(col) + "'")
197
+ }
198
+ }
199
+ return this as any
200
+ }
201
+
202
+ public groupBy(...items: (any | SqlExpression<string, string, any>)[]) {
203
+ for (let i = 0; i < items.length; i++) {
204
+ const item = items[i];
205
+ if (item instanceof SqlExpression) {
206
+ this._groupBy.push(item.expression);
207
+ } else if (typeof item === "string") {
208
+ this._groupBy.push(escapeId(item));
209
+ } else if (item === undefined || item === null || item === "") {
210
+ // skip
211
+ } else {
212
+ throw new Error("Invalid argument to groupBy! Type: '" + (typeof item) + "' String: '" + String(item) + "'")
213
+ }
214
+ }
215
+ return this as any
216
+ }
217
+
218
+ public groupByF(func: (res: any | AliasedTable<string, string, Result, unknown, any>) => (any | SqlExpression<string, string, any>)[]) {
219
+ const proxy: any = new Proxy({}, {
220
+ get(target: {}, p: string, receiver: any): any {
221
+ if (p === "" || p === "undefined") {
222
+ return undefined;
223
+ }
224
+ return new SqlExpression(p, p)
225
+ }
226
+ })
227
+ this.groupBy(...(func(proxy) as any));
228
+ return this as any
229
+ }
230
+
231
+ public having(...items: (any | SqlExpression<string, string, any>)[]) {
232
+ for (let i = 0; i < items.length; i++) {
233
+ const item = items[i];
234
+ if (item instanceof SqlExpression) {
235
+ this._having.push(item.expression);
236
+ } else if (typeof item === "string") {
237
+ this._having.push(escapeId(item));
238
+ } else if (item === undefined || item === null || item === "") {
239
+ // skip
240
+ } else {
241
+ throw new Error("Invalid argument to having! Type: '" + (typeof item) + "' String: '" + String(item) + "'")
242
+ }
243
+ }
244
+ return this as any
245
+ }
246
+
247
+ public havingF(func: (res: any | AliasedTable<string, string, Result, unknown, any>) => (any | SqlExpression<string, string, any>)[]) {
248
+ const proxy: any = new Proxy({}, {
249
+ get(target: {}, p: string, receiver: any): any {
250
+ if (p === "" || p === "undefined") {
251
+ return undefined;
252
+ }
253
+ return new SqlExpression(p, p)
254
+ }
255
+ })
256
+ this.having(...(func(proxy) as any));
257
+ return this
258
+ }
259
+
260
+ public orderBy(...items: (any | SqlExpression<string, string, any>)[]) {
261
+ this._orderBy = orderByStructureToSqlString(items as any)
262
+ return this as any
263
+ }
264
+
265
+ public orderByF(func: (res: any | AliasedTable<string, string, Result, unknown, any>) => (any | SqlExpression<string, string, any>)[]) {
266
+ const proxy: any = new Proxy({}, {
267
+ get(target: {}, p: string, receiver: any): any {
268
+ if (p === "" || p === "undefined") {
269
+ return undefined;
270
+ }
271
+ return new SqlExpression(p, p)
272
+ }
273
+ })
274
+ this.orderBy(...(func(proxy) as any));
275
+ return this
276
+ }
277
+
278
+ public noLimit() {
279
+ return this as any
280
+ }
281
+
282
+ public limit(limit: number | [number, number]) {
283
+ if (Array.isArray(limit)) {
284
+ this._limit = Number(limit[0]) + "," + Number(limit[1]);
285
+ } else if (limit !== undefined && limit !== null && String(limit) !== "") {
286
+ this._limit = String(Number(limit));
287
+ }
288
+ return this as any
289
+ }
290
+
291
+ public limit1() {
292
+ return this.limit(1) as any
293
+ }
294
+
295
+ public forUpdate() {
296
+ this._forUpdate = true;
297
+ return this as any
298
+ }
299
+
300
+ public asScalar(alias: any): any {
301
+ return SqlExpression.create("(\n" + this.toString(2) + TAB + ")", alias);
302
+ }
303
+
304
+ public as(alias: any): any {
305
+ return MysqlTable.defineDbTable("(\n" + this.toString(2) + ")" as "(SUBQUERY)", alias, this._columnStruct)
306
+ }
307
+
308
+ public async transformResult<T>(rows: T[]): Promise<T[]> {
309
+ for (let r = 0; r < rows.length; r++) {
310
+ const row: any = rows[r];
311
+ for (let i = 0; i < this.transformers.length; i++) {
312
+ const parser = this.transformers[i]
313
+ const res = parser.transformer(row[parser.property]);
314
+ if (res instanceof Promise) {
315
+ row[parser.property] = await res;
316
+ } else {
317
+ row[parser.property] = res;
318
+ }
319
+ }
320
+ }
321
+ return rows;
322
+ }
323
+
324
+ public toString(lvl: number = 0) {
325
+ if (this.transformers.length > 0) {
326
+ throw new Error("Select.toString() call might be accidental! This query uses transforms and it may cause errors in the application! " +
327
+ "This is safety measure to avoid executing queries that have transforms that would not get executed! " +
328
+ "You can call toSqlQuery() method to still get a sql string!")
329
+ }
330
+ return this._toString(lvl);
331
+ }
332
+
333
+ public toSqlString() {
334
+ return this._toString();
335
+ }
336
+
337
+ private _toString(lvl: number = 0) {
338
+ const tabs = TAB.repeat(lvl);
339
+ let base: string;
340
+ if (this.unions.length > 0) {
341
+ base = this.unions.join("") + "\n";
342
+ } else {
343
+ base = (this._withQueries.size > 0 ? tabs + "WITH\n" + TAB + Array.from(this._withQueries.values()).join(",\n\n" + TAB) + "\n\n" : "") +
344
+ tabs + "SELECT " + (this._distinct ? "DISTINCT " : "") + "\n" +
345
+ tabs + TAB + this._columns.join(",\n" + tabs + TAB) + "\n" +
346
+ tabs + "FROM " + this._from + "\n" +
347
+ (this._joins.length > 0 ? tabs + this._joins.join("\n") + "\n" : "") +
348
+ (this._where.length > 0 ? tabs + "WHERE " + this._where.join("\n" + TAB + " AND ") + "\n" : "")
349
+ }
350
+
351
+ return base +
352
+ (this._groupBy.length > 0 ? tabs + "GROUP BY " + this._groupBy.join(", ") + "\n" : "") +
353
+ (this._having.length > 0 ? tabs + "HAVING " + this._having.join("\n" + TAB + " AND ") + "\n" : "") +
354
+ (this._windows.length > 0 ? tabs + "WINDOW " + this._windows.join(",\n" + TAB) + "\n" : "") +
355
+ (this._orderBy.length > 0 ? tabs + "ORDER BY " + this._orderBy.join(", ") + "\n" : "") +
356
+ (this._limit ? tabs + "LIMIT " + this._limit + "\n" : "") +
357
+ (this._forUpdate && this.unions.length === 0 ? tabs + "FOR UPDATE\n" : "");
358
+ }
359
+
360
+ public async exec<Args extends any[]>(executor: SelectExecutor<Result, Args>, ...args: Args): Promise<Result[]> {
361
+ const res = await executor(this.toSqlString(), ...args);
362
+ if (res && res.length > 0 && this.transformers.length > 0) {
363
+ await this.transformResult(res)
364
+ }
365
+ return res;
366
+ }
367
+
368
+ public async execOne<Args extends any[]>(executor: SelectExecutor<Result, Args>, ...args: Args): Promise<Result> {
369
+ return (await this.exec(executor, ...args))?.[0]
370
+ }
371
+
372
+ }
@@ -0,0 +1,31 @@
1
+ import {ExecMethods} from "./S7Exec";
2
+ import {OrderByStructure} from "../../Types";
3
+
4
+
5
+ export interface GatewayWhereMethods<Entity, Result> {
6
+
7
+ where(where: Partial<Entity>): GatewaySelectGroupByMethods<Entity, Result> & GatewaySelectOrderByMethods<Entity, Result> & GatewaySelectLimitMethods<Result> & ExecMethods<Result>
8
+
9
+ }
10
+
11
+ export interface GatewaySelectGroupByMethods<Entity, Result> extends GatewaySelectLimitMethods<Result> {
12
+
13
+ groupBy(...fields: (keyof Entity)[]): GatewaySelectOrderByMethods<Entity, Result> & GatewaySelectLimitMethods<Result> & ExecMethods<Result>
14
+
15
+ }
16
+
17
+ export interface GatewaySelectOrderByMethods<Entity, Result> extends GatewaySelectLimitMethods<Result> {
18
+
19
+ orderBy(...fields: OrderByStructure<keyof Entity>): GatewaySelectLimitMethods<Result> & ExecMethods<Result>
20
+
21
+ }
22
+
23
+ export interface GatewaySelectLimitMethods<Result> {
24
+
25
+ noLimit(): ExecMethods<Result>
26
+
27
+ limit(limit: number | [number, number]): ExecMethods<Result>
28
+
29
+ limit1(): ExecMethods<Result>
30
+
31
+ }
@@ -0,0 +1,43 @@
1
+ import {ExecMethods} from "./S7Exec";
2
+ import {GroupByMethods} from "./S3GroupBy";
3
+
4
+ export interface UnionMethods<Result> {
5
+
6
+ union<Exec, MergedResult = Merge<Result, Exec>>(
7
+ table: Check<Result, Exec> & Exec
8
+ ): UnionMethods<MergedResult> & GroupByMethods<MergedResult, {}>
9
+
10
+
11
+ unionAll<Exec, MergedResult = Merge<Result, Exec>>(
12
+ table: Check<Result, Exec> & Exec
13
+ ): UnionMethods<MergedResult> & GroupByMethods<MergedResult, {}>
14
+ }
15
+
16
+ type Check<Result1, Exec> = Exec extends ExecMethods<infer Result2>
17
+ ? Key1Checker<Result1, Result2> extends never
18
+ ? Key2Checker<Result1, Result2> extends never
19
+ ? Exec
20
+ : Key2Checker<Result1, Result2>
21
+ : Key1Checker<Result1, Result2>
22
+ : never
23
+
24
+ type Key1Checker<Result1, Result2> = {
25
+ [K in keyof Result1]: K extends keyof Result2
26
+ ? never
27
+ : `Missing column '${K extends string ? K : "???"}' on added union table! (...,${K extends string ? K : "???"}) UNION (..., ${K extends string ? K : "???"} <- Missing!)
28
+ `
29
+ // Empty line is intentional to have only this message as an Error and no obejct comparison.
30
+ }[keyof Result1]
31
+
32
+ type Key2Checker<Result1, Result2> = {
33
+ [K in keyof Result2]: K extends keyof Result1
34
+ ? never
35
+ : `Column '${K extends string ? K : "???"}' does not exist in previous queries! (...) UNION (...,'${K extends string ? K : "???"}' <--- is a mistake (or add it to previous queries)!)
36
+ `
37
+ // Empty line is intentional to have only this message as an Error and no obejct comparison.
38
+ }[keyof Result2]
39
+
40
+
41
+ type Merge<Result, Exec> = Exec extends ExecMethods<infer Result2> ? {
42
+ [K in keyof Result]: K extends keyof Result2 ? Result[K] | Result2[K] : never
43
+ } : never;
@@ -0,0 +1,21 @@
1
+ import {AliasedTable, Key, NotUsingWithPart} from "../../Types";
2
+ import {JoinMethods} from "./S1Join";
3
+
4
+ export interface UsesMethods<Aliases, Tables> {
5
+
6
+ // uses<
7
+ // Alias extends string,
8
+ // TableRef extends `${string} as ${Alias}`
9
+ // >(
10
+ // table: isAliasAlreadyUsed<Aliases, Alias, AliasedTable<Alias, TableRef, any, NotUsingWithPart>>
11
+ // ): UsesMethods<Aliases & Key<Alias>, Tables & Key<TableRef>>
12
+
13
+
14
+ selectFrom<
15
+ Alias extends string,
16
+ TableRef extends `${string} as ${Alias}`
17
+ >(
18
+ table: AliasedTable<Alias, TableRef, object, object, string | NotUsingWithPart>
19
+ ): JoinMethods<Aliases & Key<Alias>, {}, Tables & Key<TableRef>>
20
+
21
+ }
@@ -0,0 +1,21 @@
1
+ import {AliasedTable, Key, NotUsingWithPart} from "../../Types";
2
+ import {JoinMethods} from "./S1Join";
3
+
4
+ export interface WithMethods<AliasesFromWith> {
5
+
6
+ // with<
7
+ // Alias extends string,
8
+ // TableRef extends `${string} as ${Alias}`
9
+ // >(
10
+ // table: isAliasAlreadyUsed<AliasesFromWith, Alias, AliasedTable<Alias, TableRef, object, NotUsingWithPart>>
11
+ // ): WithMethods<AliasesFromWith & Key<Alias>>
12
+
13
+ selectFrom<
14
+ Alias extends string,
15
+ TableRef extends `${string} as ${Alias}`
16
+ >(
17
+ table: AliasedTable<Alias, TableRef, object, object, string | NotUsingWithPart>
18
+ ): JoinMethods<Key<Alias>, AliasesFromWith, Key<TableRef>>
19
+
20
+ }
21
+
@@ -0,0 +1,39 @@
1
+ import {AliasedTable, isAliasAlreadyUsed, isTableReferenced, Key, NotUsingWithPart, SQL_BOOL} from "../../Types";
2
+ import {Expr, Over} from "../../SqlExpression";
3
+ import {ColumnsMethods} from "./S2Columns";
4
+
5
+ export interface JoinMethods<Aliases, AliasesFromWith, Tables> extends ColumnsMethods<{}, Tables> {
6
+
7
+ join<
8
+ Alias extends string,
9
+ TableRef extends `${string} as ${Alias}`,
10
+ RefAlias extends NotUsingWithPart | string,
11
+ ColTableRef extends string
12
+ >(
13
+ table: isRefAliasInAliasesFromWith<AliasesFromWith, RefAlias, isAliasAlreadyUsed<Aliases & AliasesFromWith, Alias, AliasedTable<Alias, TableRef, object, object, RefAlias>>>,
14
+ condition: isConditionUsingJoinedTable<TableRef, ColTableRef, isTableReferenced<Tables & Key<TableRef>, Key<ColTableRef>, Expr<ColTableRef, unknown, SQL_BOOL>>>
15
+ ): JoinMethods<Aliases & Key<Alias>, AliasesFromWith, Tables & Key<TableRef>>
16
+
17
+ leftJoin<
18
+ Alias extends string,
19
+ TableRef extends `${string} as ${Alias}`,
20
+ RefAlias extends NotUsingWithPart | string,
21
+ ColTableRef extends string
22
+ >(
23
+ table: isRefAliasInAliasesFromWith<AliasesFromWith, RefAlias, isAliasAlreadyUsed<Aliases & AliasesFromWith, Alias, AliasedTable<Alias, TableRef, object, object, RefAlias>>>,
24
+ condition: isConditionUsingJoinedTable<TableRef, ColTableRef, isTableReferenced<Tables & Key<TableRef>, Key<ColTableRef>, Expr<ColTableRef, unknown, SQL_BOOL>>>
25
+ ): JoinMethods<Aliases & Key<Alias>, AliasesFromWith, Tables & Key<TableRef>>
26
+
27
+ window<
28
+ WindowName extends string,
29
+ UsedTablesRef extends string
30
+ >(
31
+ name: isAliasAlreadyUsed<Aliases & AliasesFromWith, WindowName, WindowName>,
32
+ func: (builder: Over<never>) => Over<UsedTablesRef>
33
+ ): JoinMethods<Aliases & Key<WindowName>, AliasesFromWith, Tables & Key<`(window) as ${WindowName}`>>
34
+
35
+ }
36
+
37
+ type isConditionUsingJoinedTable<TableRef, ColTableRef, OUT> = TableRef extends ColTableRef ? OUT : "Join condition should use columns from the joined table!"
38
+
39
+ type isRefAliasInAliasesFromWith<AliasesFromWith, RefAlias, OUT> = RefAlias extends NotUsingWithPart | string & keyof AliasesFromWith ? OUT : `Alias '${RefAlias extends string ? RefAlias : RefAlias extends NotUsingWithPart ? "NOT_REFERENCED" : "???"}' is not defined by any of the with queries!`
@@ -0,0 +1,68 @@
1
+ import {WhereMethods} from "./S2Where";
2
+ import {Expr} from "../../SqlExpression";
3
+ import {AliasedTable, NotUsingWithPart} from "../../Types";
4
+
5
+ export interface ColumnsMethods<Result, Tables> {
6
+
7
+ distinct(): ColumnsMethods<Result, Tables>
8
+
9
+ allColumnsFrom<TableRef, Entity, Result2 = Result & Entity>(table: AliasedTable<string, TableRef, Entity, any, NotUsingWithPart>): ColumnsMethods<Result2, Tables> & WhereMethods<Result2, Tables>
10
+
11
+ one(): WhereMethods<Result & { one: 1 }, Tables>
12
+
13
+ columns<
14
+ TableRef,
15
+ Columns extends Expr<TableRef, string, any>[]
16
+ >(
17
+ //...columns: Columns - this will enable seeing sources of Result object properties.
18
+ ...columns: isColumnOkToAdd<Result, Tables, Columns>
19
+ ): WhereMethods<Result & ExtractObj<Columns>, Tables>
20
+
21
+ }
22
+
23
+ // --------------------------------------------------------------------
24
+
25
+ /**
26
+ * Take array of Col-s and convert to Record<key, value> & ... object.
27
+ */
28
+ export type ExtractObj<Columns extends Expr<any, string, any>[]> = {
29
+ [K in Columns[number]['nameAs']]: Extract<Columns[number], { nameAs: K }>['type']
30
+ }
31
+
32
+
33
+ // --------------------------------------------------------------------
34
+
35
+ type _checkIfExistsInOtherFields<Rest extends any[], Expr> =
36
+ Rest extends []
37
+ ? Expr
38
+ : Expr extends { nameAs: string } ?
39
+ Expr["nameAs"] extends (Rest extends { nameAs: infer A }[] ? A : never)
40
+ ? `'${Expr["nameAs"]}' already exists in columns!`
41
+ : Expr
42
+ : Expr extends { nameAs: unknown } ?
43
+ `Is missing column name. Add .as('name')`
44
+ : Expr
45
+
46
+ type _checkIfExistsInResult<Result, Expr> =
47
+ Expr extends { nameAs: string } ?
48
+ Expr["nameAs"] extends keyof Result
49
+ ? `'${Expr["nameAs"]}' already exists in result columns!`
50
+ : Expr
51
+ : Expr
52
+
53
+ type _checkThatTableIsReferenced<Tables, Expr> =
54
+ Expr extends { tableRef: string } ?
55
+ Expr["tableRef"] extends keyof Tables
56
+ ? Expr
57
+ : `'${Expr["tableRef"]}' is not used in this query!`
58
+ : Expr
59
+
60
+ type isColumnOkToAdd<Result, Tables, ColumnExpressions> =
61
+ ColumnExpressions extends []
62
+ ? ColumnExpressions
63
+ : ColumnExpressions extends [...(infer Rest), infer A]
64
+ ? [...isColumnOkToAdd<Result, Tables, Rest>, _checkIfExistsInOtherFields<Rest, _checkIfExistsInResult<Result, _checkThatTableIsReferenced<Tables, A>>>]
65
+ : ColumnExpressions;
66
+
67
+
68
+ // --------------------------------------------------------------------
@@ -0,0 +1,51 @@
1
+ import {isTableReferenced, Key, SQL_BOOL} from "../../Types";
2
+ import {GroupByMethods} from "./S3GroupBy";
3
+ import {Expr} from "../../SqlExpression";
4
+ import {OrderByMethods} from "./S5OrderBy";
5
+ import {LimitMethods} from "./S6Limit";
6
+ import {ExecMethods} from "./S7Exec";
7
+
8
+ export interface WhereMethods<Result, Tables> {
9
+
10
+ noWhere(): GroupByMethods<Result, Tables> & OrderByMethods<Result, Tables> & LimitMethods<Result> & ExecMethods<Result>
11
+
12
+ where<
13
+ T1 extends string,
14
+ T2 extends string = never,
15
+ T3 extends string = never,
16
+ T4 extends string = never,
17
+ T5 extends string = never,
18
+ T6 extends string = never,
19
+ T7 extends string = never,
20
+ T8 extends string = never,
21
+ T9 extends string = never,
22
+ T10 extends string = never,
23
+ T11 extends string = never,
24
+ T12 extends string = never,
25
+ T13 extends string = never,
26
+ T14 extends string = never,
27
+ T15 extends string = never,
28
+ T = Tables
29
+ >(
30
+ c1: C<T, T1>,
31
+ c2?: C<T, T2>,
32
+ c3?: C<T, T3>,
33
+ c4?: C<T, T4>,
34
+ c5?: C<T, T5>,
35
+ c6?: C<T, T6>,
36
+ c7?: C<T, T7>,
37
+ c8?: C<T, T8>,
38
+ c9?: C<T, T9>,
39
+ c10?: C<T, T10>,
40
+ c11?: C<T, T11>,
41
+ c12?: C<T, T12>,
42
+ c13?: C<T, T13>,
43
+ c14?: C<T, T14>,
44
+ c15?: C<T, T15>,
45
+ ): GroupByMethods<Result, Tables> & OrderByMethods<Result, Tables> & LimitMethods<Result> & ExecMethods<Result>
46
+
47
+ }
48
+
49
+ type C<Tables, T extends string> = isTableReferenced<Tables, Key<T>, Expr<T, unknown, SQL_BOOL>>
50
+
51
+
@@ -0,0 +1,23 @@
1
+ import {AliasedTable, isColumnOkToUse, Key, NotUsingWithPart} from "../../Types";
2
+ import {HavingMethods} from "./S4Having";
3
+ import {Expr} from "../../SqlExpression";
4
+ import {OrderByMethods} from "./S5OrderBy";
5
+ import {LimitMethods} from "./S6Limit";
6
+
7
+ export interface GroupByMethods<Result, Tables> extends OrderByMethods<Result, Tables>, LimitMethods<Result> {
8
+ groupBy<
9
+ TableRef,
10
+ Columns extends Expr<TableRef, string | unknown, any>[]
11
+ >(
12
+ ...items: isColumnOkToUse<Tables, Columns>
13
+ ): HavingMethods<Result, Tables>
14
+
15
+ groupByF<
16
+ TableRef,
17
+ Columns extends Expr<TableRef, string | unknown, any>[]
18
+ >(
19
+ func: (columnsTable: AliasedTable<"(columns)", "(columns)", Result, object, NotUsingWithPart>) => isColumnOkToUse<Tables & Key<"(columns)">, Columns>
20
+ ): HavingMethods<Result, Tables>
21
+ }
22
+
23
+