This is an automated email from the ASF dual-hosted git repository.

xuzifu666 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new 07bd13a71f [CALCITE-4985] Elasticsearch Adapter fails to execute a 
prepared statement with a bind variable
07bd13a71f is described below

commit 07bd13a71f20e39331c2527953bd60543b93715b
Author: Yu Xu <[email protected]>
AuthorDate: Sat Oct 31 22:50:10 2026 +0800

    [CALCITE-4985] Elasticsearch Adapter fails to execute a prepared statement 
with a bind variable
---
 .../adapter/elasticsearch/ElasticsearchRules.java  | 10 ++++++
 .../adapter/elasticsearch/PredicateAnalyzer.java   | 10 ++++++
 .../elasticsearch/AggregationAndSortTest.java      | 39 ++++++++++++++++++++++
 3 files changed, 59 insertions(+)

diff --git 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java
 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java
index b4c78dc471..bec1b48785 100644
--- 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java
+++ 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java
@@ -38,6 +38,7 @@
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.rex.RexVisitorImpl;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
@@ -292,6 +293,15 @@ protected ElasticsearchFilterRule(Config config) {
       super(config);
     }
 
+    @Override public boolean matches(RelOptRuleCall call) {
+      final LogicalFilter filter = call.rel(0);
+      // Bound variables of a prepared statement are not known at planning
+      // time, so a condition that references them cannot be translated into
+      // an Elasticsearch query. Keep such filters above the adapter and let
+      // Calcite evaluate them once the parameters are bound.
+      return !RexUtil.containsDynamicParam(filter.getCondition());
+    }
+
     @Override public RelNode convert(RelNode relNode) {
       final LogicalFilter filter = (LogicalFilter) relNode;
       final RelTraitSet traitSet = filter.getTraitSet().replace(out);
diff --git 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java
 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java
index de51a90013..6ca9f92630 100644
--- 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java
+++ 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java
@@ -21,6 +21,7 @@
 import 
org.apache.calcite.adapter.elasticsearch.QueryBuilders.RangeQueryBuilder;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexDynamicParam;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
@@ -140,6 +141,15 @@ private Visitor() {
       return new LiteralExpression(literal);
     }
 
+    @Override public Expression visitDynamicParam(RexDynamicParam 
dynamicParam) {
+      // Bound variables of a prepared statement have no value at planning
+      // time and thus cannot be translated into an Elasticsearch query.
+      // Normally such filters are not pushed down at all
+      // (see ElasticsearchFilterRule#matches), so this is a safety net.
+      throw new PredicateAnalyzerException(
+          "Dynamic parameter is not supported: " + dynamicParam);
+    }
+
     private static boolean supportedRexCall(RexCall call) {
       final SqlSyntax syntax = call.getOperator().getSyntax();
       switch (syntax) {
diff --git 
a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/AggregationAndSortTest.java
 
b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/AggregationAndSortTest.java
index 20bcef9d83..5b9b88741c 100644
--- 
a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/AggregationAndSortTest.java
+++ 
b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/AggregationAndSortTest.java
@@ -567,6 +567,45 @@ private static Connection 
createConnectionWithConformance(String lex, String con
         .returns("EXPR$0=3\n");
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-4985";>[CALCITE-4985]
+   * Elasticsearch adapter fails to prepare a statement with dynamic
+   * parameters in a filter</a>.
+   */
+  @Test void testPrepareWithDynamicParam() {
+    // Bound variables are not known at planning time, so the filter is not
+    // pushed down to Elasticsearch; it is evaluated by Calcite at runtime
+    // once the parameter is bound.
+    CalciteAssert.that()
+        .with(AggregationAndSortTest::createConnection)
+        .query("select cat1 from view where cat5 = ?")
+        .consumesPreparedStatement(p -> p.setInt(1, 1))
+        .returns("cat1=a\n");
+
+    CalciteAssert.that()
+        .with(AggregationAndSortTest::createConnection)
+        .query("select cat1 from view where cat5 = ?")
+        .consumesPreparedStatement(p -> p.setInt(1, 2))
+        .returns("cat1=b\n");
+
+    // multiple dynamic parameters
+    CalciteAssert.that()
+        .with(AggregationAndSortTest::createConnection)
+        .query("select cat1 from view where cat5 = ? and cat2 = ?")
+        .consumesPreparedStatement(p -> {
+          p.setInt(1, 1);
+          p.setString(2, "g");
+        })
+        .returns("cat1=a\n");
+
+    // parameter that matches no document
+    CalciteAssert.that()
+        .with(AggregationAndSortTest::createConnection)
+        .query("select cat1 from view where cat5 = ?")
+        .consumesPreparedStatement(p -> p.setInt(1, 42))
+        .returnsCount(0);
+  }
+
   /** Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-4232";>[CALCITE-4232]
    * Elasticsearch IN Query is not supported</a>.

Reply via email to