Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

apache calcite, querying without using the jdbc api

I would like to use the apache calcite api raw without using jdbc connections. I can use the jdbc api just fine but I am getting null ptr exceptions when trying to use the api. What I did so far is:

package calcite.examples

import java.util.Properties

import calcite.demo.DemoSchema
import org.apache.calcite.DataContext
import org.apache.calcite.config.CalciteConnectionConfigImpl
import org.apache.calcite.jdbc.CalcitePrepare.Query
import org.apache.calcite.jdbc.{CalcitePrepare, CalciteSchema, JavaTypeFactoryImpl}
import org.apache.calcite.prepare.CalcitePrepareImpl

import scala.collection.JavaConverters._

object TryIt extends App
{
    val ctx = new AdapterContext
    val sql = Query.of[Any]("SELECT * FROM dep")
    //  assert(sql.rel != null)

    val elementType = classOf[Array[Object]]
    val prepared = new CalcitePrepareImpl().prepareSql(ctx, sql, elementType, -1)
    val enumerable = prepared.enumerable(new MyDataContext)
}

class AdapterContext extends CalcitePrepare.Context
{
    private val properties = new Properties
    private val rootSchema = CalciteSchema.createRootSchema(true)
    rootSchema.add("default", new DemoSchema)

    // default schema names
    override def getDefaultSchemaPath = List("default").asJava

    override def spark() = {
        val enable = config.spark
        CalcitePrepare.Dummy.getSparkHandler(enable)
    }

    override val config = new CalciteConnectionConfigImpl(properties)

    override val getTypeFactory = new JavaTypeFactoryImpl

    override def getRootSchema = rootSchema

    override def getDataContext = new MyDataContext
}

class MyDataContext extends DataContext
{
    override def get(name: String) = {
        println(s"MyDataContext name=$name")
        null
    }

    override def getTypeFactory = ???

    override def getQueryProvider = ???

    override def getRootSchema = ???
}

But when I run this I get

MyDataContext name=v0stashed

Exception in thread "main" java.lang.NullPointerException
at org.apache.calcite.interpreter.Interpreter.<init>(Interpreter.java:71)
at Baz.bind(Unknown Source)
at org.apache.calcite.jdbc.CalcitePrepare$CalciteSignature.enumerable(CalcitePrepare.java:327)
at calcite.examples.TryIt$.delayedEndpoint$calcite$examples$TryIt$1(TryIt.scala:26)
at calcite.examples.TryIt$delayedInit$body.apply(TryIt.scala:18)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at calcite.examples.TryIt$.main(TryIt.scala:18)
at calcite.examples.TryIt.main(TryIt.scala)
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:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Notice that it tries to get v0stashed from the context, which I don't know what it should be. The only CalcitePrepare.Context impl I see is one that uses a CalciteConnection, which I am trying to avoid using. Also I took snippets of code from the calcite docs but it was out of date with calcite 1.7

Ideas?

like image 748
kostas.kougios Avatar asked Mar 29 '16 11:03

kostas.kougios


1 Answers

There's some crazy stuff going on here apparently. You need to pass internalParameters that you get out of the prepare call into your DataContext, and look them up in get. Apparently Calcite uses this to pass the query object around. You probably want to implement the other DataContext keys (current time, etc) as well.

final class MyDataContext(rootSchema: SchemaPlus, map: util.Map[String, Object])
        extends DataContext {
    override def get(name: String): AnyRef = map.get(name)

...
}

// ctx is your AdapterContext from above
val prepared = new CalcitePrepareImpl().prepareSql(ctx, query, classOf[Array[Object]], -1)
val dataContext = new DerpDataContext(
  ctx.getRootSchema.plus(),
  prepared.internalParameters
)
like image 156
Steve Avatar answered Oct 29 '22 19:10

Steve