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

preetham02 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new d32c96c6b8 [ASTERIXDB-3688][COMP] Improving Index Selection for 
Index-Only Query Plans
d32c96c6b8 is described below

commit d32c96c6b86f99c46e19313ea65816c8c5e28d49
Author: Shahrzad Shirazi <[email protected]>
AuthorDate: Thu Jan 8 17:14:32 2026 -0800

    [ASTERIXDB-3688][COMP] Improving Index Selection for Index-Only Query Plans
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details: This change ensures that a secondary index capable of supporting 
an index-only query plan is selected when available.
    
    
    Ext-ref: MB-69514
    
    
    Change-Id: I4f996ee7b6eb03067fb384161fb4eb60f94e8353
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20774
    Tested-by: Jenkins <[email protected]>
    Integration-Tests: Jenkins <[email protected]>
    Reviewed-by: Ali Alsuliman <[email protected]>
---
 .../am/AbstractIntroduceAccessMethodRule.java      |  11 +-
 .../rules/am/IntroduceSelectAccessMethodRule.java  | 126 ++++++++++++++++++---
 .../simple-index-only.10.query.sqlpp               |  32 ++++++
 .../simple-index-only.11.query.sqlpp               |  31 +++++
 .../simple-index-only.5.ddl.sqlpp                  |  28 +++++
 .../simple-index-only.6.query.sqlpp                |  26 +++++
 .../simple-index-only.7.query.sqlpp                |  26 +++++
 .../simple-index-only.8.query.sqlpp                |  34 ++++++
 .../simple-index-only.9.query.sqlpp                |  31 +++++
 .../simple-index-only/simple-index-only.10.plan    |  30 +++++
 .../simple-index-only/simple-index-only.11.plan    |  30 +++++
 .../simple-index-only/simple-index-only.6.plan     |  30 +++++
 .../simple-index-only/simple-index-only.7.plan     |  30 +++++
 .../simple-index-only/simple-index-only.8.plan     |  30 +++++
 .../simple-index-only/simple-index-only.9.plan     |  30 +++++
 .../simple-index-only/simple-index-only.10.plan    |  30 +++++
 .../simple-index-only/simple-index-only.11.plan    |  30 +++++
 .../simple-index-only/simple-index-only.6.plan     |  32 ++++++
 .../simple-index-only/simple-index-only.7.plan     |  32 ++++++
 .../simple-index-only/simple-index-only.8.plan     |  30 +++++
 .../simple-index-only/simple-index-only.9.plan     |  30 +++++
 21 files changed, 691 insertions(+), 18 deletions(-)

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
index ce6a0d4c42..6dc0906495 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
@@ -287,8 +287,15 @@ public abstract class AbstractIntroduceAccessMethodRule 
implements IAlgebraicRew
                         // 2) functions that take keyword as an argument, e.g. 
