参考Calcite 文档的“背景”章节,我定义了以下“表格”:
public class Employee {
public int empid = 0;
public int deptno = 0;
public Employee(int empid, int deptno) {
this.empid = empid;
this.deptno = deptno;
}
}
public class Department {
public int deptno = 0;
public Department(int deptno) {
this.deptno = deptno;
}
}
和以下“数据库”:
public class HrSchema {
public final Employee[] emps = new Employee[]{
new Employee(1, 7),
new Employee(2, 6),
new Employee(3, 6)
};
public final Department[] depts = new Department[]{
new Department(7),
new Department(6)
};
}
我使用 ReflectiveSchema 与这个“数据库”建立了连接:
Class.forName("org.apache.calcite.jdbc.Driver");
Properties info = new Properties();
info.setProperty("lex", "JAVA");
Connection connection =
DriverManager.getConnection("jdbc:calcite:", info);
CalciteConnection calciteConnection =
connection.unwrap(CalciteConnection.class);
SchemaPlus rootSchema = calciteConnection.getRootSchema();
ReflectiveSchema schema = new ReflectiveSchema(new HrSchema());
rootSchema.add("hr", schema);
由于我更喜欢 Linq 查询组合而不是 SQL 语句连接,因此在参考LinqFrontJdbcBackTest.java之后,我自适应地进行了以下查询:
ParameterExpression e =
Expressions.parameter(Employee.class, "e");
List<Employee> s =
Schemas.queryable(Schemas.createDataContext(connection, rootSchema),
rootSchema.getSubSchema("hr"),
Employee.class, "emps")
.where(
Expressions.lambda(
Expressions.greaterThan(
Expressions.field(e, "empid"),
Expressions.constant(0)
), e)
)
.toList();
for (Employee emp : s ) {
System.out.println(emp.empid);
}
最后我得到了:
Exception in thread "main" java.lang.RuntimeException: Error while compiling generated Java code:
public static class Record2_1 implements java.io.Serializable {
public int empid;
public int deptno;
public Record2_1() {}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Record2_1)) {
return false;
}
return this.empid == ((Record2_1) o).empid && this.deptno == ((Record2_1) o).deptno;
}
public int hashCode() {
int h = 0;
h = org.apache.calcite.runtime.Utilities.hash(h, this.empid);
h = org.apache.calcite.runtime.Utilities.hash(h, this.deptno);
return h;
}
public int compareTo(Record2_1 that) {
int c;
c = org.apache.calcite.runtime.Utilities.compare(this.empid, that.empid);
if (c != 0) {
return c;
}
c = org.apache.calcite.runtime.Utilities.compare(this.deptno, that.deptno);
if (c != 0) {
return c;
}
return 0;
}
public String toString() {
return "{empid=" + this.empid + ", deptno=" + this.deptno + "}";
}
}
public org.apache.calcite.linq4j.Enumerable bind(final org.apache.calcite.DataContext root) {
final org.apache.calcite.linq4j.Enumerable _inputEnumerable = org.apache.calcite.linq4j.Linq4j.asEnumerable(((demo.HrSchema) ((org.apache.calcite.adapter.java.ReflectiveSchema) root.getRootSchema().getSubSchema("hr").unwrap(org.apache.calcite.adapter.java.ReflectiveSchema.class)).getTarget()).emps);
return new org.apache.calcite.linq4j.AbstractEnumerable(){
public org.apache.calcite.linq4j.Enumerator enumerator() {
return new org.apache.calcite.linq4j.Enumerator(){
public final org.apache.calcite.linq4j.Enumerator inputEnumerator = _inputEnumerable.enumerator();
public void reset() {
inputEnumerator.reset();
}
public boolean moveNext() {
while (inputEnumerator.moveNext()) {
if (((demo.Employee) inputEnumerator.current()).empid > 0) {
return true;
}
}
return false;
}
public void close() {
inputEnumerator.close();
}
public Object current() {
final demo.Employee current = (demo.Employee) inputEnumerator.current();
return new Record2_1(
current.empid,
current.deptno);
}
};
}
};
}
public Class getElementType() {
return Record2_1.class;
}
at org.apache.calcite.avatica.Helper.wrap(Helper.java:37)
at org.apache.calcite.adapter.enumerable.EnumerableInterpretable.toBindable(EnumerableInterpretable.java:129)
at org.apache.calcite.prepare.CalcitePrepareImpl$CalcitePreparingStmt.implement(CalcitePrepareImpl.java:1130)
at org.apache.calcite.prepare.CalcitePrepareImpl$CalcitePreparingStmt.prepare_(CalcitePrepareImpl.java:1032)
at org.apache.calcite.prepare.CalcitePrepareImpl$CalcitePreparingStmt.prepareQueryable(CalcitePrepareImpl.java:979)
at org.apache.calcite.prepare.CalcitePrepareImpl.prepare2_(CalcitePrepareImpl.java:663)
at org.apache.calcite.prepare.CalcitePrepareImpl.prepare_(CalcitePrepareImpl.java:513)
at org.apache.calcite.prepare.CalcitePrepareImpl.prepareQueryable(CalcitePrepareImpl.java:474)
at org.apache.calcite.jdbc.CalciteStatement.prepare(CalciteStatement.java:80)
at org.apache.calcite.jdbc.CalciteConnectionImpl.executeQuery(CalciteConnectionImpl.java:299)
at org.apache.calcite.linq4j.QueryableDefaults$ReplayableQueryable.enumerator(QueryableDefaults.java:1171)
at org.apache.calcite.linq4j.EnumerableDefaults.into(EnumerableDefaults.java:3810)
at org.apache.calcite.linq4j.DefaultEnumerable.into(DefaultEnumerable.java:372)
at org.apache.calcite.linq4j.EnumerableDefaults.toList(EnumerableDefaults.java:3556)
at org.apache.calcite.linq4j.DefaultEnumerable.toList(DefaultEnumerable.java:744)
at demo.Main.main(Main.java:61)
Caused by: org.codehaus.commons.compiler.CompileException: Line 66, Column 25: No applicable constructor/method found for actual parameters "int, int"; candidates are: "Baz$Record2_1()"
at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:12211)
at org.codehaus.janino.UnitCompiler.findMostSpecificIInvocable(UnitCompiler.java:9263)
at org.codehaus.janino.UnitCompiler.invokeConstructor(UnitCompiler.java:7971)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:5409)
at org.codehaus.janino.UnitCompiler.access$9800(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$16.visitNewClassInstance(UnitCompiler.java:4435)
at org.codehaus.janino.UnitCompiler$16.visitNewClassInstance(UnitCompiler.java:4396)
at org.codehaus.janino.Java$NewClassInstance.accept(Java.java:5190)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:4396)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:5662)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2649)
at org.codehaus.janino.UnitCompiler.access$2800(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1504)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1487)
at org.codehaus.janino.Java$ReturnStatement.accept(Java.java:3563)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1487)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1567)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3388)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1357)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1330)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:822)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:981)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:951)
at org.codehaus.janino.UnitCompiler.access$200(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$2.visitAnonymousClassDeclaration(UnitCompiler.java:409)
at org.codehaus.janino.UnitCompiler$2.visitAnonymousClassDeclaration(UnitCompiler.java:406)
at org.codehaus.janino.Java$AnonymousClassDeclaration.accept(Java.java:1149)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:406)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:5509)
at org.codehaus.janino.UnitCompiler.access$9500(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$16.visitNewAnonymousClassInstance(UnitCompiler.java:4432)
at org.codehaus.janino.UnitCompiler$16.visitNewAnonymousClassInstance(UnitCompiler.java:4396)
at org.codehaus.janino.Java$NewAnonymousClassInstance.accept(Java.java:5238)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:4396)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:5662)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2649)
at org.codehaus.janino.UnitCompiler.access$2800(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1504)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1487)
at org.codehaus.janino.Java$ReturnStatement.accept(Java.java:3563)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1487)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1567)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3388)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1357)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1330)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:822)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:981)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:951)
at org.codehaus.janino.UnitCompiler.access$200(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$2.visitAnonymousClassDeclaration(UnitCompiler.java:409)
at org.codehaus.janino.UnitCompiler$2.visitAnonymousClassDeclaration(UnitCompiler.java:406)
at org.codehaus.janino.Java$AnonymousClassDeclaration.accept(Java.java:1149)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:406)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:5509)
at org.codehaus.janino.UnitCompiler.access$9500(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$16.visitNewAnonymousClassInstance(UnitCompiler.java:4432)
at org.codehaus.janino.UnitCompiler$16.visitNewAnonymousClassInstance(UnitCompiler.java:4396)
at org.codehaus.janino.Java$NewAnonymousClassInstance.accept(Java.java:5238)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:4396)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:5662)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2649)
at org.codehaus.janino.UnitCompiler.access$2800(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1504)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1487)
at org.codehaus.janino.Java$ReturnStatement.accept(Java.java:3563)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1487)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1567)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3388)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1357)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1330)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:822)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:432)
at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:411)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:406)
at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1414)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:406)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:378)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:237)
at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:465)
at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:313)
at org.codehaus.janino.ClassBodyEvaluator.cook(ClassBodyEvaluator.java:235)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:207)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:50)
at org.codehaus.janino.ClassBodyEvaluator.createInstance(ClassBodyEvaluator.java:347)
at org.apache.calcite.adapter.enumerable.EnumerableInterpretable.getBindable(EnumerableInterpretable.java:163)
at org.apache.calcite.adapter.enumerable.EnumerableInterpretable.toBindable(EnumerableInterpretable.java:126)
... 14 more
Process finished with exit code 1
但是,如果我替换Expressions.field(e, "empid")
为Expressions.constant(5)
,则完全没有问题!查询成功返回:
1
2
3
ReflectiveSchema 与“where”子句中的 Expressions.field 相处一定有问题。因为在“where”子句之外构造表达式没有任何问题。
Expressions.lambda(
Expressions.greaterThan(
Expressions.field(e, "empid"),
Expressions.constant(0)
), e);
Expressions.field(e, "empid")
必须有正确的字段,因为当表达式稍微修改为 时Expressions.field(e, "empi")
,会出现异常:
Exception in thread "main" java.lang.RuntimeException: Unknown field 'empi' in class class demo.Employee
at org.apache.calcite.linq4j.tree.Types.getField(Types.java:110)
at org.apache.calcite.linq4j.tree.Types.getField(Types.java:121)
at org.apache.calcite.linq4j.tree.Expressions.field(Expressions.java:840)
at demo.main(Main.java:51)
Caused by: java.lang.NoSuchFieldException: empi
at java.lang.Class.getField(Class.java:1703)
at org.apache.calcite.linq4j.tree.Types.getField(Types.java:108)
... 3 more
有人知道问题出在哪里吗?让“where”子句对基于 ReflectiveSchema 的“数据库”上的包含 ParameterExpression 的 Linq 比较查询有意义所需的任何配置?