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,136 @@
|
|
|
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/postgresql.ts
|
|
16
|
+
var PG_CAST_TYPES = /* @__PURE__ */ new Set(["INTEGER", "TEXT", "BIGINT", "BOOLEAN", "REAL", "NUMERIC", "DATE", "TIMESTAMP", "JSON", "JSONB"]);
|
|
17
|
+
var postgresqlContextFns = (quoteFn) => ({
|
|
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
|
+
stringAgg: (col, sep) => sqlExpr(`STRING_AGG(${quoteFn(col)}, '${esc(sep)}')`),
|
|
25
|
+
arrayAgg: (col) => sqlExpr(`ARRAY_AGG(${quoteFn(col)})`),
|
|
26
|
+
stddevPop: (col) => sqlExpr(`STDDEV_POP(${quoteFn(col)})`),
|
|
27
|
+
stddevSamp: (col) => sqlExpr(`STDDEV_SAMP(${quoteFn(col)})`),
|
|
28
|
+
varPop: (col) => sqlExpr(`VAR_POP(${quoteFn(col)})`),
|
|
29
|
+
varSamp: (col) => sqlExpr(`VAR_SAMP(${quoteFn(col)})`),
|
|
30
|
+
boolAnd: (col) => sqlExpr(`BOOL_AND(${quoteFn(col)})`),
|
|
31
|
+
boolOr: (col) => sqlExpr(`BOOL_OR(${quoteFn(col)})`),
|
|
32
|
+
jsonAgg: (col) => sqlExpr(`JSON_AGG(${quoteFn(col)})`),
|
|
33
|
+
bitAnd: (col) => sqlExpr(`BIT_AND(${quoteFn(col)})`),
|
|
34
|
+
bitOr: (col) => sqlExpr(`BIT_OR(${quoteFn(col)})`),
|
|
35
|
+
jsonObjectAgg: (key, val) => sqlExpr(`JSON_OBJECT_AGG(${quoteFn(key)}, ${quoteFn(val)})`),
|
|
36
|
+
concat: (...args) => {
|
|
37
|
+
if (args.length === 0) throw new Error("concat: requires at least one argument");
|
|
38
|
+
return sqlExpr(`CONCAT(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
39
|
+
},
|
|
40
|
+
substring: (col, start, len) => sqlExpr(`SUBSTRING(${resolveArg(col, quoteFn)}, ${start}${len !== void 0 ? `, ${len}` : ""})`),
|
|
41
|
+
left: (col, n) => sqlExpr(`LEFT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
42
|
+
right: (col, n) => sqlExpr(`RIGHT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
43
|
+
repeat: (col, n) => sqlExpr(`REPEAT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
44
|
+
reverse: (col) => sqlExpr(`REVERSE(${resolveArg(col, quoteFn)})`),
|
|
45
|
+
lpad: (col, len, pad) => sqlExpr(`LPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
46
|
+
rpad: (col, len, pad) => sqlExpr(`RPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
47
|
+
initcap: (col) => sqlExpr(`INITCAP(${resolveArg(col, quoteFn)})`),
|
|
48
|
+
strpos: (col, substr) => sqlExpr(`STRPOS(${resolveArg(col, quoteFn)}, '${esc(substr)}')`),
|
|
49
|
+
splitPart: (col, delimiter, field) => sqlExpr(`SPLIT_PART(${resolveArg(col, quoteFn)}, '${esc(delimiter)}', ${field})`),
|
|
50
|
+
btrim: (col, chars) => sqlExpr(`BTRIM(${resolveArg(col, quoteFn)}${chars !== void 0 ? `, '${esc(chars)}'` : ""})`),
|
|
51
|
+
md5: (col) => sqlExpr(`MD5(${resolveArg(col, quoteFn)})`),
|
|
52
|
+
// Control flow
|
|
53
|
+
greatest: (...args) => {
|
|
54
|
+
if (args.length === 0) throw new Error("greatest: requires at least one argument");
|
|
55
|
+
return sqlExpr(`GREATEST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
56
|
+
},
|
|
57
|
+
least: (...args) => {
|
|
58
|
+
if (args.length === 0) throw new Error("least: requires at least one argument");
|
|
59
|
+
return sqlExpr(`LEAST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
60
|
+
},
|
|
61
|
+
// DateTime overrides
|
|
62
|
+
now: () => sqlExpr("NOW()"),
|
|
63
|
+
curDate: () => sqlExpr("CURRENT_DATE"),
|
|
64
|
+
year: (col) => sqlExpr(`EXTRACT(YEAR FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
65
|
+
month: (col) => sqlExpr(`EXTRACT(MONTH FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
66
|
+
day: (col) => sqlExpr(`EXTRACT(DAY FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
67
|
+
hour: (col) => sqlExpr(`EXTRACT(HOUR FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
68
|
+
minute: (col) => sqlExpr(`EXTRACT(MINUTE FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
69
|
+
second: (col) => sqlExpr(`EXTRACT(SECOND FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
70
|
+
// PG-only DateTime fns
|
|
71
|
+
extract: (field, col) => sqlExpr(`EXTRACT(${field} FROM ${resolveArg(col, quoteFn)})`),
|
|
72
|
+
dateTrunc: (unit, col) => sqlExpr(`DATE_TRUNC('${unit}', ${resolveArg(col, quoteFn)})`),
|
|
73
|
+
/**
|
|
74
|
+
* PG `AGE()` returns an `interval`. Typed as `string` since node-postgres serializes
|
|
75
|
+
* intervals as strings (e.g. `"1 year 2 mons 3 days"`). Arithmetic on the result
|
|
76
|
+
* must be done in SQL, not JS — use `sqlExpr` to compose further expressions.
|
|
77
|
+
*/
|
|
78
|
+
age: (ts1, ts2) => sqlExpr(ts2 !== void 0 ? `AGE(${resolveArg(ts1, quoteFn)}, ${resolveArg(ts2, quoteFn)})` : `AGE(${resolveArg(ts1, quoteFn)})`),
|
|
79
|
+
toDate: (text, fmt) => sqlExpr(`TO_DATE(${resolveArg(text, quoteFn)}, '${esc(fmt)}')`),
|
|
80
|
+
// ── Math ─────────────────────────────────────────────────────────────────
|
|
81
|
+
abs: (col) => sqlExpr(`ABS(${resolveArg(col, quoteFn)})`),
|
|
82
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
83
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`),
|
|
84
|
+
round: (col, decimals) => sqlExpr(decimals !== void 0 ? `ROUND(${resolveArg(col, quoteFn)}, ${decimals})` : `ROUND(${resolveArg(col, quoteFn)})`),
|
|
85
|
+
power: (base, exp) => sqlExpr(`POWER(${resolveArg(base, quoteFn)}, ${typeof exp === "number" ? exp : exp.sql})`),
|
|
86
|
+
sqrt: (col) => sqlExpr(`SQRT(${resolveArg(col, quoteFn)})`),
|
|
87
|
+
mod: (col, divisor) => sqlExpr(`MOD(${resolveArg(col, quoteFn)}, ${divisor})`),
|
|
88
|
+
sign: (col) => sqlExpr(`SIGN(${resolveArg(col, quoteFn)})`),
|
|
89
|
+
exp: (col) => sqlExpr(`EXP(${resolveArg(col, quoteFn)})`),
|
|
90
|
+
// ── Math (PostgreSQL-specific) ────────────────────────────────────────────
|
|
91
|
+
pi: () => sqlExpr("PI()"),
|
|
92
|
+
ln: (x) => sqlExpr(`LN(${resolveArg(x, quoteFn)})`),
|
|
93
|
+
log: (x) => sqlExpr(`LOG(${resolveArg(x, quoteFn)})`),
|
|
94
|
+
logBase: (base, x) => sqlExpr(`LOG(${base}, ${resolveArg(x, quoteFn)})`),
|
|
95
|
+
trunc: (x, n) => sqlExpr(n !== void 0 ? `TRUNC(${resolveArg(x, quoteFn)}, ${n})` : `TRUNC(${resolveArg(x, quoteFn)})`),
|
|
96
|
+
div: (x, y) => sqlExpr(`DIV(${resolveArg(x, quoteFn)}, ${y})`),
|
|
97
|
+
random: () => sqlExpr("RANDOM()"),
|
|
98
|
+
// ── Type coercion ────────────────────────────────────────────────────────
|
|
99
|
+
cast: (expr, type) => {
|
|
100
|
+
if (!PG_CAST_TYPES.has(type)) throw new Error(`cast: invalid cast type '${String(type)}'`);
|
|
101
|
+
return sqlExpr(`CAST(${resolveArg(expr, quoteFn)} AS ${type})`);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
var postgresqlDialect = {
|
|
105
|
+
name: "postgresql",
|
|
106
|
+
needsBooleanCoercion: () => false,
|
|
107
|
+
quote: (id, _isAlias) => `"${id}"`,
|
|
108
|
+
quoteTableIdentifier: (name, _isAlias) => `"${name}"`,
|
|
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/postgresql-v7.ts
|
|
127
|
+
var postgresqlV7ContextFns = (quoteFn) => ({
|
|
128
|
+
...postgresqlContextFns(quoteFn),
|
|
129
|
+
countAll: () => sqlExpr("COUNT(*)"),
|
|
130
|
+
count: (col) => sqlExpr(col === "*" ? "COUNT(*)" : `COUNT(${quoteFn(col)})`),
|
|
131
|
+
countDistinct: (col) => sqlExpr(`COUNT(DISTINCT ${quoteFn(col)})`),
|
|
132
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
133
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`)
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
export { postgresqlDialect, postgresqlV7ContextFns };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Dialect } from './types.js';
|
|
2
|
+
import { S as SQLExpr } from '../sql-expr-BaKWzJ-r.js';
|
|
3
|
+
import { J as JSONValue } from '../types-D84lxYVc.js';
|
|
4
|
+
import { FilterCols, ColName } from './shared.js';
|
|
5
|
+
import '@prisma/client/runtime/client';
|
|
6
|
+
|
|
7
|
+
type PgCastTypeMap = {
|
|
8
|
+
INTEGER: number;
|
|
9
|
+
TEXT: string;
|
|
10
|
+
BIGINT: bigint;
|
|
11
|
+
BOOLEAN: boolean;
|
|
12
|
+
REAL: number;
|
|
13
|
+
NUMERIC: number;
|
|
14
|
+
DATE: Date;
|
|
15
|
+
TIMESTAMP: Date;
|
|
16
|
+
JSON: JSONValue;
|
|
17
|
+
JSONB: JSONValue;
|
|
18
|
+
};
|
|
19
|
+
type PgExtractField = 'YEAR' | 'MONTH' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' | 'DOW' | 'DOY' | 'EPOCH' | 'WEEK' | 'QUARTER';
|
|
20
|
+
type PgDateTruncUnit = 'microseconds' | 'milliseconds' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year' | 'decade' | 'century' | 'millennium';
|
|
21
|
+
declare const postgresqlContextFns: <TColEntries extends [string, unknown] = never>(quoteFn: (ref: string) => string) => {
|
|
22
|
+
avg: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
23
|
+
sum: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
24
|
+
countAll: () => SQLExpr<number>;
|
|
25
|
+
count: (col: ColName<TColEntries> | "*") => SQLExpr<number>;
|
|
26
|
+
countDistinct: (col: ColName<TColEntries>) => SQLExpr<number>;
|
|
27
|
+
length: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<number>;
|
|
28
|
+
stringAgg: (col: ColName<TColEntries>, sep: string) => SQLExpr<string>;
|
|
29
|
+
arrayAgg: (col: ColName<TColEntries>) => SQLExpr<unknown[]>;
|
|
30
|
+
stddevPop: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
31
|
+
stddevSamp: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
32
|
+
varPop: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
33
|
+
varSamp: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
34
|
+
boolAnd: (col: FilterCols<TColEntries, boolean>) => SQLExpr<boolean>;
|
|
35
|
+
boolOr: (col: FilterCols<TColEntries, boolean>) => SQLExpr<boolean>;
|
|
36
|
+
jsonAgg: (col: ColName<TColEntries>) => SQLExpr<JSONValue[]>;
|
|
37
|
+
bitAnd: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
38
|
+
bitOr: (col: FilterCols<TColEntries, number>) => SQLExpr<number>;
|
|
39
|
+
jsonObjectAgg: (key: ColName<TColEntries>, val: ColName<TColEntries>) => SQLExpr<JSONValue>;
|
|
40
|
+
concat: (args_0: SQLExpr<string> | FilterCols<TColEntries, string>, ...args: (SQLExpr<string> | FilterCols<TColEntries, string>)[]) => SQLExpr<string>;
|
|
41
|
+
substring: (col: FilterCols<TColEntries, string> | SQLExpr<string>, start: number, len?: number) => SQLExpr<string>;
|
|
42
|
+
left: (col: FilterCols<TColEntries, string> | SQLExpr<string>, n: number) => SQLExpr<string>;
|
|
43
|
+
right: (col: FilterCols<TColEntries, string> | SQLExpr<string>, n: number) => SQLExpr<string>;
|
|
44
|
+
repeat: (col: FilterCols<TColEntries, string> | SQLExpr<string>, n: number) => SQLExpr<string>;
|
|
45
|
+
reverse: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<string>;
|
|
46
|
+
lpad: (col: FilterCols<TColEntries, string> | SQLExpr<string>, len: number, pad: string) => SQLExpr<string>;
|
|
47
|
+
rpad: (col: FilterCols<TColEntries, string> | SQLExpr<string>, len: number, pad: string) => SQLExpr<string>;
|
|
48
|
+
initcap: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<string>;
|
|
49
|
+
strpos: (col: FilterCols<TColEntries, string> | SQLExpr<string>, substr: string) => SQLExpr<number>;
|
|
50
|
+
splitPart: (col: FilterCols<TColEntries, string> | SQLExpr<string>, delimiter: string, field: number) => SQLExpr<string>;
|
|
51
|
+
btrim: (col: FilterCols<TColEntries, string> | SQLExpr<string>, chars?: string) => SQLExpr<string>;
|
|
52
|
+
md5: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<string>;
|
|
53
|
+
greatest: <T>(args_0: FilterCols<TColEntries, T> | SQLExpr<T>, ...args: (FilterCols<TColEntries, T> | SQLExpr<T>)[]) => SQLExpr<T>;
|
|
54
|
+
least: <T>(args_0: FilterCols<TColEntries, T> | SQLExpr<T>, ...args: (FilterCols<TColEntries, T> | SQLExpr<T>)[]) => SQLExpr<T>;
|
|
55
|
+
now: () => SQLExpr<Date>;
|
|
56
|
+
curDate: () => SQLExpr<Date>;
|
|
57
|
+
year: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
58
|
+
month: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
59
|
+
day: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
60
|
+
hour: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
61
|
+
minute: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
62
|
+
second: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
63
|
+
extract: (field: PgExtractField, col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
64
|
+
dateTrunc: (unit: PgDateTruncUnit, col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<Date>;
|
|
65
|
+
age: (ts1: FilterCols<TColEntries, Date> | SQLExpr<Date>, ts2?: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
66
|
+
toDate: (text: FilterCols<TColEntries, string> | SQLExpr<string>, fmt: string) => SQLExpr<Date>;
|
|
67
|
+
abs: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
68
|
+
ceil: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
69
|
+
floor: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
70
|
+
round: (col: FilterCols<TColEntries, number> | SQLExpr<number>, decimals?: number) => SQLExpr<number>;
|
|
71
|
+
power: (base: FilterCols<TColEntries, number> | SQLExpr<number>, exp: number | SQLExpr<number>) => SQLExpr<number>;
|
|
72
|
+
sqrt: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
73
|
+
mod: (col: FilterCols<TColEntries, number> | SQLExpr<number>, divisor: number) => SQLExpr<number>;
|
|
74
|
+
sign: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
75
|
+
exp: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
76
|
+
pi: () => SQLExpr<number>;
|
|
77
|
+
ln: (x: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
78
|
+
log: (x: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
79
|
+
logBase: (base: number, x: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
80
|
+
trunc: (x: FilterCols<TColEntries, number> | SQLExpr<number>, n?: number) => SQLExpr<number>;
|
|
81
|
+
div: (x: FilterCols<TColEntries, number> | SQLExpr<number>, y: number) => SQLExpr<number>;
|
|
82
|
+
random: () => SQLExpr<number>;
|
|
83
|
+
cast: <T extends keyof PgCastTypeMap>(expr: ColName<TColEntries> | SQLExpr<unknown>, type: T) => SQLExpr<PgCastTypeMap[T]>;
|
|
84
|
+
};
|
|
85
|
+
type DialectFns<TColEntries extends [string, unknown] = never, _TCriteria extends object = object> = ReturnType<typeof postgresqlContextFns<TColEntries>>;
|
|
86
|
+
declare const supportedJoinMethods: readonly ["join", "joinUnsafeTypeEnforced", "joinUnsafeIgnoreType", "innerJoin", "innerJoinUnsafeTypeEnforced", "innerJoinUnsafeIgnoreType", "leftJoin", "leftJoinUnsafeTypeEnforced", "leftJoinUnsafeIgnoreType", "rightJoin", "rightJoinUnsafeTypeEnforced", "rightJoinUnsafeIgnoreType", "fullJoin", "fullJoinUnsafeTypeEnforced", "fullJoinUnsafeIgnoreType", "crossJoin", "crossJoinUnsafeTypeEnforced", "crossJoinUnsafeIgnoreType", "manyToManyJoin"];
|
|
87
|
+
declare const postgresqlDialect: Dialect;
|
|
88
|
+
|
|
89
|
+
export { type DialectFns, type PgDateTruncUnit, type PgExtractField, postgresqlContextFns, postgresqlDialect, supportedJoinMethods };
|
|
@@ -0,0 +1,147 @@
|
|
|
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/postgresql.ts
|
|
16
|
+
var PG_CAST_TYPES = /* @__PURE__ */ new Set(["INTEGER", "TEXT", "BIGINT", "BOOLEAN", "REAL", "NUMERIC", "DATE", "TIMESTAMP", "JSON", "JSONB"]);
|
|
17
|
+
var postgresqlContextFns = (quoteFn) => ({
|
|
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
|
+
stringAgg: (col, sep) => sqlExpr(`STRING_AGG(${quoteFn(col)}, '${esc(sep)}')`),
|
|
25
|
+
arrayAgg: (col) => sqlExpr(`ARRAY_AGG(${quoteFn(col)})`),
|
|
26
|
+
stddevPop: (col) => sqlExpr(`STDDEV_POP(${quoteFn(col)})`),
|
|
27
|
+
stddevSamp: (col) => sqlExpr(`STDDEV_SAMP(${quoteFn(col)})`),
|
|
28
|
+
varPop: (col) => sqlExpr(`VAR_POP(${quoteFn(col)})`),
|
|
29
|
+
varSamp: (col) => sqlExpr(`VAR_SAMP(${quoteFn(col)})`),
|
|
30
|
+
boolAnd: (col) => sqlExpr(`BOOL_AND(${quoteFn(col)})`),
|
|
31
|
+
boolOr: (col) => sqlExpr(`BOOL_OR(${quoteFn(col)})`),
|
|
32
|
+
jsonAgg: (col) => sqlExpr(`JSON_AGG(${quoteFn(col)})`),
|
|
33
|
+
bitAnd: (col) => sqlExpr(`BIT_AND(${quoteFn(col)})`),
|
|
34
|
+
bitOr: (col) => sqlExpr(`BIT_OR(${quoteFn(col)})`),
|
|
35
|
+
jsonObjectAgg: (key, val) => sqlExpr(`JSON_OBJECT_AGG(${quoteFn(key)}, ${quoteFn(val)})`),
|
|
36
|
+
concat: (...args) => {
|
|
37
|
+
if (args.length === 0) throw new Error("concat: requires at least one argument");
|
|
38
|
+
return sqlExpr(`CONCAT(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
39
|
+
},
|
|
40
|
+
substring: (col, start, len) => sqlExpr(`SUBSTRING(${resolveArg(col, quoteFn)}, ${start}${len !== void 0 ? `, ${len}` : ""})`),
|
|
41
|
+
left: (col, n) => sqlExpr(`LEFT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
42
|
+
right: (col, n) => sqlExpr(`RIGHT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
43
|
+
repeat: (col, n) => sqlExpr(`REPEAT(${resolveArg(col, quoteFn)}, ${n})`),
|
|
44
|
+
reverse: (col) => sqlExpr(`REVERSE(${resolveArg(col, quoteFn)})`),
|
|
45
|
+
lpad: (col, len, pad) => sqlExpr(`LPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
46
|
+
rpad: (col, len, pad) => sqlExpr(`RPAD(${resolveArg(col, quoteFn)}, ${len}, '${esc(pad)}')`),
|
|
47
|
+
initcap: (col) => sqlExpr(`INITCAP(${resolveArg(col, quoteFn)})`),
|
|
48
|
+
strpos: (col, substr) => sqlExpr(`STRPOS(${resolveArg(col, quoteFn)}, '${esc(substr)}')`),
|
|
49
|
+
splitPart: (col, delimiter, field) => sqlExpr(`SPLIT_PART(${resolveArg(col, quoteFn)}, '${esc(delimiter)}', ${field})`),
|
|
50
|
+
btrim: (col, chars) => sqlExpr(`BTRIM(${resolveArg(col, quoteFn)}${chars !== void 0 ? `, '${esc(chars)}'` : ""})`),
|
|
51
|
+
md5: (col) => sqlExpr(`MD5(${resolveArg(col, quoteFn)})`),
|
|
52
|
+
// Control flow
|
|
53
|
+
greatest: (...args) => {
|
|
54
|
+
if (args.length === 0) throw new Error("greatest: requires at least one argument");
|
|
55
|
+
return sqlExpr(`GREATEST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
56
|
+
},
|
|
57
|
+
least: (...args) => {
|
|
58
|
+
if (args.length === 0) throw new Error("least: requires at least one argument");
|
|
59
|
+
return sqlExpr(`LEAST(${args.map((a) => resolveArg(a, quoteFn)).join(", ")})`);
|
|
60
|
+
},
|
|
61
|
+
// DateTime overrides
|
|
62
|
+
now: () => sqlExpr("NOW()"),
|
|
63
|
+
curDate: () => sqlExpr("CURRENT_DATE"),
|
|
64
|
+
year: (col) => sqlExpr(`EXTRACT(YEAR FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
65
|
+
month: (col) => sqlExpr(`EXTRACT(MONTH FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
66
|
+
day: (col) => sqlExpr(`EXTRACT(DAY FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
67
|
+
hour: (col) => sqlExpr(`EXTRACT(HOUR FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
68
|
+
minute: (col) => sqlExpr(`EXTRACT(MINUTE FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
69
|
+
second: (col) => sqlExpr(`EXTRACT(SECOND FROM ${resolveArg(col, quoteFn)})::integer`),
|
|
70
|
+
// PG-only DateTime fns
|
|
71
|
+
extract: (field, col) => sqlExpr(`EXTRACT(${field} FROM ${resolveArg(col, quoteFn)})`),
|
|
72
|
+
dateTrunc: (unit, col) => sqlExpr(`DATE_TRUNC('${unit}', ${resolveArg(col, quoteFn)})`),
|
|
73
|
+
/**
|
|
74
|
+
* PG `AGE()` returns an `interval`. Typed as `string` since node-postgres serializes
|
|
75
|
+
* intervals as strings (e.g. `"1 year 2 mons 3 days"`). Arithmetic on the result
|
|
76
|
+
* must be done in SQL, not JS — use `sqlExpr` to compose further expressions.
|
|
77
|
+
*/
|
|
78
|
+
age: (ts1, ts2) => sqlExpr(ts2 !== void 0 ? `AGE(${resolveArg(ts1, quoteFn)}, ${resolveArg(ts2, quoteFn)})` : `AGE(${resolveArg(ts1, quoteFn)})`),
|
|
79
|
+
toDate: (text, fmt) => sqlExpr(`TO_DATE(${resolveArg(text, quoteFn)}, '${esc(fmt)}')`),
|
|
80
|
+
// ── Math ─────────────────────────────────────────────────────────────────
|
|
81
|
+
abs: (col) => sqlExpr(`ABS(${resolveArg(col, quoteFn)})`),
|
|
82
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
83
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`),
|
|
84
|
+
round: (col, decimals) => sqlExpr(decimals !== void 0 ? `ROUND(${resolveArg(col, quoteFn)}, ${decimals})` : `ROUND(${resolveArg(col, quoteFn)})`),
|
|
85
|
+
power: (base, exp) => sqlExpr(`POWER(${resolveArg(base, quoteFn)}, ${typeof exp === "number" ? exp : exp.sql})`),
|
|
86
|
+
sqrt: (col) => sqlExpr(`SQRT(${resolveArg(col, quoteFn)})`),
|
|
87
|
+
mod: (col, divisor) => sqlExpr(`MOD(${resolveArg(col, quoteFn)}, ${divisor})`),
|
|
88
|
+
sign: (col) => sqlExpr(`SIGN(${resolveArg(col, quoteFn)})`),
|
|
89
|
+
exp: (col) => sqlExpr(`EXP(${resolveArg(col, quoteFn)})`),
|
|
90
|
+
// ── Math (PostgreSQL-specific) ────────────────────────────────────────────
|
|
91
|
+
pi: () => sqlExpr("PI()"),
|
|
92
|
+
ln: (x) => sqlExpr(`LN(${resolveArg(x, quoteFn)})`),
|
|
93
|
+
log: (x) => sqlExpr(`LOG(${resolveArg(x, quoteFn)})`),
|
|
94
|
+
logBase: (base, x) => sqlExpr(`LOG(${base}, ${resolveArg(x, quoteFn)})`),
|
|
95
|
+
trunc: (x, n) => sqlExpr(n !== void 0 ? `TRUNC(${resolveArg(x, quoteFn)}, ${n})` : `TRUNC(${resolveArg(x, quoteFn)})`),
|
|
96
|
+
div: (x, y) => sqlExpr(`DIV(${resolveArg(x, quoteFn)}, ${y})`),
|
|
97
|
+
random: () => sqlExpr("RANDOM()"),
|
|
98
|
+
// ── Type coercion ────────────────────────────────────────────────────────
|
|
99
|
+
cast: (expr, type) => {
|
|
100
|
+
if (!PG_CAST_TYPES.has(type)) throw new Error(`cast: invalid cast type '${String(type)}'`);
|
|
101
|
+
return sqlExpr(`CAST(${resolveArg(expr, quoteFn)} AS ${type})`);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
var supportedJoinMethods = [
|
|
105
|
+
"join",
|
|
106
|
+
"joinUnsafeTypeEnforced",
|
|
107
|
+
"joinUnsafeIgnoreType",
|
|
108
|
+
"innerJoin",
|
|
109
|
+
"innerJoinUnsafeTypeEnforced",
|
|
110
|
+
"innerJoinUnsafeIgnoreType",
|
|
111
|
+
"leftJoin",
|
|
112
|
+
"leftJoinUnsafeTypeEnforced",
|
|
113
|
+
"leftJoinUnsafeIgnoreType",
|
|
114
|
+
"rightJoin",
|
|
115
|
+
"rightJoinUnsafeTypeEnforced",
|
|
116
|
+
"rightJoinUnsafeIgnoreType",
|
|
117
|
+
"fullJoin",
|
|
118
|
+
"fullJoinUnsafeTypeEnforced",
|
|
119
|
+
"fullJoinUnsafeIgnoreType",
|
|
120
|
+
"crossJoin",
|
|
121
|
+
"crossJoinUnsafeTypeEnforced",
|
|
122
|
+
"crossJoinUnsafeIgnoreType",
|
|
123
|
+
"manyToManyJoin"
|
|
124
|
+
];
|
|
125
|
+
var postgresqlDialect = {
|
|
126
|
+
name: "postgresql",
|
|
127
|
+
needsBooleanCoercion: () => false,
|
|
128
|
+
quote: (id, _isAlias) => `"${id}"`,
|
|
129
|
+
quoteTableIdentifier: (name, _isAlias) => `"${name}"`,
|
|
130
|
+
quoteQualifiedColumn: (ref) => {
|
|
131
|
+
if (!ref.includes(".")) return `"${ref}"`;
|
|
132
|
+
const [table, col] = ref.split(".", 2);
|
|
133
|
+
return `"${table}"."${col}"`;
|
|
134
|
+
},
|
|
135
|
+
quoteOrderByClause: (clause) => {
|
|
136
|
+
const parts = clause.trim().split(/\s+/);
|
|
137
|
+
const colRef = parts[0] ?? "";
|
|
138
|
+
const suffix = parts.slice(1).join(" ");
|
|
139
|
+
const quoted = colRef.includes(".") ? (() => {
|
|
140
|
+
const [table, col] = colRef.split(".", 2);
|
|
141
|
+
return `"${table}"."${col}"`;
|
|
142
|
+
})() : `"${colRef}"`;
|
|
143
|
+
return suffix ? `${quoted} ${suffix}` : quoted;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export { postgresqlContextFns, postgresqlDialect, supportedJoinMethods };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const sharedFunctions: {};
|
|
2
|
+
declare const esc: (s: string) => string;
|
|
3
|
+
type FilterCols<TEntries extends [string, unknown], T> = TEntries extends [infer N extends string, infer V] ? NonNullable<V> extends T ? N : never : never;
|
|
4
|
+
type ColName<TEntries extends [string, unknown]> = TEntries extends [infer N extends string, unknown] ? N : never;
|
|
5
|
+
|
|
6
|
+
export { type ColName, type FilterCols, esc, sharedFunctions };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Dialect } from './types.js';
|
|
2
|
+
import { S as SQLExpr } from '../sql-expr-BaKWzJ-r.js';
|
|
3
|
+
import { FilterCols, ColName } from './shared.js';
|
|
4
|
+
|
|
5
|
+
type SqliteMinMaxResult<TColEntries extends [string, unknown], Col extends string> = TColEntries extends [Col, infer V] ? NonNullable<V> extends number ? bigint | null : V | null : never;
|
|
6
|
+
type SqliteCastTypeMap = {
|
|
7
|
+
INTEGER: bigint;
|
|
8
|
+
TEXT: string;
|
|
9
|
+
REAL: number;
|
|
10
|
+
NUMERIC: number;
|
|
11
|
+
BLOB: Buffer;
|
|
12
|
+
};
|
|
13
|
+
declare const sqliteContextFns: <TColEntries extends [string, unknown] = never, TCriteria extends object = object>(quoteFn: (ref: string) => string, condFn: (criteria: TCriteria) => string) => {
|
|
14
|
+
avg: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
15
|
+
sum: (col: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<bigint | number>;
|
|
16
|
+
countAll: () => SQLExpr<bigint>;
|
|
17
|
+
count: (col: ColName<TColEntries> | "*") => SQLExpr<bigint>;
|
|
18
|
+
countDistinct: (col: ColName<TColEntries>) => SQLExpr<bigint>;
|
|
19
|
+
length: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<bigint>;
|
|
20
|
+
groupConcat: (col: ColName<TColEntries>, sep?: string) => SQLExpr<string>;
|
|
21
|
+
total: (col: ColName<TColEntries>) => SQLExpr<number>;
|
|
22
|
+
min: <Col extends ColName<TColEntries>>(col: Col) => SQLExpr<SqliteMinMaxResult<TColEntries, Col>>;
|
|
23
|
+
max: <Col extends ColName<TColEntries>>(col: Col) => SQLExpr<SqliteMinMaxResult<TColEntries, Col>>;
|
|
24
|
+
concat: (args_0: FilterCols<TColEntries, string> | SQLExpr<string>, ...args: (FilterCols<TColEntries, string> | SQLExpr<string>)[]) => SQLExpr<string>;
|
|
25
|
+
substr: (col: FilterCols<TColEntries, string> | SQLExpr<string>, start: number, len?: number) => SQLExpr<string>;
|
|
26
|
+
instr: (col: FilterCols<TColEntries, string> | SQLExpr<string>, substr: string) => SQLExpr<bigint>;
|
|
27
|
+
char: (...codes: number[]) => SQLExpr<string>;
|
|
28
|
+
hex: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<string>;
|
|
29
|
+
unicode: (col: FilterCols<TColEntries, string> | SQLExpr<string>) => SQLExpr<bigint>;
|
|
30
|
+
iif: <T>(cond: TCriteria | SQLExpr<unknown>, trueVal: SQLExpr<T>, falseVal: SQLExpr<T>) => SQLExpr<T>;
|
|
31
|
+
ifNull: <T>(col: FilterCols<TColEntries, T> | SQLExpr<T>, fallback: SQLExpr<NonNullable<T>>) => SQLExpr<NonNullable<T>>;
|
|
32
|
+
now: () => SQLExpr<Date>;
|
|
33
|
+
curDate: () => SQLExpr<Date>;
|
|
34
|
+
year: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
35
|
+
month: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
36
|
+
day: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
37
|
+
hour: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
38
|
+
minute: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
39
|
+
second: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
40
|
+
strftime: (fmt: string, col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
41
|
+
julianday: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<number>;
|
|
42
|
+
date: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
43
|
+
datetime: (col: FilterCols<TColEntries, Date> | SQLExpr<Date>) => SQLExpr<string>;
|
|
44
|
+
abs: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>) => SQLExpr<bigint | number>;
|
|
45
|
+
ceil: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>) => SQLExpr<bigint | number>;
|
|
46
|
+
floor: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>) => SQLExpr<bigint | number>;
|
|
47
|
+
round: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>, decimals?: number) => SQLExpr<bigint | number>;
|
|
48
|
+
power: (base: FilterCols<TColEntries, number> | SQLExpr<number | bigint>, exp: number | SQLExpr<number | bigint>) => SQLExpr<number>;
|
|
49
|
+
sqrt: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>) => SQLExpr<number>;
|
|
50
|
+
mod: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>, divisor: number) => SQLExpr<bigint | number>;
|
|
51
|
+
sign: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>) => SQLExpr<bigint | number>;
|
|
52
|
+
exp: (col: FilterCols<TColEntries, number> | SQLExpr<number | bigint>) => SQLExpr<number>;
|
|
53
|
+
random: () => SQLExpr<bigint>;
|
|
54
|
+
log: (x: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
55
|
+
log2: (x: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
56
|
+
log10: (x: FilterCols<TColEntries, number> | SQLExpr<number>) => SQLExpr<number>;
|
|
57
|
+
cast: <T extends keyof SqliteCastTypeMap>(expr: ColName<TColEntries> | SQLExpr<unknown>, type: T) => SQLExpr<SqliteCastTypeMap[T]>;
|
|
58
|
+
};
|
|
59
|
+
type DialectFns<TColEntries extends [string, unknown] = never, TCriteria extends object = object> = ReturnType<typeof sqliteContextFns<TColEntries, TCriteria>>;
|
|
60
|
+
declare const supportedJoinMethods: readonly ["join", "joinUnsafeTypeEnforced", "joinUnsafeIgnoreType", "innerJoin", "innerJoinUnsafeTypeEnforced", "innerJoinUnsafeIgnoreType", "leftJoin", "leftJoinUnsafeTypeEnforced", "leftJoinUnsafeIgnoreType", "crossJoin", "crossJoinUnsafeTypeEnforced", "crossJoinUnsafeIgnoreType", "manyToManyJoin"];
|
|
61
|
+
declare const sqliteDialect: Dialect;
|
|
62
|
+
|
|
63
|
+
export { type DialectFns, sqliteContextFns, sqliteDialect, supportedJoinMethods };
|
|
@@ -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/sqlite.ts
|
|
13
|
+
var SQLITE_CAST_TYPES = /* @__PURE__ */ new Set(["INTEGER", "TEXT", "REAL", "NUMERIC", "BLOB"]);
|
|
14
|
+
var dateArg = (col, quoteFn) => {
|
|
15
|
+
if (typeof col !== "string") return col.sql;
|
|
16
|
+
const ref = quoteFn(col);
|
|
17
|
+
return `CASE WHEN typeof(${ref}) = 'integer' THEN datetime(${ref}/1000, 'unixepoch') ELSE ${ref} END`;
|
|
18
|
+
};
|
|
19
|
+
var sqliteContextFns = (quoteFn, condFn) => ({
|
|
20
|
+
avg: (col) => sqlExpr(`AVG(${resolveArg(col, quoteFn)})`),
|
|
21
|
+
// SQLite SUM returns INTEGER (→ bigint) for integer columns, REAL (→ number) for float columns
|
|
22
|
+
sum: (col) => sqlExpr(`SUM(${resolveArg(col, quoteFn)})`),
|
|
23
|
+
// Aggregate integer-result fns — SQLite returns INTEGER → bigint
|
|
24
|
+
countAll: () => sqlExpr("COUNT(*)"),
|
|
25
|
+
count: (col) => sqlExpr(col === "*" ? "COUNT(*)" : `COUNT(${quoteFn(col)})`),
|
|
26
|
+
countDistinct: (col) => sqlExpr(`COUNT(DISTINCT ${quoteFn(col)})`),
|
|
27
|
+
// LENGTH returns INTEGER → bigint in SQLite
|
|
28
|
+
length: (col) => sqlExpr(`LENGTH(${resolveArg(col, quoteFn)})`),
|
|
29
|
+
groupConcat: (col, sep) => sqlExpr(`GROUP_CONCAT(${quoteFn(col)}${sep !== void 0 ? `, '${sep.replace(/'/g, "''")}'` : ""})`),
|
|
30
|
+
total: (col) => sqlExpr(`TOTAL(${quoteFn(col)})`),
|
|
31
|
+
// SQLite MIN/MAX return bigint for integer columns — override base (number) return types
|
|
32
|
+
min: (col) => sqlExpr(`MIN(${quoteFn(col)})`),
|
|
33
|
+
max: (col) => sqlExpr(`MAX(${quoteFn(col)})`),
|
|
34
|
+
concat: (...args) => {
|
|
35
|
+
if (args.length === 0) throw new Error("concat: requires at least one argument");
|
|
36
|
+
return sqlExpr(args.map((a) => resolveArg(a, quoteFn)).join(" || "));
|
|
37
|
+
},
|
|
38
|
+
substr: (col, start, len) => sqlExpr(`SUBSTR(${resolveArg(col, quoteFn)}, ${start}${len !== void 0 ? `, ${len}` : ""})`),
|
|
39
|
+
instr: (col, substr) => sqlExpr(`INSTR(${resolveArg(col, quoteFn)}, '${substr.replace(/'/g, "''")}')`),
|
|
40
|
+
char: (...codes) => sqlExpr(`CHAR(${codes.join(", ")})`),
|
|
41
|
+
hex: (col) => sqlExpr(`HEX(${resolveArg(col, quoteFn)})`),
|
|
42
|
+
unicode: (col) => sqlExpr(`UNICODE(${resolveArg(col, quoteFn)})`),
|
|
43
|
+
// Control flow
|
|
44
|
+
// Note: SQLite has no GREATEST()/LEAST() functions — it uses scalar MAX(a,b)/MIN(a,b) instead.
|
|
45
|
+
// Omitted here because the naming diverges from the MySQL/PG convention.
|
|
46
|
+
iif: (cond, trueVal, falseVal) => {
|
|
47
|
+
const condSql = typeof cond === "object" && cond !== null && "sql" in cond ? cond.sql : condFn(cond);
|
|
48
|
+
return sqlExpr(`IIF(${condSql}, ${trueVal.sql}, ${falseVal.sql})`);
|
|
49
|
+
},
|
|
50
|
+
ifNull: (col, fallback) => sqlExpr(`IFNULL(${resolveArg(col, quoteFn)}, ${fallback.sql})`),
|
|
51
|
+
// DateTime overrides
|
|
52
|
+
now: () => sqlExpr(`datetime('now')`),
|
|
53
|
+
curDate: () => sqlExpr(`date('now')`),
|
|
54
|
+
year: (col) => sqlExpr(`strftime('%Y', ${dateArg(col, quoteFn)})`),
|
|
55
|
+
month: (col) => sqlExpr(`strftime('%m', ${dateArg(col, quoteFn)})`),
|
|
56
|
+
day: (col) => sqlExpr(`strftime('%d', ${dateArg(col, quoteFn)})`),
|
|
57
|
+
hour: (col) => sqlExpr(`strftime('%H', ${dateArg(col, quoteFn)})`),
|
|
58
|
+
minute: (col) => sqlExpr(`strftime('%M', ${dateArg(col, quoteFn)})`),
|
|
59
|
+
second: (col) => sqlExpr(`strftime('%S', ${dateArg(col, quoteFn)})`),
|
|
60
|
+
// SQLite-only DateTime fns
|
|
61
|
+
/**
|
|
62
|
+
* SQLite `strftime` returns `NULL` if the date value is `NULL` or cannot be parsed.
|
|
63
|
+
* Unknown format directives (e.g. `%q`) are passed through literally, not as errors.
|
|
64
|
+
*/
|
|
65
|
+
strftime: (fmt, col) => sqlExpr(`strftime('${fmt.replace(/'/g, "''")}', ${dateArg(col, quoteFn)})`),
|
|
66
|
+
julianday: (col) => sqlExpr(`julianday(${dateArg(col, quoteFn)})`),
|
|
67
|
+
date: (col) => sqlExpr(`date(${dateArg(col, quoteFn)})`),
|
|
68
|
+
datetime: (col) => sqlExpr(`datetime(${dateArg(col, quoteFn)})`),
|
|
69
|
+
// ── Math ─────────────────────────────────────────────────────────────────
|
|
70
|
+
// SQLite returns bigint for integer results (ceil, floor, sign, mod) and number for floats.
|
|
71
|
+
// All inputs accept SQLExpr<number | bigint> so composed calls (e.g. sqrt(power(...))) type-check.
|
|
72
|
+
// sqrt/exp always return REAL, so they are typed as number.
|
|
73
|
+
abs: (col) => sqlExpr(`ABS(${resolveArg(col, quoteFn)})`),
|
|
74
|
+
ceil: (col) => sqlExpr(`CEIL(${resolveArg(col, quoteFn)})`),
|
|
75
|
+
floor: (col) => sqlExpr(`FLOOR(${resolveArg(col, quoteFn)})`),
|
|
76
|
+
round: (col, decimals) => sqlExpr(decimals !== void 0 ? `ROUND(${resolveArg(col, quoteFn)}, ${decimals})` : `ROUND(${resolveArg(col, quoteFn)})`),
|
|
77
|
+
// SQLite's POWER() always returns REAL regardless of input type
|
|
78
|
+
power: (base, exp) => sqlExpr(`POWER(${resolveArg(base, quoteFn)}, ${typeof exp === "number" ? exp : exp.sql})`),
|
|
79
|
+
sqrt: (col) => sqlExpr(`SQRT(${resolveArg(col, quoteFn)})`),
|
|
80
|
+
mod: (col, divisor) => sqlExpr(`MOD(${resolveArg(col, quoteFn)}, ${divisor})`),
|
|
81
|
+
sign: (col) => sqlExpr(`SIGN(${resolveArg(col, quoteFn)})`),
|
|
82
|
+
exp: (col) => sqlExpr(`EXP(${resolveArg(col, quoteFn)})`),
|
|
83
|
+
// ── Math (SQLite 3.35+) ──────────────────────────────────────────────────
|
|
84
|
+
// SQLite RANDOM() returns a 64-bit signed integer — always bigint
|
|
85
|
+
random: () => sqlExpr("RANDOM()"),
|
|
86
|
+
log: (x) => sqlExpr(`LOG(${resolveArg(x, quoteFn)})`),
|
|
87
|
+
log2: (x) => sqlExpr(`LOG2(${resolveArg(x, quoteFn)})`),
|
|
88
|
+
log10: (x) => sqlExpr(`LOG10(${resolveArg(x, quoteFn)})`),
|
|
89
|
+
// ── Type coercion ────────────────────────────────────────────────────────
|
|
90
|
+
cast: (expr, type) => {
|
|
91
|
+
if (!SQLITE_CAST_TYPES.has(type)) throw new Error(`cast: invalid cast type '${String(type)}'`);
|
|
92
|
+
return sqlExpr(`CAST(${resolveArg(expr, quoteFn)} AS ${type})`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
var supportedJoinMethods = [
|
|
96
|
+
"join",
|
|
97
|
+
"joinUnsafeTypeEnforced",
|
|
98
|
+
"joinUnsafeIgnoreType",
|
|
99
|
+
"innerJoin",
|
|
100
|
+
"innerJoinUnsafeTypeEnforced",
|
|
101
|
+
"innerJoinUnsafeIgnoreType",
|
|
102
|
+
"leftJoin",
|
|
103
|
+
"leftJoinUnsafeTypeEnforced",
|
|
104
|
+
"leftJoinUnsafeIgnoreType",
|
|
105
|
+
"crossJoin",
|
|
106
|
+
"crossJoinUnsafeTypeEnforced",
|
|
107
|
+
"crossJoinUnsafeIgnoreType",
|
|
108
|
+
"manyToManyJoin"
|
|
109
|
+
];
|
|
110
|
+
var sqliteDialect = {
|
|
111
|
+
name: "sqlite",
|
|
112
|
+
needsBooleanCoercion: () => true,
|
|
113
|
+
quote: (name, _isAlias) => {
|
|
114
|
+
if (_isAlias) return "`" + name + "`";
|
|
115
|
+
return name;
|
|
116
|
+
},
|
|
117
|
+
quoteTableIdentifier: (name, _isAlias) => {
|
|
118
|
+
if (_isAlias) return "`" + name + "`";
|
|
119
|
+
return name;
|
|
120
|
+
},
|
|
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 { sqliteContextFns, sqliteDialect, supportedJoinMethods };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Dialect = {
|
|
2
|
+
name: "sqlite" | "mysql" | "postgresql";
|
|
3
|
+
quote: (identifier: string, isAlias?: boolean) => string;
|
|
4
|
+
needsBooleanCoercion: () => boolean;
|
|
5
|
+
quoteTableIdentifier: (name: string, isAlias: boolean) => string;
|
|
6
|
+
quoteQualifiedColumn: (ref: string) => string;
|
|
7
|
+
quoteOrderByClause: (clause: string) => string;
|
|
8
|
+
};
|
|
9
|
+
declare const SUPPORTED_PROVIDERS: readonly ["sqlite", "mysql", "postgresql"];
|
|
10
|
+
type SupportedProvider = typeof SUPPORTED_PROVIDERS[keyof typeof SUPPORTED_PROVIDERS];
|
|
11
|
+
|
|
12
|
+
export { type Dialect, SUPPORTED_PROVIDERS, type SupportedProvider };
|