sumak 0.0.4 → 0.0.5

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.
Files changed (121) hide show
  1. package/README.md +255 -5
  2. package/dist/ast/expression.d.mts +26 -0
  3. package/dist/ast/expression.mjs +140 -0
  4. package/dist/ast/nodes.d.mts +298 -0
  5. package/dist/ast/nodes.mjs +59 -0
  6. package/dist/ast/transformer.d.mts +10 -0
  7. package/dist/ast/transformer.mjs +140 -0
  8. package/dist/ast/typed-expression.d.mts +37 -0
  9. package/dist/ast/typed-expression.mjs +77 -0
  10. package/dist/ast/visitor.d.mts +13 -0
  11. package/dist/ast/visitor.mjs +11 -0
  12. package/dist/builder/delete.d.mts +18 -0
  13. package/dist/builder/delete.mjs +94 -0
  14. package/dist/builder/eb.d.mts +210 -0
  15. package/dist/builder/eb.mjs +399 -0
  16. package/dist/builder/expression.d.mts +5 -0
  17. package/dist/builder/expression.mjs +10 -0
  18. package/dist/builder/insert.d.mts +40 -0
  19. package/dist/builder/insert.mjs +146 -0
  20. package/dist/builder/merge.d.mts +20 -0
  21. package/dist/builder/merge.mjs +100 -0
  22. package/dist/builder/raw.d.mts +2 -0
  23. package/dist/builder/raw.mjs +4 -0
  24. package/dist/builder/select.d.mts +38 -0
  25. package/dist/builder/select.mjs +242 -0
  26. package/dist/builder/typed-delete.d.mts +43 -0
  27. package/dist/builder/typed-delete.mjs +77 -0
  28. package/dist/builder/typed-insert.d.mts +74 -0
  29. package/dist/builder/typed-insert.mjs +136 -0
  30. package/dist/builder/typed-merge.d.mts +31 -0
  31. package/dist/builder/typed-merge.mjs +93 -0
  32. package/dist/builder/typed-select.d.mts +125 -0
  33. package/dist/builder/typed-select.mjs +217 -0
  34. package/dist/builder/typed-update.d.mts +55 -0
  35. package/dist/builder/typed-update.mjs +102 -0
  36. package/dist/builder/update.d.mts +18 -0
  37. package/dist/builder/update.mjs +102 -0
  38. package/dist/dialect/mssql.d.mts +2 -0
  39. package/dist/dialect/mssql.mjs +9 -0
  40. package/dist/dialect/mysql.d.mts +2 -0
  41. package/dist/dialect/mysql.mjs +9 -0
  42. package/dist/dialect/pg.d.mts +2 -0
  43. package/dist/dialect/pg.mjs +9 -0
  44. package/dist/dialect/sqlite.d.mts +2 -0
  45. package/dist/dialect/sqlite.mjs +9 -0
  46. package/dist/dialect/types.d.mts +6 -0
  47. package/dist/dialect/types.mjs +1 -0
  48. package/dist/errors.d.mts +12 -0
  49. package/dist/errors.mjs +24 -0
  50. package/dist/index.d.mts +49 -806
  51. package/dist/index.mjs +46 -3
  52. package/dist/mssql.d.mts +2 -2
  53. package/dist/mssql.mjs +2 -1
  54. package/dist/mysql.d.mts +2 -2
  55. package/dist/mysql.mjs +2 -1
  56. package/dist/pg.d.mts +2 -2
  57. package/dist/pg.mjs +2 -1
  58. package/dist/plugin/camel-case.d.mts +11 -0
  59. package/dist/plugin/camel-case.mjs +16 -0
  60. package/dist/plugin/hooks.d.mts +72 -0
  61. package/dist/plugin/hooks.mjs +49 -0
  62. package/dist/plugin/plugin-manager.d.mts +17 -0
  63. package/dist/plugin/plugin-manager.mjs +37 -0
  64. package/dist/plugin/soft-delete.d.mts +27 -0
  65. package/dist/plugin/soft-delete.mjs +52 -0
  66. package/dist/plugin/types.d.mts +19 -0
  67. package/dist/plugin/types.mjs +1 -0
  68. package/dist/plugin/with-schema.d.mts +21 -0
  69. package/dist/plugin/with-schema.mjs +53 -0
  70. package/dist/printer/base.d.mts +48 -0
  71. package/dist/printer/base.mjs +450 -0
  72. package/dist/printer/document.d.mts +45 -0
  73. package/dist/printer/document.mjs +153 -0
  74. package/dist/printer/formatter.d.mts +5 -0
  75. package/dist/printer/formatter.mjs +134 -0
  76. package/dist/printer/mssql.d.mts +10 -0
  77. package/dist/printer/mssql.mjs +161 -0
  78. package/dist/printer/mysql.d.mts +8 -0
  79. package/dist/printer/mysql.mjs +41 -0
  80. package/dist/printer/pg.d.mts +6 -0
  81. package/dist/printer/pg.mjs +9 -0
  82. package/dist/printer/sqlite.d.mts +8 -0
  83. package/dist/printer/sqlite.mjs +29 -0
  84. package/dist/printer/types.d.mts +11 -0
  85. package/dist/printer/types.mjs +1 -0
  86. package/dist/schema/column.d.mts +52 -0
  87. package/dist/schema/column.mjs +120 -0
  88. package/dist/schema/index.d.mts +6 -0
  89. package/dist/schema/index.mjs +4 -0
  90. package/dist/schema/table.d.mts +37 -0
  91. package/dist/schema/table.mjs +7 -0
  92. package/dist/schema/type-utils.d.mts +46 -0
  93. package/dist/schema/type-utils.mjs +1 -0
  94. package/dist/schema/types.d.mts +64 -0
  95. package/dist/schema/types.mjs +1 -0
  96. package/dist/schema.d.mts +2 -2
  97. package/dist/schema.mjs +1 -1
  98. package/dist/sqlite.d.mts +2 -2
  99. package/dist/sqlite.mjs +2 -1
  100. package/dist/sumak.d.mts +98 -0
  101. package/dist/sumak.mjs +132 -0
  102. package/dist/types.d.mts +14 -0
  103. package/dist/types.mjs +1 -0
  104. package/dist/utils/identifier.d.mts +3 -0
  105. package/dist/utils/identifier.mjs +14 -0
  106. package/dist/utils/param.d.mts +2 -0
  107. package/dist/utils/param.mjs +8 -0
  108. package/package.json +1 -1
  109. package/dist/_chunks/base.mjs +0 -1
  110. package/dist/_chunks/errors.mjs +0 -1
  111. package/dist/_chunks/index.d.mts +0 -136
  112. package/dist/_chunks/mssql.d.mts +0 -11
  113. package/dist/_chunks/mssql.mjs +0 -1
  114. package/dist/_chunks/mysql.d.mts +0 -9
  115. package/dist/_chunks/mysql.mjs +0 -1
  116. package/dist/_chunks/pg.d.mts +0 -7
  117. package/dist/_chunks/pg.mjs +0 -1
  118. package/dist/_chunks/schema.mjs +0 -1
  119. package/dist/_chunks/sqlite.d.mts +0 -9
  120. package/dist/_chunks/sqlite.mjs +0 -1
  121. package/dist/_chunks/types.d.mts +0 -338