edit_distance_check() when the threshold is 1
                         || (chosenAccessMethod == 
InvertedIndexAccessMethod.INSTANCE && isKeywordIndexChosen
                                 && 
isSameFullTextConfigInIndexAndQuery(analysisCtx, 
chosenIndex.getIndexDetails()))) {
-
-                    if 
(resultVarsToIndexTypesMap.containsKey(indexEntry.getValue())) {
+                    // For Btrees and Rtrees we need to keep all the indexes 
to be able to find the covering ones.
+                    // therefore we add them without needing to check their 
index type.
+                    if ((chosenAccessMethod == RTreeAccessMethod.INSTANCE && 
indexType == IndexType.RTREE)
+                            || (chosenAccessMethod == 
BTreeAccessMethod.INSTANCE && indexType == IndexType.BTREE)) {
+                        result.add(
+                                new 
IntroduceSelectAccessMethodRule.IndexAccessInfo(chosenAccessMethod, 
chosenIndex));
+                    }
+                    // this if seems to be needed for ngram indexes. todo: can 
we remove this for other types as well?
+                    else if 
(resultVarsToIndexTypesMap.containsKey(indexEntry.getValue())) {
                         List<IndexType> appliedIndexTypes = 
resultVarsToIndexTypesMap.get(indexEntry.getValue());
                         if (!appliedIndexTypes.contains(indexType)) {
                             appliedIndexTypes.add(indexType);
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
index b246ff2614..a7a01dc077 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
@@ -19,11 +19,13 @@
 package org.apache.asterix.optimizer.rules.am;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.TreeMap;
+import java.util.stream.IntStream;
 
 import org.apache.asterix.algebra.operators.CommitOperator;
 import org.apache.asterix.common.cluster.PartitioningProperties;
@@ -50,6 +52,7 @@ import 
org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
+import 
org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator.ExecutionMode;
@@ -383,7 +386,8 @@ public class IntroduceSelectAccessMethodRule extends 
AbstractIntroduceAccessMeth
         return true;
     }
 
-    protected void removeSmallerPrefixIndexes(List<IndexAccessInfo> indexes) 
throws CompilationException {
+    protected void keepBestPrefixIndexes(List<IndexAccessInfo> indexes, 
List<Integer> numberOfMatchedKeys)
+            throws CompilationException {
         int len = indexes.size();
         int i, j;
         Index indexI, indexJ;
@@ -412,10 +416,19 @@ public class IntroduceSelectAccessMethodRule extends 
AbstractIntroduceAccessMeth
                                 fieldNamesJ = findKeyFieldNames(indexJ);
                                 if (fieldNamesI.size() <= fieldNamesJ.size()) {
                                     if (prefix(fieldNamesI, fieldNamesJ)) {
-                                        include[i] = false;
+                                        if (numberOfMatchedKeys.get(j) > 
numberOfMatchedKeys.get(i)) {
+                                            include[i] = false;
+                                        } else {
+                                            include[j] = false;
+
+                                        }
                                     }
                                 } else if (prefix(fieldNamesJ, fieldNamesI)) {
-                                    include[j] = false;
+                                    if (numberOfMatchedKeys.get(i) > 
numberOfMatchedKeys.get(j)) {
+                                        include[j] = false;
+                                    } else {
+                                        include[i] = false;
+                                    }
                                 }
                             }
                         }
@@ -548,13 +561,16 @@ public class IntroduceSelectAccessMethodRule extends 
AbstractIntroduceAccessMeth
 
                 // Choose all indexes that will be applied.
                 chooseAllIndexes(analyzedAMs, chosenIndexes);
-                removeSmallerPrefixIndexes(chosenIndexes);
-
                 if (chosenIndexes == null || chosenIndexes.isEmpty()) {
                     // We can't apply any index for this SELECT operator
                     context.addToDontApplySet(this, selectRef.getValue());
                     return false;
                 }
+                List<Integer> matchedKeyCountsNonCovering = new ArrayList<>();
+                List<Integer> matchedKeyCountsCovering = new ArrayList<>();
+                List<IndexAccessInfo> nonCoverigIndexes = new ArrayList<>();
+                List<IndexAccessInfo> coverigIndexes = new ArrayList<>();
+                fillFieldNamesInTheSubTree(subTree, context);
 
                 for (IndexAccessInfo indexAccessInfo : chosenIndexes) {
                     AccessMethodAnalysisContext analysisCtx = 
analyzedAMs.get(indexAccessInfo.getAccessMethod());
@@ -565,7 +581,15 @@ public class IntroduceSelectAccessMethodRule extends 
AbstractIntroduceAccessMeth
                     AccessMethodUtils.indexOnlyPlanCheck(afterSelectRefs, 
selectRef, subTree, null,
                             indexAccessInfo.getIndex(), analysisCtx, context, 
indexOnlyPlanInfo, false);
                     
indexAccessInfo.setIsIndexOnlyPlan(indexOnlyPlanInfo.getFirst());
+                    if (indexAccessInfo.isIndexOnlyPlan) {
+                        
matchedKeyCountsCovering.add(analysisCtx.getNumberOfMatchedKeys(indexAccessInfo.getIndex()));
+                        coverigIndexes.add(indexAccessInfo);
+                    } else {
+                        
matchedKeyCountsNonCovering.add(analysisCtx.getNumberOfMatchedKeys(indexAccessInfo.getIndex()));
+                        nonCoverigIndexes.add(indexAccessInfo);
+                    }
                 }
+                keepBestPrefixIndexes(nonCoverigIndexes, 
matchedKeyCountsNonCovering);
 
                 if (checkApplicableOnly) {
                     return true;
@@ -574,28 +598,36 @@ public class IntroduceSelectAccessMethodRule extends 
AbstractIntroduceAccessMeth
                 // Apply plan transformation using chosen index.
                 boolean res;
                 // Primary index applicable?
+                // We should look in the list including both covering and non 
covering.
                 IndexAccessInfo chosenPrimaryIndex = 
fetchPrimaryIndexAmongChosenIndexes(chosenIndexes);
                 if (chosenPrimaryIndex != null) {
+                    subTree.getVarsToFieldNameMap().clear();
                     AccessMethodAnalysisContext analysisCtx = 
analyzedAMs.get(chosenPrimaryIndex.getAccessMethod());
                     res = 
chosenPrimaryIndex.getAccessMethod().applySelectPlanTransformation(afterSelectRefs,
 selectRef,
                             subTree, chosenPrimaryIndex.getIndex(), 
analysisCtx, context);
                     context.addToDontApplySet(this, selectRef.getValue());
-                } else if (chosenIndexes.size() == 1) {
-                    // Index-only plan possible?
+                } else if (coverigIndexes.isEmpty() && 
nonCoverigIndexes.size() == 1) {
                     // Gets the analysis context for the given index.
-                    AccessMethodAnalysisContext analysisCtx = 
analyzedAMs.get(chosenIndexes.get(0).getAccessMethod());
-
-                    // Finds the field name of each variable in the sub-tree.
-                    fillFieldNamesInTheSubTree(subTree, context);
+                    AccessMethodAnalysisContext analysisCtx =
+                            
analyzedAMs.get(nonCoverigIndexes.get(0).getAccessMethod());
 
                     // Finally, try to apply plan transformation using chosen 
index.
-                    res = 
chosenIndexes.get(0).getAccessMethod().applySelectPlanTransformation(afterSelectRefs,
-                            selectRef, subTree, 
chosenIndexes.get(0).getIndex(), analysisCtx, context);
+                    res = 
nonCoverigIndexes.get(0).getAccessMethod().applySelectPlanTransformation(afterSelectRefs,
+                            selectRef, subTree, 
nonCoverigIndexes.get(0).getIndex(), analysisCtx, context);
                     context.addToDontApplySet(this, selectRef.getValue());
                 } else {
-                    // Multiple secondary indexes applicable?
-                    res = intersectAllSecondaryIndexes(chosenIndexes, 
analyzedAMs, context);
-                    context.addToDontApplySet(this, selectRef.getValue());
+                    if (!coverigIndexes.isEmpty()) {
+                        IndexAccessInfo bestCoveringIndex =
+                                chooseBestCoveringIndex(coverigIndexes, 
matchedKeyCountsCovering, analyzedAMs);
+                        AccessMethodAnalysisContext analysisCtx = 
analyzedAMs.get(bestCoveringIndex.getAccessMethod());
+                        res = 
bestCoveringIndex.getAccessMethod().applySelectPlanTransformation(afterSelectRefs,
+                                selectRef, subTree, 
bestCoveringIndex.getIndex(), analysisCtx, context);
+                        context.addToDontApplySet(this, selectRef.getValue());
+                    } else {
+                        subTree.getVarsToFieldNameMap().clear();
+                        res = intersectAllSecondaryIndexes(nonCoverigIndexes, 
analyzedAMs, context);
+                        context.addToDontApplySet(this, selectRef.getValue());
+                    }
                 }
 
                 // If the plan transformation is successful, we don't need to 
traverse
@@ -619,6 +651,68 @@ public class IntroduceSelectAccessMethodRule extends 
AbstractIntroduceAccessMeth
 
     }
 
+    private IndexAccessInfo chooseBestCoveringIndex(List<IndexAccessInfo> 
indexes,
+            List<Integer> numberOfMatchedKeysForCoveringindexes,
+            Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs) 
throws CompilationException {
+
+        if (indexes.size() == 1) {
+            return indexes.get(0);
+        }
+
+        // 1) Keep only indexes with max matched keys
+        int max = 
numberOfMatchedKeysForCoveringindexes.stream().mapToInt(Integer::intValue).max().orElse(0);
+        List<IndexAccessInfo> indexesWithMaxMatchedKeys = IntStream.range(0, 
indexes.size())
+                .filter(i -> numberOfMatchedKeysForCoveringindexes.get(i) == 
max).mapToObj(indexes::get).toList();
+        if (indexesWithMaxMatchedKeys.size() == 1) {
+            return indexesWithMaxMatchedKeys.get(0);
+        }
+
+        // 2) Find earliest equality positions
+        List<IndexInfo> indexesWithMaxMatchedKeysInfo = new 
ArrayList<>(indexesWithMaxMatchedKeys.size());
+        for (IndexAccessInfo indexAccessInfo : indexesWithMaxMatchedKeys) {
+            List<List<String>> indexFields = 
findKeyFieldNames(indexAccessInfo.getIndex());
+            List<IOptimizableFuncExpr> funcExprs =
+                    
analyzedAMs.get(indexAccessInfo.getAccessMethod()).getMatchedFuncExprs();
+            IndexInfo indexInfo = new IndexInfo();
+            indexInfo.indexExprs = new 
ArrayList<>(Collections.nCopies(funcExprs.size(), null));
+            indexInfo.numKeys = indexFields.size();
+            indexInfo.indexaccessinfo = indexAccessInfo;
+            for (IOptimizableFuncExpr expr : funcExprs) {
+                for (int i = 0; i < expr.getNumLogicalVars(); i++) {
+                    int i1 = indexFields.indexOf(expr.getFieldName(i));
+                    indexInfo.indexExprs.set(i1, 
expr.getFuncExpr().getFunctionIdentifier());
+                }
+            }
+            indexesWithMaxMatchedKeysInfo.add(indexInfo);
+        }
+        return 
indexesWithMaxMatchedKeysInfo.stream().sorted().toList().getFirst().indexaccessinfo;
+    }
+
+    class IndexInfo implements Comparable<IndexInfo> {
+        List<FunctionIdentifier> indexExprs = new ArrayList<>();
+        int numKeys;
+        IndexAccessInfo indexaccessinfo;
+
+        @Override
+        public int compareTo(IndexInfo other) {
+            for (int i = 0; i < this.indexExprs.size() && i < 
other.indexExprs.size(); i++) {
+                if (this.indexExprs.get(i) == AlgebricksBuiltinFunctions.EQ
+                        && other.indexExprs.get(i) != 
AlgebricksBuiltinFunctions.EQ) {
+                    return -1;
+                } else if (this.indexExprs.get(i) != 
AlgebricksBuiltinFunctions.EQ
+                        && other.indexExprs.get(i) == 
AlgebricksBuiltinFunctions.EQ) {
+                    return 1;
+                }
+            }
+
+            if (this.indexExprs.size() != other.indexExprs.size()) {
+                return 0;
+            }
+
+            return Integer.compare(this.numKeys, other.numKeys);
+        }
+    }
+
     @Override
     public Map<FunctionIdentifier, List<IAccessMethod>> getAccessMethods() {
         return accessMethods;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.10.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.10.query.sqlpp
new file mode 100644
index 0000000000..76a9295ea7
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.10.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+use test;
+
+drop index Orders.idx9_early_eq if exists;
+drop index Orders.idx9_late_eq if exists;
+
+create index idx10_thin on Orders(city,country,storeName);
+create index idx10_thick on Orders(city,country,storeName,extra1,extra2);
+
+
+explain select o.city, o.country, o.storeName
+from Orders o
+where o.city = 'NYC' and o.country > 'USA';
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.11.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.11.query.sqlpp
new file mode 100644
index 0000000000..4a1daec5e1
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.11.query.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+use test;
+
+drop index Orders.idx10_thin if exists;
+drop index Orders.idx10_thick if exists;
+
+create index idx11_stops on Orders(city,pp,country,storeName);
+create index idx11_all_searchable on Orders(city,country,storeName);
+
+explain select o.city, o.country, o.storeName
+from Orders o
+where o.city = 'NYC' and o.country > 'USA';
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.5.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.5.ddl.sqlpp
new file mode 100644
index 0000000000..57ce6986df
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.5.ddl.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+
+
+create index storeName_idx on Orders(storeName);
+create index country_idx2 on Orders(storeName,city,country);
+create index storeName_city_idx2 on Orders(storeName,city);
+create index storeName_city_idx1 on Orders(city,storeName);
+create index country_idx1 on Orders(storeName,city,country);
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.6.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.6.query.sqlpp
new file mode 100644
index 0000000000..ada0025a0d
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.6.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+
+explain select o.city
+from Orders o
+where o.storeName="big store";
+
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.7.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.7.query.sqlpp
new file mode 100644
index 0000000000..b0df755ad1
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.7.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+
+explain select o.storeName
+from Orders o
+where o.storeName="big store";
+
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.8.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.8.query.sqlpp
new file mode 100644
index 0000000000..ee09139fd6
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.8.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+use test;
+
+drop index Orders.storeName_idx if exists;
+drop index Orders.country_idx2 if exists;
+drop index Orders.storeName_city_idx2 if exists;
+drop index Orders.storeName_city_idx1 if exists;
+drop index Orders.country_idx1 if exists;
+
+create index idx8_more_fields on Orders(city,country,storeName);
+create index idx8_fewer_fields on Orders(city,storeName,country);
+
+explain select o.city, o.country, o.storeName
+from Orders o
+where o.city = 'NYC' and o.country > 'USA';
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.9.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.9.query.sqlpp
new file mode 100644
index 0000000000..00f4075061
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/index-only-testcases/simple-index-only/simple-index-only.9.query.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+drop index Orders.idx8_more_fields if exists;
+drop index Orders.idx8_fewer_fields if exists;
+
+create index idx9_early_eq on Orders(city,country,storeName);
+create index idx9_late_eq on Orders(country,city,storeName);
+
+
+explain select o.city, o.country, o.storeName
+from Orders o
+where o.city = 'NYC' and o.country > 'USA';
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.10.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.10.plan
new file mode 100644
index 0000000000..29f8093f07
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.10.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx10_thin", 0, "Default", "test", "Orders", false, false, 2, 
$$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.11.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.11.plan
new file mode 100644
index 0000000000..0b1dc1633e
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.11.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx11_all_searchable", 0, "Default", "test", "Orders", false, 
false, 2, $$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.6.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.6.plan
new file mode 100644
index 0000000000..1da2f86474
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.6.plan
@@ -0,0 +1,30 @@
+distribute result [$$18] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$18] <- [{"city": $$21}] project: [$$18] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$21]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$26]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$26) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$26(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (eq($$20, "big store")) project: [$$21, $$26] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$20, $$21, $$26] <- 
index-search("storeName_city_idx2", 0, "Default", "test", "Orders", false, 
false, 1, $$22, 1, $$23, true, true, true) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$22, $$23] <- ["big store", "big store"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.7.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.7.plan
new file mode 100644
index 0000000000..273e6a1876
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.7.plan
@@ -0,0 +1,30 @@
+distribute result [$$18] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$18] <- [{"storeName": $$19}] project: [$$18] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$19]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$24]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$24) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$24(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (eq($$19, "big store")) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$19, $$24] <- index-search("storeName_idx", 
0, "Default", "test", "Orders", false, false, 1, $$21, 1, $$22, true, true, 
true) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$21, $$22] <- ["big store", "big store"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.8.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.8.plan
new file mode 100644
index 0000000000..196b4bce24
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.8.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx8_more_fields", 0, "Default", "test", "Orders", false, false, 
2, $$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.9.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.9.plan
new file mode 100644
index 0000000000..53eaf603ee
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/index-only-testcases/simple-index-only/simple-index-only.9.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx9_early_eq", 0, "Default", "test", "Orders", false, false, 2, 
$$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.10.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.10.plan
new file mode 100644
index 0000000000..43ce176ef7
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.10.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 8.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
8.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx10_thin", 0, "Default", "test", "Orders", false, false, 2, 
$$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.11.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.11.plan
new file mode 100644
index 0000000000..9ced96f360
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.11.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 8.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
8.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx11_all_searchable", 0, "Default", "test", "Orders", false, 
false, 2, $$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.6.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.6.plan
new file mode 100644
index 0000000000..a9d92dbf50
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.6.plan
@@ -0,0 +1,32 @@
+distribute result [$$18] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$18] <- [{"city": $$21}] project: [$$18] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$21]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
8.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$27) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$27(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (eq($$20, "big store")) project: [$$21, $$27] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    project ([$$20, $$21, $$27]) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        unnest-map [$$20, $$21, $$26, $$27] <- 
index-search("country_idx1", 0, "Default", "test", "Orders", false, false, 1, 
$$22, 1, $$23, true, true, true) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- BTREE_SEARCH  |PARTITIONED|
+                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            assign [$$22, $$23] <- ["big store", "big store"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- ASSIGN  |PARTITIONED|
+                              empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.7.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.7.plan
new file mode 100644
index 0000000000..04becec922
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.7.plan
@@ -0,0 +1,32 @@
+distribute result [$$18] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$18] <- [{"storeName": $$19}] project: [$$18] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$19]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
8.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$26]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$26) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$26(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (eq($$19, "big store")) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    project ([$$19, $$26]) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        unnest-map [$$19, $$24, $$25, $$26] <- 
index-search("country_idx1", 0, "Default", "test", "Orders", false, false, 1, 
$$21, 1, $$22, true, true, true) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- BTREE_SEARCH  |PARTITIONED|
+                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            assign [$$21, $$22] <- ["big store", "big store"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- ASSIGN  |PARTITIONED|
+                              empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.8.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.8.plan
new file mode 100644
index 0000000000..88e342227f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.8.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 8.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
8.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx8_more_fields", 0, "Default", "test", "Orders", false, false, 
2, $$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.9.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.9.plan
new file mode 100644
index 0000000000..6486a346ca
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/index-only-testcases/simple-index-only/simple-index-only.9.plan
@@ -0,0 +1,30 @@
+distribute result [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$23] <- [{"city": $$24, "country": $$25, "storeName": $$27}] 
project: [$$23] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 8.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$24, $$25, $$27]) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 8.0]
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
8.0]
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          distinct ([$$34]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 8.0]
+          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              order (ASC, $$34) [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+              -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  select (and(gt($$25, "USA"), eq($$24, "NYC"))) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                  -- STREAM_SELECT  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      unnest-map [$$24, $$25, $$27, $$34] <- 
index-search("idx9_early_eq", 0, "Default", "test", "Orders", false, false, 2, 
$$28, $$29, 1, $$30, false, false, true) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
+                      -- BTREE_SEARCH  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          assign [$$28, $$29, $$30] <- ["NYC", "USA", "NYC"] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- ASSIGN  |PARTITIONED|
+                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|

Reply via email to