measurr 0.1.0

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.
@@ -0,0 +1,218 @@
1
+ // src/expr.ts
2
+ class Expr2 {
3
+ node;
4
+ sqlType;
5
+ valueType;
6
+ constructor(node) {
7
+ this.node = node;
8
+ }
9
+ isNull() {
10
+ return new Expr2({ kind: "isNull", item: this.node, negated: false });
11
+ }
12
+ isNotNull() {
13
+ return new Expr2({ kind: "isNull", item: this.node, negated: true });
14
+ }
15
+ add(other) {
16
+ return arithmetic("+", this, other);
17
+ }
18
+ sub(other) {
19
+ return arithmetic("-", this, other);
20
+ }
21
+ mul(other) {
22
+ return arithmetic("*", this, other);
23
+ }
24
+ div(other) {
25
+ return arithmetic("/", this, other);
26
+ }
27
+ }
28
+ function arithmetic(op, left, right) {
29
+ return new Expr2({
30
+ kind: "arithmetic",
31
+ op,
32
+ left: left.node,
33
+ right: toNode(right)
34
+ });
35
+ }
36
+
37
+ class Table2 {
38
+ ref;
39
+ row;
40
+ constructor(ref) {
41
+ this.ref = ref;
42
+ }
43
+ col(key) {
44
+ return new Expr2({
45
+ kind: "column",
46
+ table: this.ref,
47
+ column: key
48
+ });
49
+ }
50
+ leftJoin(other, on) {
51
+ return this.join("left", other, on);
52
+ }
53
+ innerJoin(other, on) {
54
+ return this.join("inner", other, on);
55
+ }
56
+ join(type, other, on) {
57
+ const ref = {
58
+ name: other.ref.name,
59
+ alias: other.ref.alias,
60
+ join: undefined
61
+ };
62
+ const joined = new Table2(ref);
63
+ ref.join = { type, parent: this.ref, on: on(joined).node };
64
+ return joined;
65
+ }
66
+ }
67
+ function table2(name, alias) {
68
+ return new Table2({ name, alias, join: undefined });
69
+ }
70
+ function toNode(value) {
71
+ if (value instanceof Expr2)
72
+ return value.node;
73
+ return { kind: "param", value };
74
+ }
75
+ function literal2(value) {
76
+ return new Expr2({ kind: "param", value });
77
+ }
78
+ function compare(op, left, right) {
79
+ return new Expr2({
80
+ kind: "compare",
81
+ op,
82
+ left: left.node,
83
+ right: toNode(right)
84
+ });
85
+ }
86
+ function eq2(left, right) {
87
+ return compare("=", left, right);
88
+ }
89
+ function ne2(left, right) {
90
+ return compare("<>", left, right);
91
+ }
92
+ function gt2(left, right) {
93
+ return compare(">", left, right);
94
+ }
95
+ function gte2(left, right) {
96
+ return compare(">=", left, right);
97
+ }
98
+ function lt2(left, right) {
99
+ return compare("<", left, right);
100
+ }
101
+ function lte2(left, right) {
102
+ return compare("<=", left, right);
103
+ }
104
+ function and2(...items) {
105
+ return new Expr2({
106
+ kind: "logical",
107
+ op: "and",
108
+ items: items.map((i) => i.node)
109
+ });
110
+ }
111
+ function or2(...items) {
112
+ return new Expr2({
113
+ kind: "logical",
114
+ op: "or",
115
+ items: items.map((i) => i.node)
116
+ });
117
+ }
118
+ function not2(item) {
119
+ if (item.node.kind === "exists") {
120
+ return new Expr2({ ...item.node, negated: !item.node.negated });
121
+ }
122
+ return new Expr2({ kind: "not", item: item.node });
123
+ }
124
+ function isNull2(item) {
125
+ return item.isNull();
126
+ }
127
+ function isNotNull2(item) {
128
+ return item.isNotNull();
129
+ }
130
+ function caseWhen2(branches, otherwise) {
131
+ if (branches.length === 0) {
132
+ throw new Error("caseWhen needs at least one branch");
133
+ }
134
+ return new Expr2({
135
+ kind: "case",
136
+ branches: branches.map(([when, then]) => ({
137
+ when: when.node,
138
+ result: toNode(then)
139
+ })),
140
+ otherwise: otherwise === undefined ? null : toNode(otherwise)
141
+ });
142
+ }
143
+ function exists2(from, where) {
144
+ return new Expr2({
145
+ kind: "exists",
146
+ table: from.ref,
147
+ where: where.node,
148
+ negated: false
149
+ });
150
+ }
151
+ function coalesce2(first, ...rest) {
152
+ return new Expr2({
153
+ kind: "coalesce",
154
+ items: [first.node, ...rest.map((item) => toNode(item))]
155
+ });
156
+ }
157
+ function inList2(item, values) {
158
+ return new Expr2({
159
+ kind: "in",
160
+ item: item.node,
161
+ values: values.map((value) => toNode(value)),
162
+ negated: false
163
+ });
164
+ }
165
+ function toText2(item) {
166
+ return new Expr2({ kind: "toText", item: item.node });
167
+ }
168
+ function minutesAgo2(minutes) {
169
+ return new Expr2({ kind: "minutesAgo", minutes });
170
+ }
171
+ function rootOf(ref) {
172
+ let current = ref;
173
+ while (current.join)
174
+ current = current.join.parent;
175
+ return current;
176
+ }
177
+ function directChildren(node) {
178
+ switch (node.kind) {
179
+ case "compare":
180
+ case "arithmetic":
181
+ return [node.left, node.right];
182
+ case "logical":
183
+ case "coalesce":
184
+ return node.items;
185
+ case "not":
186
+ case "isNull":
187
+ case "lower":
188
+ case "toText":
189
+ case "timeBucket":
190
+ case "timePart":
191
+ return [node.item];
192
+ case "in":
193
+ return [node.item, ...node.values];
194
+ case "case":
195
+ return [
196
+ ...node.branches.flatMap((branch) => [branch.when, branch.result]),
197
+ ...node.otherwise ? [node.otherwise] : []
198
+ ];
199
+ case "aggregate":
200
+ return [
201
+ ...node.arg ? [node.arg] : [],
202
+ ...node.where ? [node.where] : []
203
+ ];
204
+ case "exists":
205
+ return [node.where];
206
+ case "column":
207
+ case "param":
208
+ case "minutesAgo":
209
+ return [];
210
+ }
211
+ }
212
+ function walk(node, visit) {
213
+ visit(node);
214
+ for (const child of directChildren(node))
215
+ walk(child, visit);
216
+ }
217
+
218
+ export { Expr2, Table2, table2, literal2, eq2, ne2, gt2, gte2, lt2, lte2, and2, or2, not2, isNull2, isNotNull2, caseWhen2, exists2, coalesce2, inList2, toText2, minutesAgo2, rootOf, directChildren, walk };