0

我正在使用 Apache Calcite 解析一个简单的 SQL 语句并返回它的关系树。我使用与简单 SQLite 数据库的 JDBC 连接来获取数据库模式。然后使用 FrameworkConfig 添加架构。然后修改解析器配置以处理标识符引用和大小写(不敏感)。但是,SQL 验证器无法在 SQL 语句中找到引用的表标识符。解析器不知何故忽略了配置设置并将表转换为大写。引发 SqlValidatorException,说明未找到表名。我怀疑,配置没有正确更新?我已经验证表名正确包含在模式的元数据中。

公共类 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://calcite/students.db")
                            .add("jdbcUser", "root")
                                .add("jdbcPassword", "root");

        Map<String, JsonValue> JsonObject = builder.build();

        //argument for JdbcSchema.Factory().create(....)
        Map<String, Object> operand = new HashMap<String, Object>();

        //explicitly extract JsonString(s) 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);
        rootSchema.add("students", schema);

        //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();

        //use SQL parser config builder to ignore case of quoted identifier
        SqlParser.configBuilder(frameworkdConfig.getParserConfig()).setQuotedCasing(Casing.UNCHANGED).build();
        //use SQL parser config builder to set SQL case sensitive = false
        SqlParser.configBuilder(frameworkdConfig.getParserConfig()).setCaseSensitive(false).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

} // 结束类

***** 错误消息****** 2016 年 1 月 20 日晚上 8:54:51 org.apache.calcite.sql.validate.SqlValidatorException 严重:org.apache.calcite.sql.validate.SqlValidatorException:表'找不到学生

4

1 回答 1

1

这是一个区分大小写的问题,类似于table not found with apache calcite。因为您在 SQL 语句中将表名括在引号中,所以验证器正在寻找一个名为“Students”的表,而错误消息证明了这一点。如果你的桌子叫做“学生”,我很惊讶 Calcite 找不到它。

您使用 SqlParser.ConfigBuilder 的方式存在问题。当您调用 build() 时,您没有使用它创建的 SqlParser.Config 对象。如果你将该对象传递给 Frameworks.ConfigBuilder.parserConfig,我想你会得到你想要的行为。

于 2016-02-10T03:04:14.143 回答