package/README.md CHANGED
@@ -208,10 +208,13 @@ db.selectFrom("users").crossJoin("posts").compile(db.printer())
208
208
  ### Aggregates
209
209
 
210
210
  ```ts
211
- import { count, sum, avg, min, max, coalesce } from "sumak"
211
+ import { count, countDistinct, sum, avg, min, max, coalesce } from "sumak"
212
212
 
213
213
  db.selectFrom("users").selectExpr(count(), "total").compile(db.printer())
214
214
 
215
+ db.selectFrom("users").selectExpr(countDistinct(col.dept), "uniqueDepts").compile(db.printer())
216
+ // SELECT COUNT(DISTINCT "dept") AS "uniqueDepts" FROM "users"
217
+
215
218
  db.selectFrom("orders").selectExpr(sum(col.amount), "totalAmount").compile(db.printer())
216
219
 
217
220
  db.selectFrom("orders").selectExpr(avg(col.amount), "avgAmount").compile(db.printer())
@@ -292,6 +295,122 @@ db.selectFrom("users")
292
295
  .compile(db.printer())
293
296
  ```
294
297
 
298
+ ## Window Functions
299
+
300
+ ```ts
301
+ import { over, rowNumber, rank, denseRank, lag, lead, ntile, count, sum } from "sumak"
302
+
303
+ // ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC)
304
+ db.selectFrom("employees")
305
+ .selectExpr(
306
+ over(rowNumber(), (w) => w.partitionBy("dept").orderBy("salary", "DESC")),
307
+ "rn",
308
+ )
309
+ .compile(db.printer())
310
+
311
+ // RANK() OVER (ORDER BY score DESC)
312
+ db.selectFrom("students")
313
+ .selectExpr(
314
+ over(rank(), (w) => w.orderBy("score", "DESC")),
315
+ "rnk",
316
+ )
317
+ .compile(db.printer())
318
+
319
+ // Running total with frame
320
+ db.selectFrom("orders")
321
+ .selectExpr(
322
+ over(sum(col.amount), (w) =>
323
+ w
324
+ .partitionBy("userId")
325
+ .orderBy("createdAt")
326
+ .rows({ type: "unbounded_preceding" }, { type: "current_row" }),
327
+ ),
328
+ "runningTotal",
329
+ )
330
+ .compile(db.printer())
331
+
332
+ // LAG / LEAD
333
+ db.selectFrom("prices")
334
+ .selectExpr(
335
+ over(lag(col.price, 1), (w) => w.orderBy("date")),
336
+ "prevPrice",
337
+ )
338
+ .compile(db.printer())
339
+
340
+ // NTILE(4)
341
+ db.selectFrom("employees")
342
+ .selectExpr(
343
+ over(ntile(4), (w) => w.orderBy("salary", "DESC")),
344
+ "quartile",
345
+ )
346
+ .compile(db.printer())
347
+ ```
348
+
349
+ ## SQL Functions
350
+
351
+ ### String Functions
352
+
353
+ ```ts
354
+ import { upper, lower, concat, substring, trim, length } from "sumak"
355
+
356
+ db.selectFrom("users").selectExpr(upper(col.name), "upperName").compile(db.printer())
357
+ // SELECT UPPER("name") AS "upperName" FROM "users"
358
+
359
+ db.selectFrom("users").selectExpr(lower(col.email), "lowerEmail").compile(db.printer())
360
+
361
+ db.selectFrom("users")
362
+ .selectExpr(concat(col.firstName, val(" "), col.lastName), "fullName")
363
+ .compile(db.printer())
364
+
365
+ db.selectFrom("users")
366
+ .selectExpr(substring(col.name, 1, 3), "prefix")
367
+ .compile(db.printer())
368
+
369
+ db.selectFrom("users").selectExpr(trim(col.name), "trimmed").compile(db.printer())
370
+
371
+ db.selectFrom("users").selectExpr(length(col.name), "nameLen").compile(db.printer())
372
+ ```
373
+
374
+ ### Numeric Functions
375
+
376
+ ```ts
377
+ import { abs, round, ceil, floor } from "sumak"
378
+
379
+ db.selectFrom("orders").selectExpr(abs(col.balance), "absBalance").compile(db.printer())
380
+
381
+ db.selectFrom("orders").selectExpr(round(col.price, 2), "rounded").compile(db.printer())
382
+
383
+ db.selectFrom("orders").selectExpr(ceil(col.amount), "ceiling").compile(db.printer())
384
+
385
+ db.selectFrom("orders").selectExpr(floor(col.amount), "floored").compile(db.printer())
386
+ ```
387
+
388
+ ### Conditional Functions
389
+
390
+ ```ts
391
+ import { nullif, greatest, least } from "sumak"
392
+
393
+ db.selectFrom("users")
394
+ .selectExpr(nullif(col.age, val(0)), "ageOrNull")
395
+ .compile(db.printer())
396
+
397
+ db.selectFrom("products")
398
+ .selectExpr(greatest(col.price, col.minPrice), "effectivePrice")
399
+ .compile(db.printer())
400
+
401
+ db.selectFrom("products")
402
+ .selectExpr(least(col.price, col.maxPrice), "cappedPrice")
403
+ .compile(db.printer())
404
+ ```
405
+
406
+ ### Date/Time Functions
407
+
408
+ ```ts
409
+ import { now, currentTimestamp } from "sumak"
410
+
411
+ db.selectFrom("users").selectExpr(now(), "currentTime").compile(db.printer())
412
+ ```
413
+
295
414
  ## Set Operations
