Calcite developers,

I am a university researcher trying to use Calcite to develop a distributed
query capability. I have read the Calcite tutorial and some example code,
but am still unclear on how to create a calcite SQL parser, parse a simple
SQL statement and examine its associated relational expression (tree).

I start by building a JSON object that represents operands  consumed by a
JdbcSchema.Factory(), which  builds a JdbcSchema supplied by a SQLite
database. Once I have the schema, I assign it to the Calcite framework
using the FrameworkConfig builder, then configure the SQL parser to ignore
case in a  query (case insensitive). I verify the schema has been build and
print out its tables successfully, e.g. "Students", "Grades". I then obtain
the PLANNER and parser the following statement:

 "SELECT * FROM Students WHERE age > 15.0"

Next, when I attempt to VALIDATE the syntax correctness of the statement,
an error reports:

org.apache.calcite.sql.validate.SqlValidatorException: Table 'STUDENTS' not
found

The framework appears to convert schema table names to UPPERCASE, even
though I try to configure the SQL parser to be case insensitive. It
therefore fails to find the "Students" table imported from the SQLite
database and reports the error.

Finally, If and when I get the SQL parser working, I want to examine the
relational tree produced by the Calcite planner, and perhaps display it
graphically? Later I intend to add rules to the planner that support
distributing a query across multiple nodes.

I see value in the Calcite project and would like to learn more to
contribute. My simple Eclipse program ParseSql.java is attached along with
the trivial SQLite database used to experiment with the parser. Your
suggestion and guidance is very much appreciated.

Is there a developer chat room?

Regards
David Holland


-- 
David Holland
512-300-8396

package parser;


import java.util.HashMap;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonObjectBuilder;
import javax.json.JsonString;
import javax.json.JsonValue;

import org.apache.calcite.adapter.jdbc.JdbcSchema;
import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.schema.Table;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParser.ConfigBuilder;
import org.apache.calcite.tools.FrameworkConfig;
import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.tools.Planner;
import org.apache.calcite.tools.RelConversionException;
import org.apache.calcite.tools.ValidationException;

public class ParseSQL {

	public static void main(String[] args) {
		
		
		try {
			
			// register the JDBC driver 
	        String sDriverName = "org.sqlite.JDBC";
	        Class.forName(sDriverName);
			
			
	        JsonObjectBuilder builder = Json.createObjectBuilder();
	 
	        
	        builder.add("jdbcDriver", "org.sqlite.JDBC")
	                        .add("jdbcUrl", "jdbc:sqlite://home/david/Dropbox/DBaaS_Docker_Notes/calcite/students.db")
	                            .add("jdbcUser", "root")
	        						.add("jdbcPassword", "root");
	         
	     	         
	        Map<String, JsonValue> JsonObject = builder.build();
	        //operand: map argument for JdbcSchema.Factory().create(rootSchema, "students",  operand) 
			Map<String, Object> operand = new HashMap<String, Object>();
			
			//have to explicitly extract JsonString(s) from builder object and load into operand map
			for(String key : JsonObject.keySet()) {
				JsonString value = (JsonString) JsonObject.get(key);
				operand.put(key, value.getString());
			}
			
			final SchemaPlus rootSchema = Frameworks.createRootSchema(true);
			Schema schema =  new JdbcSchema.Factory().create(rootSchema, "students",  operand);
			//output tables to validate database schema has been read in correctly
			for(String tableName : schema.getTableNames()){
				System.out.println(tableName);
				Table table = schema.getTable(tableName);
				System.out.println(table.toString());
			}
			 
			//build a FrameworkConfig using defaults where values aren't required
			Frameworks.ConfigBuilder configBuilder  =  Frameworks.newConfigBuilder();
			//set defaultSchema
			configBuilder.defaultSchema(rootSchema);
			//build configuration
			FrameworkConfig frameworkdConfig = configBuilder.build();
		
			
			//get parser config builder and modify set SQL case sensitive to false
			ConfigBuilder parserConfig = SqlParser.configBuilder(frameworkdConfig.getParserConfig());
			parserConfig.setCaseSensitive(false);
			parserConfig.setConfig(parserConfig.build());
			
			//get planner
			Planner planner =  Frameworks.getPlanner(frameworkdConfig);
			//parse SQL statement
			SqlNode sql_node = planner.parse("SELECT * FROM Students WHERE age > 15.0");
			System.out.println("\n" + sql_node.toString());
			//validate SQL
			SqlNode sql_validated = planner.validate(sql_node);
			//get associated relational expression
			RelRoot relationalExpression = planner.rel(sql_validated);
			relationalExpression.toString();
			
		} catch (SqlParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RelConversionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ValidationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		

	}  // end main

} // end class

Reply via email to