Skip to content

Commit

Permalink
More function tests and fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
broneill committed Jul 31, 2024
1 parent d6ef3d7 commit 276ca00
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ public FunctionApplier validate(List<Expr> args, Map<String, Expr> namedArgs,
return null;
}

Type originalType = args.get(0).type();
Type originalType = args.isEmpty() ? BasicType.BOOLEAN : args.get(0).type();
Type valueType = originalType;

return new StandardWindowFunctions.count(resultType, valueType, originalType, frame);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ static final class count extends WindowFunction {
super(resultType, valueType, originalType, frame);
}

@Override
protected Variable evalArg(GroupContext context) {
if (context.args().isEmpty()) {
// TODO: Filling a buffer with "true" values isn't terribly efficient. Instead,
// use a simple counter value. It might be possible to implement a WindowBuffer
// which does this.
return context.methodMaker().var(boolean.class).set(true);
} else {
return super.evalArg(context);
}
}

@Override
protected Variable compute(Variable bufferVar, Object frameStart, Object frameEnd) {
return bufferVar.invoke("frameCount", frameStart, frameEnd);
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/org/cojen/tupl/table/expr/ValueBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ private static Class generateClass(Type type) {

cm.public_();

boolean addBridges = false;

if (!type.isNumber() && !type.isPrimitive()) {
cm.extend(ValueBuffer.class);
addBridges = true;
}

cm.addField(arrayClass, "values").private_();
cm.addField(int.class, "first").private_();
cm.addField(int.class, "size").private_();
Expand Down Expand Up @@ -286,6 +293,11 @@ private static Class generateClass(Type type) {
var valuesVar = mm.field("values").get();
var firstField = mm.field("first");
mm.return_(valuesVar.aget(ixVar(valuesVar, firstField, mm.param(0))));

if (addBridges) {
mm = cm.addMethod(Object.class, "get", int.class).public_().final_().bridge();
mm.return_(mm.this_().invoke(clazz, "get", null, mm.param(0)));
}
}

{
Expand All @@ -306,6 +318,11 @@ private static Class generateClass(Type type) {
firstField.set(ixVar(valuesVar, firstVar, 1));
mm.field("size").inc(-1);
mm.return_(valuesVar.aget(ixVar(valuesVar, firstVar, null)));

if (addBridges) {
mm = cm.addMethod(Object.class, "removeFirst").public_().final_().bridge();
mm.return_(mm.this_().invoke(clazz, "removeFirst", null));
}
}

{
Expand All @@ -324,8 +341,6 @@ private static Class generateClass(Type type) {

if (type.isNumber()) {
addNumericalMethods(cm, type);
} else if (!type.isPrimitive()) {
cm.extend(ValueBuffer.class);
}

return cm.finish();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public void accumulate(GroupContext context) {
mm.field(mRemainingFieldName).inc(1);
}

private Variable evalArg(GroupContext context) {
protected Variable evalArg(GroupContext context) {
var valueVar = context.args().get(0).eval(true);

if (!mValueType.equals(mOriginalType)) {
Expand Down
55 changes: 55 additions & 0 deletions src/test/java/org/cojen/tupl/table/expr/FunctionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ public void random() throws Exception {
assertTrue(e.getMessage().contains("must be a number"));
}

try {
Parser.parse(IdentityTable.THE, "{v = random(99999999999999999999999999999)}");
fail();
} catch (QueryException e) {
assertTrue(e.getMessage().contains("unsupported argument type"));
}

CompiledQuery q = parse
("{a = random(), b = random(), " +
"c = random(100), d = random(1000L), e = random(10f), f = random(-100, 10d) " +
Expand Down Expand Up @@ -186,6 +193,54 @@ public void random() throws Exception {
double f = row.get_double("f");
assertTrue(rowStr, -100d <= f && f < 10d);
}

q = parse("{a = random(? + 0) - 100}").makeCompiledQuery();

try (Scanner s = q.newScanner(null, 100)) {
var row = (Row) s.row();
var rowStr = row.toString();
int a = row.get_int("a");
assertTrue(rowStr, -100 <= a && a < 0);
}
}

@Test
public void count() throws Exception {
try {
Parser.parse(IdentityTable.THE, "{v = count(1, 2)}");
fail();
} catch (QueryException e) {
assertTrue(e.getMessage().contains("at most 1 argument"));
}

try {
Parser.parse(IdentityTable.THE, "{v = count()}");
fail();
} catch (QueryException e) {
assertTrue(e.getMessage().contains("requires grouping"));
}

verify("{; v = count()}", "{v=1}");

Table<TestRow> table = fill(4);

verify(table, "{; v = count()}", "{v=4}");
verify(table, "{; v = count(name)}", "{v=4}");
verify(table, "{; v = count(value)}", "{v=2}");
verify(table, "{value; v = count()}",
"{value=value-1, v=1}", "{value=value-3, v=1}", "{value=null, v=2}");
verify(table, "{value; +v = count(value)}",
"{value=null, v=0}", "{value=value-1, v=1}", "{value=value-3, v=1}");

verify(table, "{value; v = count(value, rows:..)}",
"{value=value-1, v=1}", "{value=value-3, v=1}",
"{value=null, v=0}", "{value=null, v=0}");

verify(table, "{id = (id + 1) / 2; v = count(coalesce(value, 'hello'), rows:..0)}",
"{id=1, v=1}", "{id=1, v=2}", "{id=2, v=1}", "{id=2, v=2}");

verify(table, "{id = (id + 1) / 2; v = count(rows:0..)}",
"{id=1, v=2}", "{id=1, v=1}", "{id=2, v=2}", "{id=2, v=1}");
}

private static RelationExpr parse(String query) {
Expand Down

0 comments on commit 276ca00

Please sign in to comment.