296
415
 
297
416
  ```ts
@@ -311,11 +430,13 @@ active.union(premium).compile(db.printer())
311
430
  // UNION ALL
312
431
  active.unionAll(premium).compile(db.printer())
313
432
 
314
- // INTERSECT
433
+ // INTERSECT / INTERSECT ALL
315
434
  active.intersect(premium).compile(db.printer())
435
+ active.intersectAll(premium).compile(db.printer())
316
436
 
317
- // EXCEPT
437
+ // EXCEPT / EXCEPT ALL
318
438
  active.except(premium).compile(db.printer())
439
+ active.exceptAll(premium).compile(db.printer())
319
440
  ```
320
441
 
321
442
  ## CTEs (WITH)
@@ -362,20 +483,73 @@ db.update("users")
362
483
  // UPDATE "users" SET "name" = $1 FROM "posts" WHERE ("id" = $2)
363
484
  ```
364
485
 
486
+ ## Conditional Query Building
487
+
488
+ ```ts
489
+ const withFilter = true
490
+ const withOrder = false
491
+
492
+ db.selectFrom("users")
493
+ .select("id", "name")
494
+ .$if(withFilter, (qb) => qb.where(({ age }) => age.gt(18)))
495
+ .$if(withOrder, (qb) => qb.orderBy("name"))
496
+ .compile(db.printer())
497
+ // WHERE applied, ORDER BY skipped
498
+
499
+ // Multiple .where() calls are AND'd together
500
+ db.selectFrom("users")
501
+ .select("id")
502
+ .where(({ age }) => age.gt(18))
503
+ .where(({ active }) => active.eq(true))
504
+ .compile(db.printer())
505
+ // WHERE ("age" > $1) AND ("active" = $2)
506
+ ```
507
+
508
+ ## INSERT Advanced
509
+
510
+ ```ts
511
+ // INSERT ... SELECT
512
+ const selectQuery = db.selectFrom("users").select("name", "age").build()
513
+ db.insertInto("archive").fromSelect(selectQuery).compile(db.printer())
514
+
515
+ // INSERT ... DEFAULT VALUES
516
+ db.insertInto("users").defaultValues().compile(db.printer())
517
+
518
+ // SQLite: INSERT OR IGNORE / INSERT OR REPLACE
519
+ db.insertInto("users").values({ name: "Alice" }).orIgnore().compile(db.printer())
520
+ // INSERT OR IGNORE INTO "users" ...
521
+
522
+ db.insertInto("users").values({ name: "Alice" }).orReplace().compile(db.printer())
523
+ // INSERT OR REPLACE INTO "users" ...
524
+ ```
525
+
365
526
  ## ON CONFLICT
366
527
 
367
528
  ```ts
