Skip to content

Commit e67ad0a

Browse files
committed
feat: Implement physical expressions (part 2)
- add support for aggregate (MAX, MIN, SUM) expr - fix ArrowVectorBuilder to expose setNull and setSafe methods because f#ing Java - strings are still complicated in java circa 2025
1 parent c8b458f commit e67ad0a

File tree

13 files changed

+754
-6
lines changed

13 files changed

+754
-6
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package co.clflushopt.glint.query.functional;
2+
3+
/**
4+
* Accumaulator interface defines a function that accumulates values streamed to
5+
* it.
6+
*
7+
* Accumulator
8+
*/
9+
public interface Accumulator {
10+
11+
/**
12+
* Accumulate the value.
13+
*
14+
* @param value the value to accumulate.
15+
*/
16+
public void accumulate(Object value);
17+
18+
/**
19+
* Get the result of the accumulation.
20+
*
21+
* @return the result of the accumulation.
22+
*/
23+
public Object getResult();
24+
25+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package co.clflushopt.glint.query.functional;
2+
3+
/**
4+
* Implementation of an accumulator that accumulates the maximum value.
5+
*
6+
* MaxAccumulator
7+
*/
8+
public class MaxAccumulator implements Accumulator {
9+
private Object value;
10+
11+
/**
12+
* Create a new MaxAccumulator.
13+
*
14+
*/
15+
public MaxAccumulator() {
16+
this.value = null;
17+
}
18+
19+
/**
20+
* Accumulate a new value.
21+
*/
22+
@SuppressWarnings("unchecked")
23+
@Override
24+
public void accumulate(Object value) {
25+
if (value != null) {
26+
if (this.value == null || ((Comparable<Object>) value).compareTo(this.value) > 0) {
27+
this.value = value;
28+
} else {
29+
if (value instanceof Double) {
30+
this.value = Math.max((Double) this.value, (Double) value);
31+
} else if (value instanceof Long) {
32+
this.value = Math.max((Long) this.value, (Long) value);
33+
} else if (value instanceof Integer) {
34+
this.value = Math.max((Integer) this.value, (Integer) value);
35+
} else if (value instanceof Float) {
36+
this.value = Math.max((Float) this.value, (Float) value);
37+
} else if (value instanceof Short) {
38+
this.value = Math.max((Short) this.value, (Short) value);
39+
} else if (value instanceof Byte) {
40+
this.value = Math.max((Byte) this.value, (Byte) value);
41+
} else if (value instanceof String) {
42+
this.value = ((String) this.value).compareTo((String) value) > 0 ? this.value
43+
: value;
44+
} else {
45+
throw new UnsupportedOperationException("Unsupported type for MaxAccumulator");
46+
}
47+
}
48+
}
49+
50+
}
51+
52+
/**
53+
* Returns the result of the accumulation.
54+
*
55+
*/
56+
@Override
57+
public Object getResult() {
58+
return value;
59+
}
60+
61+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package co.clflushopt.glint.query.functional;
2+
3+
/**
4+
* Implementation of an accumulator that accumulates the minimum value.
5+
*
6+
* MinAccumulator
7+
*/
8+
public class MinAccumulator implements Accumulator {
9+
private Object value;
10+
11+
/**
12+
* Create a new MinAccumulator.
13+
*
14+
*/
15+
public MinAccumulator() {
16+
this.value = null;
17+
}
18+
19+
/**
20+
* Accumulate a new value.
21+
*/
22+
@SuppressWarnings("unchecked")
23+
@Override
24+
public void accumulate(Object value) {
25+
if (value != null) {
26+
if (this.value == null || ((Comparable<Object>) value).compareTo(this.value) > 0) {
27+
this.value = value;
28+
} else {
29+
if (value instanceof Double) {
30+
this.value = Math.min((Double) this.value, (Double) value);
31+
} else if (value instanceof Long) {
32+
this.value = Math.min((Long) this.value, (Long) value);
33+
} else if (value instanceof Integer) {
34+
this.value = Math.min((Integer) this.value, (Integer) value);
35+
} else if (value instanceof Float) {
36+
this.value = Math.min((Float) this.value, (Float) value);
37+
} else if (value instanceof Short) {
38+
this.value = Math.min((Short) this.value, (Short) value);
39+
} else if (value instanceof Byte) {
40+
this.value = Math.min((Byte) this.value, (Byte) value);
41+
} else if (value instanceof String) {
42+
this.value = ((String) this.value).compareTo((String) value) < 0 ? this.value
43+
: value;
44+
} else {
45+
throw new UnsupportedOperationException("Unsupported type for MinAccumulator");
46+
}
47+
}
48+
}
49+
50+
}
51+
52+
/**
53+
* Returns the result of the accumulation.
54+
*
55+
*/
56+
@Override
57+
public Object getResult() {
58+
return value;
59+
}
60+
61+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package co.clflushopt.glint.query.functional;
2+
3+
/**
4+
* Implements an accumulator that computes the sum of an expression.
5+
*
6+
* SumAccumulator
7+
*/
8+
public class SumAccumulator implements Accumulator {
9+
private Double sum = 0.0;
10+
11+
/**
12+
* Create a new sum accumulator.
13+
*
14+
*/
15+
public SumAccumulator() {
16+
this.sum = 0.0;
17+
}
18+
19+
@Override
20+
public void accumulate(Object value) {
21+
if (value != null) {
22+
if (value instanceof Double) {
23+
sum += (Double) value;
24+
} else if (value instanceof Long) {
25+
sum += (Long) value;
26+
} else if (value instanceof Integer) {
27+
sum += (Integer) value;
28+
} else if (value instanceof Float) {
29+
sum += (Float) value;
30+
} else if (value instanceof Short) {
31+
sum += (Short) value;
32+
} else if (value instanceof Byte) {
33+
sum += (Byte) value;
34+
} else {
35+
throw new UnsupportedOperationException("Unsupported type for SumAccumulator");
36+
}
37+
}
38+
}
39+
40+
@Override
41+
public Object getResult() {
42+
return sum;
43+
}
44+
45+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package co.clflushopt.glint.query.physical.expr;
2+
3+
import co.clflushopt.glint.query.functional.Accumulator;
4+
5+
/**
6+
* Interface for aggregate expressions.
7+
*
8+
* AggregateExpr
9+
*/
10+
public interface AggregateExpr {
11+
12+
/**
13+
* Get the accumulator for the aggregate expression.
14+
*
15+
* @return
16+
*/
17+
public Accumulator getAccumulator();
18+
19+
/**
20+
* Get the input expression for the aggregate expression.
21+
*
22+
* @return
23+
*/
24+
public Expr getInputExpr();
25+
}

glint/src/main/java/co/clflushopt/glint/query/physical/expr/BooleanExpr.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ protected boolean evaluate(Object left, Object right, ArrowType type) {
112112
} else if (type.equals(ArrowTypes.DoubleType)) {
113113
return ((Double) left).equals((Double) right);
114114
} else if (type.equals(ArrowTypes.StringType)) {
115-
return toString(left).equals(toString(right));
115+
return left.toString().equals(right.toString());
116116
}
117117
throw new IllegalStateException(
118118
"Unsupported data type in comparison expression: " + type);
@@ -139,7 +139,7 @@ protected boolean evaluate(Object left, Object right, ArrowType type) {
139139
} else if (type.equals(ArrowTypes.DoubleType)) {
140140
return !((Double) left).equals((Double) right);
141141
} else if (type.equals(ArrowTypes.StringType)) {
142-
return !toString(left).equals(toString(right));
142+
return !left.toString().equals(right.toString());
143143
}
144144
throw new IllegalStateException(
145145
"Unsupported data type in comparison expression: " + type);
@@ -166,7 +166,7 @@ protected boolean evaluate(Object left, Object right, ArrowType type) {
166166
} else if (type.equals(ArrowTypes.DoubleType)) {
167167
return (Double) left < (Double) right;
168168
} else if (type.equals(ArrowTypes.StringType)) {
169-
return toString(left).compareTo(toString(right)) < 0;
169+
return left.toString().compareTo(right.toString()) < 0;
170170
}
171171
throw new IllegalStateException(
172172
"Unsupported data type in comparison expression: " + type);
@@ -193,7 +193,7 @@ protected boolean evaluate(Object left, Object right, ArrowType type) {
193193
} else if (type.equals(ArrowTypes.DoubleType)) {
194194
return (Double) left > (Double) right;
195195
} else if (type.equals(ArrowTypes.StringType)) {
196-
return toString(left).compareTo(toString(right)) > 0;
196+
return left.toString().compareTo(right.toString()) > 0;
197197
}
198198
throw new IllegalStateException(
199199
"Unsupported data type in comparison expression: " + type);
@@ -220,10 +220,12 @@ protected boolean evaluate(Object left, Object right, ArrowType type) {
220220
} else if (type.equals(ArrowTypes.DoubleType)) {
221221
return (Double) left <= (Double) right;
222222
} else if (type.equals(ArrowTypes.StringType)) {
223-
return toString(left).compareTo(toString(right)) <= 0;
223+
return left.toString().compareTo(right.toString()) <= 0;
224224
}
225+
225226
throw new IllegalStateException(
226227
"Unsupported data type in comparison expression: " + type);
228+
227229
}
228230
}
229231

@@ -247,10 +249,11 @@ protected boolean evaluate(Object left, Object right, ArrowType type) {
247249
} else if (type.equals(ArrowTypes.DoubleType)) {
248250
return (Double) left >= (Double) right;
249251
} else if (type.equals(ArrowTypes.StringType)) {
250-
return toString(left).compareTo(toString(right)) >= 0;
252+
return left.toString().compareTo(right.toString()) >= 0;
251253
}
252254
throw new IllegalStateException(
253255
"Unsupported data type in comparison expression: " + type);
256+
254257
}
255258
}
256259
}

0 commit comments

Comments
 (0)