I'm trying to push down projections while querying a DB but I'm facing the
below exception. I've written the following code based on my understanding
of the Druid adapter as it seems to be analogous to what I need to achieve.
*Projection pushdown rule*
> import static com.google.common.collect.ImmutableList.of;
> import static java.util.Arrays.asList;
> import static org.apache.calcite.util.Util.last;
>
> public class SQLiProjectionRule extends RelOptRule {
>
> public SQLiProjectionRule() {
> super(operand(LogicalProject.class, operand(SQLiQuery.class,
> any())), "ProjectionRule");
> }
>
> @Override
> public Convention getOutConvention() {
> return BindableConvention.INSTANCE;
> }
>
> @Override
> public void onMatch(RelOptRuleCall call) {
> SQLiQuery query = call.rel(1);
>
> LogicalProject project = call.rel(0);
> RelNode newProject = project.copy(project.getTraitSet(),
> of(last(query.getInputs())));
>
> SQLiQuery newNode = (SQLiQuery)
> query.copy(project.getTraitSet().replace(getOutConvention()),
> asList(newProject));
>
> call.transformTo(newNode);
> }
> }
>
*SQLiQuery portions*
>
> @Override
> protected RelDataType deriveRowType() {
> List<RelDataTypeField> topMostRelFieldList =
> Util.last(inputs).getRowType().getFieldList();
> return
> getCluster().getTypeFactory().createStructType(Util.right(topMostRelFieldList),
> Util.left(topMostRelFieldList));
> }
>
> @Override
> public RelNode copy(RelTraitSet traitSet, List<RelNode> extraInputs) {
> List<RelNode> copiedInputs = new ArrayList<>();
> if (this.inputs != null) copiedInputs.addAll(this.inputs);
> if (extraInputs != null) copiedInputs.addAll(extraInputs);
> return new SQLiQuery(getTable(), this.sqliTable, this.rowType,
> getCluster(), traitSet, copiedInputs);
> }
>
*Stacktrace*
> java.sql.SQLException: Error while executing SQL "SELECT COUNTRY_NAME FROM
> SALES.COUNTRIES": Index: 0, Size: 0
> at org.apache.calcite.avatica.Helper.createException(Helper.java:56)
> at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
> at
> org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:156)
> at
> org.apache.calcite.avatica.AvaticaStatement.executeQuery(AvaticaStatement.java:218)
> at
> com.sqlinterface.data.provider.calcite.internal.Test_SQLi.test(Test_SQLi.java:34)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
> at
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> at
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
> at
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
> at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
> at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
> at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
> at
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> at
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
> at
> org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
> at
> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
> *Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0*
> at java.util.ArrayList.rangeCheck(ArrayList.java:657)
> at java.util.ArrayList.get(ArrayList.java:433)
> at
> org.apache.calcite.rel.externalize.RelWriterImpl.checkInputsPresentInExplain(RelWriterImpl.java:167)
> at
> org.apache.calcite.rel.externalize.RelWriterImpl.done(RelWriterImpl.java:152)
> at
> org.apache.calcite.rel.AbstractRelNode.explain(AbstractRelNode.java:314)
> at
> org.apache.calcite.rel.AbstractRelNode.computeDigest(AbstractRelNode.java:422)
> at
> org.apache.calcite.rel.AbstractRelNode.recomputeDigest(AbstractRelNode.java:358)
> at
> org.apache.calcite.plan.hep.HepPlanner.updateVertex(HepPlanner.java:842)
> at
> org.apache.calcite.plan.hep.HepPlanner.addRelToGraph(HepPlanner.java:782)
> at
> org.apache.calcite.plan.hep.HepPlanner.addRelToGraph(HepPlanner.java:758)
> at org.apache.calcite.plan.hep.HepPlanner.setRoot(HepPlanner.java:150)
> at org.apache.calcite.tools.Programs$2.run(Programs.java:212)
> at
> org.apache.calcite.tools.Programs$SequenceProgram.run(Programs.java:387)
> at org.apache.calcite.prepare.Prepare.optimize(Prepare.java:188)
> at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:319)
> at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:230)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl.prepare2_(CalcitePrepareImpl.java:781)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl.prepare_(CalcitePrepareImpl.java:640)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl.prepareSql(CalcitePrepareImpl.java:610)
> at
> org.apache.calcite.jdbc.CalciteConnectionImpl.parseQuery(CalciteConnectionImpl.java:221)
> at
> org.apache.calcite.jdbc.CalciteMetaImpl.prepareAndExecute(CalciteMetaImpl.java:603)
> at
> org.apache.calcite.avatica.AvaticaConnection.prepareAndExecuteInternal(AvaticaConnection.java:638)
> at
> org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:149)
> ... 27 more
>
The exception occurs in this method because *values.size() == 0*
> private boolean checkInputsPresentInExplain(RelNode node) {
> int i = 0;
> if (values.size() > 0 && values.get(0).left.equals("subset")) {
> ++i;
> }
> for (RelNode input : node.getInputs()) {
> assert values.get(i).right == input; *// Exception thrown here*
> ++i;
> }
> return true;
> }
>
Please tell me if I need to provide more information.
Thanks,
Gelbana