368
- // DO NOTHING
529
+ // DO NOTHING (by columns)
369
530
  db.insertInto("users")
370
531
  .values({ name: "Alice", email: "a@b.com" })
371
532
  .onConflictDoNothing("email")
372
533
  .compile(db.printer())
373
534
 
374
- // DO UPDATE
535
+ // DO UPDATE (by columns)
375
536
  db.insertInto("users")
376
537
  .values({ name: "Alice", email: "a@b.com" })
377
538
  .onConflictDoUpdate(["email"], [{ column: "name", value: val("Alice") }])
378
539
  .compile(db.printer())
540
+
541
+ // DO NOTHING (by constraint name)
542
+ db.insertInto("users")
543
+ .values({ name: "Alice", email: "a@b.com" })
544
+ .onConflictConstraintDoNothing("users_email_key")
545
+ .compile(db.printer())
546
+ // ON CONFLICT ON CONSTRAINT "users_email_key" DO NOTHING
547
+
548
+ // MySQL: ON DUPLICATE KEY UPDATE
549
+ db.insertInto("users")
550
+ .values({ name: "Alice" })
551
+ .onDuplicateKeyUpdate([{ column: "name", value: val("Alice") }])
552
+ .compile(db.printer())
379
553
  ```
380
554
 
381
555
  ## MERGE (SQL:2003)
@@ -395,6 +569,82 @@ db.mergeInto("users", "staging", "s", ({ target, source }) => target.id.eqCol(so
395
569
  .compile(db.printer())
396
570
  ```
397
571
 
