sumak 0.0.5 → 0.0.6
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/README.md +155 -1
- package/dist/ast/nodes.d.mts +12 -1
- package/dist/builder/delete.d.mts +2 -0
- package/dist/builder/delete.mjs +19 -0
- package/dist/builder/eb.d.mts +108 -6
- package/dist/builder/eb.mjs +248 -6
- package/dist/builder/select.d.mts +3 -0
- package/dist/builder/select.mjs +38 -0
- package/dist/builder/typed-delete.d.mts +6 -0
- package/dist/builder/typed-delete.mjs +12 -0
- package/dist/builder/typed-insert.d.mts +13 -1
- package/dist/builder/typed-insert.mjs +23 -0
- package/dist/builder/typed-select.d.mts +43 -4
- package/dist/builder/typed-select.mjs +94 -2
- package/dist/builder/typed-update.d.mts +4 -0
- package/dist/builder/typed-update.mjs +8 -0
- package/dist/builder/update.d.mts +2 -0
- package/dist/builder/update.mjs +19 -0
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +3 -1
- package/dist/printer/base.d.mts +2 -1
- package/dist/printer/base.mjs +25 -3
- package/dist/sumak.d.mts +12 -0
- package/dist/sumak.mjs +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -150,6 +150,19 @@ db.selectFrom("users").crossJoin("posts").compile(db.printer())
|
|
|
150
150
|
.where(({ name }) =>
|
|
151
151
|
name.like("%ali%"),
|
|
152
152
|
)
|
|
153
|
+
|
|
154
|
+
.where(({ name }) =>
|
|
155
|
+
name.notLike("%bob%"),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
// Case-insensitive (PG)
|
|
159
|
+
.where(({ name }) =>
|
|
160
|
+
name.ilike("%alice%"),
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
.where(({ email }) =>
|
|
164
|
+
email.notIlike("%spam%"),
|
|
165
|
+
)
|
|
153
166
|
```
|
|
154
167
|
|
|
155
168
|
### Range & List
|
|
@@ -159,6 +172,15 @@ db.selectFrom("users").crossJoin("posts").compile(db.printer())
|
|
|
159
172
|
age.between(18, 65),
|
|
160
173
|
)
|
|
161
174
|
|
|
175
|
+
.where(({ age }) =>
|
|
176
|
+
age.notBetween(18, 65),
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
// Order-independent (PG)
|
|
180
|
+
.where(({ age }) =>
|
|
181
|
+
age.betweenSymmetric(65, 18),
|
|
182
|
+
)
|
|
183
|
+
|
|
162
184
|
.where(({ id }) =>
|
|
163
185
|
id.in([1, 2, 3]),
|
|
164
186
|
)
|
|
@@ -205,10 +227,24 @@ db.selectFrom("users").crossJoin("posts").compile(db.printer())
|
|
|
205
227
|
)
|
|
206
228
|
```
|
|
207
229
|
|
|
230
|
+
### Null-Safe Comparisons
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
// IS DISTINCT FROM — null-safe inequality
|
|
234
|
+
.where(({ age }) =>
|
|
235
|
+
age.isDistinctFrom(null),
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
// IS NOT DISTINCT FROM — null-safe equality
|
|
239
|
+
.where(({ age }) =>
|
|
240
|
+
age.isNotDistinctFrom(25),
|
|
241
|
+
)
|
|
242
|
+
```
|
|
243
|
+
|
|
208
244
|
### Aggregates
|
|
209
245
|
|
|
210
246
|
```ts
|
|
211
|
-
import { count, countDistinct, sum, avg, min, max, coalesce } from "sumak"
|
|
247
|
+
import { count, countDistinct, sumDistinct, avgDistinct, sum, avg, min, max, coalesce } from "sumak"
|
|
212
248
|
|
|
213
249
|
db.selectFrom("users").selectExpr(count(), "total").compile(db.printer())
|
|
214
250
|
|
|
@@ -222,6 +258,50 @@ db.selectFrom("orders").selectExpr(avg(col.amount), "avgAmount").compile(db.prin
|
|
|
222
258
|
db.selectFrom("orders")
|
|
223
259
|
.selectExpr(coalesce(col.discount, val(0)), "safeDiscount")
|
|
224
260
|
.compile(db.printer())
|
|
261
|
+
|
|
262
|
+
// SUM(DISTINCT), AVG(DISTINCT)
|
|
263
|
+
db.selectFrom("orders").selectExpr(sumDistinct(col.amount), "uniqueSum").compile(db.printer())
|
|
264
|
+
db.selectFrom("orders").selectExpr(avgDistinct(col.amount), "uniqueAvg").compile(db.printer())
|
|
265
|
+
|
|
266
|
+
// COALESCE with multiple fallbacks
|
|
267
|
+
db.selectFrom("users")
|
|
268
|
+
.selectExpr(coalesce(col.nick, col.name, val("Anonymous")), "displayName")
|
|
269
|
+
.compile(db.printer())
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### String & JSON Aggregates
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import { stringAgg, arrayAgg, jsonAgg, jsonBuildObject } from "sumak"
|
|
276
|
+
|
|
277
|
+
// STRING_AGG with ORDER BY
|
|
278
|
+
db.selectFrom("users")
|
|
279
|
+
.selectExpr(stringAgg(col.name, ", ", [{ expr: col.name, direction: "ASC" }]), "names")
|
|
280
|
+
.compile(db.printer())
|
|
281
|
+
// STRING_AGG("name", ', ' ORDER BY "name" ASC)
|
|
282
|
+
|
|
283
|
+
// ARRAY_AGG
|
|
284
|
+
db.selectFrom("users").selectExpr(arrayAgg(col.id), "ids").compile(db.printer())
|
|
285
|
+
|
|
286
|
+
// JSON_AGG / JSON_BUILD_OBJECT
|
|
287
|
+
db.selectFrom("users").selectExpr(jsonAgg(col.name), "namesJson").compile(db.printer())
|
|
288
|
+
|
|
289
|
+
db.selectFrom("users")
|
|
290
|
+
.selectExpr(jsonBuildObject(["name", col.name], ["age", col.age]), "obj")
|
|
291
|
+
.compile(db.printer())
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Arithmetic
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
import { add, sub, mul, div, mod, neg } from "sumak"
|
|
298
|
+
|
|
299
|
+
db.selectFrom("orders").selectExpr(mul(col.price, col.qty), "total").compile(db.printer())
|
|
300
|
+
// ("price" * "qty") AS "total"
|
|
301
|
+
|
|
302
|
+
db.selectFrom("orders")
|
|
303
|
+
.selectExpr(add(col.price, val(10)), "adjusted")
|
|
304
|
+
.compile(db.printer())
|
|
225
305
|
```
|
|
226
306
|
|
|
227
307
|
### EXISTS / NOT EXISTS
|
|
@@ -505,6 +585,28 @@ db.selectFrom("users")
|
|
|
505
585
|
// WHERE ("age" > $1) AND ("active" = $2)
|
|
506
586
|
```
|
|
507
587
|
|
|
588
|
+
## Reusable Query Fragments
|
|
589
|
+
|
|
590
|
+
```ts
|
|
591
|
+
// $call — pipe builder through a function
|
|
592
|
+
const withPagination = (qb) => qb.limit(10).offset(20)
|
|
593
|
+
const withActiveFilter = (qb) => qb.where(({ active }) => active.eq(true))
|
|
594
|
+
|
|
595
|
+
db.selectFrom("users")
|
|
596
|
+
.select("id", "name")
|
|
597
|
+
.$call(withActiveFilter)
|
|
598
|
+
.$call(withPagination)
|
|
599
|
+
.compile(db.printer())
|
|
600
|
+
|
|
601
|
+
// selectExprs — multiple aliased expressions at once
|
|
602
|
+
db.selectFrom("users")
|
|
603
|
+
.selectExprs({
|
|
604
|
+
total: count(),
|
|
605
|
+
greeting: val("hello"),
|
|
606
|
+
})
|
|
607
|
+
.compile(db.printer())
|
|
608
|
+
```
|
|
609
|
+
|
|
508
610
|
## INSERT Advanced
|
|
509
611
|
|
|
510
612
|
```ts
|
|
@@ -621,6 +723,58 @@ db.update("orders")
|
|
|
621
723
|
.compile(db.printer())
|
|
622
724
|
```
|
|
623
725
|
|
|
726
|
+
## Lateral JOIN
|
|
727
|
+
|
|
728
|
+
```ts
|
|
729
|
+
// INNER JOIN LATERAL — correlated subquery join
|
|
730
|
+
const recentPosts = db
|
|
731
|
+
.selectFrom("posts")
|
|
732
|
+
.select("id", "title")
|
|
733
|
+
.where(({ userId }) => userId.eq(1))
|
|
734
|
+
.limit(3)
|
|
735
|
+
|
|
736
|
+
db.selectFrom("users").innerJoinLateral(recentPosts, "rp", onExpr).compile(db.printer())
|
|
737
|
+
// SELECT * FROM "users" INNER JOIN LATERAL (SELECT ...) AS "rp" ON ...
|
|
738
|
+
|
|
739
|
+
// LEFT JOIN LATERAL
|
|
740
|
+
db.selectFrom("users").leftJoinLateral(recentPosts, "rp", onExpr).compile(db.printer())
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
## Tuple Comparisons
|
|
744
|
+
|
|
745
|
+
```ts
|
|
746
|
+
import { tuple, val } from "sumak"
|
|
747
|
+
|
|
748
|
+
// Row-value comparison: (id, age) = (1, 25)
|
|
749
|
+
db.selectFrom("users")
|
|
750
|
+
.selectExpr(tuple(val(1), val(2), val(3)), "triple")
|
|
751
|
+
.compile(db.printer())
|
|
752
|
+
// (1, 2, 3)
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
## SQL Template Literal
|
|
756
|
+
|
|
757
|
+
```ts
|
|
758
|
+
import { sql, val } from "sumak"
|
|
759
|
+
|
|
760
|
+
// Tagged template with auto-parameterization
|
|
761
|
+
sql`SELECT * FROM users WHERE name = ${"Alice"}`
|
|
762
|
+
// params: ["Alice"]
|
|
763
|
+
|
|
764
|
+
// Inline Expression values
|
|
765
|
+
sql`SELECT * FROM users WHERE active = ${val(true)}`
|
|
766
|
+
// → SELECT * FROM users WHERE active = TRUE
|
|
767
|
+
|
|
768
|
+
// Helpers
|
|
769
|
+
sql`SELECT ${sql.ref("id")} FROM ${sql.table("users", "public")}`
|
|
770
|
+
// → SELECT "id" FROM "public"."users"
|
|
771
|
+
|
|
772
|
+
// Use in selectExpr
|
|
773
|
+
db.selectFrom("users")
|
|
774
|
+
.selectExpr(sql`CURRENT_DATE`, "today")
|
|
775
|
+
.compile(db.printer())
|
|
776
|
+
```
|
|
777
|
+
|
|
624
778
|
## Aggregate FILTER (WHERE)
|
|
625
779
|
|
|
626
780
|
```ts
|
package/dist/ast/nodes.d.mts
CHANGED
|
@@ -6,7 +6,7 @@ export interface ExplainNode {
|
|
|
6
6
|
analyze?: boolean;
|
|
7
7
|
format?: "TEXT" | "JSON" | "YAML" | "XML";
|
|
8
8
|
}
|
|
9
|
-
export type ExpressionNode = ColumnRefNode | LiteralNode | BinaryOpNode | UnaryOpNode | FunctionCallNode | ParamNode | RawNode | SubqueryNode | BetweenNode | InNode | IsNullNode | CaseNode | CastNode | ExistsNode | StarNode | JsonAccessNode | ArrayExprNode | WindowFunctionNode | AliasedExprNode | FullTextSearchNode;
|
|
9
|
+
export type ExpressionNode = ColumnRefNode | LiteralNode | BinaryOpNode | UnaryOpNode | FunctionCallNode | ParamNode | RawNode | SubqueryNode | BetweenNode | InNode | IsNullNode | CaseNode | CastNode | ExistsNode | StarNode | JsonAccessNode | ArrayExprNode | WindowFunctionNode | AliasedExprNode | FullTextSearchNode | TupleNode;
|
|
10
10
|
export interface ColumnRefNode {
|
|
11
11
|
type: "column_ref";
|
|
12
12
|
table?: string;
|
|
@@ -35,6 +35,7 @@ export interface FunctionCallNode {
|
|
|
35
35
|
args: ExpressionNode[];
|
|
36
36
|
distinct?: boolean;
|
|
37
37
|
filter?: ExpressionNode;
|
|
38
|
+
orderBy?: OrderByNode[];
|
|
38
39
|
alias?: string;
|
|
39
40
|
}
|
|
40
41
|
export interface ParamNode {
|
|
@@ -58,6 +59,7 @@ export interface BetweenNode {
|
|
|
58
59
|
low: ExpressionNode;
|
|
59
60
|
high: ExpressionNode;
|
|
60
61
|
negated: boolean;
|
|
62
|
+
symmetric?: boolean;
|
|
61
63
|
}
|
|
62
64
|
export interface InNode {
|
|
63
65
|
type: "in";
|
|
@@ -102,6 +104,10 @@ export interface FullTextSearchNode {
|
|
|
102
104
|
language?: string;
|
|
103
105
|
alias?: string;
|
|
104
106
|
}
|
|
107
|
+
export interface TupleNode {
|
|
108
|
+
type: "tuple";
|
|
109
|
+
elements: ExpressionNode[];
|
|
110
|
+
}
|
|
105
111
|
export interface AliasedExprNode {
|
|
106
112
|
type: "aliased_expr";
|
|
107
113
|
expr: ExpressionNode;
|
|
@@ -137,6 +143,7 @@ export interface JoinNode {
|
|
|
137
143
|
joinType: JoinType;
|
|
138
144
|
table: TableRefNode | SubqueryNode;
|
|
139
145
|
on?: ExpressionNode;
|
|
146
|
+
lateral?: boolean;
|
|
140
147
|
}
|
|
141
148
|
export interface JsonAccessNode {
|
|
142
149
|
type: "json_access";
|
|
@@ -256,6 +263,8 @@ export interface UpdateNode {
|
|
|
256
263
|
from?: TableRefNode;
|
|
257
264
|
joins: JoinNode[];
|
|
258
265
|
ctes: CTENode[];
|
|
266
|
+
orderBy?: OrderByNode[];
|
|
267
|
+
limit?: ExpressionNode;
|
|
259
268
|
}
|
|
260
269
|
export interface DeleteNode {
|
|
261
270
|
type: "delete";
|
|
@@ -265,6 +274,8 @@ export interface DeleteNode {
|
|
|
265
274
|
ctes: CTENode[];
|
|
266
275
|
using?: TableRefNode;
|
|
267
276
|
joins: JoinNode[];
|
|
277
|
+
orderBy?: OrderByNode[];
|
|
278
|
+
limit?: ExpressionNode;
|
|
268
279
|
}
|
|
269
280
|
export interface MergeWhenMatched {
|
|
270
281
|
type: "matched";
|
|
@@ -11,6 +11,8 @@ export declare class DeleteBuilder {
|
|
|
11
11
|
join(type: JoinType, table: string | TableRefNode, on?: ExpressionNode): DeleteBuilder;
|
|
12
12
|
innerJoin(table: string | TableRefNode, on: ExpressionNode): DeleteBuilder;
|
|
13
13
|
leftJoin(table: string | TableRefNode, on: ExpressionNode): DeleteBuilder;
|
|
14
|
+
orderBy(expr: string | ExpressionNode, direction?: "ASC" | "DESC"): DeleteBuilder;
|
|
15
|
+
limit(n: ExpressionNode): DeleteBuilder;
|
|
14
16
|
returning(...exprs: ExpressionNode[]): DeleteBuilder;
|
|
15
17
|
with(name: string, query: SelectNode, recursive?: boolean): DeleteBuilder;
|
|
16
18
|
build(): DeleteNode;
|
package/dist/builder/delete.mjs
CHANGED
|
@@ -68,6 +68,25 @@ export class DeleteBuilder {
|
|
|
68
68
|
leftJoin(table, on) {
|
|
69
69
|
return this.join("LEFT", table, on);
|
|
70
70
|
}
|
|
71
|
+
orderBy(expr, direction = "ASC") {
|
|
72
|
+
const node = {
|
|
73
|
+
expr: typeof expr === "string" ? {
|
|
74
|
+
type: "column_ref",
|
|
75
|
+
column: expr
|
|
76
|
+
} : expr,
|
|
77
|
+
direction
|
|
78
|
+
};
|
|
79
|
+
return new DeleteBuilder({
|
|
80
|
+
...this.node,
|
|
81
|
+
orderBy: [...this.node.orderBy ?? [], node]
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
limit(n) {
|
|
85
|
+
return new DeleteBuilder({
|
|
86
|
+
...this.node,
|
|
87
|
+
limit: n
|
|
88
|
+
});
|
|
89
|
+
}
|
|
71
90
|
returning(...exprs) {
|
|
72
91
|
return new DeleteBuilder({
|
|
73
92
|
...this.node,
|
package/dist/builder/eb.d.mts
CHANGED
|
@@ -26,6 +26,12 @@ export declare class Col<T> {
|
|
|
26
26
|
lte(value: T): Expression<boolean>;
|
|
27
27
|
/** LIKE (string columns only) */
|
|
28
28
|
like(this: Col<string>, pattern: string): Expression<boolean>;
|
|
29
|
+
/** NOT LIKE */
|
|
30
|
+
notLike(this: Col<string>, pattern: string): Expression<boolean>;
|
|
31
|
+
/** ILIKE — case-insensitive LIKE (PG) */
|
|
32
|
+
ilike(this: Col<string>, pattern: string): Expression<boolean>;
|
|
33
|
+
/** NOT ILIKE (PG) */
|
|
34
|
+
notIlike(this: Col<string>, pattern: string): Expression<boolean>;
|
|
29
35
|
/** IN (value1, value2, ...) */
|
|
30
36
|
in(values: T[]): Expression<boolean>;
|
|
31
37
|
/** NOT IN */
|
|
@@ -36,8 +42,42 @@ export declare class Col<T> {
|
|
|
36
42
|
isNotNull(): Expression<boolean>;
|
|
37
43
|
/** BETWEEN low AND high */
|
|
38
44
|
between(low: T, high: T): Expression<boolean>;
|
|
45
|
+
/** NOT BETWEEN low AND high */
|
|
46
|
+
notBetween(low: T, high: T): Expression<boolean>;
|
|
47
|
+
/** BETWEEN SYMMETRIC low AND high (PG) — order-independent range check */
|
|
48
|
+
betweenSymmetric(low: T, high: T): Expression<boolean>;
|
|
49
|
+
/** IN (SELECT ...) — subquery */
|
|
50
|
+
inSubquery(query: SelectNode): Expression<boolean>;
|
|
51
|
+
/** NOT IN (SELECT ...) — subquery */
|
|
52
|
+
notInSubquery(query: SelectNode): Expression<boolean>;
|
|
53
|
+
/** = with Expression value */
|
|
54
|
+
eqExpr(value: Expression<T>): Expression<boolean>;
|
|
55
|
+
/** != with Expression value */
|
|
56
|
+
neqExpr(value: Expression<T>): Expression<boolean>;
|
|
57
|
+
/** > with Expression value */
|
|
58
|
+
gtExpr(value: Expression<T>): Expression<boolean>;
|
|
59
|
+
/** >= with Expression value */
|
|
60
|
+
gteExpr(value: Expression<T>): Expression<boolean>;
|
|
61
|
+
/** < with Expression value */
|
|
62
|
+
ltExpr(value: Expression<T>): Expression<boolean>;
|
|
63
|
+
/** <= with Expression value */
|
|
64
|
+
lteExpr(value: Expression<T>): Expression<boolean>;
|
|
65
|
+
/** IS DISTINCT FROM — null-safe inequality */
|
|
66
|
+
isDistinctFrom(value: T): Expression<boolean>;
|
|
67
|
+
/** IS NOT DISTINCT FROM — null-safe equality */
|
|
68
|
+
isNotDistinctFrom(value: T): Expression<boolean>;
|
|
39
69
|
/** Compare with another column: col1.eqCol(col2) */
|
|
40
70
|
eqCol(other: Col<T>): Expression<boolean>;
|
|
71
|
+
/** != another column */
|
|
72
|
+
neqCol(other: Col<T>): Expression<boolean>;
|
|
73
|
+
/** > another column */
|
|
74
|
+
gtCol(other: Col<T>): Expression<boolean>;
|
|
75
|
+
/** < another column */
|
|
76
|
+
ltCol(other: Col<T>): Expression<boolean>;
|
|
77
|
+
/** >= another column */
|
|
78
|
+
gteCol(other: Col<T>): Expression<boolean>;
|
|
79
|
+
/** <= another column */
|
|
80
|
+
lteCol(other: Col<T>): Expression<boolean>;
|
|
41
81
|
/** As raw Expression<T> for advanced use */
|
|
42
82
|
toExpr(): Expression<T>;
|
|
43
83
|
}
|
|
@@ -69,12 +109,21 @@ export type WhereCallback<
|
|
|
69
109
|
DB,
|
|
70
110
|
TB extends keyof DB
|
|
71
111
|
> = (cols: ColumnProxies<DB, TB>) => Expression<boolean>;
|
|
72
|
-
/** AND
|
|
73
|
-
export declare function and(
|
|
74
|
-
/** OR
|
|
75
|
-
export declare function or(
|
|
112
|
+
/** AND expressions — variadic: and(a, b) or and(a, b, c, ...) */
|
|
113
|
+
export declare function and(...exprs: Expression<boolean>[]): Expression<boolean>;
|
|
114
|
+
/** OR expressions — variadic: or(a, b) or or(a, b, c, ...) */
|
|
115
|
+
export declare function or(...exprs: Expression<boolean>[]): Expression<boolean>;
|
|
76
116
|
/** Raw literal value as expression */
|
|
77
117
|
export declare function val<T extends string | number | boolean | null>(value: T): Expression<T>;
|
|
118
|
+
/**
|
|
119
|
+
* Raw SQL expression — escape hatch for arbitrary SQL in expressions.
|
|
120
|
+
*
|
|
121
|
+
* ```ts
|
|
122
|
+
* .where(() => rawExpr("age > 18"))
|
|
123
|
+
* .selectExpr(rawExpr<number>("EXTRACT(YEAR FROM created_at)"), "year")
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export declare function rawExpr<T = unknown>(sql: string, params?: unknown[]): Expression<T>;
|
|
78
127
|
/** SQL function call */
|
|
79
128
|
export declare function sqlFn(name: string, ...args: Expression<any>[]): Expression<any>;
|
|
80
129
|
/** COUNT(*) */
|
|
@@ -83,16 +132,32 @@ export declare function count(): Expression<number>;
|
|
|
83
132
|
export declare function countDistinct(expr: Expression<any>): Expression<number>;
|
|
84
133
|
/** SUM(expr) */
|
|
85
134
|
export declare function sum(expr: Expression<number>): Expression<number>;
|
|
135
|
+
/** SUM(DISTINCT expr) */
|
|
136
|
+
export declare function sumDistinct(expr: Expression<number>): Expression<number>;
|
|
86
137
|
/** AVG(expr) */
|
|
87
138
|
export declare function avg(expr: Expression<number>): Expression<number>;
|
|
139
|
+
/** AVG(DISTINCT expr) */
|
|
140
|
+
export declare function avgDistinct(expr: Expression<number>): Expression<number>;
|
|
88
141
|
/** MIN(expr) */
|
|
89
142
|
export declare function min<T>(expr: Expression<T>): Expression<T>;
|
|
90
143
|
/** MAX(expr) */
|
|
91
144
|
export declare function max<T>(expr: Expression<T>): Expression<T>;
|
|
92
|
-
/** COALESCE(
|
|
93
|
-
export declare function coalesce<T>(
|
|
145
|
+
/** COALESCE(a, b, c, ...) — returns first non-null value */
|
|
146
|
+
export declare function coalesce<T>(...args: Expression<T | null>[]): Expression<T>;
|
|
94
147
|
/** NOT expr */
|
|
95
148
|
export declare function not(expr: Expression<boolean>): Expression<boolean>;
|
|
149
|
+
/** Add: a + b */
|
|
150
|
+
export declare function add(a: Expression<number>, b: Expression<number>): Expression<number>;
|
|
151
|
+
/** Subtract: a - b */
|
|
152
|
+
export declare function sub(a: Expression<number>, b: Expression<number>): Expression<number>;
|
|
153
|
+
/** Multiply: a * b */
|
|
154
|
+
export declare function mul(a: Expression<number>, b: Expression<number>): Expression<number>;
|
|
155
|
+
/** Divide: a / b */
|
|
156
|
+
export declare function div(a: Expression<number>, b: Expression<number>): Expression<number>;
|
|
157
|
+
/** Modulo: a % b */
|
|
158
|
+
export declare function mod(a: Expression<number>, b: Expression<number>): Expression<number>;
|
|
159
|
+
/** Unary minus: -expr */
|
|
160
|
+
export declare function neg(expr: Expression<number>): Expression<number>;
|
|
96
161
|
/** EXISTS (subquery) */
|
|
97
162
|
export declare function exists(query: SelectNode): Expression<boolean>;
|
|
98
163
|
/** NOT EXISTS (subquery) */
|
|
@@ -156,6 +221,7 @@ export declare class WindowBuilder {
|
|
|
156
221
|
orderBy(column: string, direction?: "ASC" | "DESC"): WindowBuilder;
|
|
157
222
|
rows(start: FrameBound, end?: FrameBound): WindowBuilder;
|
|
158
223
|
range(start: FrameBound, end?: FrameBound): WindowBuilder;
|
|
224
|
+
groups(start: FrameBound, end?: FrameBound): WindowBuilder;
|
|
159
225
|
}
|
|
160
226
|
/** ROW_NUMBER() — must be used with over() */
|
|
161
227
|
export declare function rowNumber(): Expression<number>;
|
|
@@ -197,8 +263,44 @@ export declare function abs(expr: Expression<number>): Expression<number>;
|
|
|
197
263
|
export declare function round(expr: Expression<number>, precision?: number): Expression<number>;
|
|
198
264
|
/** CEIL(expr) */
|
|
199
265
|
export declare function ceil(expr: Expression<number>): Expression<number>;
|
|
266
|
+
/** JSON_AGG(expr) — aggregate rows into JSON array (PG) */
|
|
267
|
+
export declare function jsonAgg<T>(expr: Expression<T>): Expression<T[]>;
|
|
268
|
+
/** TO_JSON(expr) — convert value to JSON (PG) */
|
|
269
|
+
export declare function toJson<T>(expr: Expression<T>): Expression<unknown>;
|
|
270
|
+
/** JSON_BUILD_OBJECT(key, value, ...) — build JSON object (PG) */
|
|
271
|
+
export declare function jsonBuildObject(...pairs: [string, Expression<any>][]): Expression<Record<string, unknown>>;
|
|
272
|
+
/** @> (array contains) */
|
|
273
|
+
export declare function arrayContains(arr: Expression<any>, values: Expression<any>): Expression<boolean>;
|
|
274
|
+
/** <@ (array contained by) */
|
|
275
|
+
export declare function arrayContainedBy(arr: Expression<any>, values: Expression<any>): Expression<boolean>;
|
|
276
|
+
/** && (array overlaps) */
|
|
277
|
+
export declare function arrayOverlaps(arr: Expression<any>, values: Expression<any>): Expression<boolean>;
|
|
200
278
|
/** FLOOR(expr) */
|
|
201
279
|
export declare function floor(expr: Expression<number>): Expression<number>;
|
|
280
|
+
/** STRING_AGG(expr, delimiter) — aggregate strings with separator */
|
|
281
|
+
export declare function stringAgg(expr: Expression<string>, delimiter: string, orderBy?: {
|
|
282
|
+
expr: Expression<any>;
|
|
283
|
+
direction?: "ASC" | "DESC";
|
|
284
|
+
}[]): Expression<string>;
|
|
285
|
+
/** ARRAY_AGG(expr) — aggregate values into array */
|
|
286
|
+
export declare function arrayAgg<T>(expr: Expression<T>, orderBy?: {
|
|
287
|
+
expr: Expression<any>;
|
|
288
|
+
direction?: "ASC" | "DESC";
|
|
289
|
+
}[]): Expression<T[]>;
|
|
290
|
+
/** Attach ORDER BY to an existing aggregate expression. */
|
|
291
|
+
export declare function aggOrderBy<T>(agg: Expression<T>, orderBy: {
|
|
292
|
+
expr: Expression<any>;
|
|
293
|
+
direction?: "ASC" | "DESC";
|
|
294
|
+
}[]): Expression<T>;
|
|
295
|
+
/**
|
|
296
|
+
* Row-value tuple for comparisons.
|
|
297
|
+
*
|
|
298
|
+
* ```ts
|
|
299
|
+
* // (a, b) = (1, 2)
|
|
300
|
+
* tuple(cols.a.toExpr(), cols.b.toExpr())
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
export declare function tuple(...exprs: Expression<any>[]): Expression<any>;
|
|
202
304
|
/**
|
|
203
305
|
* Attach FILTER (WHERE ...) to an aggregate expression.
|
|
204
306
|
*
|