prisma-ts-select 0.0.33 → 0.1.2
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 -0
- package/README.md +1455 -263
- package/dist/bin.cjs +1 -1
- package/dist/bin.js +1 -1
- package/dist/chunk-47KZVQLD.js +283 -0
- package/dist/chunk-54D2J5AR.cjs +291 -0
- package/dist/extend/dialects/index.d.ts +13 -0
- package/dist/extend/dialects/index.js +186 -0
- package/dist/extend/dialects/mysql-v6.d.ts +100 -0
- package/dist/extend/dialects/mysql-v6.js +152 -0
- package/dist/extend/dialects/mysql-v7.d.ts +6 -0
- package/dist/extend/dialects/mysql-v7.js +138 -0
- package/dist/extend/dialects/mysql.d.ts +90 -0
- package/dist/extend/dialects/mysql.js +156 -0
- package/dist/extend/dialects/postgresql-v6.d.ts +97 -0
- package/dist/extend/dialects/postgresql-v6.js +136 -0
- package/dist/extend/dialects/postgresql-v7.d.ts +97 -0
- package/dist/extend/dialects/postgresql-v7.js +136 -0
- package/dist/extend/dialects/postgresql.d.ts +89 -0
- package/dist/extend/dialects/postgresql.js +147 -0
- package/dist/extend/dialects/shared.d.ts +6 -0
- package/dist/extend/dialects/shared.js +5 -0
- package/dist/extend/dialects/sqlite.d.ts +63 -0
- package/dist/extend/dialects/sqlite.js +138 -0
- package/dist/extend/dialects/types.d.ts +12 -0
- package/dist/extend/dialects/types.js +4 -0
- package/dist/extend/extend.d.ts +342 -57
- package/dist/extend/extend.js +813 -161
- package/dist/extend/sql-expr-BaKWzJ-r.d.ts +10 -0
- package/dist/extend/types-D84lxYVc.d.ts +5 -0
- package/dist/generator.cjs +1 -1
- package/dist/generator.js +1 -1
- package/package.json +52 -41
- package/built/extend.cjs +0 -565
- package/built/extend.d.cts +0 -451
- package/built/extend.d.ts +0 -451
- package/built/extend.js +0 -563
- package/dist/chunk-G66FOFCO.cjs +0 -195
- package/dist/chunk-GBXPF5FT.js +0 -187
- package/dist/extend/extend.cjs +0 -277
- package/dist/extend/extend.d.cts +0 -222
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// src/dialects/types.ts
|
|
2
|
+
var SUPPORTED_PROVIDERS = ["sqlite", "mysql", "postgresql"];
|
|
3
|
+
|
|
4
|
+
// src/sql-expr.ts
|
|
5
|
+
function sqlExpr(sql) {
|
|
6
|
+
return { sql, toString() {
|
|
7
|
+
return sql;
|
|
8
|
+
} };
|
|
9
|
+
}
|
|
10
|
+
function resolveArg(arg, quoteFn) {
|
|
11
|
+
if (typeof arg !== "string") return arg.sql;
|
|
12
|
+
return quoteFn(arg);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/dialects/sqlite.ts
|
|
16
|
+
var SQLITE_CAST_TYPES = /* @__PURE__ */ new Set(["INTEGER", "TEXT", "REAL", "NUMERIC", "BLOB"]);
|
|
17
|
+
var dateArg = (col, quoteFn) => {
|
|
18
|
+
if (typeof col !== "string") return col.sql;
|
|
19
|
+
const ref = quoteFn(col);
|
|
20
|
+
return `CASE WHEN typeof(${ref}) = 'integer' THEN datetime(${ref}/1000, 'unixepoch') ELSE ${ref} END`;
|
|
21
|
+
};
|
|
22
|
+
var sqliteContextFns = (quoteFn, condFn) => ({
|
|
23
|
+
avg: (col) => sqlExpr(`AVG(${resolveArg(col, quoteFn)})`),
|
|
24
|
+
// SQLite SUM returns INTEGER (→ bigint) for integer columns, REAL (→ number) for float columns
|
|
25
|
+
sum: (col) => sqlExpr(`SUM(${resolveArg(col, quoteFn)})`),
|
|
26
|
+
// Aggregate integer-result fns — SQLite returns INTEGER → bigint
|
|
27
|
+
countAll: () => sqlExpr("COUNT(*)"),
|
|
28
|
+
count: (col) => sqlExpr(col === "*" ? "COUNT(*)" : `COUNT(${quoteFn(col)})`),
|
|
29
|
+
countDistinct: (col) => sqlExpr(`COUNT(DISTINCT ${quoteFn(col)})`),
|
|
30
|
+
// LENGTH returns INTEGER → bigint in SQLite
|
|
31
|
+
length: (col) => sqlExpr(`LENGTH(${resolveArg(col, quoteFn)})`),
|
|
32
|
+
groupConcat: (col, sep) => sqlExpr(`GROUP_CONCAT(${quoteFn(col)}${sep !== void 0 ? `, '${sep.replace(/'/g, "''")}'` : ""})`),
|
|
33
|
+
total: (col) => sqlExpr(`TOTAL(${quoteFn(col)})`),
|
|
34
|
+
// SQLite MIN/MAX return bigint for integer columns — override base (number) return types
|
|
35
|
+
min: (col) => sqlExpr(`MIN(${quoteFn(col)})`),
|
|
36
|
+
max: (col) => sqlExpr(`MAX(${quoteFn(col)})`),
|
|
37
|
+
concat: (...args) => {
|
|
38
|
+
if (args.length === 0) throw new Error("concat: requires at least one argument");
|
|
39
|
+
return sqlExpr(args.map((a) => resolveArg(a, quoteFn)).join(" || "));
|
|
40
|
+
},
|
|
41
|
+
substr: (col, start, len) => sqlExpr(`SUBSTR(${resolveArg(col, quoteFn)}, ${start}${len !== void 0 ? `, ${len}` : ""})`),
|
|
42
|
+
instr: (col, substr) => sqlExpr(`INSTR(${resolveArg(col, quoteFn)}, '${substr.replace(/'/g, "''")}')`),
|
|
43
|
+
char: (...codes) => sqlExpr(`CHAR(${codes.join(", ")})`),
|
|
44
|
+
hex: (col) => sqlExpr(`HEX(${resolveArg(col, quoteFn)})`),
|
|
45
|
+
unicode: (col) => sqlExpr(`UNICODE(${resolveArg(col, quoteFn)})`),
|
|
46
|
+
// Control flow
|
|
47
|
+
// Note: SQLite has no GREATEST()/LEAST() functions — it uses scalar MAX(a,b)/MIN(a,b) instead.
|
|
48
|
+
// Omitted here because the naming diverges from the MySQL/PG convention.
|
|
49
|
+
iif: (cond, trueVal, falseVal) => {
|
|
50
|
+
const condSql = typeof cond === "object" && cond !== null && "sql" in cond ? cond.sql : condFn(cond);
|
|
51
|
+
return sqlExpr(`IIF(${condSql}, ${trueVal.sql}, ${falseVal.sql})`);
|
|
52
|
+
},
|
|
53
|
+
ifNull: (col, fallback) => sqlExpr(`IFNULL(${resolveArg(col, quoteFn)}, ${fallback.sql})`),
|
|
54
|
+
// DateTime overrides
|
|
55
|
+
now: () => sqlExpr(`datetime('now')`),
|
|
56
|
+
curDate: () => sqlExpr(`date('now')`),
|
|
57
|
+
year: (col) => sqlExpr(`strftime('%Y', ${dateArg(col, quoteFn)})`),
|
|
58
|
+
month: (col) => sqlExpr(`strftime('%m', ${dateArg(col, quoteFn)})`),
|
|
59
|
+
day: (col) => sqlExpr(`strftime('%d', ${dateArg(col, quoteFn)})`),
|
|
60
|
+
hour: (col) => sqlExpr(`strftime('%H', ${dateArg(col, quoteFn)})`),
|
|
61
|
+
minute: (col) => sqlExpr(`strftime('%M', ${dateArg(col, quoteFn)})`),
|
|
62
|
+
second: (col) => sqlExpr(`strftime('%S', ${dateArg(col, quoteFn)})`),
|
|
63
|
+
// SQLite-only DateTime fns
|
|
64
|
+
/**
|
|
65
|
+
* SQLite `strftime` returns `NULL` if the date value is `NULL` or cannot be parsed.
|
|
66
|
+
* Unknown format directives (e.g. `%q`) are passed through literally, not as errors.
|
|
67
|
+
*/
|
|
68
|
+
strftime: (fmt, col) => sqlExpr(`strftime('${fmt.replace(/'/g, "''")}', ${dateArg(col, quoteFn)})`),
|
|
69
|
+
julianday: (col) => sqlExpr(`julianday(${dateArg(col, quoteFn)})`),
|
|
70
|
+
date: (col) => sqlExpr(`date(${dateArg(col, quoteFn)})`),
|
|
71
|
+
datetime: (col) => sqlExpr(`datetime(${dateArg(col, quoteFn)})`),
|
|
72
|
+
// ── Math ─────────────────────────────────────────────────────────────────
|
|
73
|
+
// SQLite returns bigint for integer results (ceil, floor, sign, mod) and number for floats.
|
|
74
|
+
// All inputs accept SQLExpr<number | bigint> so composed calls (e.g. sqrt(power(...))) type-check.
|
|
75
|
+
// sqrt/exp always return REAL, so they are typed as number.
|
|
76
|
+
abs: (col) => sqlExpr(`ABS(${resolveArg(col, quoteFn)})`),
|
|
77
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
78
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`),
|
|
79
|
+
round: (col, decimals) => sqlExpr(decimals !== void 0 ? `ROUND(${resolveArg(col, quoteFn)}, ${decimals})` : `ROUND(${resolveArg(col, quoteFn)})`),
|
|
80
|
+
// SQLite's POWER() always returns REAL regardless of input type
|
|
81
|
+
power: (base, exp) => sqlExpr(`POWER(${resolveArg(base, quoteFn)}, ${typeof exp === "number" ? exp : exp.sql})`),
|
|
82
|
+
sqrt: (col) => sqlExpr(`SQRT(${resolveArg(col, quoteFn)})`),
|
|
83
|
+
mod: (col, divisor) => sqlExpr(`MOD(${resolveArg(col, quoteFn)}, ${divisor})`),
|
|
84
|
+
sign: (col) => sqlExpr(`SIGN(${resolveArg(col, quoteFn)})`),
|
|
85
|
+
exp: (col) => sqlExpr(`EXP(${resolveArg(col, quoteFn)})`),
|
|
86
|
+
// ── Math (SQLite 3.35+) ──────────────────────────────────────────────────
|
|
87
|
+
// SQLite RANDOM() returns a 64-bit signed integer — always bigint
|
|
88
|
+
random: () => sqlExpr("RANDOM()"),
|
|
89
|
+
log: (x) => sqlExpr(`LOG(${resolveArg(x, quoteFn)})`),
|
|
90
|
+
log2: (x) => sqlExpr(`LOG2(${resolveArg(x, quoteFn)})`),
|
|
91
|
+
log10: (x) => sqlExpr(`LOG10(${resolveArg(x, quoteFn)})`),
|
|
92
|
+
// ── Type coercion ────────────────────────────────────────────────────────
|
|
93
|
+
cast: (expr, type) => {
|
|
94
|
+
if (!SQLITE_CAST_TYPES.has(type)) throw new Error(`cast: invalid cast type '${String(type)}'`);
|
|
95
|
+
return sqlExpr(`CAST(${resolveArg(expr, quoteFn)} AS ${type})`);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
var sqliteDialect = {
|
|
99
|
+
name: "sqlite",
|
|
100
|
+
needsBooleanCoercion: () => true,
|
|
101
|
+
quote: (name, _isAlias) => {
|
|
102
|
+
if (_isAlias) return "`" + name + "`";
|
|
103
|
+
return name;
|
|
104
|
+
},
|
|
105
|
+
quoteTableIdentifier: (name, _isAlias) => {
|
|
106
|
+
if (_isAlias) return "`" + name + "`";
|
|
107
|
+
return name;
|
|
108
|
+
},
|
|
109
|
+
quoteQualifiedColumn: (ref) => {
|
|
110
|
+
if (!ref.includes(".")) return ref;
|
|
111
|
+
const [table, col] = ref.split(".", 2);
|
|
112
|
+
return `${table}.${col}`;
|
|
113
|
+
},
|
|
114
|
+
quoteOrderByClause: (clause) => {
|
|
115
|
+
const parts = clause.trim().split(/\s+/);
|
|
116
|
+
const colRef = parts[0] ?? "";
|
|
117
|
+
const suffix = parts.slice(1).join(" ");
|
|
118
|
+
const quoted = colRef.includes(".") ? (() => {
|
|
119
|
+
const [table, col] = colRef.split(".", 2);
|
|
120
|
+
return `${table}.${col}`;
|
|
121
|
+
})() : `${colRef}`;
|
|
122
|
+
return suffix ? `${quoted} ${suffix}` : quoted;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// src/dialects/mysql.ts
|
|
127
|
+
var mysqlDialect = {
|
|
128
|
+
name: "mysql",
|
|
129
|
+
needsBooleanCoercion: () => true,
|
|
130
|
+
quote: (id, _isAlias) => `\`${id}\``,
|
|
131
|
+
quoteTableIdentifier: (name, _isAlias) => `\`${name}\``,
|
|
132
|
+
quoteQualifiedColumn: (ref) => {
|
|
133
|
+
if (!ref.includes(".")) return `\`${ref}\``;
|
|
134
|
+
const [table, col] = ref.split(".", 2);
|
|
135
|
+
return `\`${table}\`.\`${col}\``;
|
|
136
|
+
},
|
|
137
|
+
quoteOrderByClause: (clause) => {
|
|
138
|
+
const parts = clause.trim().split(/\s+/);
|
|
139
|
+
const colRef = parts[0] ?? "";
|
|
140
|
+
const suffix = parts.slice(1).join(" ");
|
|
141
|
+
const quoted = colRef.includes(".") ? (() => {
|
|
142
|
+
const [table, col] = colRef.split(".", 2);
|
|
143
|
+
return `\`${table}\`.\`${col}\``;
|
|
144
|
+
})() : `\`${colRef}\``;
|
|
145
|
+
return suffix ? `${quoted} ${suffix}` : quoted;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// src/dialects/postgresql.ts
|
|
150
|
+
var postgresqlDialect = {
|
|
151
|
+
name: "postgresql",
|
|
152
|
+
needsBooleanCoercion: () => false,
|
|
153
|
+
quote: (id, _isAlias) => `"${id}"`,
|
|
154
|
+
quoteTableIdentifier: (name, _isAlias) => `"${name}"`,
|
|
155
|
+
quoteQualifiedColumn: (ref) => {
|
|
156
|
+
if (!ref.includes(".")) return `"${ref}"`;
|
|
157
|
+
const [table, col] = ref.split(".", 2);
|
|
158
|
+
return `"${table}"."${col}"`;
|
|
159
|
+
},
|
|
160
|
+
quoteOrderByClause: (clause) => {
|
|
161
|
+
const parts = clause.trim().split(/\s+/);
|
|
162
|
+
const colRef = parts[0] ?? "";
|
|
163
|
+
const suffix = parts.slice(1).join(" ");
|
|
164
|
+
const quoted = colRef.includes(".") ? (() => {
|
|
165
|
+
const [table, col] = colRef.split(".", 2);
|
|
166
|
+
return `"${table}"."${col}"`;
|
|
167
|
+
})() : `"${colRef}"`;
|
|
168
|
+
return suffix ? `${quoted} ${suffix}` : quoted;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// src/dialects/index.ts
|
|
173
|
+
function getDialect(provider) {
|
|
174
|
+
switch (provider) {
|
|
175
|
+
case "sqlite":
|
|
176
|
+
return sqliteDialect;
|
|
177
|
+
case "mysql":
|
|
178
|
+
return mysqlDialect;
|
|
179
|
+
case "postgresql":
|
|
180
|
+
return postgresqlDialect;
|
|
181
|
+
default:
|
|
182
|
+
return sqliteDialect;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export { SUPPORTED_PROVIDERS, sqliteDialect as dialect, sqliteContextFns as dialectContextFns, getDialect, mysqlDialect, postgresqlDialect, sqliteDialect };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { IntervalUnit } from './mysql.js';
|
|
2
|
+
export { mysqlDialect } from './mysql.js';
|
|
3
|
+
import { J as JSONValue } from '../types-D84lxYVc.js';
|
|
4
|
+
import * as _prisma_client_runtime_client from '@prisma/client/runtime/client';
|
|
5
|
+
import { S as SQLExpr } from '../sql-expr-BaKWzJ-r.js';
|
|
6
|
+
import { ColName, FilterCols } from './shared.js';
|
|
7
|
+
import './types.js';
|
|
8
|
+
|
|
9
|
+
declare const mysqlV6ContextFns: <TColEntries extends [string, unknown] = never, TCriteria extends object = object>(quoteFn: (ref: string) => string, condFn: (criteria: TCriteria) => string) => {
|
|
10
|
+
countAll: () => SQLExpr<bigint>;
|
|
11
|
+
count: (col: ColName<TColEntries> | "*") => SQLExpr<bigint>;
|
|
12
|
+
countDistinct: (col: ColName<TColEntries>) => SQLExpr<bigint>;
|
|
13
|
+
length: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<bigint>;
|
|
14
|
+
abs: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<bigint | number>;
|
|
15
|
+
ceil: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<bigint | number>;
|
|
16
|
+
floor: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<bigint | number>;
|
|
17
|
+
mod: (col: FilterCols<TColEntries, number> | SQLExpr<number>, divisor: number) => SQLExpr<bigint | number>;
|
|
18
|
+
sign: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<bigint | number>;
|
|
19
|
+
avg: (col: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<_prisma_client_runtime_client.Decimal>;
|
|
20
|
+
sum: (col: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<_prisma_client_runtime_client.Decimal>;
|
|
21
|
+
groupConcat: (col: ColName<TColEntries>, sep?: string) => SQLExpr<string>;
|
|
22
|
+
bitAnd: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
23
|
+
bitOr: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
24
|
+
bitXor: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
25
|
+
stddev: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
26
|
+
stddevSamp: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
27
|
+
variance: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
28
|
+
varSamp: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
29
|
+
jsonArrayAgg: (col: ColName<TColEntries>) => SQLExpr<JSONValue>;
|
|
30
|
+
jsonObjectAgg: (key: ColName<TColEntries>, val: ColName<TColEntries>) => SQLExpr<JSONValue>;
|
|
31
|
+
concat: (args_0: SQLExpr<string> | FilterCols<TColEntries, string>, ...args: (SQLExpr<string> | FilterCols<TColEntries, string>)[]) => SQLExpr<string>;
|
|
32
|
+
substring: (col: SQLExpr<string> | FilterCols<TColEntries, string>, start: number, len?: number) => SQLExpr<string>;
|
|
33
|
+
left: (col: SQLExpr<string> | FilterCols<TColEntries, string>, n: number) => SQLExpr<string>;
|
|
34
|
+
right: (col: SQLExpr<string> | FilterCols<TColEntries, string>, n: number) => SQLExpr<string>;
|
|
35
|
+
repeat: (col: SQLExpr<string> | FilterCols<TColEntries, string>, n: number) => SQLExpr<string>;
|
|
36
|
+
reverse: (col: SQLExpr<string> | FilterCols<TColEntries, string>) => SQLExpr<string>;
|
|
37
|
+
lpad: (col: SQLExpr<string> | FilterCols<TColEntries, string>, len: number, pad: string) => SQLExpr<string>;
|
|
38
|
+
rpad: (col: SQLExpr<string> | FilterCols<TColEntries, string>, len: number, pad: string) => SQLExpr<string>;
|
|
39
|
+
locate: (substr: string, col: SQLExpr<string> | FilterCols<TColEntries, string>) => SQLExpr<bigint>;
|
|
40
|
+
space: (n: number) => SQLExpr<string>;
|
|
41
|
+
now: () => SQLExpr<Date>;
|
|
42
|
+
curDate: () => SQLExpr<Date>;
|
|
43
|
+
year: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<bigint>;
|
|
44
|
+
month: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<bigint>;
|
|
45
|
+
day: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<bigint>;
|
|
46
|
+
hour: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<bigint>;
|
|
47
|
+
minute: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<number>;
|
|
48
|
+
second: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<number>;
|
|
49
|
+
$if: <T>(cond: SQLExpr<unknown> | TCriteria, trueVal: SQLExpr<T>, falseVal: SQLExpr<T>) => SQLExpr<T>;
|
|
50
|
+
ifNull: <T>(col: FilterCols<TColEntries, T> | SQLExpr<T>, fallback: SQLExpr<NonNullable<T>>) => SQLExpr<NonNullable<T>>;
|
|
51
|
+
greatest: <T>(args_0: FilterCols<TColEntries, T> | SQLExpr<T>, ...args: (FilterCols<TColEntries, T> | SQLExpr<T>)[]) => SQLExpr<T | null>;
|
|
52
|
+
least: <T>(args_0: FilterCols<TColEntries, T> | SQLExpr<T>, ...args: (FilterCols<TColEntries, T> | SQLExpr<T>)[]) => SQLExpr<T | null>;
|
|
53
|
+
dateAdd: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>, n: number, unit: IntervalUnit) => SQLExpr<Date>;
|
|
54
|
+
dateSub: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>, n: number, unit: IntervalUnit) => SQLExpr<Date>;
|
|
55
|
+
dateFormat: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>, fmt: string) => SQLExpr<string>;
|
|
56
|
+
dateDiff: (d1: SQLExpr<Date> | FilterCols<TColEntries, Date>, d2: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<number>;
|
|
57
|
+
quarter: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<bigint>;
|
|
58
|
+
weekOfYear: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<number>;
|
|
59
|
+
dayName: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<string>;
|
|
60
|
+
lastDay: (col: SQLExpr<Date> | FilterCols<TColEntries, Date>) => SQLExpr<Date>;
|
|
61
|
+
round: (col: SQLExpr<number> | FilterCols<TColEntries, number>, decimals?: number) => SQLExpr<number>;
|
|
62
|
+
power: (base: SQLExpr<number> | FilterCols<TColEntries, number>, exp: number | SQLExpr<number>) => SQLExpr<number>;
|
|
63
|
+
sqrt: (col: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
64
|
+
exp: (col: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
65
|
+
pi: () => SQLExpr<number>;
|
|
66
|
+
ln: (x: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
67
|
+
log: (x: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
68
|
+
log2: (x: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
69
|
+
log10: (x: SQLExpr<number> | FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
70
|
+
truncate: (x: SQLExpr<number> | FilterCols<TColEntries, number>, n: number) => SQLExpr<number>;
|
|
71
|
+
rand: (seed?: number) => SQLExpr<number>;
|
|
72
|
+
cast: <T extends keyof {
|
|
73
|
+
SIGNED: bigint;
|
|
74
|
+
UNSIGNED: bigint;
|
|
75
|
+
DECIMAL: _prisma_client_runtime_client.Decimal;
|
|
76
|
+
CHAR: string;
|
|
77
|
+
BINARY: Buffer;
|
|
78
|
+
DATE: Date;
|
|
79
|
+
DATETIME: Date;
|
|
80
|
+
TIME: string;
|
|
81
|
+
JSON: JSONValue;
|
|
82
|
+
FLOAT: number;
|
|
83
|
+
DOUBLE: number;
|
|
84
|
+
}>(expr: SQLExpr<unknown> | ColName<TColEntries>, type: T) => SQLExpr<{
|
|
85
|
+
SIGNED: bigint;
|
|
86
|
+
UNSIGNED: bigint;
|
|
87
|
+
DECIMAL: _prisma_client_runtime_client.Decimal;
|
|
88
|
+
CHAR: string;
|
|
89
|
+
BINARY: Buffer;
|
|
90
|
+
DATE: Date;
|
|
91
|
+
DATETIME: Date;
|
|
92
|
+
TIME: string;
|
|
93
|
+
JSON: JSONValue;
|
|
94
|
+
FLOAT: number;
|
|
95
|
+
DOUBLE: number;
|
|
96
|
+
}[T]>;
|
|
97
|
+
};
|
|
98
|
+
type DialectFns<TColEntries extends [string, unknown] = never, TCriteria extends object = object> = ReturnType<typeof mysqlV6ContextFns<TColEntries, TCriteria>>;
|
|
99
|
+
|
|
100
|
+
export { type DialectFns, IntervalUnit, mysqlV6ContextFns };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// src/sql-expr.ts
|
|
2
|
+
function sqlExpr(sql) {
|
|
3
|
+
return { sql, toString() {
|
|
4
|
+
return sql;
|
|
5
|
+
} };
|
|
6
|
+
}
|
|
7
|
+
function resolveArg(arg, quoteFn) {
|
|
8
|
+
if (typeof arg !== "string") return arg.sql;
|
|
9
|
+
return quoteFn(arg);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/dialects/shared.ts
|
|
13
|
+
var esc = (s) => s.replace(/'/g, "''");
|
|
14
|
+
|
|
15
|
+
// src/dialects/mysql.ts
|
|
16
|
+
var MYSQL_CAST_TYPES = /* @__PURE__ */ new Set(["SIGNED", "UNSIGNED", "DECIMAL", "CHAR", "BINARY", "DATE", "DATETIME", "TIME", "JSON", "FLOAT", "DOUBLE"]);
|
|
17
|
+
var mysqlContextFns = (quoteFn, condFn) => ({
|
|
18
|
+
avg: (col) => sqlExpr(`AVG(${resolveArg(col, quoteFn)})`),
|
|
19
|
+
sum: (col) => sqlExpr(`SUM(${resolveArg(col, quoteFn)})`),
|
|
20
|
+
countAll: () => sqlExpr("COUNT(*)"),
|
|
21
|
+
count: (col) => sqlExpr(col === "*" ? "COUNT(*)" : `COUNT(${quoteFn(col)})`),
|
|
22
|
+
countDistinct: (col) => sqlExpr(`COUNT(DISTINCT ${quoteFn(col)})`),
|
|
23
|
+
length: (col) => sqlExpr(`LENGTH(${resolveArg(col, quoteFn)})`),
|
|
24
|
+
groupConcat: (col, sep) => sqlExpr(`GROUP_CONCAT(${quoteFn(col)}${sep !== void 0 ? ` SEPARATOR '${esc(sep)}'` : ""})`),
|
|
25
|
+
bitAnd: (col) => sqlExpr(`BIT_AND(${quoteFn(col)})`),
|
|
26
|
+
bitOr: (col) => sqlExpr(`BIT_OR(${quoteFn(col)})`),
|
|
27
|
+
bitXor: (col) => sqlExpr(`BIT_XOR(${quoteFn(col)})`),
|
|
28
|
+
stddev: (col) => sqlExpr(`STDDEV(${quoteFn(col)})`),
|
|
29
|
+
stddevSamp: (col) => sqlExpr(`STDDEV_SAMP(${quoteFn(col)})`),
|
|
30
|
+
variance: (col) => sqlExpr(`VARIANCE(${quoteFn(col)})`),
|
|
31
|
+
varSamp: (col) => sqlExpr(`VAR_SAMP(${quoteFn(col)})`),
|
|
32
|
+
jsonArrayAgg: (col) => sqlExpr(`JSON_ARRAYAGG(${quoteFn(col)})`),
|
|
33
|
+
jsonObjectAgg: (key, val) => sqlExpr(`JSON_OBJECTAGG(${quoteFn(key)}, ${quoteFn(val)})`),
|
|
34
|
+
concat: (...args) => {
|
|
35
|
+
if (args.length === 0) throw new Error("concat: requires at least one argument");
|
|
36
|
+
return sqlExpr(`CONCAT(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
37
|
+
},
|
|
38
|
+
substring: (col, start, len) => sqlExpr(`SUBSTRING(${resolveArg(col, quoteFn)}, ${start}${len !== void 0 ? `, ${len}` : ""})`),
|
|
39
|
+
left: (col, n) => sqlExpr(`LEFT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
40
|
+
right: (col, n) => sqlExpr(`RIGHT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
41
|
+
repeat: (col, n) => sqlExpr(`REPEAT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
42
|
+
reverse: (col) => sqlExpr(`REVERSE(${resolveArg(col, quoteFn)})`),
|
|
43
|
+
lpad: (col, len, pad) => sqlExpr(`LPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
44
|
+
rpad: (col, len, pad) => sqlExpr(`RPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
45
|
+
locate: (substr, col) => sqlExpr(`LOCATE('${esc(substr)}', ${resolveArg(col, quoteFn)})`),
|
|
46
|
+
space: (n) => sqlExpr(`SPACE(${n})`),
|
|
47
|
+
// DateTime base fns (MySQL defaults)
|
|
48
|
+
now: () => sqlExpr("NOW()"),
|
|
49
|
+
curDate: () => sqlExpr("CURDATE()"),
|
|
50
|
+
year: (col) => sqlExpr(`YEAR(${resolveArg(col, quoteFn)})`),
|
|
51
|
+
month: (col) => sqlExpr(`MONTH(${resolveArg(col, quoteFn)})`),
|
|
52
|
+
day: (col) => sqlExpr(`DAY(${resolveArg(col, quoteFn)})`),
|
|
53
|
+
hour: (col) => sqlExpr(`HOUR(${resolveArg(col, quoteFn)})`),
|
|
54
|
+
minute: (col) => sqlExpr(`MINUTE(${resolveArg(col, quoteFn)})`),
|
|
55
|
+
second: (col) => sqlExpr(`SECOND(${resolveArg(col, quoteFn)})`),
|
|
56
|
+
// Control flow
|
|
57
|
+
$if: (cond, trueVal, falseVal) => {
|
|
58
|
+
const condSql = typeof cond === "object" && cond !== null && "sql" in cond ? cond.sql : condFn(cond);
|
|
59
|
+
return sqlExpr(`IF(${condSql}, ${trueVal.sql}, ${falseVal.sql})`);
|
|
60
|
+
},
|
|
61
|
+
ifNull: (col, fallback) => sqlExpr(`IFNULL(${resolveArg(col, quoteFn)}, ${fallback.sql})`),
|
|
62
|
+
// NULL-poisoned: returns NULL if any arg is NULL
|
|
63
|
+
greatest: (...args) => {
|
|
64
|
+
if (args.length === 0) throw new Error("greatest: requires at least one argument");
|
|
65
|
+
return sqlExpr(`GREATEST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
66
|
+
},
|
|
67
|
+
// NULL-poisoned: returns NULL if any arg is NULL
|
|
68
|
+
least: (...args) => {
|
|
69
|
+
if (args.length === 0) throw new Error("least: requires at least one argument");
|
|
70
|
+
return sqlExpr(`LEAST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
71
|
+
},
|
|
72
|
+
// DateTime fns (MySQL-only)
|
|
73
|
+
dateAdd: (col, n, unit) => {
|
|
74
|
+
if (!Number.isFinite(n)) throw new Error(`dateAdd: n must be a finite number, got ${n}`);
|
|
75
|
+
return sqlExpr(`DATE_ADD(${resolveArg(col, quoteFn)}, INTERVAL ${n} ${unit})`);
|
|
76
|
+
},
|
|
77
|
+
dateSub: (col, n, unit) => {
|
|
78
|
+
if (!Number.isFinite(n)) throw new Error(`dateSub: n must be a finite number, got ${n}`);
|
|
79
|
+
return sqlExpr(`DATE_SUB(${resolveArg(col, quoteFn)}, INTERVAL ${n} ${unit})`);
|
|
80
|
+
},
|
|
81
|
+
/**
|
|
82
|
+
* MySQL `DATE_FORMAT` returns `NULL` if the date column value is `NULL`.
|
|
83
|
+
* Unknown format specifiers are passed through literally, not as errors.
|
|
84
|
+
*/
|
|
85
|
+
dateFormat: (col, fmt) => sqlExpr(`DATE_FORMAT(${resolveArg(col, quoteFn)}, '${esc(fmt)}')`),
|
|
86
|
+
dateDiff: (d1, d2) => sqlExpr(`DATEDIFF(${resolveArg(d1, quoteFn)}, ${resolveArg(d2, quoteFn)})`),
|
|
87
|
+
quarter: (col) => sqlExpr(`QUARTER(${resolveArg(col, quoteFn)})`),
|
|
88
|
+
weekOfYear: (col) => sqlExpr(`WEEKOFYEAR(${resolveArg(col, quoteFn)})`),
|
|
89
|
+
dayName: (col) => sqlExpr(`DAYNAME(${resolveArg(col, quoteFn)})`),
|
|
90
|
+
lastDay: (col) => sqlExpr(`LAST_DAY(${resolveArg(col, quoteFn)})`),
|
|
91
|
+
// ── Math ─────────────────────────────────────────────────────────────────
|
|
92
|
+
abs: (col) => sqlExpr(`ABS(${resolveArg(col, quoteFn)})`),
|
|
93
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
94
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`),
|
|
95
|
+
round: (col, decimals) => sqlExpr(decimals !== void 0 ? `ROUND(${resolveArg(col, quoteFn)}, ${decimals})` : `ROUND(${resolveArg(col, quoteFn)})`),
|
|
96
|
+
power: (base, exp) => sqlExpr(`POWER(${resolveArg(base, quoteFn)}, ${typeof exp === "number" ? exp : exp.sql})`),
|
|
97
|
+
sqrt: (col) => sqlExpr(`SQRT(${resolveArg(col, quoteFn)})`),
|
|
98
|
+
mod: (col, divisor) => sqlExpr(`MOD(${resolveArg(col, quoteFn)}, ${divisor})`),
|
|
99
|
+
sign: (col) => sqlExpr(`SIGN(${resolveArg(col, quoteFn)})`),
|
|
100
|
+
exp: (col) => sqlExpr(`EXP(${resolveArg(col, quoteFn)})`),
|
|
101
|
+
// ── Math (MySQL-specific) ─────────────────────────────────────────────────
|
|
102
|
+
pi: () => sqlExpr("PI()"),
|
|
103
|
+
ln: (x) => sqlExpr(`LN(${resolveArg(x, quoteFn)})`),
|
|
104
|
+
/** Natural log (ln(x)). Use `log10(x)` for base-10. Note: PG `log(x)` is base-10 — opposite semantics. */
|
|
105
|
+
log: (x) => sqlExpr(`LOG(${resolveArg(x, quoteFn)})`),
|
|
106
|
+
log2: (x) => sqlExpr(`LOG2(${resolveArg(x, quoteFn)})`),
|
|
107
|
+
log10: (x) => sqlExpr(`LOG10(${resolveArg(x, quoteFn)})`),
|
|
108
|
+
truncate: (x, n) => sqlExpr(`TRUNCATE(${resolveArg(x, quoteFn)}, ${n})`),
|
|
109
|
+
rand: (seed) => sqlExpr(seed !== void 0 ? `RAND(${seed})` : "RAND()"),
|
|
110
|
+
// ── Type coercion ────────────────────────────────────────────────────────
|
|
111
|
+
cast: (expr, type) => {
|
|
112
|
+
if (!MYSQL_CAST_TYPES.has(type)) throw new Error(`cast: invalid cast type '${String(type)}'`);
|
|
113
|
+
return sqlExpr(`CAST(${resolveArg(expr, quoteFn)} AS ${type})`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
var mysqlDialect = {
|
|
117
|
+
name: "mysql",
|
|
118
|
+
needsBooleanCoercion: () => true,
|
|
119
|
+
quote: (id, _isAlias) => `\`${id}\``,
|
|
120
|
+
quoteTableIdentifier: (name, _isAlias) => `\`${name}\``,
|
|
121
|
+
quoteQualifiedColumn: (ref) => {
|
|
122
|
+
if (!ref.includes(".")) return `\`${ref}\``;
|
|
123
|
+
const [table, col] = ref.split(".", 2);
|
|
124
|
+
return `\`${table}\`.\`${col}\``;
|
|
125
|
+
},
|
|
126
|
+
quoteOrderByClause: (clause) => {
|
|
127
|
+
const parts = clause.trim().split(/\s+/);
|
|
128
|
+
const colRef = parts[0] ?? "";
|
|
129
|
+
const suffix = parts.slice(1).join(" ");
|
|
130
|
+
const quoted = colRef.includes(".") ? (() => {
|
|
131
|
+
const [table, col] = colRef.split(".", 2);
|
|
132
|
+
return `\`${table}\`.\`${col}\``;
|
|
133
|
+
})() : `\`${colRef}\``;
|
|
134
|
+
return suffix ? `${quoted} ${suffix}` : quoted;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// src/dialects/mysql-v6.ts
|
|
139
|
+
var mysqlV6ContextFns = (quoteFn, condFn) => ({
|
|
140
|
+
...mysqlContextFns(quoteFn, condFn),
|
|
141
|
+
countAll: () => sqlExpr("COUNT(*)"),
|
|
142
|
+
count: (col) => sqlExpr(col === "*" ? "COUNT(*)" : `COUNT(${quoteFn(col)})`),
|
|
143
|
+
countDistinct: (col) => sqlExpr(`COUNT(DISTINCT ${quoteFn(col)})`),
|
|
144
|
+
length: (col) => sqlExpr(`LENGTH(${resolveArg(col, quoteFn)})`),
|
|
145
|
+
abs: (col) => sqlExpr(`ABS(${resolveArg(col, quoteFn)})`),
|
|
146
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
147
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`),
|
|
148
|
+
mod: (col, divisor) => sqlExpr(`MOD(${resolveArg(col, quoteFn)}, ${divisor})`),
|
|
149
|
+
sign: (col) => sqlExpr(`SIGN(${resolveArg(col, quoteFn)})`)
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export { mysqlDialect, mysqlV6ContextFns };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// src/sql-expr.ts
|
|
2
|
+
function sqlExpr(sql) {
|
|
3
|
+
return { sql, toString() {
|
|
4
|
+
return sql;
|
|
5
|
+
} };
|
|
6
|
+
}
|
|
7
|
+
function resolveArg(arg, quoteFn) {
|
|
8
|
+
if (typeof arg !== "string") return arg.sql;
|
|
9
|
+
return quoteFn(arg);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/dialects/shared.ts
|
|
13
|
+
var esc = (s) => s.replace(/'/g, "''");
|
|
14
|
+
|
|
15
|
+
// src/dialects/mysql.ts
|
|
16
|
+
var MYSQL_CAST_TYPES = /* @__PURE__ */ new Set(["SIGNED", "UNSIGNED", "DECIMAL", "CHAR", "BINARY", "DATE", "DATETIME", "TIME", "JSON", "FLOAT", "DOUBLE"]);
|
|
17
|
+
var mysqlContextFns = (quoteFn, condFn) => ({
|
|
18
|
+
avg: (col) => sqlExpr(`AVG(${resolveArg(col, quoteFn)})`),
|
|
19
|
+
sum: (col) => sqlExpr(`SUM(${resolveArg(col, quoteFn)})`),
|
|
20
|
+
countAll: () => sqlExpr("COUNT(*)"),
|
|
21
|
+
count: (col) => sqlExpr(col === "*" ? "COUNT(*)" : `COUNT(${quoteFn(col)})`),
|
|
22
|
+
countDistinct: (col) => sqlExpr(`COUNT(DISTINCT ${quoteFn(col)})`),
|
|
23
|
+
length: (col) => sqlExpr(`LENGTH(${resolveArg(col, quoteFn)})`),
|
|
24
|
+
groupConcat: (col, sep) => sqlExpr(`GROUP_CONCAT(${quoteFn(col)}${sep !== void 0 ? ` SEPARATOR '${esc(sep)}'` : ""})`),
|
|
25
|
+
bitAnd: (col) => sqlExpr(`BIT_AND(${quoteFn(col)})`),
|
|
26
|
+
bitOr: (col) => sqlExpr(`BIT_OR(${quoteFn(col)})`),
|
|
27
|
+
bitXor: (col) => sqlExpr(`BIT_XOR(${quoteFn(col)})`),
|
|
28
|
+
stddev: (col) => sqlExpr(`STDDEV(${quoteFn(col)})`),
|
|
29
|
+
stddevSamp: (col) => sqlExpr(`STDDEV_SAMP(${quoteFn(col)})`),
|
|
30
|
+
variance: (col) => sqlExpr(`VARIANCE(${quoteFn(col)})`),
|
|
31
|
+
varSamp: (col) => sqlExpr(`VAR_SAMP(${quoteFn(col)})`),
|
|
32
|
+
jsonArrayAgg: (col) => sqlExpr(`JSON_ARRAYAGG(${quoteFn(col)})`),
|
|
33
|
+
jsonObjectAgg: (key, val) => sqlExpr(`JSON_OBJECTAGG(${quoteFn(key)}, ${quoteFn(val)})`),
|
|
34
|
+
concat: (...args) => {
|
|
35
|
+
if (args.length === 0) throw new Error("concat: requires at least one argument");
|
|
36
|
+
return sqlExpr(`CONCAT(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
37
|
+
},
|
|
38
|
+
substring: (col, start, len) => sqlExpr(`SUBSTRING(${resolveArg(col, quoteFn)}, ${start}${len !== void 0 ? `, ${len}` : ""})`),
|
|
39
|
+
left: (col, n) => sqlExpr(`LEFT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
40
|
+
right: (col, n) => sqlExpr(`RIGHT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
41
|
+
repeat: (col, n) => sqlExpr(`REPEAT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
42
|
+
reverse: (col) => sqlExpr(`REVERSE(${resolveArg(col, quoteFn)})`),
|
|
43
|
+
lpad: (col, len, pad) => sqlExpr(`LPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
44
|
+
rpad: (col, len, pad) => sqlExpr(`RPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
45
|
+
locate: (substr, col) => sqlExpr(`LOCATE('${esc(substr)}', ${resolveArg(col, quoteFn)})`),
|
|
46
|
+
space: (n) => sqlExpr(`SPACE(${n})`),
|
|
47
|
+
// DateTime base fns (MySQL defaults)
|
|
48
|
+
now: () => sqlExpr("NOW()"),
|
|
49
|
+
curDate: () => sqlExpr("CURDATE()"),
|
|
50
|
+
year: (col) => sqlExpr(`YEAR(${resolveArg(col, quoteFn)})`),
|
|
51
|
+
month: (col) => sqlExpr(`MONTH(${resolveArg(col, quoteFn)})`),
|
|
52
|
+
day: (col) => sqlExpr(`DAY(${resolveArg(col, quoteFn)})`),
|
|
53
|
+
hour: (col) => sqlExpr(`HOUR(${resolveArg(col, quoteFn)})`),
|
|
54
|
+
minute: (col) => sqlExpr(`MINUTE(${resolveArg(col, quoteFn)})`),
|
|
55
|
+
second: (col) => sqlExpr(`SECOND(${resolveArg(col, quoteFn)})`),
|
|
56
|
+
// Control flow
|
|
57
|
+
$if: (cond, trueVal, falseVal) => {
|
|
58
|
+
const condSql = typeof cond === "object" && cond !== null && "sql" in cond ? cond.sql : condFn(cond);
|
|
59
|
+
return sqlExpr(`IF(${condSql}, ${trueVal.sql}, ${falseVal.sql})`);
|
|
60
|
+
},
|
|
61
|
+
ifNull: (col, fallback) => sqlExpr(`IFNULL(${resolveArg(col, quoteFn)}, ${fallback.sql})`),
|
|
62
|
+
// NULL-poisoned: returns NULL if any arg is NULL
|
|
63
|
+
greatest: (...args) => {
|
|
64
|
+
if (args.length === 0) throw new Error("greatest: requires at least one argument");
|
|
65
|
+
return sqlExpr(`GREATEST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
66
|
+
},
|
|
67
|
+
// NULL-poisoned: returns NULL if any arg is NULL
|
|
68
|
+
least: (...args) => {
|
|
69
|
+
if (args.length === 0) throw new Error("least: requires at least one argument");
|
|
70
|
+
return sqlExpr(`LEAST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
71
|
+
},
|
|
72
|
+
// DateTime fns (MySQL-only)
|
|
73
|
+
dateAdd: (col, n, unit) => {
|
|
74
|
+
if (!Number.isFinite(n)) throw new Error(`dateAdd: n must be a finite number, got ${n}`);
|
|
75
|
+
return sqlExpr(`DATE_ADD(${resolveArg(col, quoteFn)}, INTERVAL ${n} ${unit})`);
|
|
76
|
+
},
|
|
77
|
+
dateSub: (col, n, unit) => {
|
|
78
|
+
if (!Number.isFinite(n)) throw new Error(`dateSub: n must be a finite number, got ${n}`);
|
|
79
|
+
return sqlExpr(`DATE_SUB(${resolveArg(col, quoteFn)}, INTERVAL ${n} ${unit})`);
|
|
80
|
+
},
|
|
81
|
+
/**
|
|
82
|
+
* MySQL `DATE_FORMAT` returns `NULL` if the date column value is `NULL`.
|
|
83
|
+
* Unknown format specifiers are passed through literally, not as errors.
|
|
84
|
+
*/
|
|
85
|
+
dateFormat: (col, fmt) => sqlExpr(`DATE_FORMAT(${resolveArg(col, quoteFn)}, '${esc(fmt)}')`),
|
|
86
|
+
dateDiff: (d1, d2) => sqlExpr(`DATEDIFF(${resolveArg(d1, quoteFn)}, ${resolveArg(d2, quoteFn)})`),
|
|
87
|
+
quarter: (col) => sqlExpr(`QUARTER(${resolveArg(col, quoteFn)})`),
|
|
88
|
+
weekOfYear: (col) => sqlExpr(`WEEKOFYEAR(${resolveArg(col, quoteFn)})`),
|
|
89
|
+
dayName: (col) => sqlExpr(`DAYNAME(${resolveArg(col, quoteFn)})`),
|
|
90
|
+
lastDay: (col) => sqlExpr(`LAST_DAY(${resolveArg(col, quoteFn)})`),
|
|
91
|
+
// ── Math ─────────────────────────────────────────────────────────────────
|
|
92
|
+
abs: (col) => sqlExpr(`ABS(${resolveArg(col, quoteFn)})`),
|
|
93
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
94
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`),
|
|
95
|
+
round: (col, decimals) => sqlExpr(decimals !== void 0 ? `ROUND(${resolveArg(col, quoteFn)}, ${decimals})` : `ROUND(${resolveArg(col, quoteFn)})`),
|
|
96
|
+
power: (base, exp) => sqlExpr(`POWER(${resolveArg(base, quoteFn)}, ${typeof exp === "number" ? exp : exp.sql})`),
|
|
97
|
+
sqrt: (col) => sqlExpr(`SQRT(${resolveArg(col, quoteFn)})`),
|
|
98
|
+
mod: (col, divisor) => sqlExpr(`MOD(${resolveArg(col, quoteFn)}, ${divisor})`),
|
|
99
|
+
sign: (col) => sqlExpr(`SIGN(${resolveArg(col, quoteFn)})`),
|
|
100
|
+
exp: (col) => sqlExpr(`EXP(${resolveArg(col, quoteFn)})`),
|
|
101
|
+
// ── Math (MySQL-specific) ─────────────────────────────────────────────────
|
|
102
|
+
pi: () => sqlExpr("PI()"),
|
|
103
|
+
ln: (x) => sqlExpr(`LN(${resolveArg(x, quoteFn)})`),
|
|
104
|
+
/** Natural log (ln(x)). Use `log10(x)` for base-10. Note: PG `log(x)` is base-10 — opposite semantics. */
|
|
105
|
+
log: (x) => sqlExpr(`LOG(${resolveArg(x, quoteFn)})`),
|
|
106
|
+
log2: (x) => sqlExpr(`LOG2(${resolveArg(x, quoteFn)})`),
|
|
107
|
+
log10: (x) => sqlExpr(`LOG10(${resolveArg(x, quoteFn)})`),
|
|
108
|
+
truncate: (x, n) => sqlExpr(`TRUNCATE(${resolveArg(x, quoteFn)}, ${n})`),
|
|
109
|
+
rand: (seed) => sqlExpr(seed !== void 0 ? `RAND(${seed})` : "RAND()"),
|
|
110
|
+
// ── Type coercion ────────────────────────────────────────────────────────
|
|
111
|
+
cast: (expr, type) => {
|
|
112
|
+
if (!MYSQL_CAST_TYPES.has(type)) throw new Error(`cast: invalid cast type '${String(type)}'`);
|
|
113
|
+
return sqlExpr(`CAST(${resolveArg(expr, quoteFn)} AS ${type})`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
var mysqlDialect = {
|
|
117
|
+
name: "mysql",
|
|
118
|
+
needsBooleanCoercion: () => true,
|
|
119
|
+
quote: (id, _isAlias) => `\`${id}\``,
|
|
120
|
+
quoteTableIdentifier: (name, _isAlias) => `\`${name}\``,
|
|
121
|
+
quoteQualifiedColumn: (ref) => {
|
|
122
|
+
if (!ref.includes(".")) return `\`${ref}\``;
|
|
123
|
+
const [table, col] = ref.split(".", 2);
|
|
124
|
+
return `\`${table}\`.\`${col}\``;
|
|
125
|
+
},
|
|
126
|
+
quoteOrderByClause: (clause) => {
|
|
127
|
+
const parts = clause.trim().split(/\s+/);
|
|
128
|
+
const colRef = parts[0] ?? "";
|
|
129
|
+
const suffix = parts.slice(1).join(" ");
|
|
130
|
+
const quoted = colRef.includes(".") ? (() => {
|
|
131
|
+
const [table, col] = colRef.split(".", 2);
|
|
132
|
+
return `\`${table}\`.\`${col}\``;
|
|
133
|
+
})() : `\`${colRef}\``;
|
|
134
|
+
return suffix ? `${quoted} ${suffix}` : quoted;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export { mysqlDialect, mysqlContextFns as mysqlV7ContextFns };
|