572
+ ## Row Locking
573
+
574
+ ```ts
575
+ // FOR UPDATE
576
+ db.selectFrom("users").select("id").forUpdate().compile(db.printer())
577
+
578
+ // FOR SHARE
579
+ db.selectFrom("users").select("id").forShare().compile(db.printer())
580
+
581
+ // FOR NO KEY UPDATE / FOR KEY SHARE (PG)
582
+ db.selectFrom("users").select("id").forNoKeyUpdate().compile(db.printer())
583
+ db.selectFrom("users").select("id").forKeyShare().compile(db.printer())
584
+
585
+ // SKIP LOCKED / NOWAIT
586
+ db.selectFrom("users").select("id").forUpdate().skipLocked().compile(db.printer())
587
+ db.selectFrom("users").select("id").forUpdate().noWait().compile(db.printer())
588
+ ```
589
+
590
+ ## DISTINCT ON (PG)
591
+
592
+ ```ts
593
+ db.selectFrom("users")
594
+ .selectAll()
595
+ .distinctOn("dept")
596
+ .orderBy("dept")
597
+ .orderBy("salary", "DESC")
598
+ .compile(db.printer())
599
+ // SELECT DISTINCT ON ("dept") * FROM "users" ORDER BY "dept" ASC, "salary" DESC
600
+ ```
601
+
602
+ ## DELETE USING / JOIN in UPDATE & DELETE
603
+
604
+ ```ts
605
+ // PG: DELETE ... USING
606
+ db.deleteFrom("orders")
607
+ .using("users")
608
+ .where(eq(col("orders.user_id"), col("users.id")))
609
+ .compile(db.printer())
610
+
611
+ // MySQL: DELETE with JOIN
612
+ db.deleteFrom("orders")
613
+ .innerJoin("users", eq(col("user_id", "orders"), col("id", "users")))
614
+ .where(eq(col("name", "users"), lit("Alice")))
615
+ .compile(db.printer())
616
+
617
+ // MySQL: UPDATE with JOIN
618
+ db.update("orders")
619
+ .set({ total: 0 })
620
+ .innerJoin("users", eq(col("user_id", "orders"), col("id", "users")))
621
+ .compile(db.printer())
622
+ ```
623
+
624
+ ## Aggregate FILTER (WHERE)
625
+
626
+ ```ts
627
+ import { filter, count, sum } from "sumak"
628
+
629
+ // COUNT(*) FILTER (WHERE active = true)
630
+ db.selectFrom("users").selectExpr(filter(count(), activeExpr), "activeCount").compile(db.printer())
631
+ ```
632
+
633
+ ## EXPLAIN
634
+
635
+ ```ts
636
+ // EXPLAIN
637
+ db.selectFrom("users").select("id").explain().compile(db.printer())
638
+ // EXPLAIN SELECT "id" FROM "users"
639
+
640
+ // EXPLAIN ANALYZE
641
+ db.selectFrom("users").select("id").explain({ analyze: true }).compile(db.printer())
642
+
643
+ // EXPLAIN with format
644
+ db.selectFrom("users").select("id").explain({ format: "JSON" }).compile(db.printer())
645
+ // EXPLAIN (FORMAT JSON) SELECT "id" FROM "users"
646
+ ```
647
+
398
648
  ## Full-Text Search
399
649
 
400
650
  Dialect-aware FTS — same API, different SQL per dialect:
