@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,283 @@
1
+ import {escape} from "./escape";
2
+
3
+ export class MysqlTableStructureParser {
4
+
5
+ public static getSchemaRowsQuery(database: string): string {
6
+ return "SELECT " +
7
+ " table_schema as tableSchema, \n" +
8
+ " table_name as tableName, \n" +
9
+ " is_nullable as isNullable, \n" +
10
+ " column_default as columnDefault, \n" +
11
+ " column_name as columnName, \n" +
12
+ " collation_name as collationName, \n" +
13
+ " column_type as columnType, \n" +
14
+ " column_key as columnKey, \n" +
15
+ " ordinal_position as ordinalPosition, \n" +
16
+ " character_octet_length as characterOctetLength, \n" +
17
+ " numeric_precision as numericPrecision, \n" +
18
+ " numeric_scale as numericScale, \n" +
19
+ " data_type as dataType, \n" +
20
+ " character_maximum_length as characterMaximumLength, \n" +
21
+ " datetime_precision as datetimePrecision, \n" +
22
+ " character_set_name as characterSetName, \n" +
23
+ " extra as extra, \n" +
24
+ " column_comment as columnComment \n" +
25
+ "FROM INFORMATION_SCHEMA.columns \n" +
26
+ "WHERE table_schema LIKE " + escape(database) + " " +
27
+ "ORDER BY table_schema, table_name, ordinal_position ";
28
+ }
29
+
30
+ public static parse(schema: SchemaRow[]): TableStructure[] {
31
+ const tables: Map<string, TableStructure> = new Map()
32
+ for (const row of schema) {
33
+ if (!tables.has(row.tableName)) {
34
+ tables.set(row.tableName, {name: row.tableName, columns: []})
35
+ }
36
+ tables.get(row.tableName).columns.push(this.parseColumn(row));
37
+ }
38
+ return Array.from(tables.values()).sort((a, b) => a.name >= b.name ? 1 : -1);
39
+ }
40
+
41
+ private static parseColumn(row: SchemaRow): AnyColumn {
42
+ const type = row.dataType.toUpperCase() as ColumnDataType;
43
+ const column: Column = {
44
+ type: type,
45
+ name: row.columnName,
46
+ dataType: row.dataType.toUpperCase(),
47
+ columnType: row.columnType,
48
+ tsType: MYSQL_TYPE_TO_TS_TYPE.get(type),
49
+ isNullable: row.isNullable.toUpperCase().indexOf("YES") >= 0,
50
+ default: this.parseDefault(row.columnDefault),
51
+ columnKey: this.parseColumnKey(row.columnKey),
52
+ extra: row.extra,
53
+ comment: row.columnComment
54
+ };
55
+ if (type === ColumnDataType.MEDIUMTEXT || type === ColumnDataType.TEXT || type === ColumnDataType.LONGTEXT) {
56
+ const res: ColumnText = {
57
+ ...column,
58
+ type: type,
59
+ characterSetName: row.characterSetName,
60
+ collationName: row.collationName
61
+ }
62
+ return res;
63
+
64
+ } else if (type === ColumnDataType.CHAR || type === ColumnDataType.VARCHAR) {
65
+ const res: ColumnChar = {
66
+ ...column,
67
+ type: type,
68
+ characterSetName: row.characterSetName,
69
+ collationName: row.collationName,
70
+ characterMaximumLength: row.characterMaxLength,
71
+ characterOctetLength: row.characterOctetLength
72
+ }
73
+ return res;
74
+
75
+ } else if (type === ColumnDataType.TINYINT || type === ColumnDataType.SMALLINT || type === ColumnDataType.INT || type === ColumnDataType.MEDIUMINT
76
+ || type === ColumnDataType.BIGINT || type === ColumnDataType.DECIMAL || type === ColumnDataType.FLOAT || type === ColumnDataType.BIT) {
77
+ const typeNum = Number(row.columnType.split("(").pop().split(")").shift());
78
+ const res: ColumnNumber = {
79
+ ...column,
80
+ type: type,
81
+ typeNum: isNaN(typeNum) ? undefined : typeNum,
82
+ scale: row.numericScale,
83
+ precision: row.numericPos,
84
+ isUnsigned: row.columnType.toUpperCase().indexOf("UNSIGNED") >= 0,
85
+ isAutoIncrement: row.extra.toUpperCase().indexOf("AUTO_INCREMENT") >= 0
86
+ }
87
+ return res;
88
+
89
+ } else if (type === ColumnDataType.ENUM) {
90
+ const res: ColumnEnum = {
91
+ ...column,
92
+ type: type,
93
+ values: row.columnType.match(/'([^']+)'/g).map(e => e.replace(/'/g, "").replace(/"/g, ""))
94
+ }
95
+ return res;
96
+ } else if (type === ColumnDataType.SET) {
97
+ const res: ColumnSet = {
98
+ ...column,
99
+ type: type,
100
+ values: row.columnType.match(/'([^']+)'/g).map(e => e.replace(/'/g, "").replace(/"/g, ""))
101
+ }
102
+ return res;
103
+ } else {
104
+ return column as AnyColumn;
105
+ }
106
+ }
107
+
108
+ private static parseDefault(def: string): string | number {
109
+ if (!def || def === "NULL") {
110
+ return null;
111
+ } else if (!isNaN(Number(def))) {
112
+ return def;
113
+ } else {
114
+ return String(def).split("'").join("");
115
+ }
116
+ }
117
+
118
+ private static parseColumnKey(columnKey: string): KeyType[] {
119
+ return columnKey.split(",").map((e) => {
120
+ const key = e.toUpperCase();
121
+ if (key === "PRI") {
122
+ return KeyType.PRIMARY
123
+ } else if (key === "UNI") {
124
+ return KeyType.UNIQUE
125
+ } else if (key === "MUL") {
126
+ return KeyType.MULTIPLE
127
+ } else {
128
+ return null;
129
+ }
130
+ }).filter(e => e);
131
+ }
132
+ }
133
+
134
+ export interface TableStructure {
135
+ name: string;
136
+ columns: AnyColumn[];
137
+ }
138
+
139
+ export enum ColumnDataType {
140
+ TINYINT = "TINYINT",
141
+ SMALLINT = "SMALLINT",
142
+ MEDIUMINT = "MEDIUMINT",
143
+ INT = "INT",
144
+ BIGINT = "BIGINT",
145
+ DECIMAL = "DECIMAL",
146
+ FLOAT = "FLOAT",
147
+ CHAR = "CHAR",
148
+ VARCHAR = "VARCHAR",
149
+ MEDIUMTEXT = "MEDIUMTEXT",
150
+ TEXT = "TEXT",
151
+ LONGTEXT = "LONGTEXT",
152
+ TIMESTAMP = "TIMESTAMP",
153
+ DATETIME = "DATETIME",
154
+ DATE = "DATE",
155
+ TIME = "TIME",
156
+ YEAR = "YEAR",
157
+ ENUM = "ENUM",
158
+ SET = "SET",
159
+ BIT = "BIT",
160
+ LONGBLOB = "LONGBLOB",
161
+ JSON = "JSON"
162
+ }
163
+
164
+ const MYSQL_TYPE_TO_TS_TYPE: Map<ColumnDataType, string> = new Map([
165
+ [ColumnDataType.TINYINT, "number"],
166
+ [ColumnDataType.SMALLINT, "number"],
167
+ [ColumnDataType.MEDIUMINT, "number"],
168
+ [ColumnDataType.INT, "number"],
169
+ [ColumnDataType.BIGINT, "number"],
170
+ [ColumnDataType.DECIMAL, "number"],
171
+ [ColumnDataType.FLOAT, "number"],
172
+ [ColumnDataType.CHAR, "string"],
173
+ [ColumnDataType.VARCHAR, "string"],
174
+ [ColumnDataType.MEDIUMTEXT, "string"],
175
+ [ColumnDataType.TEXT, "string"],
176
+ [ColumnDataType.LONGTEXT, "string"],
177
+ [ColumnDataType.TIMESTAMP, "string"],
178
+ [ColumnDataType.DATETIME, "string"],
179
+ [ColumnDataType.DATE, "string"],
180
+ [ColumnDataType.TIME, "number"],
181
+ [ColumnDataType.YEAR, "number"],
182
+ [ColumnDataType.ENUM, "string"],
183
+ [ColumnDataType.SET, "string"],
184
+ [ColumnDataType.BIT, "number"],
185
+ [ColumnDataType.LONGBLOB, "string"],
186
+ [ColumnDataType.JSON, "string"]
187
+ ])
188
+
189
+
190
+ export type AnyColumn = ColumnText | ColumnChar | ColumnNumber | ColumnSet | ColumnEnum | ColumnDateTimeLike
191
+
192
+ export interface Column {
193
+ type: ColumnDataType;
194
+ name: string;
195
+ tsType: string;
196
+ dataType: string // Type like INT
197
+ columnType: string; // Type like INT(11)
198
+ typeNum?: number | undefined // for INT(11), this would be 11
199
+ default: string | number;
200
+ isNullable: boolean;
201
+ columnKey: KeyType[];
202
+ extra: string;
203
+ comment: string;
204
+ }
205
+
206
+ export interface ColumnDateTimeLike extends Column {
207
+ type: ColumnDataType.DATE |
208
+ ColumnDataType.DATETIME |
209
+ ColumnDataType.TIMESTAMP |
210
+ ColumnDataType.YEAR
211
+ }
212
+
213
+ export interface ColumnText extends Column {
214
+ type: ColumnDataType.CHAR |
215
+ ColumnDataType.VARCHAR |
216
+ ColumnDataType.MEDIUMTEXT |
217
+ ColumnDataType.TEXT |
218
+ ColumnDataType.LONGTEXT;
219
+ characterSetName: string;
220
+ collationName: string;
221
+ }
222
+
223
+ export interface ColumnChar extends ColumnText {
224
+ type: ColumnDataType.VARCHAR |
225
+ ColumnDataType.CHAR;
226
+ characterMaximumLength: number;
227
+ characterOctetLength: number;
228
+ }
229
+
230
+ export interface ColumnNumber extends Column {
231
+ type:
232
+ ColumnDataType.TINYINT |
233
+ ColumnDataType.SMALLINT |
234
+ ColumnDataType.MEDIUMINT |
235
+ ColumnDataType.INT |
236
+ ColumnDataType.BIGINT |
237
+ ColumnDataType.DECIMAL |
238
+ ColumnDataType.FLOAT |
239
+ ColumnDataType.BIT
240
+ isUnsigned: boolean;
241
+ isAutoIncrement: boolean;
242
+ precision: number;
243
+ scale: number;
244
+ }
245
+
246
+ export interface ColumnEnum extends Column {
247
+ type: ColumnDataType.ENUM;
248
+ values: string[];
249
+ }
250
+
251
+ export interface ColumnSet extends Column {
252
+ type: ColumnDataType.SET;
253
+ values: string[];
254
+ }
255
+
256
+ export enum KeyType {
257
+ PRIMARY = "primary",
258
+ UNIQUE = "unique",
259
+ MULTIPLE = "multiple"
260
+ }
261
+
262
+ interface SchemaRow {
263
+ tableSchema: string;
264
+ tableName: string;
265
+ columnName: string;
266
+ ordinalPosition: number;
267
+ columnDefault: string;
268
+ isNullable: string;
269
+ dataType: string;
270
+ characterMaxLength: number;
271
+ characterOctetLength: number;
272
+ numericPos: number;
273
+ numericScale: number;
274
+ dateTimePrecision: number;
275
+ characterSetName: string;
276
+ collationName: string;
277
+ columnType: string;
278
+ columnKey: string;
279
+ extra: string;
280
+ columnComment: string;
281
+ isGenerated: string;
282
+ generationExpression: string;
283
+ }
package/src/SQL.ts ADDED
@@ -0,0 +1,244 @@
1
+ import {SelectBuilder} from "./select/SelectBuilder";
2
+ import {AliasedTable, DbTableDefinition, Key, NotUsingWithPart, PrepareQueryArgument, SqlQuery} from "./Types";
3
+ import {SQL_ALIAS, SQL_ENTITY, SQL_EXPRESSION} from "./Symbols";
4
+ import {escape, escapeId} from "./escape";
5
+ import {MysqlTable} from "./MysqlTable";
6
+ import {JoinMethods} from "./select/parts/S1Join";
7
+ import {UsesMethods} from "./select/parts/S0Uses";
8
+ import {WithMethods} from "./select/parts/S0With";
9
+ import {ExecMethods} from "./select/parts/S7Exec";
10
+ import {DeleteBuilder} from "./delete/DeleteBuilder";
11
+ import {DeleteWhereMethods} from "./delete/DeleteInterfaces";
12
+ import {InsertBuilder} from "./insert/InsertBuilder";
13
+ import {InsertSetMethods} from "./insert/InsertInterfaces";
14
+ import {UpdateSetMethods} from "./update/UpdateInterfaces";
15
+ import {UpdateBuilder} from "./update/UpdateBuilder";
16
+
17
+ export class SQL {
18
+
19
+
20
+ public static insertInto<
21
+ Entity,
22
+ EditEntity,
23
+ Alias extends string,
24
+ TableRef extends `${string} as ${Alias}`,
25
+ >(
26
+ table: AliasedTable<Alias, TableRef, Entity, EditEntity, NotUsingWithPart>): InsertSetMethods<EditEntity> {
27
+ return new InsertBuilder().to(table[SQL_EXPRESSION]);
28
+ }
29
+
30
+ public static insertIgnoreInto<
31
+ Entity,
32
+ EditEntity,
33
+ Alias extends string,
34
+ TableRef extends `${string} as ${Alias}`,
35
+ >(
36
+ table: AliasedTable<Alias, TableRef, Entity, EditEntity, NotUsingWithPart>
37
+ ): InsertSetMethods<EditEntity> {
38
+ return new InsertBuilder().to(table[SQL_EXPRESSION]).ignore();
39
+ }
40
+
41
+ public static update<
42
+ Entity,
43
+ EditEntity,
44
+ Alias extends string,
45
+ TableRef extends `${string} as ${Alias}`,
46
+ >(
47
+ table: AliasedTable<Alias, TableRef, Entity, EditEntity, NotUsingWithPart>
48
+ ): UpdateSetMethods<Entity, Key<TableRef>> {
49
+ return new UpdateBuilder().in(table[SQL_EXPRESSION], table[SQL_ALIAS]);
50
+ }
51
+
52
+ public static updateIgnore<
53
+ Entity,
54
+ EditEntity,
55
+ Alias extends string,
56
+ TableRef extends `${string} as ${Alias}`,
57
+ >(
58
+ table: AliasedTable<Alias, TableRef, Entity, EditEntity, NotUsingWithPart>
59
+ ): UpdateSetMethods<Entity, Key<TableRef>> {
60
+ return new UpdateBuilder().in(table[SQL_EXPRESSION], table[SQL_ALIAS]).ignore()
61
+ }
62
+
63
+ public static deleteFrom<
64
+ Alias extends string,
65
+ TableRef extends `${string} as ${Alias}`,
66
+ >(
67
+ table: AliasedTable<Alias, TableRef, object, object, string | NotUsingWithPart>
68
+ ): DeleteWhereMethods<Key<TableRef>> {
69
+ return new DeleteBuilder().from(table[SQL_EXPRESSION], table[SQL_ALIAS]);
70
+ }
71
+
72
+ public static selectFrom<
73
+ Alias extends string,
74
+ TableRef extends `${string} as ${Alias}`
75
+ >(
76
+ table: AliasedTable<Alias, TableRef, object, object, string | NotUsingWithPart>
77
+ ): JoinMethods<Key<Alias>, {}, Key<TableRef>> {
78
+ return new SelectBuilder().selectFrom(table)
79
+ }
80
+
81
+ /**
82
+ * Start building a select query that most probably will be used as a scalar subquery.
83
+ *
84
+ * for example:
85
+ * SELECT
86
+ * (SELECT id FROM child WHERE child.id = parent.id ) <--- scalar subquery
87
+ * FROM parent
88
+ *
89
+ * In the uses part you add parent table refererence.
90
+ */
91
+ public static uses<
92
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
93
+ >(
94
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>
95
+ ): UsesMethods<Key<Alias1>, Key<TableRef1>>
96
+ public static uses<
97
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
98
+ Alias2 extends string, TableRef2 extends `${string} as ${Alias2}`,
99
+ >(
100
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>,
101
+ table2: AliasedTable<Alias2, TableRef2, object, object, NotUsingWithPart>,
102
+ ): UsesMethods<Key<Alias1> & Key<Alias2>, Key<TableRef1> & Key<TableRef2>>
103
+ public static uses<
104
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
105
+ Alias2 extends string, TableRef2 extends `${string} as ${Alias2}`,
106
+ Alias3 extends string, TableRef3 extends `${string} as ${Alias3}`
107
+ >(
108
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>,
109
+ table2: AliasedTable<Alias2, TableRef2, object, object, NotUsingWithPart>,
110
+ table3: AliasedTable<Alias3, TableRef3, object, object, NotUsingWithPart>,
111
+ ): UsesMethods<Key<Alias1> & Key<Alias2> & Key<Alias3>, Key<TableRef1> & Key<TableRef2> & Key<TableRef3>>
112
+ public static uses<
113
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
114
+ Alias2 extends string, TableRef2 extends `${string} as ${Alias2}`,
115
+ Alias3 extends string, TableRef3 extends `${string} as ${Alias3}`,
116
+ Alias4 extends string, TableRef4 extends `${string} as ${Alias4}`,
117
+ >(
118
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>,
119
+ table2: AliasedTable<Alias2, TableRef2, object, object, NotUsingWithPart>,
120
+ table3: AliasedTable<Alias3, TableRef3, object, object, NotUsingWithPart>,
121
+ table4: AliasedTable<Alias4, TableRef4, object, object, NotUsingWithPart>,
122
+ ): UsesMethods<Key<Alias1> & Key<Alias2> & Key<Alias3> & Key<Alias4>, Key<TableRef1> & Key<TableRef2> & Key<TableRef3> & Key<TableRef4>>
123
+ public static uses(table1: any, table2?: any, table3?: any, table4?: any) {
124
+ return new SelectBuilder();
125
+ }
126
+
127
+ /**
128
+ * Start building a select query that uses WITH queries.
129
+ *
130
+ * for example:
131
+ * WITH user2 AS (
132
+ * SELECT id FROM user <-- this query AliasedTable is argument to this method. ( SQL.select()...as("user2") )
133
+ * )
134
+ * SELECT *
135
+ * FROM user2
136
+ *
137
+ * With a
138
+ */
139
+ public static with<
140
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
141
+ >(
142
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>
143
+ ): WithMethods<Key<Alias1>>
144
+ public static with<
145
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
146
+ Alias2 extends string, TableRef2 extends `${string} as ${Alias2}`,
147
+ >(
148
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>,
149
+ table2: AliasedTable<Alias2, TableRef2, object, object, NotUsingWithPart>,
150
+ ): WithMethods<Key<Alias1> & Key<Alias2>>
151
+ public static with<
152
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
153
+ Alias2 extends string, TableRef2 extends `${string} as ${Alias2}`,
154
+ Alias3 extends string, TableRef3 extends `${string} as ${Alias3}`
155
+ >(
156
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>,
157
+ table2: AliasedTable<Alias2, TableRef2, object, object, NotUsingWithPart>,
158
+ table3: AliasedTable<Alias3, TableRef3, object, object, NotUsingWithPart>,
159
+ ): WithMethods<Key<Alias1> & Key<Alias2> & Key<Alias3>>
160
+ public static with<
161
+ Alias1 extends string, TableRef1 extends `${string} as ${Alias1}`,
162
+ Alias2 extends string, TableRef2 extends `${string} as ${Alias2}`,
163
+ Alias3 extends string, TableRef3 extends `${string} as ${Alias3}`,
164
+ Alias4 extends string, TableRef4 extends `${string} as ${Alias4}`,
165
+ >(
166
+ table1: AliasedTable<Alias1, TableRef1, object, object, NotUsingWithPart>,
167
+ table2: AliasedTable<Alias2, TableRef2, object, object, NotUsingWithPart>,
168
+ table3: AliasedTable<Alias3, TableRef3, object, object, NotUsingWithPart>,
169
+ table4: AliasedTable<Alias4, TableRef4, object, object, NotUsingWithPart>,
170
+ ): WithMethods<Key<Alias1> & Key<Alias2> & Key<Alias3> & Key<Alias4>>
171
+ public static with(...tables: any[]) {
172
+ return new SelectBuilder().with(...tables);
173
+ }
174
+
175
+ /**
176
+ * Creates a prepared query.
177
+ *
178
+ * Prepared query is a fixed query that will be prebuilt for higher performance. It will only replace arguments in a prebuilt SQL query string.
179
+ * Main drawback of this is that query has to be static and can't have anything dynamic in it.
180
+ *
181
+ * This is not Mysql prepared statement, it is only preparing and caching a string of the SQL query.
182
+ *
183
+ * Usage
184
+ *
185
+ * const prepared = SQL.prepare( ( args:{id: number} ) => {
186
+ * const c = MyDb.user("c");
187
+ * return SQL.select().from(c)...where( c.id.eq(args.id).noLimit()
188
+ * })
189
+ *
190
+ * exec(prepared({id: 10}))
191
+ *
192
+ */
193
+ public static prepare<PrepareQueryArguments extends { [key: string]: any }, Result>(func: (args: PrepareQueryArguments) => ExecMethods<Result>): (args: PrepareQueryArguments) => SqlQuery<Result> {
194
+ let sqlQuery: string = undefined;
195
+ const seenArguments: Map<string, string> = new Map();
196
+ const getSqlString = () => {
197
+ if (sqlQuery === undefined) {
198
+ const p: PrepareQueryArguments = new Proxy({}, {
199
+ get(_: {}, p: string): PrepareQueryArgument {
200
+ if (!/^[A-Za-z]+$/.test(p)) {
201
+ throw new Error("Invalid prepare query argument named '" + p + "'. Can only contain ascii letters!")
202
+ }
203
+ const variable = "<<|_arg:|>>" + p + "<<|:_arg|>>";
204
+ seenArguments.set(p, variable);
205
+ return {__prepare_argument: true, expression: variable};
206
+ }
207
+ }) as any
208
+ sqlQuery = func(p).toSqlString();
209
+ }
210
+ return sqlQuery;
211
+ }
212
+ return (args: PrepareQueryArguments) => {
213
+ return {
214
+ [SQL_ENTITY]: undefined,
215
+ toSqlString: (): string => {
216
+ let usedQuery = getSqlString();
217
+ seenArguments.forEach((variable, key) => {
218
+ usedQuery = usedQuery.replace(variable, escape(args[key]));
219
+ })
220
+ return usedQuery
221
+ },
222
+ }
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Create a reference for a query that is used in WITH part and you want to use it in from(X) or join(X) call.
228
+ */
229
+ public static createRef<
230
+ Alias extends string,
231
+ TableRef extends `${string} as ${Alias}`,
232
+ Entity,
233
+ EditEntity,
234
+ NewAlias extends string
235
+ >(table: AliasedTable<Alias, TableRef, Entity, EditEntity, NotUsingWithPart>, newAlias: NewAlias): AliasedTable<NewAlias, `${Alias} as ${NewAlias}`, Entity, EditEntity, Alias> {
236
+ const definition: DbTableDefinition<Entity> = {} as any;
237
+ for (const k in table) {
238
+ (definition as any)[k] = (table as any)[k];
239
+ }
240
+ return MysqlTable.defineDbTable(escapeId(table[SQL_ALIAS]), newAlias, definition) as any;
241
+ }
242
+
243
+ }
244
+