@grest-ts/sql 0.0.6 → 0.0.7
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.
- package/LICENSE +21 -21
- package/README.md +498 -498
- package/dist/src/select/parts/S0Union.d.ts +2 -2
- package/dist/tsconfig.publish.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/MysqlTable.ts +101 -101
- package/src/MysqlTableStructureParser.ts +283 -283
- package/src/SQL.ts +244 -244
- package/src/SqlExpression.ts +172 -172
- package/src/SqlFunctions.ts +471 -471
- package/src/Symbols.ts +10 -10
- package/src/Types.ts +244 -244
- package/src/delete/DeleteBuilder.ts +64 -64
- package/src/delete/DeleteInterfaces.ts +70 -70
- package/src/escape.ts +51 -51
- package/src/index.ts +5 -5
- package/src/insert/InsertBuilder.ts +75 -75
- package/src/insert/InsertInterfaces.ts +16 -16
- package/src/select/SelectBuilder.ts +371 -371
- package/src/select/parts/GatewayWhere.ts +30 -30
- package/src/select/parts/S0Union.ts +43 -43
- package/src/select/parts/S0Uses.ts +21 -21
- package/src/select/parts/S0With.ts +21 -21
- package/src/select/parts/S1Join.ts +38 -38
- package/src/select/parts/S2Columns.ts +68 -68
- package/src/select/parts/S2Where.ts +51 -51
- package/src/select/parts/S3GroupBy.ts +23 -23
- package/src/select/parts/S4Having.ts +24 -24
- package/src/select/parts/S5OrderBy.ts +21 -21
- package/src/select/parts/S6Limit.ts +9 -9
- package/src/select/parts/S7Exec.ts +41 -41
- package/src/update/UpdateBuilder.ts +95 -95
- package/src/update/UpdateInterfaces.ts +87 -87
package/src/SqlFunctions.ts
CHANGED
|
@@ -1,471 +1,471 @@
|
|
|
1
|
-
import {COMPARISON_SIGNS, ComparisonOperandsLookup, DATE_ADD_UNITS, DateAddUnitsLookup, isPrepareArgument, OrderByStructure, PrepareQueryArgument, SQL_BOOL} from "./Types";
|
|
2
|
-
import {AnyBoolExpr, AnyExpr, Expr, ExprWithOver, SqlExpression, SqlExpressionWithOver} from "./SqlExpression";
|
|
3
|
-
import {escape} from "./escape";
|
|
4
|
-
import {escapeId} from "./escape";
|
|
5
|
-
import {tDate, tDateTime} from "@grest-ts/schema";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Type is the value. (If string "aa" is given, type of the column will be "aa")
|
|
9
|
-
* Useful for enum values etc.
|
|
10
|
-
*/
|
|
11
|
-
export function VALUE<Type>(value: Type): Expr<never, unknown, Type> {
|
|
12
|
-
return SqlExpression.create(escape(value as any))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function NULL<Name extends string = never>(as?: Name): Expr<never, Name, null> {
|
|
16
|
-
return SqlExpression.create("NULL", as)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function BOOL<Name extends string = never>(value: SQL_BOOL, as?: Name): Expr<never, Name, SQL_BOOL> {
|
|
20
|
-
return SqlExpression.create(value ? "1" : "0", as)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function ONE(): Expr<never, "one", 1> {
|
|
24
|
-
return SqlExpression.create("1", "one")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* DO NOT USE THIS METHOD :)
|
|
29
|
-
*
|
|
30
|
-
* Using this method is very dangerous, it DOES NOT escape strings passed to the function.
|
|
31
|
-
* If you use a unsafe variable from somewhere to construct a string you are open to SQL injection.
|
|
32
|
-
*
|
|
33
|
-
* If you do happen to use it, make all strings as literals and DO NOT use any variables to construct the string. It will bite you!
|
|
34
|
-
*
|
|
35
|
-
* To safely use columns do this (but in practice this example is dumb, you should do Sql.round(c.price)): ("ROUND(", c.price,")")
|
|
36
|
-
*
|
|
37
|
-
* DO NOT USE THIS METHOD :)
|
|
38
|
-
*/
|
|
39
|
-
export function DANGEROUS_SQL_EXPRESSION<TableRef>(arg: {
|
|
40
|
-
I_DID_NOT_USE_UNSAFE_VARIABLES_TO_CONSTRUCT_THIS_STRING: (string | Expr<TableRef, string | unknown, string | number | unknown>)[]
|
|
41
|
-
}): Expr<TableRef, unknown, unknown> {
|
|
42
|
-
return SqlExpression.create("(" + arg.I_DID_NOT_USE_UNSAFE_VARIABLES_TO_CONSTRUCT_THIS_STRING.map(e => typeof e === "string" ? e : e.expression).join("") + ")")
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// -------------------------------------------------------------------
|
|
46
|
-
// BOOLEAN CHECKS
|
|
47
|
-
// -------------------------------------------------------------------
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Accepts undefined as well.
|
|
51
|
-
*/
|
|
52
|
-
export function OR<T1 extends string, T2 extends string>(
|
|
53
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>
|
|
54
|
-
): Expr<T1 | T2, unknown, SQL_BOOL>
|
|
55
|
-
export function OR<T1 extends string, T2 extends string, T3 extends string>(
|
|
56
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>
|
|
57
|
-
): Expr<T1 | T2 | T3, unknown, SQL_BOOL>
|
|
58
|
-
export function OR<T1 extends string, T2 extends string, T3 extends string, T4 extends string>(
|
|
59
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>
|
|
60
|
-
): Expr<T1 | T2 | T3 | T4, unknown, SQL_BOOL>
|
|
61
|
-
export function OR<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string>(
|
|
62
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>
|
|
63
|
-
): Expr<T1 | T2 | T3 | T4 | T5, unknown, SQL_BOOL>
|
|
64
|
-
export function OR<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string>(
|
|
65
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>
|
|
66
|
-
): Expr<T1 | T2 | T3 | T4 | T5 | T6, unknown, SQL_BOOL>
|
|
67
|
-
export function OR(...col: any[]): any {
|
|
68
|
-
return SqlExpression.create("(" + col.filter(e => e).map(e => e.expression).join(" OR ") + ")")
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Accepts undefined as well.
|
|
73
|
-
*/
|
|
74
|
-
export function AND<T1 extends string, T2 extends string>(
|
|
75
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>
|
|
76
|
-
): Expr<T1 | T2, unknown, SQL_BOOL>
|
|
77
|
-
export function AND<T1 extends string, T2 extends string, T3 extends string>(
|
|
78
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>
|
|
79
|
-
): Expr<T1 | T2 | T3, unknown, SQL_BOOL>
|
|
80
|
-
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string>(
|
|
81
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>
|
|
82
|
-
): Expr<T1 | T2 | T3 | T4, unknown, SQL_BOOL>
|
|
83
|
-
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string>(
|
|
84
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>
|
|
85
|
-
): Expr<T1 | T2 | T3 | T4 | T5, unknown, SQL_BOOL>
|
|
86
|
-
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string>(
|
|
87
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>
|
|
88
|
-
): Expr<T1 | T2 | T3 | T4 | T5 | T6, unknown, SQL_BOOL>
|
|
89
|
-
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string, T7 extends string>(
|
|
90
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>, col7: AnyBoolExpr<T7>
|
|
91
|
-
): Expr<T1 | T2 | T3 | T4 | T5 | T6 | T7, unknown, SQL_BOOL>
|
|
92
|
-
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string, T7 extends string, T8 extends string>(
|
|
93
|
-
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>, col7: AnyBoolExpr<T7>, col8: AnyBoolExpr<T8>
|
|
94
|
-
): Expr<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8, unknown, SQL_BOOL>
|
|
95
|
-
|
|
96
|
-
export function AND(...col: any[]): any {
|
|
97
|
-
return SqlExpression.create("(" + col.filter(e => e).map(e => e.expression).join(" AND ") + ")")
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function IF<
|
|
101
|
-
Type extends string | number,
|
|
102
|
-
TableRef1 extends string = never,
|
|
103
|
-
TableRef2 extends string = never,
|
|
104
|
-
TableRef3 extends string = never
|
|
105
|
-
>(
|
|
106
|
-
col: Expr<TableRef1, string | unknown, SQL_BOOL>,
|
|
107
|
-
col2: Type | Expr<TableRef2, string | unknown, Type> | PrepareQueryArgument,
|
|
108
|
-
col3: Type | Expr<TableRef3, string | unknown, Type> | PrepareQueryArgument
|
|
109
|
-
): Expr<TableRef1 | TableRef2 | TableRef3, unknown, Type> {
|
|
110
|
-
return SqlExpression.create("IF( " + col.expression + ", " + toSql(col2) + ", " + toSql(col3) + " )")
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function IFNULL<
|
|
114
|
-
Type1 extends string | number,
|
|
115
|
-
Type2 extends string | number,
|
|
116
|
-
TableRef1 extends string = never,
|
|
117
|
-
TableRef2 extends string = never
|
|
118
|
-
>(
|
|
119
|
-
col1: Type1 | null | Expr<TableRef2, string | unknown, Type1> | PrepareQueryArgument,
|
|
120
|
-
col2: Type2 | null | Expr<TableRef2, string | unknown, Type2> | PrepareQueryArgument,
|
|
121
|
-
): Expr<TableRef1 | TableRef2, unknown, Type1 | Type2> {
|
|
122
|
-
return SqlExpression.create("IFNULL( " + toSql(col1) + ", " + toSql(col2) + " )")
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function NOT<TableRef>(col: Expr<TableRef, string | unknown, SQL_BOOL>): Expr<TableRef, unknown, SQL_BOOL> {
|
|
126
|
-
return SqlExpression.create("NOT (" + col.expression + ")")
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function EXISTS<TableRef>(col: Expr<TableRef, string | unknown, any>): Expr<TableRef, unknown, SQL_BOOL> {
|
|
130
|
-
return SqlExpression.create("EXISTS (" + col.expression + ")")
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export function NOT_EXISTS<TableRef>(col: Expr<TableRef, string | unknown, any>): Expr<TableRef, unknown, SQL_BOOL> {
|
|
134
|
-
return SqlExpression.create("NOT EXISTS (" + col.expression + ")")
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function IS_NULL<TableRef, Name, Type extends string | number>(col: Expr<TableRef, Name, Type>): Expr<TableRef, Name, SQL_BOOL> {
|
|
138
|
-
return SqlExpression.create(col.expression + " IS NULL")
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function NOT_NULL<TableRef, Name, Type extends string | number>(col: Expr<TableRef, Name, Type>): Expr<TableRef, Name, SQL_BOOL> {
|
|
142
|
-
return SqlExpression.create(col.expression + " IS NOT NULL")
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// export function in<TableRef, Type extends (string | number)[] | PrepareQueryArgument>(
|
|
146
|
-
// col: Expr<TableRef, string, Type>,
|
|
147
|
-
// values: Type
|
|
148
|
-
// ): Expr<TableRef, unknown, SQL_BOOL>
|
|
149
|
-
export function IN<Type extends string | number, TableRef1 = never, TableRef2 = never>(
|
|
150
|
-
col1: Type | Expr<TableRef1, string | unknown, Type> | PrepareQueryArgument,
|
|
151
|
-
col2: Type[] | Expr<TableRef2, string | unknown, Type> | PrepareQueryArgument
|
|
152
|
-
): Expr<TableRef1 | TableRef2, unknown, Type> {
|
|
153
|
-
if (Array.isArray(col2) && col2.length === 0) {
|
|
154
|
-
return SqlExpression.create("1=0")
|
|
155
|
-
}
|
|
156
|
-
return SqlExpression.create(toSql(col1) + " IN ( " + toSql(col2) + ")")
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// export function eq<TableRef, Type extends string | number | PrepareQueryArgument>(
|
|
160
|
-
// col: Expr<TableRef, string, Type>,
|
|
161
|
-
// value: Type
|
|
162
|
-
// ): Expr<TableRef, unknown, SQL_BOOL>
|
|
163
|
-
export function EQ<Type1 extends string | number, TableRef1 = never, TableRef2 = never>(
|
|
164
|
-
col1: Type1 | Expr<TableRef1, string | unknown, Type1> | PrepareQueryArgument,
|
|
165
|
-
col2: Type1 | Expr<TableRef2, string | unknown, Type1> | PrepareQueryArgument
|
|
166
|
-
): Expr<TableRef1 | TableRef2, unknown, SQL_BOOL> {
|
|
167
|
-
return COMPARE(col1, "=", col2);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export function COMPARE<Type extends string | number, TableRef = never, TableRef2 = never>(
|
|
171
|
-
col1: Type | Expr<TableRef, string | unknown, Type> | PrepareQueryArgument,
|
|
172
|
-
op: COMPARISON_SIGNS,
|
|
173
|
-
col2: Type | Expr<TableRef2, string | unknown, Type> | PrepareQueryArgument
|
|
174
|
-
): Expr<TableRef | TableRef2, unknown, SQL_BOOL> {
|
|
175
|
-
if (!ComparisonOperandsLookup.has(op)) {
|
|
176
|
-
throw new Error("Invalid comparison operand '" + op + "'")
|
|
177
|
-
}
|
|
178
|
-
return SqlExpression.create(toSql(col1) + " " + op + " " + toSql(col2))
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export function LIKE<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string | PrepareQueryArgument): Expr<TableRef, unknown, SQL_BOOL> {
|
|
182
|
-
return SqlExpression.create(col.expression + " LIKE " + escape(value));
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Does LIKE %X% search.
|
|
187
|
-
*/
|
|
188
|
-
export function CONTAINS<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string): Expr<TableRef, unknown, SQL_BOOL> {
|
|
189
|
-
return SqlExpression.create(col.expression + " LIKE " + escape("%" + value + "%"));
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Does LIKE X% search.
|
|
194
|
-
*/
|
|
195
|
-
export function STARTS_WITH<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string): Expr<TableRef, unknown, SQL_BOOL> {
|
|
196
|
-
return SqlExpression.create(col.expression + " LIKE " + escape(value + "%"));
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Does LIKE %X search.
|
|
201
|
-
*/
|
|
202
|
-
export function ENDS_WITH<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string): Expr<TableRef, unknown, SQL_BOOL> {
|
|
203
|
-
return SqlExpression.create(col.expression + " LIKE " + escape("%" + value));
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// -------------------------------------------------------------------
|
|
207
|
-
// STRING MANIPULATION
|
|
208
|
-
// -------------------------------------------------------------------
|
|
209
|
-
|
|
210
|
-
export function TRIM<Type extends string, TableRef = never>(value: string | Expr<TableRef, string | unknown, Type> | PrepareQueryArgument): Expr<TableRef, unknown, Type> {
|
|
211
|
-
return SqlExpression.create("TRIM(" + toSql(value) + ")")
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* normal SQL length function, but JS does not allow usage of length.
|
|
216
|
-
*/
|
|
217
|
-
export function LENGTH<TableRef = never>(value: string | Expr<TableRef, string | unknown, string> | PrepareQueryArgument): Expr<TableRef, unknown, number> {
|
|
218
|
-
return SqlExpression.create("LENGTH(" + toSql(value) + ")")
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export function CONCAT<TableRef = never>(...expr: (string | PrepareQueryArgument | Expr<TableRef, any, any>)[]): Expr<TableRef, unknown, string> {
|
|
222
|
-
return SqlExpression.create("CONCAT (" + expr.map(toSql) + ")")
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export function CONCAT_WS<TableRef = never>(separator: string, ...expr: (string | PrepareQueryArgument | Expr<TableRef, any, any>)[]): Expr<TableRef, unknown, string> {
|
|
226
|
-
return SqlExpression.create("CONCAT_WS(" + escape(separator) + "," + expr.map(toSql) + ")")
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export function GROUP_CONCAT<TableRef, TableRef2 = never>(
|
|
230
|
-
call?: (arg: GroupConcat<TableRef2>) => GroupConcat<TableRef2>
|
|
231
|
-
): Expr<TableRef | TableRef2, unknown, string> {
|
|
232
|
-
const builder = new GroupConcat();
|
|
233
|
-
call(builder);
|
|
234
|
-
return SqlExpression.create("GROUP_CONCAT(" + builder.toString() + ")");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
export class GroupConcat<TableRef = never> {
|
|
239
|
-
|
|
240
|
-
private _columns: any[] = [];
|
|
241
|
-
private _distinct: boolean = false;
|
|
242
|
-
private _orderBy: string[] = [];
|
|
243
|
-
private _separator: string = undefined;
|
|
244
|
-
|
|
245
|
-
public all<TableRef2>(...args: (string | PrepareQueryArgument | Expr<TableRef2, any, any>)[]): GroupConcat<TableRef | TableRef2> {
|
|
246
|
-
this._columns = args.map(toSql);
|
|
247
|
-
return this;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
public distinct<TableRef2>(...args: (string | PrepareQueryArgument | Expr<TableRef2, any, any>)[]): GroupConcat<TableRef | TableRef2> {
|
|
251
|
-
this._distinct = true;
|
|
252
|
-
this._columns = args.map(toSql);
|
|
253
|
-
return this;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
public orderBy<TableRef2>(...cols: OrderByStructure<Expr<TableRef2, string, any>>): GroupConcat<TableRef | TableRef2> {
|
|
257
|
-
this._orderBy = orderByStructureToSqlString(cols)
|
|
258
|
-
return this;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
public separator(separator: string): this {
|
|
262
|
-
this._separator = separator;
|
|
263
|
-
return this;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
public toString() {
|
|
267
|
-
return (this._distinct ? "DISTINCT " : "") +
|
|
268
|
-
"" + this._columns +
|
|
269
|
-
(this._orderBy && this._orderBy.length > 0 ? " ORDER BY " + this._orderBy.join(", ") : "") +
|
|
270
|
-
(this._separator ? " SEPARATOR " + escape(this._separator) : "");
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// -------------------------------------------------------------------
|
|
276
|
-
// DATE MANIPULATION
|
|
277
|
-
// -------------------------------------------------------------------
|
|
278
|
-
|
|
279
|
-
export function NOW(): Expr<never, unknown, tDateTime> {
|
|
280
|
-
return SqlExpression.create("NOW()")
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
export function CUR_DATE(): Expr<never, unknown, tDate> {
|
|
284
|
-
return SqlExpression.create("CURDATE()")
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
export function YEAR<Name, TableRef>(field: Expr<TableRef, Name, tDate | tDateTime>): Expr<TableRef, Name, number> {
|
|
288
|
-
return SqlExpression.create("YEAR(" + field.expression + ")")
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
export function UNIX_TIMESTAMP<Name, TableRef>(field: Expr<TableRef, Name, tDate | tDateTime>): Expr<TableRef, Name, number> {
|
|
292
|
-
return SqlExpression.create("UNIX_TIMESTAMP(" + field.expression + ")")
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export function DATE<Name, TableRef>(field: Expr<TableRef, Name, tDate | tDateTime>): Expr<TableRef, Name, tDate> {
|
|
296
|
-
return SqlExpression.create("DATE(" + field.expression + ")")
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export function DATE_TIME<Name, TableRef>(field: Expr<TableRef, Name, tDateTime>): Expr<TableRef, Name, tDateTime> {
|
|
300
|
-
return SqlExpression.create("DATETIME(" + field.expression + ")")
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export function DATE_FORMAT<Name, TableRef = never>(col: tDate | tDateTime | Expr<TableRef, Name, tDate | tDateTime>, format: string): Expr<TableRef, Name, string> {
|
|
304
|
-
return SqlExpression.create("DATE_FORMAT(" + toSql(col) + ", " + escape(format) + ")")
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export function DATEDIFF<TableRef1 = never, TableRef2 = never>(
|
|
308
|
-
col1: tDate | tDateTime | Expr<TableRef1, string | unknown, tDate | tDateTime> | PrepareQueryArgument,
|
|
309
|
-
col2: tDate | tDateTime | Expr<TableRef2, string | unknown, tDate | tDateTime> | PrepareQueryArgument
|
|
310
|
-
): Expr<TableRef1 | TableRef2, unknown, number> {
|
|
311
|
-
return SqlExpression.create("DATEDIFF(" + toSql(col1) + ", " + toSql(col2) + ")")
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
export function DATE_SUB<Name, TableRef = never>(col: tDate | tDateTime | Expr<TableRef, Name, tDate | tDateTime>, interval: string | number, unit: DATE_ADD_UNITS): Expr<TableRef, Name, tDateTime> {
|
|
315
|
-
if (!DateAddUnitsLookup.has(unit)) {
|
|
316
|
-
throw new Error("Invalid unit '" + unit + "'")
|
|
317
|
-
}
|
|
318
|
-
return SqlExpression.create("DATE_SUB(" + toSql(col) + ", INTERVAL " + escape(interval) + " " + unit + ")")
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
export function DATE_ADD<Name, TableRef = never>(col: tDate | tDateTime | Expr<TableRef, Name, tDate | tDateTime>, interval: string | number, unit: DATE_ADD_UNITS): Expr<TableRef, Name, tDateTime> {
|
|
322
|
-
if (!DateAddUnitsLookup.has(unit)) {
|
|
323
|
-
throw new Error("Invalid unit '" + unit + "'")
|
|
324
|
-
}
|
|
325
|
-
return SqlExpression.create("DATE_ADD(" + toSql(col) + ", INTERVAL " + escape(interval) + " " + unit + ")")
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// -------------------------------------------------------------------
|
|
329
|
-
// NUMBER MANIPULATION
|
|
330
|
-
// -------------------------------------------------------------------
|
|
331
|
-
|
|
332
|
-
export function MATH<Name, TableRef>(expression: string, args: Expr<TableRef, Name, number>[]): Expr<TableRef, Name, number> {
|
|
333
|
-
const pattern = /^[0-9+\-*/()?. ]*$/
|
|
334
|
-
if (!pattern.test(expression)) {
|
|
335
|
-
throw new Error("Invalid expression. Expression must match this pattern: " + pattern)
|
|
336
|
-
}
|
|
337
|
-
for (let i = 0; i < args.length; i++) {
|
|
338
|
-
expression = expression.replace("?", args[i].expression);
|
|
339
|
-
}
|
|
340
|
-
return SqlExpression.create("(" + expression + ")")
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
export function ABS<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
344
|
-
return SqlExpression.create("ABS(" + col.expression + ")", col.nameAs)
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export function CEIL<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
348
|
-
return SqlExpression.create("CEIL(" + col.expression + ")", col.nameAs)
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export function FLOOR<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
352
|
-
return SqlExpression.create("FLOOR(" + col.expression + ")", col.nameAs)
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
export function ROUND<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
356
|
-
return SqlExpression.create("ROUND(" + col.expression + ")", col.nameAs)
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
export function SIGN<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, -1 | 0 | 1> {
|
|
360
|
-
return SqlExpression.create("SIGN(" + col.expression + ")", col.nameAs)
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
export function SQRT<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
364
|
-
return SqlExpression.create("SQRT(" + col.expression + ")", col.nameAs)
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// -------------------------------------------------------------------
|
|
368
|
-
// AGGREGATE FUNCTIONS
|
|
369
|
-
// -------------------------------------------------------------------
|
|
370
|
-
|
|
371
|
-
export function MIN<Type, Name, TableRef>(col: Expr<TableRef, Name, Type>): ExprWithOver<TableRef, Name, Type> {
|
|
372
|
-
return SqlExpressionWithOver.create("MIN(" + col.expression + ")", col.nameAs)
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export function MAX<Type, Name, TableRef>(col: Expr<TableRef, Name, Type>): ExprWithOver<TableRef, Name, Type> {
|
|
376
|
-
return SqlExpressionWithOver.create("MAX(" + col.expression + ")", col.nameAs)
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
export function SUM<Type, Name, TableRef = never>(col: Type | Expr<TableRef, Name, Type>): ExprWithOver<TableRef, Name, number> {
|
|
380
|
-
return SqlExpressionWithOver.create("SUM(" + toSql(col) + ")", (col instanceof SqlExpression ? col.nameAs : undefined))
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
export function COUNT<Type, Name, TableRef = never>(col: Type | Expr<TableRef, Name, Type>): Expr<TableRef, Name, number> {
|
|
384
|
-
return SqlExpressionWithOver.create("COUNT(" + toSql(col) + ")", (col instanceof SqlExpression ? col.nameAs : undefined))
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
export function RANK(): ExprWithOver<never, unknown, number> {
|
|
388
|
-
return SqlExpressionWithOver.create("RANK()", undefined)
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
export function ROW_NUMBER(): ExprWithOver<never, unknown, number> {
|
|
392
|
-
return SqlExpressionWithOver.create("ROW_NUMBER()", undefined)
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
export function LAG<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>, n?: number, def?: number): ExprWithOver<TableRef, unknown, Type> {
|
|
396
|
-
return SqlExpressionWithOver.create("LAG(" + col.expression + "," + (n ? Number(n) : 0) + "," + (def ? Number(def) : 0) + ")", undefined)
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
export function LEAD<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>, n?: number, def?: number): ExprWithOver<TableRef, unknown, Type> {
|
|
400
|
-
return SqlExpressionWithOver.create("LEAD(" + col.expression + "," + (n ? Number(n) : 0) + "," + (def ? Number(def) : 0) + ")", undefined)
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
export function FIRST_VALUE<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>): ExprWithOver<TableRef, unknown, Type> {
|
|
404
|
-
return SqlExpressionWithOver.create("FIRST_VALUE(" + col.expression + ")", undefined)
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
export function LAST_VALUE<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>): ExprWithOver<TableRef, unknown, Type> {
|
|
408
|
-
return SqlExpressionWithOver.create("LAST_VALUE(" + col.expression + ")", undefined)
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
export function NTH_VALUE<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>, value: number): ExprWithOver<TableRef, unknown, Type> {
|
|
412
|
-
return SqlExpressionWithOver.create("NTH_VALUE(" + col.expression + "," + (value ? Number(value) : 0) + ")", undefined)
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
// -------------------------------------------------------------------
|
|
417
|
-
// MISC
|
|
418
|
-
// -------------------------------------------------------------------
|
|
419
|
-
|
|
420
|
-
export function BIN_TO_UUID<TableRef, Name>(col: Expr<TableRef, Name, any>): Expr<TableRef, Name, string> {
|
|
421
|
-
return SqlExpression.create("BIN_TO_UINT(" + col.expression + ")", col.nameAs)
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// -------------------------------------------------------------------
|
|
425
|
-
// UTILITY
|
|
426
|
-
// -------------------------------------------------------------------
|
|
427
|
-
|
|
428
|
-
export function orderByStructureToSqlString(items: [] | OrderByStructure<any>): string[] {
|
|
429
|
-
const parts: string[] = [];
|
|
430
|
-
for (let i = 0; i < items.length; i++) {
|
|
431
|
-
const item = items[i];
|
|
432
|
-
if (item === undefined || item === null || item === "") {
|
|
433
|
-
// skip
|
|
434
|
-
} else if (item === "asc" || item === "ASC") {
|
|
435
|
-
parts[parts.length - 1] += " ASC"
|
|
436
|
-
} else if (item === "desc" || item === "DESC") {
|
|
437
|
-
parts[parts.length - 1] += " DESC"
|
|
438
|
-
} else if (item instanceof SqlExpression) {
|
|
439
|
-
parts.push(item.expression)
|
|
440
|
-
} else if (typeof item === "string") {
|
|
441
|
-
parts.push(escapeId(item))
|
|
442
|
-
} else {
|
|
443
|
-
throw new Error("Invalid argument to having! Type: '" + (typeof item) + "' String: '" + String(item) + "'")
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
return parts;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
export function toSql(e: unknown | number | string | boolean | PrepareQueryArgument | AnyExpr | any): string | number {
|
|
450
|
-
if (typeof e === "string") {
|
|
451
|
-
return escape(e);
|
|
452
|
-
} else if (typeof e === "number") {
|
|
453
|
-
return Number(e);
|
|
454
|
-
} else if (e === null || e === undefined) {
|
|
455
|
-
return "NULL";
|
|
456
|
-
} else if (e === true) {
|
|
457
|
-
return "1";
|
|
458
|
-
} else if (e === false) {
|
|
459
|
-
return "0";
|
|
460
|
-
} else if (e instanceof SqlExpression) {
|
|
461
|
-
return e.expression
|
|
462
|
-
} else if (isPrepareArgument(e)) {
|
|
463
|
-
return e.expression;
|
|
464
|
-
} else if (Array.isArray(e)) {
|
|
465
|
-
return e.map(toSql).join(", ")
|
|
466
|
-
} else if (typeof e === "object") {
|
|
467
|
-
return escape(JSON.stringify(e));
|
|
468
|
-
} else {
|
|
469
|
-
throw new Error("Invalid argument of type " + (typeof e) + "! toString: " + String(e));
|
|
470
|
-
}
|
|
471
|
-
}
|
|
1
|
+
import {COMPARISON_SIGNS, ComparisonOperandsLookup, DATE_ADD_UNITS, DateAddUnitsLookup, isPrepareArgument, OrderByStructure, PrepareQueryArgument, SQL_BOOL} from "./Types";
|
|
2
|
+
import {AnyBoolExpr, AnyExpr, Expr, ExprWithOver, SqlExpression, SqlExpressionWithOver} from "./SqlExpression";
|
|
3
|
+
import {escape} from "./escape";
|
|
4
|
+
import {escapeId} from "./escape";
|
|
5
|
+
import {tDate, tDateTime} from "@grest-ts/schema";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Type is the value. (If string "aa" is given, type of the column will be "aa")
|
|
9
|
+
* Useful for enum values etc.
|
|
10
|
+
*/
|
|
11
|
+
export function VALUE<Type>(value: Type): Expr<never, unknown, Type> {
|
|
12
|
+
return SqlExpression.create(escape(value as any))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function NULL<Name extends string = never>(as?: Name): Expr<never, Name, null> {
|
|
16
|
+
return SqlExpression.create("NULL", as)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function BOOL<Name extends string = never>(value: SQL_BOOL, as?: Name): Expr<never, Name, SQL_BOOL> {
|
|
20
|
+
return SqlExpression.create(value ? "1" : "0", as)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function ONE(): Expr<never, "one", 1> {
|
|
24
|
+
return SqlExpression.create("1", "one")
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* DO NOT USE THIS METHOD :)
|
|
29
|
+
*
|
|
30
|
+
* Using this method is very dangerous, it DOES NOT escape strings passed to the function.
|
|
31
|
+
* If you use a unsafe variable from somewhere to construct a string you are open to SQL injection.
|
|
32
|
+
*
|
|
33
|
+
* If you do happen to use it, make all strings as literals and DO NOT use any variables to construct the string. It will bite you!
|
|
34
|
+
*
|
|
35
|
+
* To safely use columns do this (but in practice this example is dumb, you should do Sql.round(c.price)): ("ROUND(", c.price,")")
|
|
36
|
+
*
|
|
37
|
+
* DO NOT USE THIS METHOD :)
|
|
38
|
+
*/
|
|
39
|
+
export function DANGEROUS_SQL_EXPRESSION<TableRef>(arg: {
|
|
40
|
+
I_DID_NOT_USE_UNSAFE_VARIABLES_TO_CONSTRUCT_THIS_STRING: (string | Expr<TableRef, string | unknown, string | number | unknown>)[]
|
|
41
|
+
}): Expr<TableRef, unknown, unknown> {
|
|
42
|
+
return SqlExpression.create("(" + arg.I_DID_NOT_USE_UNSAFE_VARIABLES_TO_CONSTRUCT_THIS_STRING.map(e => typeof e === "string" ? e : e.expression).join("") + ")")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// -------------------------------------------------------------------
|
|
46
|
+
// BOOLEAN CHECKS
|
|
47
|
+
// -------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Accepts undefined as well.
|
|
51
|
+
*/
|
|
52
|
+
export function OR<T1 extends string, T2 extends string>(
|
|
53
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>
|
|
54
|
+
): Expr<T1 | T2, unknown, SQL_BOOL>
|
|
55
|
+
export function OR<T1 extends string, T2 extends string, T3 extends string>(
|
|
56
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>
|
|
57
|
+
): Expr<T1 | T2 | T3, unknown, SQL_BOOL>
|
|
58
|
+
export function OR<T1 extends string, T2 extends string, T3 extends string, T4 extends string>(
|
|
59
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>
|
|
60
|
+
): Expr<T1 | T2 | T3 | T4, unknown, SQL_BOOL>
|
|
61
|
+
export function OR<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string>(
|
|
62
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>
|
|
63
|
+
): Expr<T1 | T2 | T3 | T4 | T5, unknown, SQL_BOOL>
|
|
64
|
+
export function OR<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string>(
|
|
65
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>
|
|
66
|
+
): Expr<T1 | T2 | T3 | T4 | T5 | T6, unknown, SQL_BOOL>
|
|
67
|
+
export function OR(...col: any[]): any {
|
|
68
|
+
return SqlExpression.create("(" + col.filter(e => e).map(e => e.expression).join(" OR ") + ")")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Accepts undefined as well.
|
|
73
|
+
*/
|
|
74
|
+
export function AND<T1 extends string, T2 extends string>(
|
|
75
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>
|
|
76
|
+
): Expr<T1 | T2, unknown, SQL_BOOL>
|
|
77
|
+
export function AND<T1 extends string, T2 extends string, T3 extends string>(
|
|
78
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>
|
|
79
|
+
): Expr<T1 | T2 | T3, unknown, SQL_BOOL>
|
|
80
|
+
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string>(
|
|
81
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>
|
|
82
|
+
): Expr<T1 | T2 | T3 | T4, unknown, SQL_BOOL>
|
|
83
|
+
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string>(
|
|
84
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>
|
|
85
|
+
): Expr<T1 | T2 | T3 | T4 | T5, unknown, SQL_BOOL>
|
|
86
|
+
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string>(
|
|
87
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>
|
|
88
|
+
): Expr<T1 | T2 | T3 | T4 | T5 | T6, unknown, SQL_BOOL>
|
|
89
|
+
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string, T7 extends string>(
|
|
90
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>, col7: AnyBoolExpr<T7>
|
|
91
|
+
): Expr<T1 | T2 | T3 | T4 | T5 | T6 | T7, unknown, SQL_BOOL>
|
|
92
|
+
export function AND<T1 extends string, T2 extends string, T3 extends string, T4 extends string, T5 extends string, T6 extends string, T7 extends string, T8 extends string>(
|
|
93
|
+
col1: AnyBoolExpr<T1>, col2: AnyBoolExpr<T2>, col3: AnyBoolExpr<T3>, col4: AnyBoolExpr<T4>, col5: AnyBoolExpr<T5>, col6: AnyBoolExpr<T6>, col7: AnyBoolExpr<T7>, col8: AnyBoolExpr<T8>
|
|
94
|
+
): Expr<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8, unknown, SQL_BOOL>
|
|
95
|
+
|
|
96
|
+
export function AND(...col: any[]): any {
|
|
97
|
+
return SqlExpression.create("(" + col.filter(e => e).map(e => e.expression).join(" AND ") + ")")
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function IF<
|
|
101
|
+
Type extends string | number,
|
|
102
|
+
TableRef1 extends string = never,
|
|
103
|
+
TableRef2 extends string = never,
|
|
104
|
+
TableRef3 extends string = never
|
|
105
|
+
>(
|
|
106
|
+
col: Expr<TableRef1, string | unknown, SQL_BOOL>,
|
|
107
|
+
col2: Type | Expr<TableRef2, string | unknown, Type> | PrepareQueryArgument,
|
|
108
|
+
col3: Type | Expr<TableRef3, string | unknown, Type> | PrepareQueryArgument
|
|
109
|
+
): Expr<TableRef1 | TableRef2 | TableRef3, unknown, Type> {
|
|
110
|
+
return SqlExpression.create("IF( " + col.expression + ", " + toSql(col2) + ", " + toSql(col3) + " )")
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function IFNULL<
|
|
114
|
+
Type1 extends string | number,
|
|
115
|
+
Type2 extends string | number,
|
|
116
|
+
TableRef1 extends string = never,
|
|
117
|
+
TableRef2 extends string = never
|
|
118
|
+
>(
|
|
119
|
+
col1: Type1 | null | Expr<TableRef2, string | unknown, Type1> | PrepareQueryArgument,
|
|
120
|
+
col2: Type2 | null | Expr<TableRef2, string | unknown, Type2> | PrepareQueryArgument,
|
|
121
|
+
): Expr<TableRef1 | TableRef2, unknown, Type1 | Type2> {
|
|
122
|
+
return SqlExpression.create("IFNULL( " + toSql(col1) + ", " + toSql(col2) + " )")
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function NOT<TableRef>(col: Expr<TableRef, string | unknown, SQL_BOOL>): Expr<TableRef, unknown, SQL_BOOL> {
|
|
126
|
+
return SqlExpression.create("NOT (" + col.expression + ")")
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function EXISTS<TableRef>(col: Expr<TableRef, string | unknown, any>): Expr<TableRef, unknown, SQL_BOOL> {
|
|
130
|
+
return SqlExpression.create("EXISTS (" + col.expression + ")")
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function NOT_EXISTS<TableRef>(col: Expr<TableRef, string | unknown, any>): Expr<TableRef, unknown, SQL_BOOL> {
|
|
134
|
+
return SqlExpression.create("NOT EXISTS (" + col.expression + ")")
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function IS_NULL<TableRef, Name, Type extends string | number>(col: Expr<TableRef, Name, Type>): Expr<TableRef, Name, SQL_BOOL> {
|
|
138
|
+
return SqlExpression.create(col.expression + " IS NULL")
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function NOT_NULL<TableRef, Name, Type extends string | number>(col: Expr<TableRef, Name, Type>): Expr<TableRef, Name, SQL_BOOL> {
|
|
142
|
+
return SqlExpression.create(col.expression + " IS NOT NULL")
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// export function in<TableRef, Type extends (string | number)[] | PrepareQueryArgument>(
|
|
146
|
+
// col: Expr<TableRef, string, Type>,
|
|
147
|
+
// values: Type
|
|
148
|
+
// ): Expr<TableRef, unknown, SQL_BOOL>
|
|
149
|
+
export function IN<Type extends string | number, TableRef1 = never, TableRef2 = never>(
|
|
150
|
+
col1: Type | Expr<TableRef1, string | unknown, Type> | PrepareQueryArgument,
|
|
151
|
+
col2: Type[] | Expr<TableRef2, string | unknown, Type> | PrepareQueryArgument
|
|
152
|
+
): Expr<TableRef1 | TableRef2, unknown, Type> {
|
|
153
|
+
if (Array.isArray(col2) && col2.length === 0) {
|
|
154
|
+
return SqlExpression.create("1=0")
|
|
155
|
+
}
|
|
156
|
+
return SqlExpression.create(toSql(col1) + " IN ( " + toSql(col2) + ")")
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// export function eq<TableRef, Type extends string | number | PrepareQueryArgument>(
|
|
160
|
+
// col: Expr<TableRef, string, Type>,
|
|
161
|
+
// value: Type
|
|
162
|
+
// ): Expr<TableRef, unknown, SQL_BOOL>
|
|
163
|
+
export function EQ<Type1 extends string | number, TableRef1 = never, TableRef2 = never>(
|
|
164
|
+
col1: Type1 | Expr<TableRef1, string | unknown, Type1> | PrepareQueryArgument,
|
|
165
|
+
col2: Type1 | Expr<TableRef2, string | unknown, Type1> | PrepareQueryArgument
|
|
166
|
+
): Expr<TableRef1 | TableRef2, unknown, SQL_BOOL> {
|
|
167
|
+
return COMPARE(col1, "=", col2);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function COMPARE<Type extends string | number, TableRef = never, TableRef2 = never>(
|
|
171
|
+
col1: Type | Expr<TableRef, string | unknown, Type> | PrepareQueryArgument,
|
|
172
|
+
op: COMPARISON_SIGNS,
|
|
173
|
+
col2: Type | Expr<TableRef2, string | unknown, Type> | PrepareQueryArgument
|
|
174
|
+
): Expr<TableRef | TableRef2, unknown, SQL_BOOL> {
|
|
175
|
+
if (!ComparisonOperandsLookup.has(op)) {
|
|
176
|
+
throw new Error("Invalid comparison operand '" + op + "'")
|
|
177
|
+
}
|
|
178
|
+
return SqlExpression.create(toSql(col1) + " " + op + " " + toSql(col2))
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function LIKE<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string | PrepareQueryArgument): Expr<TableRef, unknown, SQL_BOOL> {
|
|
182
|
+
return SqlExpression.create(col.expression + " LIKE " + escape(value));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Does LIKE %X% search.
|
|
187
|
+
*/
|
|
188
|
+
export function CONTAINS<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string): Expr<TableRef, unknown, SQL_BOOL> {
|
|
189
|
+
return SqlExpression.create(col.expression + " LIKE " + escape("%" + value + "%"));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Does LIKE X% search.
|
|
194
|
+
*/
|
|
195
|
+
export function STARTS_WITH<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string): Expr<TableRef, unknown, SQL_BOOL> {
|
|
196
|
+
return SqlExpression.create(col.expression + " LIKE " + escape(value + "%"));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Does LIKE %X search.
|
|
201
|
+
*/
|
|
202
|
+
export function ENDS_WITH<TableRef>(col: (Expr<TableRef, string | unknown, string | number>), value: string): Expr<TableRef, unknown, SQL_BOOL> {
|
|
203
|
+
return SqlExpression.create(col.expression + " LIKE " + escape("%" + value));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// -------------------------------------------------------------------
|
|
207
|
+
// STRING MANIPULATION
|
|
208
|
+
// -------------------------------------------------------------------
|
|
209
|
+
|
|
210
|
+
export function TRIM<Type extends string, TableRef = never>(value: string | Expr<TableRef, string | unknown, Type> | PrepareQueryArgument): Expr<TableRef, unknown, Type> {
|
|
211
|
+
return SqlExpression.create("TRIM(" + toSql(value) + ")")
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* normal SQL length function, but JS does not allow usage of length.
|
|
216
|
+
*/
|
|
217
|
+
export function LENGTH<TableRef = never>(value: string | Expr<TableRef, string | unknown, string> | PrepareQueryArgument): Expr<TableRef, unknown, number> {
|
|
218
|
+
return SqlExpression.create("LENGTH(" + toSql(value) + ")")
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function CONCAT<TableRef = never>(...expr: (string | PrepareQueryArgument | Expr<TableRef, any, any>)[]): Expr<TableRef, unknown, string> {
|
|
222
|
+
return SqlExpression.create("CONCAT (" + expr.map(toSql) + ")")
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function CONCAT_WS<TableRef = never>(separator: string, ...expr: (string | PrepareQueryArgument | Expr<TableRef, any, any>)[]): Expr<TableRef, unknown, string> {
|
|
226
|
+
return SqlExpression.create("CONCAT_WS(" + escape(separator) + "," + expr.map(toSql) + ")")
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function GROUP_CONCAT<TableRef, TableRef2 = never>(
|
|
230
|
+
call?: (arg: GroupConcat<TableRef2>) => GroupConcat<TableRef2>
|
|
231
|
+
): Expr<TableRef | TableRef2, unknown, string> {
|
|
232
|
+
const builder = new GroupConcat();
|
|
233
|
+
call(builder);
|
|
234
|
+
return SqlExpression.create("GROUP_CONCAT(" + builder.toString() + ")");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
export class GroupConcat<TableRef = never> {
|
|
239
|
+
|
|
240
|
+
private _columns: any[] = [];
|
|
241
|
+
private _distinct: boolean = false;
|
|
242
|
+
private _orderBy: string[] = [];
|
|
243
|
+
private _separator: string = undefined;
|
|
244
|
+
|
|
245
|
+
public all<TableRef2>(...args: (string | PrepareQueryArgument | Expr<TableRef2, any, any>)[]): GroupConcat<TableRef | TableRef2> {
|
|
246
|
+
this._columns = args.map(toSql);
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public distinct<TableRef2>(...args: (string | PrepareQueryArgument | Expr<TableRef2, any, any>)[]): GroupConcat<TableRef | TableRef2> {
|
|
251
|
+
this._distinct = true;
|
|
252
|
+
this._columns = args.map(toSql);
|
|
253
|
+
return this;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
public orderBy<TableRef2>(...cols: OrderByStructure<Expr<TableRef2, string, any>>): GroupConcat<TableRef | TableRef2> {
|
|
257
|
+
this._orderBy = orderByStructureToSqlString(cols)
|
|
258
|
+
return this;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
public separator(separator: string): this {
|
|
262
|
+
this._separator = separator;
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
public toString() {
|
|
267
|
+
return (this._distinct ? "DISTINCT " : "") +
|
|
268
|
+
"" + this._columns +
|
|
269
|
+
(this._orderBy && this._orderBy.length > 0 ? " ORDER BY " + this._orderBy.join(", ") : "") +
|
|
270
|
+
(this._separator ? " SEPARATOR " + escape(this._separator) : "");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// -------------------------------------------------------------------
|
|
276
|
+
// DATE MANIPULATION
|
|
277
|
+
// -------------------------------------------------------------------
|
|
278
|
+
|
|
279
|
+
export function NOW(): Expr<never, unknown, tDateTime> {
|
|
280
|
+
return SqlExpression.create("NOW()")
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function CUR_DATE(): Expr<never, unknown, tDate> {
|
|
284
|
+
return SqlExpression.create("CURDATE()")
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function YEAR<Name, TableRef>(field: Expr<TableRef, Name, tDate | tDateTime>): Expr<TableRef, Name, number> {
|
|
288
|
+
return SqlExpression.create("YEAR(" + field.expression + ")")
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function UNIX_TIMESTAMP<Name, TableRef>(field: Expr<TableRef, Name, tDate | tDateTime>): Expr<TableRef, Name, number> {
|
|
292
|
+
return SqlExpression.create("UNIX_TIMESTAMP(" + field.expression + ")")
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function DATE<Name, TableRef>(field: Expr<TableRef, Name, tDate | tDateTime>): Expr<TableRef, Name, tDate> {
|
|
296
|
+
return SqlExpression.create("DATE(" + field.expression + ")")
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function DATE_TIME<Name, TableRef>(field: Expr<TableRef, Name, tDateTime>): Expr<TableRef, Name, tDateTime> {
|
|
300
|
+
return SqlExpression.create("DATETIME(" + field.expression + ")")
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function DATE_FORMAT<Name, TableRef = never>(col: tDate | tDateTime | Expr<TableRef, Name, tDate | tDateTime>, format: string): Expr<TableRef, Name, string> {
|
|
304
|
+
return SqlExpression.create("DATE_FORMAT(" + toSql(col) + ", " + escape(format) + ")")
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export function DATEDIFF<TableRef1 = never, TableRef2 = never>(
|
|
308
|
+
col1: tDate | tDateTime | Expr<TableRef1, string | unknown, tDate | tDateTime> | PrepareQueryArgument,
|
|
309
|
+
col2: tDate | tDateTime | Expr<TableRef2, string | unknown, tDate | tDateTime> | PrepareQueryArgument
|
|
310
|
+
): Expr<TableRef1 | TableRef2, unknown, number> {
|
|
311
|
+
return SqlExpression.create("DATEDIFF(" + toSql(col1) + ", " + toSql(col2) + ")")
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function DATE_SUB<Name, TableRef = never>(col: tDate | tDateTime | Expr<TableRef, Name, tDate | tDateTime>, interval: string | number, unit: DATE_ADD_UNITS): Expr<TableRef, Name, tDateTime> {
|
|
315
|
+
if (!DateAddUnitsLookup.has(unit)) {
|
|
316
|
+
throw new Error("Invalid unit '" + unit + "'")
|
|
317
|
+
}
|
|
318
|
+
return SqlExpression.create("DATE_SUB(" + toSql(col) + ", INTERVAL " + escape(interval) + " " + unit + ")")
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function DATE_ADD<Name, TableRef = never>(col: tDate | tDateTime | Expr<TableRef, Name, tDate | tDateTime>, interval: string | number, unit: DATE_ADD_UNITS): Expr<TableRef, Name, tDateTime> {
|
|
322
|
+
if (!DateAddUnitsLookup.has(unit)) {
|
|
323
|
+
throw new Error("Invalid unit '" + unit + "'")
|
|
324
|
+
}
|
|
325
|
+
return SqlExpression.create("DATE_ADD(" + toSql(col) + ", INTERVAL " + escape(interval) + " " + unit + ")")
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// -------------------------------------------------------------------
|
|
329
|
+
// NUMBER MANIPULATION
|
|
330
|
+
// -------------------------------------------------------------------
|
|
331
|
+
|
|
332
|
+
export function MATH<Name, TableRef>(expression: string, args: Expr<TableRef, Name, number>[]): Expr<TableRef, Name, number> {
|
|
333
|
+
const pattern = /^[0-9+\-*/()?. ]*$/
|
|
334
|
+
if (!pattern.test(expression)) {
|
|
335
|
+
throw new Error("Invalid expression. Expression must match this pattern: " + pattern)
|
|
336
|
+
}
|
|
337
|
+
for (let i = 0; i < args.length; i++) {
|
|
338
|
+
expression = expression.replace("?", args[i].expression);
|
|
339
|
+
}
|
|
340
|
+
return SqlExpression.create("(" + expression + ")")
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function ABS<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
344
|
+
return SqlExpression.create("ABS(" + col.expression + ")", col.nameAs)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function CEIL<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
348
|
+
return SqlExpression.create("CEIL(" + col.expression + ")", col.nameAs)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function FLOOR<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
352
|
+
return SqlExpression.create("FLOOR(" + col.expression + ")", col.nameAs)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export function ROUND<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
356
|
+
return SqlExpression.create("ROUND(" + col.expression + ")", col.nameAs)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export function SIGN<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, -1 | 0 | 1> {
|
|
360
|
+
return SqlExpression.create("SIGN(" + col.expression + ")", col.nameAs)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function SQRT<Name, TableRef>(col: Expr<TableRef, Name, number>): Expr<TableRef, Name, number> {
|
|
364
|
+
return SqlExpression.create("SQRT(" + col.expression + ")", col.nameAs)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// -------------------------------------------------------------------
|
|
368
|
+
// AGGREGATE FUNCTIONS
|
|
369
|
+
// -------------------------------------------------------------------
|
|
370
|
+
|
|
371
|
+
export function MIN<Type, Name, TableRef>(col: Expr<TableRef, Name, Type>): ExprWithOver<TableRef, Name, Type> {
|
|
372
|
+
return SqlExpressionWithOver.create("MIN(" + col.expression + ")", col.nameAs)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function MAX<Type, Name, TableRef>(col: Expr<TableRef, Name, Type>): ExprWithOver<TableRef, Name, Type> {
|
|
376
|
+
return SqlExpressionWithOver.create("MAX(" + col.expression + ")", col.nameAs)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export function SUM<Type, Name, TableRef = never>(col: Type | Expr<TableRef, Name, Type>): ExprWithOver<TableRef, Name, number> {
|
|
380
|
+
return SqlExpressionWithOver.create("SUM(" + toSql(col) + ")", (col instanceof SqlExpression ? col.nameAs : undefined))
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function COUNT<Type, Name, TableRef = never>(col: Type | Expr<TableRef, Name, Type>): Expr<TableRef, Name, number> {
|
|
384
|
+
return SqlExpressionWithOver.create("COUNT(" + toSql(col) + ")", (col instanceof SqlExpression ? col.nameAs : undefined))
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export function RANK(): ExprWithOver<never, unknown, number> {
|
|
388
|
+
return SqlExpressionWithOver.create("RANK()", undefined)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export function ROW_NUMBER(): ExprWithOver<never, unknown, number> {
|
|
392
|
+
return SqlExpressionWithOver.create("ROW_NUMBER()", undefined)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export function LAG<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>, n?: number, def?: number): ExprWithOver<TableRef, unknown, Type> {
|
|
396
|
+
return SqlExpressionWithOver.create("LAG(" + col.expression + "," + (n ? Number(n) : 0) + "," + (def ? Number(def) : 0) + ")", undefined)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function LEAD<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>, n?: number, def?: number): ExprWithOver<TableRef, unknown, Type> {
|
|
400
|
+
return SqlExpressionWithOver.create("LEAD(" + col.expression + "," + (n ? Number(n) : 0) + "," + (def ? Number(def) : 0) + ")", undefined)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export function FIRST_VALUE<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>): ExprWithOver<TableRef, unknown, Type> {
|
|
404
|
+
return SqlExpressionWithOver.create("FIRST_VALUE(" + col.expression + ")", undefined)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export function LAST_VALUE<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>): ExprWithOver<TableRef, unknown, Type> {
|
|
408
|
+
return SqlExpressionWithOver.create("LAST_VALUE(" + col.expression + ")", undefined)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export function NTH_VALUE<Type, TableRef>(col: Expr<TableRef, string | unknown, Type>, value: number): ExprWithOver<TableRef, unknown, Type> {
|
|
412
|
+
return SqlExpressionWithOver.create("NTH_VALUE(" + col.expression + "," + (value ? Number(value) : 0) + ")", undefined)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
// -------------------------------------------------------------------
|
|
417
|
+
// MISC
|
|
418
|
+
// -------------------------------------------------------------------
|
|
419
|
+
|
|
420
|
+
export function BIN_TO_UUID<TableRef, Name>(col: Expr<TableRef, Name, any>): Expr<TableRef, Name, string> {
|
|
421
|
+
return SqlExpression.create("BIN_TO_UINT(" + col.expression + ")", col.nameAs)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// -------------------------------------------------------------------
|
|
425
|
+
// UTILITY
|
|
426
|
+
// -------------------------------------------------------------------
|
|
427
|
+
|
|
428
|
+
export function orderByStructureToSqlString(items: [] | OrderByStructure<any>): string[] {
|
|
429
|
+
const parts: string[] = [];
|
|
430
|
+
for (let i = 0; i < items.length; i++) {
|
|
431
|
+
const item = items[i];
|
|
432
|
+
if (item === undefined || item === null || item === "") {
|
|
433
|
+
// skip
|
|
434
|
+
} else if (item === "asc" || item === "ASC") {
|
|
435
|
+
parts[parts.length - 1] += " ASC"
|
|
436
|
+
} else if (item === "desc" || item === "DESC") {
|
|
437
|
+
parts[parts.length - 1] += " DESC"
|
|
438
|
+
} else if (item instanceof SqlExpression) {
|
|
439
|
+
parts.push(item.expression)
|
|
440
|
+
} else if (typeof item === "string") {
|
|
441
|
+
parts.push(escapeId(item))
|
|
442
|
+
} else {
|
|
443
|
+
throw new Error("Invalid argument to having! Type: '" + (typeof item) + "' String: '" + String(item) + "'")
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return parts;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export function toSql(e: unknown | number | string | boolean | PrepareQueryArgument | AnyExpr | any): string | number {
|
|
450
|
+
if (typeof e === "string") {
|
|
451
|
+
return escape(e);
|
|
452
|
+
} else if (typeof e === "number") {
|
|
453
|
+
return Number(e);
|
|
454
|
+
} else if (e === null || e === undefined) {
|
|
455
|
+
return "NULL";
|
|
456
|
+
} else if (e === true) {
|
|
457
|
+
return "1";
|
|
458
|
+
} else if (e === false) {
|
|
459
|
+
return "0";
|
|
460
|
+
} else if (e instanceof SqlExpression) {
|
|
461
|
+
return e.expression
|
|
462
|
+
} else if (isPrepareArgument(e)) {
|
|
463
|
+
return e.expression;
|
|
464
|
+
} else if (Array.isArray(e)) {
|
|
465
|
+
return e.map(toSql).join(", ")
|
|
466
|
+
} else if (typeof e === "object") {
|
|
467
|
+
return escape(JSON.stringify(e));
|
|
468
|
+
} else {
|
|
469
|
+
throw new Error("Invalid argument of type " + (typeof e) + "! toString: " + String(e));
|
|
470
|
+
}
|
|
471
|
+
}
|