prisma-ts-select 0.0.34 → 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 +1242 -315
- package/assets/groupBy.gif +0 -0
- package/assets/joinUnsafeIgnoreType.gif +0 -0
- package/assets/joinUnsafeTypeEnforced.gif +0 -0
- package/assets/typesafe-join.gif +0 -0
- package/assets/typesafe-join.png +0 -0
- package/assets/whereNotNull.gif +0 -0
- package/assets/whereisNull.gif +0 -0
- 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 +286 -43
- package/dist/extend/extend.js +735 -163
- 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 +46 -42
- package/built/extend.cjs +0 -680
- package/built/extend.d.cts +0 -520
- package/built/extend.d.ts +0 -520
- package/built/extend.js +0 -678
- package/dist/chunk-TBO3MX7Q.cjs +0 -195
- package/dist/chunk-X3N5N5KQ.js +0 -187
- package/dist/extend/extend.cjs +0 -357
- package/dist/extend/extend.d.cts +0 -264
|
@@ -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 };
|