Here's some miscellaneous documentation about using Optiq and its various adapters.
To enable tracing, add the following flags to the java command line:
-Doptiq.debug=true -Djava.util.logging.config.file=core/src/test/resources/logging.properties
The first flag causes Optiq to print the Java code it generates (to execute queries) to stdout. It is especially useful if you are debugging mysterious problems like this:
Exception in thread "main" java.lang.ClassCastException: Integer cannot be cast to Long at Baz$1$1.current(Unknown Source)
The second flag specifies a config file for the java.util.logging framework. Put the following into core/src/test/resources/logging.properties:
handlers= java.util.logging.ConsoleHandler .level= INFO org.eigenbase.relopt.RelOptPlanner.level=FINER java.util.logging.ConsoleHandler.level=ALL
The line org.eigenbase.relopt.RelOptPlanner.level=FINER tells the planner to produce fairly verbose outout. You can modify the file to enable other loggers, or to change levels. For instance, if you change FINER to FINEST the planner will give you an account of the planning process so detailed that it might fill up your hard drive.
See optiq-csv tutorial.
First, download and install Optiq, and install MongoDB.
Import MongoDB's zipcode data set into MongoDB:
$ curl -o /tmp/zips.json http://media.mongodb.org/zips.json $ mongoimport --db test --collection zips --file /tmp/zips.json Tue Jun 4 16:24:14.190 check 9 29470 Tue Jun 4 16:24:14.469 imported 29470 objects
Log into MongoDB to check it's there:
$ mongo MongoDB shell version: 2.4.3 connecting to: test > db.zips.find().limit(3) { "city" : "ACMAR", "loc" : [ -86.51557, 33.584132 ], "pop" : 6055, "state" : "AL", "_id" : "35004" } { "city" : "ADAMSVILLE", "loc" : [ -86.959727, 33.588437 ], "pop" : 10616, "state" : "AL", "_id" : "35005" } { "city" : "ADGER", "loc" : [ -87.167455, 33.434277 ], "pop" : 3205, "state" : "AL", "_id" : "35006" } > exit bye
Connect using the mongo-zips-model.json Optiq model:
$ ./sqlline sqlline> !connect jdbc:optiq:model=mongodb/target/test-classes/mongo-zips-model.json admin admin Connecting to jdbc:optiq:model=mongodb/target/test-classes/mongo-zips-model.json Connected to: Optiq (version 0.4.x) Driver: Optiq JDBC Driver (version 0.4.x) Autocommit status: true Transaction isolation: TRANSACTION_REPEATABLE_READ sqlline> !tables +------------+--------------+-----------------+---------------+ | TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | +------------+--------------+-----------------+---------------+ | null | mongo_raw | zips | TABLE | | null | mongo_raw | system.indexes | TABLE | | null | mongo | ZIPS | VIEW | | null | metadata | COLUMNS | SYSTEM_TABLE | | null | metadata | TABLES | SYSTEM_TABLE | +------------+--------------+-----------------+---------------+ sqlline> select count(*) from zips; +---------+ | EXPR$0 | +---------+ | 29467 | +---------+ 1 row selected (0.746 seconds) sqlline> !quit Closing: net.hydromatic.optiq.jdbc.FactoryJdbc41$OptiqConnectionJdbc41 $
To run the test suite and sample queries against Splunk, load Splunk's tutorialdata.zip
data set as described in the Splunk tutorial.
(This step is optional, but it provides some interesting data for the sample queries. It is also necessary if you intend to run the test suite, using -Doptiq.test.splunk=true
.)
New adapters can be created by implementing OptiqPrepare.Context
:
import net.hydromatic.optiq.Schema; import net.hydromatic.optiq.impl.java.JavaTypeFactory; import net.hydromatic.optiq.jdbc.OptiqPrepare; public class AdapterContext implements OptiqPrepare.Context { @Override public JavaTypeFactory getTypeFactory() { // adapter implementation return typeFactory; } @Override public Schema getRootSchema() { // adapter implementation return rootSchema; } }
The example below shows how SQL query can be submitted to OptiqPrepare
with a custom context (AdapterContext
in this case). Optiq prepares and implements the query execution, using the resources provided by the Context
. OptiqPrepare.PrepareResult
provides access to the underlying enumerable and methods for enumeration. The enumerable itself can naturally be some adapter specific implementation.
import net.hydromatic.optiq.jdbc.OptiqPrepare; import net.hydromatic.optiq.prepare.OptiqPrepareImpl; import org.junit.Test; public class AdapterContextTest { @Test public void testSelectAllFromTable() { AdapterContext ctx = new AdapterContext(); String sql = "SELECT * FROM TABLENAME"; Type elementType = Object[].class; OptiqPrepare.PrepareResult<Object> prepared = new OptiqPrepareImpl() .prepareSql(ctx, sql, null, elementType, -1); Object enumerable = prepared.getExecutable(); // etc. } }
When Optiq compares Type
instances, it requires them to be the same object. If there are two distinct Type
instances that refer to the same Java type, Optiq may fail to recognize that they match. It is recommended to
JavaTypeFactory
within the optiq contextType
instances so that the same object is always returned for the same Type
.