@@ -0,0 +1,26 @@
1
+ import type { BetweenNode, BinaryOpNode, CastNode, ColumnRefNode, ExistsNode, ExpressionNode, FunctionCallNode, InNode, IsNullNode, LiteralNode, ParamNode, RawNode, SelectNode, StarNode, SubqueryNode, UnaryOpNode } from "./nodes.mjs";
2
+ export declare function col(column: string, table?: string): ColumnRefNode;
3
+ export declare function colAs(column: string, alias: string, table?: string): ColumnRefNode;
4
+ export declare function lit(value: string | number | boolean | null): LiteralNode;
5
+ export declare function star(table?: string): StarNode;
6
+ export declare function param(index: number, value: unknown): ParamNode;
7
+ export declare function raw(sql: string, params?: unknown[]): RawNode;
8
+ export declare function subquery(query: SelectNode, alias?: string): SubqueryNode;
9
+ export declare function fn(name: string, args: ExpressionNode[], alias?: string): FunctionCallNode;
10
+ export declare function binOp(op: string, left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
11
+ export declare function unaryOp(op: string, operand: ExpressionNode, position?: "prefix" | "postfix"): UnaryOpNode;
12
+ export declare function and(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
13
+ export declare function or(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
14
+ export declare function eq(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
15
+ export declare function neq(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
16
+ export declare function gt(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
17
+ export declare function gte(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
18
+ export declare function lt(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
19
+ export declare function lte(left: ExpressionNode, right: ExpressionNode): BinaryOpNode;
20
+ export declare function like(expr: ExpressionNode, pattern: ExpressionNode): BinaryOpNode;
21
+ export declare function between(expr: ExpressionNode, low: ExpressionNode, high: ExpressionNode, negated?: boolean): BetweenNode;
22
+ export declare function inList(expr: ExpressionNode, values: ExpressionNode[] | SelectNode, negated?: boolean): InNode;
23
+ export declare function isNull(expr: ExpressionNode, negated?: boolean): IsNullNode;
24
+ export declare function cast(expr: ExpressionNode, dataType: string): CastNode;
25
+ export declare function exists(query: SelectNode, negated?: boolean): ExistsNode;
26
+ export declare function not(operand: ExpressionNode): UnaryOpNode;
@@ -0,0 +1,140 @@
1
+ export function col(column, table) {
2
+ return {
3
+ type: "column_ref",
4
+ column,
5
+ table
6
+ };
7
+ }
8
+ export function colAs(column, alias, table) {
9
+ return {
10
+ type: "column_ref",
11
+ column,
12
+ table,
13
+ alias
14
+ };
15
+ }
16
+ export function lit(value) {
17
+ return {
18
+ type: "literal",
19
+ value
20
+ };
21
+ }
22
+ export function star(table) {
23
+ return {
24
+ type: "star",
25
+ table
26
+ };
27
+ }
28
+ export function param(index, value) {
29
+ return {
30
+ type: "param",
31
+ index,
32
+ value
33
+ };
34
+ }
35
+ export function raw(sql, params = []) {
36
+ return {
37
+ type: "raw",
38
+ sql,
39
+ params
40
+ };
41
+ }
42
+ export function subquery(query, alias) {
43
+ return {
44
+ type: "subquery",
45
+ query,
46
+ alias
47
+ };
48
+ }
49
+ export function fn(name, args, alias) {
50
+ return {
51
+ type: "function_call",
52
+ name,
53
+ args,
54
+ alias
55
+ };
56
+ }
57
+ export function binOp(op, left, right) {
58
+ return {
59
+ type: "binary_op",
60
+ op,
61
+ left,
62
+ right
63
+ };
64
+ }
65
+ export function unaryOp(op, operand, position = "prefix") {
66
+ return {
67
+ type: "unary_op",
68
+ op,
69
+ operand,
70
+ position
71
+ };
72
+ }
73
+ export function and(left, right) {
74
+ return binOp("AND", left, right);
75
+ }
76
+ export function or(left, right) {
77
+ return binOp("OR", left, right);
78
+ }
79
+ export function eq(left, right) {
80
+ return binOp("=", left, right);
81
+ }
82
+ export function neq(left, right) {
83
+ return binOp("!=", left, right);
84
+ }
85
+ export function gt(left, right) {
86
+ return binOp(">", left, right);
87
+ }
88
+ export function gte(left, right) {
89
+ return binOp(">=", left, right);
90
+ }
91
+ export function lt(left, right) {
92
+ return binOp("<", left, right);
93
+ }
94
+ export function lte(left, right) {
95
+ return binOp("<=", left, right);
96
+ }
97
+ export function like(expr, pattern) {
98
+ return binOp("LIKE", expr, pattern);
99
+ }
100
+ export function between(expr, low, high, negated = false) {
101
+ return {
102
+ type: "between",
103
+ expr,
104
+ low,
105
+ high,
106
+ negated
107
+ };
108
+ }
109
+ export function inList(expr, values, negated = false) {
110
+ return {
111
+ type: "in",
112
+ expr,
113
+ values,
114
+ negated
115
+ };
116
+ }
117
+ export function isNull(expr, negated = false) {
118
+ return {
119
+ type: "is_null",
120
+ expr,
121
+ negated
122
+ };
123
+ }
124
+ export function cast(expr, dataType) {
125
+ return {
126
+ type: "cast",
127
+ expr,
128
+ dataType
129
+ };
130
+ }
131
+ export function exists(query, negated = false) {
132
+ return {
133
+ type: "exists",
134
+ query,
135
+ negated
136
+ };
137
+ }
138
+ export function not(operand) {
139
+ return unaryOp("NOT", operand);
140
+ }