如何使用Apache Calcite Planner正确定义与设置SQL参数?
问题原因
直接将转换后的RelNode传给RelRunners.run()生成的PreparedStatement没有保留参数元数据——RelNode仅代表执行计划的逻辑结构,不存储参数的位置、类型等定义,导致调用setLong()时找不到对应参数。
正确处理流程
Calcite的Planner提供了prepare()方法专门处理参数化查询,该方法会生成包含参数元数据的RelPreparedStatement,基于它创建的JDBC PreparedStatement才能正确识别并绑定参数。
修改后的完整代码:
// custom config FrameworkConfig frameworkConfig = Frameworks.newConfigBuilder() .parserConfig(parserConfig) .defaultSchema(rootSchema) .sqlToRelConverterConfig(convertConfig) .operatorTable(operatorTable) .build(); Planner planner = Frameworks.getPlanner(frameworkConfig); String sql = "Select id, name from t where id in (?, ?)"; SqlNode parsedSqlNode = planner.parse(sql); SqlNode validatedSqlNode = planner.validate(parsedSqlNode); // 使用planner.prepare处理参数化查询,生成带参数元数据的RelPreparedStatement RelPreparedStatement relPreparedStmt = planner.prepare(validatedSqlNode); PreparedStatement preparedStatement = RelRunners.run(relPreparedStmt); preparedStatement.setLong(1, 11111); preparedStatement.setLong(2, 22222); ResultSet resultSet = preparedStatement.executeQuery(); // ....
额外说明
- 若需自定义参数类型,可在
parserConfig中配置SqlParser.Config的参数类型映射,或在验证阶段通过SqlValidator上下文指定参数类型 - 确保表
t的id字段类型与setLong()的类型匹配,避免类型转换错误
内容的提问来源于stack exchange,提问作者lilin
相关产品推荐
相关产品推荐

