You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by im...@apache.org on 2026/01/27 20:31:32 UTC

(asterixdb) branch master updated (302cccc647 -> 2cea7d8c91)

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

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


    from 302cccc647 [ASTERIXDB-3684][STO] Added testcases related to temporal types
     new b553fc3831 [ASTERIXDB-3690][COMP] Fixing Index-Only Query Plan when using LIKE in UDF or with SET
     new 23a6aaf130 [ASTERIXDB-3694][STO] Parquet reader INTERVAL support
     new 2cea7d8c91 [ASTERIXDB-3692][COMP] Allow setting frame size at query level

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../provider/SqlppCompilationProvider.java         |   2 +-
 .../optimizerts/results/ASTERIXDB-2402.plan        | 168 ++---
 .../ASTERIXDB-3682-field-access-in-join.plan       | 208 +++---
 .../resources/optimizerts/results/ch2/ch2_q16.plan |  86 +--
 .../resources/optimizerts/results/ch2/ch2_q20.plan | 142 ++--
 .../resources/optimizerts/results/ch2/ch2_q22.plan | 108 +--
 .../resources/optimizerts/results/nested_loj2.plan |  58 +-
 .../optimizerts/results/subquery/exists.plan       | 150 ++---
 .../optimizerts/results/subquery/in_let_3.plan     |  78 +--
 .../optimizerts/results/subquery/not_exists.plan   |  82 +--
 .../tpcds/query-ASTERIXDB-1581-correlated.plan     | 722 ++++++++++-----------
 .../optimizerts/results_cbo/ASTERIXDB-2402.plan    | 158 ++---
 .../optimizerts/results_cbo/ch2/ch2_q16.plan       | 102 +--
 .../optimizerts/results_cbo/nested_loj2.plan       |  52 +-
 .../parquet-cover-data-types.01.ddl.sqlpp          |   6 +-
 .../parquet-cover-data-types.02.update.sqlpp       |   2 +-
 .../parquet-cover-data-types.03.update.sqlpp       |   2 +-
 .../udf-with-like-in.01.ddl.sqlpp}                 |  20 +-
 .../udf-with-like-in.02.update.sqlpp}              |   2 +-
 .../udf-with-like-in.03.query.sqlpp}               |   7 +-
 .../udf-with-like-in.04.query.sqlpp}               |   7 +-
 .../temporal/001/{001.005.adm => 001.005.plan}     |   0
 .../temporal/001/{001.006.adm => 001.006.plan}     |   0
 .../temporal/001/{001.007.adm => 001.007.plan}     |   0
 .../parquet-cover-data-types.05.adm                |   2 +-
 .../results/profile/plansleep/sleep.3.regexjson    |  46 +-
 .../udf-with-like-in.03.plan}                      |  18 +-
 .../udf-with-like-in.04.plan}                      |  18 +-
 .../src/test/resources/runtimets/sqlpp_queries.xml |   8 +-
 .../reader/value/temporal/DurationValueReader.java |  10 +-
 .../asterix/common/config/CompilerProperties.java  |   5 +-
 .../common/config/OptimizationConfUtil.java        |  42 +-
 .../asterix/common/exceptions/ErrorCode.java       |   1 +
 .../src/main/resources/asx_errormsg/en.properties  |   1 +
 .../parquet/AsterixTypeToParquetTypeVisitor.java   |   3 +
 .../parquet/converter/ParquetConverterContext.java |  15 +
 ...BinaryConverter.java => IntervalConverter.java} |  24 +-
 .../primitve/PrimitiveConverterProvider.java       |   2 +
 .../printer/parquet/AsterixParquetTypeMap.java     |  17 +-
 .../parquet/FixedByteArrayOutputStream.java}       |  37 +-
 .../printer/parquet/ParquetSchemaBuilderUtils.java |  16 +-
 .../writer/printer/parquet/ParquetValueWriter.java |  35 +
 .../lang/sqlpp/rewrites/SqlppQueryRewriter.java    |  16 +-
 .../rewrites/visitor/LikeFunctionCallVisitor.java  |  72 ++
 .../visitor/OperatorExpressionVisitor.java         |  32 +-
 .../metadata/utils/SampleOperationsHelper.java     |   2 +-
 .../utils/SecondaryIndexOperationsHelper.java      |   3 +-
 47 files changed, 1396 insertions(+), 1191 deletions(-)
 copy asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/{user-defined-functions/inline-in-expr/inline-in-expr.01.ddl.sqlpp => udf-with-like-in/udf-with-like-in.01.ddl.sqlpp} (78%)
 copy asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/{feeds/record-reader-with-malformed-input-stream/record-reader-with-malformed-input-stream.6.query.sqlpp => udf-with-like-in/udf-with-like-in.02.update.sqlpp} (94%)
 copy asterixdb/asterix-app/src/test/resources/{metadata/queries/exception/exception_declare_system_function/exception_declare_system_function.1.query.sqlpp => runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.03.query.sqlpp} (90%)
 copy asterixdb/asterix-app/src/test/resources/{metadata/queries/exception/exception_declare_system_function/exception_declare_system_function.1.query.sqlpp => runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.04.query.sqlpp} (90%)
 rename asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/{001.005.adm => 001.005.plan} (100%)
 rename asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/{001.006.adm => 001.006.plan} (100%)
 rename asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/{001.007.adm => 001.007.plan} (100%)
 copy asterixdb/asterix-app/src/test/resources/runtimets/results/{index-only-testcases/index-only-with-Meta/index-only-with-Meta.4.plan => udf-with-like-in/udf-with-like-in.03.plan} (61%)
 copy asterixdb/asterix-app/src/test/resources/runtimets/results/{index-only-testcases/index-only-with-Meta/index-only-with-Meta.4.plan => udf-with-like-in/udf-with-like-in.04.plan} (61%)
 copy asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/{BinaryConverter.java => IntervalConverter.java} (55%)
 copy asterixdb/{asterix-column/src/main/java/org/apache/asterix/column/bytes/stream/out/ByteBufferOutputStream.java => asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/FixedByteArrayOutputStream.java} (58%)
 create mode 100644 asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/LikeFunctionCallVisitor.java


(asterixdb) 02/03: [ASTERIXDB-3694][STO] Parquet reader INTERVAL support

Posted by im...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 23a6aaf130e2951b7a0c0932aa4d685251adb435
Author: Ritik Raj <ra...@gmail.com>
AuthorDate: Wed Jan 21 15:03:27 2026 +0530

    [ASTERIXDB-3694][STO] Parquet reader INTERVAL support
    
    - user model changes: no
    - storage format changes: yes
    - interface changes: yes
    
    Details:
    Contains changes for writing duration(Parquet's Interval)
    and reading back the record via external dataset.
    
    Ext-ref: MB-70267
    Change-Id: I8dcd0da5db34991280bc4655059ca418fd8a71c9
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20834
    Reviewed-by: Ritik Raj <ri...@couchbase.com>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Wail Alkowaileet <wa...@gmail.com>
---
 .../parquet-cover-data-types.01.ddl.sqlpp          |  6 ++-
 .../parquet-cover-data-types.02.update.sqlpp       |  2 +-
 .../parquet-cover-data-types.03.update.sqlpp       |  2 +-
 .../parquet-cover-data-types.05.adm                |  2 +-
 .../reader/value/temporal/DurationValueReader.java | 10 ++--
 .../parquet/AsterixTypeToParquetTypeVisitor.java   |  3 ++
 .../parquet/converter/ParquetConverterContext.java | 15 ++++++
 .../converter/primitve/IntervalConverter.java      | 55 ++++++++++++++++++++++
 .../primitve/PrimitiveConverterProvider.java       |  2 +
 .../printer/parquet/AsterixParquetTypeMap.java     | 17 +++----
 .../parquet/FixedByteArrayOutputStream.java        | 52 ++++++++++++++++++++
 .../printer/parquet/ParquetSchemaBuilderUtils.java | 16 ++++++-
 .../writer/printer/parquet/ParquetValueWriter.java | 35 ++++++++++++++
 13 files changed, 200 insertions(+), 17 deletions(-)

diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.01.ddl.sqlpp
index 56e79c8247..c94cb73366 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.01.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.01.ddl.sqlpp
@@ -27,4 +27,8 @@ CREATE TYPE ColumnType1 AS {
   name : string
 };
 
-CREATE COLLECTION TestCollection(ColumnType1) PRIMARY KEY id;
\ No newline at end of file
+CREATE COLLECTION TestCollection(ColumnType1) PRIMARY KEY id WITH {
+    "storage-format": {
+        "format": "column"
+    }
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.02.update.sqlpp
index 4cd2ec7518..5ebaa16777 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.02.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.02.update.sqlpp
@@ -29,5 +29,5 @@ insert into TestCollection({"id":`year-month-duration`("P16Y"), "name": "John"})
 insert into TestCollection({"id":`day-time-duration`("-P3829H849.392S"), "name": "Alex"});
 */
 
-insert into TestCollection({"id":18, "name": "Virat" , "dateType":date("1988-11-05"), "timeType": time("03:10:00.493Z") , "boolType" : false , "doubleType" : 0.75, "datetimeType" : datetime("1900-02-01T00:00:00") , "uuidType" : uuid("95ca22dd-ef64-46f2-9c2a-a38005e23344")  });
+insert into TestCollection({"id":18, "name": "Virat" , "dateType":date("1988-11-05"), "timeType": time("03:10:00.493Z") , "boolType" : false , "doubleType" : 0.75, "datetimeType" : datetime("1900-02-01T00:00:00"), "durationType": duration("P5Y12M1DT24H24M1.012S"), "uuidType" : uuid("95ca22dd-ef64-46f2-9c2a-a38005e23344")  });
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.03.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.03.update.sqlpp
index 042fa99c58..e8eb644d41 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.03.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/parquet-cover-data-types/parquet-cover-data-types.03.update.sqlpp
@@ -24,7 +24,7 @@ COPY (
 ) toWriter
 TO %adapter%
 PATH (%pathprefix% "copy-to-result", "parquet-cover-data-types")
-TYPE ( {   name : string,  id : int,  dateType : date,   timeType : time,  boolType : boolean,   doubleType : double,  datetimeType : datetime , uuidType : uuid  } )
+TYPE ( {   name : string,  id : int,  dateType : date,   timeType : time,  boolType : boolean,   doubleType : double,  datetimeType : datetime, durationType: duration, uuidType : uuid  } )
 WITH {
     %template_colons%,
     %additionalProperties%
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/parquet-cover-data-types/parquet-cover-data-types.05.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/parquet-cover-data-types/parquet-cover-data-types.05.adm
index dd54be4122..758326f54d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/parquet-cover-data-types/parquet-cover-data-types.05.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/parquet-cover-data-types/parquet-cover-data-types.05.adm
@@ -1 +1 @@
-{ "name": "Virat", "id": 18, "dateType": date("1988-11-05"), "timeType": time("03:10:00.493"), "boolType": false, "doubleType": 0.75, "datetimeType": datetime("1900-02-01T00:00:00.000"), "uuidType": uuid("95ca22dd-ef64-46f2-9c2a-a38005e23344") }
\ No newline at end of file
+{ "name": "Virat", "id": 18, "dateType": date("1988-11-05"), "timeType": time("03:10:00.493"), "boolType": false, "doubleType": 0.75, "datetimeType": datetime("1900-02-01T00:00:00.000"), "durationType": duration("P6Y2DT24M1.12S"), "uuidType": uuid("95ca22dd-ef64-46f2-9c2a-a38005e23344") }
\ No newline at end of file
diff --git a/asterixdb/asterix-column/src/main/java/org/apache/asterix/column/values/reader/value/temporal/DurationValueReader.java b/asterixdb/asterix-column/src/main/java/org/apache/asterix/column/values/reader/value/temporal/DurationValueReader.java
index 27763254b9..7bd5683a8f 100644
--- a/asterixdb/asterix-column/src/main/java/org/apache/asterix/column/values/reader/value/temporal/DurationValueReader.java
+++ b/asterixdb/asterix-column/src/main/java/org/apache/asterix/column/values/reader/value/temporal/DurationValueReader.java
@@ -81,14 +81,18 @@ public class DurationValueReader extends AbstractValueReader {
         byte[] a = value.getByteArray();
         int ao = value.getStartOffset();
         int monthsA = IntegerPointable.getInteger(a, ao);
-        long millisA = LongPointable.getLong(a, ao + Integer.BYTES);
 
         byte[] b = other.getByteArray();
         int bo = other.getStartOffset();
         int monthsB = IntegerPointable.getInteger(b, bo);
-        long millisB = LongPointable.getLong(b, bo + Integer.BYTES);
 
         int cmp = Integer.compare(monthsA, monthsB);
-        return cmp != 0 ? cmp : Long.compare(millisA, millisB);
+        if (cmp != 0) {
+            return cmp;
+        }
+
+        long millisA = LongPointable.getLong(a, ao + Integer.BYTES);
+        long millisB = LongPointable.getLong(b, bo + Integer.BYTES);
+        return Long.compare(millisA, millisB);
     }
 }
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/AsterixTypeToParquetTypeVisitor.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/AsterixTypeToParquetTypeVisitor.java
index 254280d766..60a4029b53 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/AsterixTypeToParquetTypeVisitor.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/AsterixTypeToParquetTypeVisitor.java
@@ -44,6 +44,7 @@ import org.apache.parquet.schema.LogicalTypeAnnotation;
 import org.apache.parquet.schema.LogicalTypeAnnotation.DateLogicalTypeAnnotation;
 import org.apache.parquet.schema.LogicalTypeAnnotation.DecimalLogicalTypeAnnotation;
 import org.apache.parquet.schema.LogicalTypeAnnotation.IntLogicalTypeAnnotation;
+import org.apache.parquet.schema.LogicalTypeAnnotation.IntervalLogicalTypeAnnotation;
 import org.apache.parquet.schema.LogicalTypeAnnotation.TimeLogicalTypeAnnotation;
 import org.apache.parquet.schema.LogicalTypeAnnotation.TimestampLogicalTypeAnnotation;
 import org.apache.parquet.schema.LogicalTypeAnnotation.UUIDLogicalTypeAnnotation;
@@ -261,6 +262,8 @@ public class AsterixTypeToParquetTypeVisitor implements IATypeVisitor<Type, Type
         ATypeTag inferredTypeTag = ATypeTag.SYSTEM_NULL;
         if (logicalType == null || logicalType == LogicalTypeAnnotation.bsonType()) {
             inferredTypeTag = ATypeTag.BINARY;
+        } else if (logicalType instanceof IntervalLogicalTypeAnnotation) {
+            inferredTypeTag = ATypeTag.DURATION;
         } else if (logicalType == LogicalTypeAnnotation.stringType()
                 || logicalType == LogicalTypeAnnotation.enumType()) {
             inferredTypeTag = ATypeTag.STRING;
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/ParquetConverterContext.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/ParquetConverterContext.java
index 7e9b3a2052..5e9f464216 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/ParquetConverterContext.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/ParquetConverterContext.java
@@ -36,10 +36,12 @@ import org.apache.asterix.om.base.ABoolean;
 import org.apache.asterix.om.base.ADate;
 import org.apache.asterix.om.base.ADateTime;
 import org.apache.asterix.om.base.ADouble;
+import org.apache.asterix.om.base.ADuration;
 import org.apache.asterix.om.base.AInt64;
 import org.apache.asterix.om.base.AMutableDate;
 import org.apache.asterix.om.base.AMutableDateTime;
 import org.apache.asterix.om.base.AMutableDouble;
+import org.apache.asterix.om.base.AMutableDuration;
 import org.apache.asterix.om.base.AMutableInt64;
 import org.apache.asterix.om.base.AMutableTime;
 import org.apache.asterix.om.base.ANull;
@@ -84,6 +86,9 @@ public class ParquetConverterContext extends ParserContext {
     private final ISerializerDeserializer<ADateTime> datetimeSerDer =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADATETIME);
     @SuppressWarnings("unchecked")
+    private final ISerializerDeserializer<ADuration> durationSerDer =
+            SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADURATION);
+    @SuppressWarnings("unchecked")
     private final ISerializerDeserializer<ANull> nullSerDer =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
 
@@ -109,6 +114,7 @@ public class ParquetConverterContext extends ParserContext {
     private final AMutableDate mutableDate = new AMutableDate(0);
     private final AMutableTime mutableTime = new AMutableTime(0);
     private final AMutableDateTime mutableDateTime = new AMutableDateTime(0);
+    private final AMutableDuration mutableDuration = new AMutableDuration(0, 0);
 
     /*
      * ************************************************************************
@@ -297,6 +303,15 @@ public class ParquetConverterContext extends ParserContext {
         }
     }
 
+    public void serializeDuration(int months, long milliseconds, DataOutput output) {
+        try {
+            mutableDuration.setValue(months, milliseconds);
+            durationSerDer.serialize(mutableDuration, output);
+        } catch (HyracksDataException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
     public void serializeNull(DataOutput output) {
         try {
             nullSerDer.serialize(ANull.NULL, output);
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/IntervalConverter.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/IntervalConverter.java
new file mode 100644
index 0000000000..9ef83740ac
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/IntervalConverter.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.asterix.external.input.record.reader.hdfs.parquet.converter.primitve;
+
+import java.io.IOException;
+
+import org.apache.asterix.external.input.record.reader.hdfs.parquet.converter.AbstractComplexConverter;
+import org.apache.asterix.external.input.record.reader.hdfs.parquet.converter.ParquetConverterContext;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.parquet.io.api.Binary;
+
+/**
+ * Converts Parquet's logical INTERVAL type (months:int32, days:int32, millis:int32) into Asterix {@link ATypeTag#DURATION}
+ * (months:int32, millis:int64) by folding days into milliseconds (days * 86400000 + millis).
+ */
+public class IntervalConverter extends GenericPrimitiveConverter {
+    private static final long MILLIS_PER_DAY = 86_400_000L;
+
+    IntervalConverter(AbstractComplexConverter parent, String stringFieldName, int index,
+            ParquetConverterContext context) throws IOException {
+        super(ATypeTag.DURATION, parent, stringFieldName, index, context);
+    }
+
+    @Override
+    public void addBinary(Binary value) {
+        byte[] bytes = value.getBytesUnsafe();
+        int months = readIntLE(bytes, 0);
+        int days = readIntLE(bytes, 4);
+        int millis = readIntLE(bytes, 8);
+
+        long dayTimeMillis = days * MILLIS_PER_DAY + millis;
+        context.serializeDuration(months, dayTimeMillis, parent.getDataOutput());
+        parent.addValue(this);
+    }
+
+    private static int readIntLE(byte[] b, int o) {
+        return (b[o] & 0xFF) | ((b[o + 1] & 0xFF) << 8) | ((b[o + 2] & 0xFF) << 16) | ((b[o + 3] & 0xFF) << 24);
+    }
+}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/PrimitiveConverterProvider.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/PrimitiveConverterProvider.java
index 0e16c21745..cb557293ed 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/PrimitiveConverterProvider.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/hdfs/parquet/converter/primitve/PrimitiveConverterProvider.java
@@ -72,6 +72,8 @@ public class PrimitiveConverterProvider {
                 return getTimeConverter(type, parent, stringFieldName, index, context);
             case DATETIME:
                 return getTimeStampConverter(type, parent, stringFieldName, index, context);
+            case DURATION:
+                return new IntervalConverter(parent, stringFieldName, index, context);
             case ANY:
                 return new JsonStringConverter(parent, stringFieldName, index, context);
             default:
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/AsterixParquetTypeMap.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/AsterixParquetTypeMap.java
index 6bdc586c10..976ac5443c 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/AsterixParquetTypeMap.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/AsterixParquetTypeMap.java
@@ -46,15 +46,16 @@ public class AsterixParquetTypeMap {
                     Map.entry(ATypeTag.DATE, PrimitiveType.PrimitiveTypeName.INT32),
                     Map.entry(ATypeTag.TIME, PrimitiveType.PrimitiveTypeName.INT32),
                     Map.entry(ATypeTag.DATETIME, PrimitiveType.PrimitiveTypeName.INT64),
+                    Map.entry(ATypeTag.DURATION, PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY),
                     Map.entry(ATypeTag.UUID, PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY));
 
-    public static final Map<ATypeTag, LogicalTypeAnnotation> LOGICAL_TYPE_ANNOTATION_MAP =
-            Map.ofEntries(Map.entry(ATypeTag.STRING, LogicalTypeAnnotation.stringType()),
-                    Map.entry(ATypeTag.UUID, LogicalTypeAnnotation.uuidType()),
-                    Map.entry(ATypeTag.DATE, LogicalTypeAnnotation.dateType()),
-                    Map.entry(ATypeTag.TIME,
-                            LogicalTypeAnnotation.timeType(true, LogicalTypeAnnotation.TimeUnit.MILLIS)),
-                    Map.entry(ATypeTag.DATETIME,
-                            LogicalTypeAnnotation.timestampType(true, LogicalTypeAnnotation.TimeUnit.MILLIS)));
+    public static final Map<ATypeTag, LogicalTypeAnnotation> LOGICAL_TYPE_ANNOTATION_MAP = Map.ofEntries(
+            Map.entry(ATypeTag.STRING, LogicalTypeAnnotation.stringType()),
+            Map.entry(ATypeTag.UUID, LogicalTypeAnnotation.uuidType()),
+            Map.entry(ATypeTag.DATE, LogicalTypeAnnotation.dateType()),
+            Map.entry(ATypeTag.TIME, LogicalTypeAnnotation.timeType(true, LogicalTypeAnnotation.TimeUnit.MILLIS)),
+            Map.entry(ATypeTag.DATETIME,
+                    LogicalTypeAnnotation.timestampType(true, LogicalTypeAnnotation.TimeUnit.MILLIS)),
+            Map.entry(ATypeTag.DURATION, LogicalTypeAnnotation.intervalType()));
 
 }
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/FixedByteArrayOutputStream.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/FixedByteArrayOutputStream.java
new file mode 100644
index 0000000000..e42d81705e
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/FixedByteArrayOutputStream.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package org.apache.asterix.external.writer.printer.parquet;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Fixed-size output stream backed by a byte[] allocated once.
+ * reset() only resets the write position to 0 (no parameters, no resizing).
+ */
+final class FixedByteArrayOutputStream extends OutputStream {
+    private final byte[] bytes;
+    private int pos;
+
+    FixedByteArrayOutputStream(int size) {
+        this.bytes = new byte[size];
+        this.pos = 0;
+    }
+
+    void reset() {
+        pos = 0;
+    }
+
+    byte[] getByteArray() {
+        return bytes;
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        if (pos >= bytes.length) {
+            throw new IOException("FixedByteArrayOutputStream overflow. size=" + bytes.length);
+        }
+        bytes[pos++] = (byte) b;
+    }
+}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaBuilderUtils.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaBuilderUtils.java
index da0cef05d8..914d6d72b1 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaBuilderUtils.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaBuilderUtils.java
@@ -18,6 +18,8 @@
  */
 package org.apache.asterix.external.writer.printer.parquet;
 
+import static org.apache.asterix.external.writer.printer.parquet.ParquetValueWriter.INTERVAL_BINARY_LENGTH;
+
 import org.apache.parquet.schema.LogicalTypeAnnotation;
 import org.apache.parquet.schema.PrimitiveType;
 import org.apache.parquet.schema.Types;
@@ -47,9 +49,19 @@ public class ParquetSchemaBuilderUtils {
     public static Types.Builder<?, ?> getPrimitiveChild(Types.Builder parent, PrimitiveType.PrimitiveTypeName type,
             LogicalTypeAnnotation annotation) {
         if (parent instanceof Types.BaseGroupBuilder) {
-            return ((Types.BaseGroupBuilder<?, ?>) parent).optional(type).as(annotation);
+            Types.PrimitiveBuilder<?> primitiveBuilder =
+                    ((Types.BaseGroupBuilder<?, ?>) parent).optional(type).as(annotation);
+            if (annotation instanceof LogicalTypeAnnotation.IntervalLogicalTypeAnnotation) {
+                primitiveBuilder.length(INTERVAL_BINARY_LENGTH);
+            }
+            return primitiveBuilder;
         } else if (parent instanceof Types.BaseListBuilder) {
-            return ((Types.BaseListBuilder<?, ?>) parent).optionalElement(type).as(annotation);
+            Types.BaseListBuilder.ElementBuilder<?, ?> elementBuilder =
+                    ((Types.BaseListBuilder<?, ?>) parent).optionalElement(type).as(annotation);
+            if (annotation instanceof LogicalTypeAnnotation.IntervalLogicalTypeAnnotation) {
+                elementBuilder.length(INTERVAL_BINARY_LENGTH);
+            }
+            return elementBuilder;
         } else {
             return null;
         }
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetValueWriter.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetValueWriter.java
index 38d12f910a..77a839a444 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetValueWriter.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetValueWriter.java
@@ -28,6 +28,7 @@ import org.apache.asterix.dataflow.data.nontagged.serde.ABooleanSerializerDeseri
 import org.apache.asterix.dataflow.data.nontagged.serde.ADateSerializerDeserializer;
 import org.apache.asterix.dataflow.data.nontagged.serde.ADateTimeSerializerDeserializer;
 import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.ADurationSerializerDeserializer;
 import org.apache.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
 import org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
 import org.apache.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
@@ -40,24 +41,29 @@ import org.apache.asterix.om.utils.ResettableByteArrayOutputStream;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.primitive.VoidPointable;
 import org.apache.hyracks.util.string.UTF8StringUtil;
+import org.apache.parquet.bytes.BytesUtils;
 import org.apache.parquet.io.api.Binary;
 import org.apache.parquet.io.api.RecordConsumer;
 import org.apache.parquet.schema.PrimitiveType;
 
 //This class reduces the number of Java objects created each time a column is written to a Parquet file by reusing the same VoidPointable for all columns within the file.
 public class ParquetValueWriter {
+    public static final int INTERVAL_BINARY_LENGTH = 12;
     public static final String LIST_FIELD = "list";
     public static final String ELEMENT_FIELD = "element";
 
     public static final String GROUP_TYPE_ERROR_FIELD = "group";
     public static final String PRIMITIVE_TYPE_ERROR_FIELD = "primitive";
+    public static final long MILLISECONDS_IN_A_DAY = 86_400_000L;
 
     private final VoidPointable voidPointable;
     private final ResettableByteArrayOutputStream byteArrayOutputStream;
+    private final FixedByteArrayOutputStream fixedLen12ByteStream;
 
     ParquetValueWriter() {
         this.voidPointable = VoidPointable.FACTORY.createPointable();
         this.byteArrayOutputStream = new ResettableByteArrayOutputStream();
+        fixedLen12ByteStream = new FixedByteArrayOutputStream(INTERVAL_BINARY_LENGTH);
     }
 
     private void addIntegerType(long value, PrimitiveType.PrimitiveTypeName primitiveTypeName, ATypeTag typeTag,
@@ -189,6 +195,35 @@ public class ParquetValueWriter {
                 long dateTimeValue = ADateTimeSerializerDeserializer.getChronon(b, s);
                 addIntegerType(dateTimeValue, primitiveTypeName, typeTag, recordConsumer);
                 break;
+            case DURATION:
+                if (primitiveTypeName != PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY
+                        || type.getTypeLength() != 12) {
+                    throw RuntimeDataException.create(ErrorCode.TYPE_MISMATCH_GENERIC, primitiveTypeName, typeTag);
+                }
+
+                int months = ADurationSerializerDeserializer.getYearMonth(b, s);
+                long totalMillis = ADurationSerializerDeserializer.getDayTime(b, s);
+                long daysLong = Math.floorDiv(totalMillis, MILLISECONDS_IN_A_DAY);
+
+                if (daysLong < Integer.MIN_VALUE || daysLong > Integer.MAX_VALUE) {
+                    throw RuntimeDataException.create(ErrorCode.TYPE_MISMATCH_GENERIC, primitiveTypeName, typeTag);
+                }
+
+                int days = (int) daysLong;
+                long millisOfDayLong = totalMillis - (days * MILLISECONDS_IN_A_DAY);
+                int millisOfDay = (int) millisOfDayLong;
+
+                fixedLen12ByteStream.reset();
+                try {
+                    BytesUtils.writeIntLittleEndian(fixedLen12ByteStream, months);
+                    BytesUtils.writeIntLittleEndian(fixedLen12ByteStream, days);
+                    BytesUtils.writeIntLittleEndian(fixedLen12ByteStream, millisOfDay);
+                } catch (IOException e) {
+                    throw HyracksDataException.create(e);
+                }
+
+                recordConsumer.addBinary(
+                        Binary.fromReusedByteArray(fixedLen12ByteStream.getByteArray(), 0, INTERVAL_BINARY_LENGTH));
             case UUID:
                 recordConsumer.addBinary(Binary.fromReusedByteArray(b, s, l));
                 break;


(asterixdb) 03/03: [ASTERIXDB-3692][COMP] Allow setting frame size at query level

Posted by im...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 2cea7d8c915c43d598f6fc56536617b1eca1ed1d
Author: Ali Alsuliman <al...@gmail.com>
AuthorDate: Thu Jan 15 18:19:36 2026 -0800

    [ASTERIXDB-3692][COMP] Allow setting frame size at query level
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details:
    'compiler.framesize' is currently only a service-level configurable
    parameter, so changing the frame size requires a restart to reflect
    the frame size across all components. Very often, users want to try
    different frame sizes for a query. This patch is to allow users to
    set the frame size at query level. Note that there are still some
    parts of the query processing that is still using the service-level
    frame size such as the frame allocated for reading the query result.
    
    Ext-ref: MB-66320
    
    Change-Id: Icf52985cd22eed8ae93439d1faa187ce23d31630
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20801
    Reviewed-by: Murtadha Hubail <mh...@apache.org>
    Reviewed-by: Ali Alsuliman <al...@gmail.com>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
---
 .../provider/SqlppCompilationProvider.java         |  2 +-
 .../src/test/resources/runtimets/sqlpp_queries.xml |  8 ++---
 .../asterix/common/config/CompilerProperties.java  |  5 ++-
 .../common/config/OptimizationConfUtil.java        | 42 ++++++++++++++--------
 .../asterix/common/exceptions/ErrorCode.java       |  1 +
 .../src/main/resources/asx_errormsg/en.properties  |  1 +
 .../metadata/utils/SampleOperationsHelper.java     |  2 +-
 .../utils/SecondaryIndexOperationsHelper.java      |  3 +-
 8 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
index ca97aa6734..b6a9295c14 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
@@ -95,7 +95,7 @@ public class SqlppCompilationProvider implements ILangCompilationProvider {
                 CompilerProperties.COMPILER_CBO_TEST_KEY, CompilerProperties.COMPILER_FORCE_JOIN_ORDER_KEY,
                 CompilerProperties.COMPILER_QUERY_PLAN_SHAPE_KEY, CompilerProperties.COMPILER_MIN_MEMORY_ALLOCATION_KEY,
                 CompilerProperties.COMPILER_COLUMN_FILTER_KEY, CompilerProperties.COMPILER_BATCH_LOOKUP_KEY,
-                FunctionUtil.IMPORT_PRIVATE_FUNCTIONS,
+                CompilerProperties.COMPILER_FRAMESIZE_KEY, FunctionUtil.IMPORT_PRIVATE_FUNCTIONS,
                 CompilerProperties.COMPILER_MAX_VARIABLE_OCCURRENCES_INLINING_KEY,
                 CompilerProperties.COMPILER_DELTALAKE_FILESPLITS_KEY, FuzzyUtils.SIM_FUNCTION_PROP_NAME,
                 FuzzyUtils.SIM_THRESHOLD_PROP_NAME, StartFeedStatement.WAIT_FOR_COMPLETION,
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
index 57b494abc9..bc1834fefe 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
@@ -12866,7 +12866,7 @@
     <test-case FilePath="tpch-sql-sugar">
       <compilation-unit name="q17_large_gby_variant_parameter">
         <output-dir compare="Text">none</output-dir>
-        <expected-error>Invalid query parameter compiler.groupmemory -- value has to be greater than or equal to</expected-error>
+        <expected-error>Invalid `compiler.groupmemory` "-10737418240" for frame size=32768. value should be >= 4 * frame size: `compiler.groupmemory` "131072" in bytes</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="tpch-sql-sugar">
@@ -12897,7 +12897,7 @@
     <test-case FilePath="tpch-sql-sugar">
       <compilation-unit name="q01_pricing_summary_report_parameter">
         <output-dir compare="Text">none</output-dir>
-        <expected-error>Invalid query parameter compiler.sortmemory -- value has to be greater than or equal to</expected-error>
+        <expected-error>Invalid `compiler.sortmemory` "-7516192768" for frame size=32768. value should be >= 3 * frame size: `compiler.sortmemory` "98304" in bytes</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="tpch-sql-sugar">
@@ -12958,7 +12958,7 @@
     <test-case FilePath="tpch-sql-sugar">
       <compilation-unit name="q09_product_type_profit_parameter">
         <output-dir compare="Text">none</output-dir>
-        <expected-error>Invalid query parameter compiler.joinmemory -- value has to be greater than or equal to</expected-error>
+        <expected-error>Invalid `compiler.joinmemory` "-34359738368" for frame size=32768. value should be >= 5 * frame size: `compiler.joinmemory` "163840" in bytes</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="tpch-sql-sugar">
@@ -16563,7 +16563,7 @@
         <output-dir compare="Text">misc_01</output-dir>
         <expected-error>ASX0002: Type mismatch</expected-error>
         <expected-error>ASX1104: Invalid modifier FROM FIRST/LAST for function</expected-error>
-        <expected-error>ASX1037: Invalid query parameter compiler.windowmemory</expected-error>
+        <expected-error>Invalid `compiler.windowmemory` "102400" for frame size=32768. value should be >= 5 * frame size: `compiler.windowmemory` "163840" in bytes </expected-error>
         <expected-error>ASX1102: Expected window or aggregate function, got: lowercase</expected-error>
         <expected-error>ASX1079: Compilation error: count is a SQL-92 aggregate function</expected-error>
         <expected-error>ASX1104: Invalid modifier RESPECT/IGNORE NULLS for function</expected-error>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java
index da5f39b954..62be4d02c3 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java
@@ -28,6 +28,7 @@ import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER_BYTE_
 import static org.apache.hyracks.control.common.config.OptionTypes.LONG_BYTE_UNIT;
 import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER;
 import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER;
+import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER_BYTE_UNIT;
 import static org.apache.hyracks.control.common.config.OptionTypes.STRING;
 import static org.apache.hyracks.control.common.config.OptionTypes.getRangedIntegerType;
 import static org.apache.hyracks.util.StorageUtil.StorageUnit.KILOBYTE;
@@ -67,7 +68,7 @@ public class CompilerProperties extends AbstractProperties {
                 StorageUtil.getIntSizeInBytes(8, KILOBYTE),
                 "The memory budget (in bytes) for an external scan operator instance in a partition"),
         COMPILER_FRAMESIZE(
-                INTEGER_BYTE_UNIT,
+                POSITIVE_INTEGER_BYTE_UNIT,
                 StorageUtil.getIntSizeInBytes(32, KILOBYTE),
                 "The page size (in bytes) for computation"),
         COMPILER_MIN_SORTMEMORY(
@@ -196,6 +197,8 @@ public class CompilerProperties extends AbstractProperties {
         }
     }
 
+    public static final String COMPILER_FRAMESIZE_KEY = Option.COMPILER_FRAMESIZE.ini();
+
     public static final String COMPILER_SORTMEMORY_KEY = Option.COMPILER_SORTMEMORY.ini();
 
     public static final String COMPILER_GROUPMEMORY_KEY = Option.COMPILER_GROUPMEMORY.ini();
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/OptimizationConfUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/OptimizationConfUtil.java
index 6de87a9013..9ebf5c2dc3 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/OptimizationConfUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/OptimizationConfUtil.java
@@ -51,8 +51,8 @@ public class OptimizationConfUtil {
     public static PhysicalOptimizationConfig createPhysicalOptimizationConf(CompilerProperties compilerProperties,
             Map<String, Object> querySpecificConfig, Set<String> parameterNames, SourceLocation sourceLoc)
             throws AlgebricksException {
-        int frameSize = compilerProperties.getFrameSize();
-        int sortFrameLimit = getSortNumFrames(compilerProperties, querySpecificConfig, sourceLoc);
+        int frameSize = getFrameSize(compilerProperties, querySpecificConfig, sourceLoc);
+        int sortFrameLimit = getSortNumFrames(compilerProperties, querySpecificConfig, sourceLoc, frameSize);
         int groupFrameLimit = getFrameLimit(CompilerProperties.COMPILER_GROUPMEMORY_KEY,
                 (String) querySpecificConfig.get(CompilerProperties.COMPILER_GROUPMEMORY_KEY),
                 compilerProperties.getGroupMemorySize(), frameSize, MIN_FRAME_LIMIT_FOR_GROUP_BY, sourceLoc);
@@ -62,7 +62,8 @@ public class OptimizationConfUtil {
         int windowFrameLimit = getFrameLimit(CompilerProperties.COMPILER_WINDOWMEMORY_KEY,
                 (String) querySpecificConfig.get(CompilerProperties.COMPILER_WINDOWMEMORY_KEY),
                 compilerProperties.getWindowMemorySize(), frameSize, MIN_FRAME_LIMIT_FOR_WINDOW, sourceLoc);
-        int textSearchFrameLimit = getTextSearchNumFrames(compilerProperties, querySpecificConfig, sourceLoc);
+        int textSearchFrameLimit =
+                getTextSearchNumFrames(compilerProperties, frameSize, querySpecificConfig, sourceLoc);
         int sortNumSamples = getSortSamples(compilerProperties, querySpecificConfig, sourceLoc);
         boolean fullParallelSort = getBoolean(querySpecificConfig, CompilerProperties.COMPILER_SORT_PARALLEL_KEY,
                 compilerProperties.getSortParallel());
@@ -143,6 +144,21 @@ public class OptimizationConfUtil {
         return physOptConf;
     }
 
+    private static int getFrameSize(CompilerProperties compilerProperties, Map<String, Object> querySpecificConfig,
+            SourceLocation sourceLoc) throws AlgebricksException {
+        String queryFrameSize = (String) querySpecificConfig.get(CompilerProperties.COMPILER_FRAMESIZE_KEY);
+        if (queryFrameSize == null) {
+            return compilerProperties.getFrameSize();
+        }
+        @SuppressWarnings("unchecked")
+        IOptionType<Integer> type = CompilerProperties.Option.COMPILER_FRAMESIZE.type();
+        try {
+            return type.parse(queryFrameSize);
+        } catch (IllegalArgumentException e) {
+            throw AsterixException.create(ErrorCode.COMPILATION_ERROR, e, sourceLoc, e.getMessage());
+        }
+    }
+
     private static int getExternalScanBufferSize(String externalScanMemorySizeParameter,
             int compilerExternalScanMemorySize, SourceLocation sourceLoc) throws AsterixException {
         IOptionType<Integer> intByteParser = OptionTypes.INTEGER_BYTE_UNIT;
@@ -155,27 +171,25 @@ public class OptimizationConfUtil {
     }
 
     public static int getSortNumFrames(CompilerProperties compilerProperties, Map<String, Object> querySpecificConfig,
-            SourceLocation sourceLoc) throws AlgebricksException {
+            SourceLocation sourceLoc, int frameSize) throws AlgebricksException {
         return getFrameLimit(CompilerProperties.COMPILER_SORTMEMORY_KEY,
                 (String) querySpecificConfig.get(CompilerProperties.COMPILER_SORTMEMORY_KEY),
-                compilerProperties.getSortMemorySize(), compilerProperties.getFrameSize(), MIN_FRAME_LIMIT_FOR_SORT,
-                sourceLoc);
+                compilerProperties.getSortMemorySize(), frameSize, MIN_FRAME_LIMIT_FOR_SORT, sourceLoc);
     }
 
     public static int getGroupByNumFrames(CompilerProperties compilerProperties,
-            Map<String, Object> querySpecificConfig, SourceLocation sourceLoc) throws AlgebricksException {
+            Map<String, Object> querySpecificConfig, SourceLocation sourceLoc, int frameSize)
+            throws AlgebricksException {
         return getFrameLimit(CompilerProperties.COMPILER_GROUPMEMORY_KEY,
                 (String) querySpecificConfig.get(CompilerProperties.COMPILER_GROUPMEMORY_KEY),
-                compilerProperties.getGroupMemorySize(), compilerProperties.getFrameSize(),
-                MIN_FRAME_LIMIT_FOR_GROUP_BY, sourceLoc);
+                compilerProperties.getGroupMemorySize(), frameSize, MIN_FRAME_LIMIT_FOR_GROUP_BY, sourceLoc);
     }
 
-    public static int getTextSearchNumFrames(CompilerProperties compilerProperties,
+    public static int getTextSearchNumFrames(CompilerProperties compilerProperties, int frameSize,
             Map<String, Object> querySpecificConfig, SourceLocation sourceLoc) throws AlgebricksException {
         return getFrameLimit(CompilerProperties.COMPILER_TEXTSEARCHMEMORY_KEY,
                 (String) querySpecificConfig.get(CompilerProperties.COMPILER_TEXTSEARCHMEMORY_KEY),
-                compilerProperties.getTextSearchMemorySize(), compilerProperties.getFrameSize(),
-                MIN_FRAME_LIMIT_FOR_TEXT_SEARCH, sourceLoc);
+                compilerProperties.getTextSearchMemorySize(), frameSize, MIN_FRAME_LIMIT_FOR_TEXT_SEARCH, sourceLoc);
     }
 
     @SuppressWarnings("squid:S1166") // Either log or rethrow this exception
@@ -190,8 +204,8 @@ public class OptimizationConfUtil {
         }
         int frameLimit = (int) (memBudget / frameSize);
         if (frameLimit < minFrameLimit) {
-            throw AsterixException.create(ErrorCode.COMPILATION_BAD_QUERY_PARAMETER_VALUE, sourceLoc, parameterName,
-                    frameSize * minFrameLimit, "bytes");
+            throw AsterixException.create(ErrorCode.INVALID_FRAME_BASED_MEMORY_BUDGET, sourceLoc, parameterName,
+                    memBudget, frameSize, minFrameLimit, frameSize * minFrameLimit, "bytes");
         }
         // sets the frame limit to the minimum frame limit if the calculated frame limit is too small.
         return Math.max(frameLimit, minFrameLimit);
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index f604f6628e..d52fe0799b 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -346,6 +346,7 @@ public enum ErrorCode implements IError {
     ICEBERG_SNAPSHOT_ID_NOT_FOUND(1238),
     INVALID_ICEBERG_SNAPSHOT_VALUE(1239),
     NO_VALID_CREDENTIALS_PROVIDED_FOR_BIGLAKE_METASTORE_CATALOG(1240),
+    INVALID_FRAME_BASED_MEMORY_BUDGET(1241),
 
     // Feed errors
     DATAFLOW_ILLEGAL_STATE(3001),
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 16c5c99fe5..4b0fd2bd41 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -348,6 +348,7 @@
 1238 = Iceberg snapshot '%1$s' not found
 1239 = Invalid Iceberg snapshot value: '%1$s'
 1240 = No valid credentials provided to access Biglake Metastore catalog.
+1241 = Invalid `%1$s` "%2$s" for frame size=%3$s. value should be >= %4$s * frame size: `%1$s` "%5$s" in %6$s
 
 # Feed Errors
 3001 = Illegal state.
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java
index 7e3af78b59..b14e0e574b 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java
@@ -380,6 +380,6 @@ public class SampleOperationsHelper implements ISecondaryIndexOperationsHelper {
             throws AlgebricksException {
         return OptimizationConfUtil.getGroupByNumFrames(
                 metadataProvider.getApplicationContext().getCompilerProperties(), metadataProvider.getConfig(),
-                sourceLoc);
+                sourceLoc, metadataProvider.getApplicationContext().getCompilerProperties().getFrameSize());
     }
 }
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryIndexOperationsHelper.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryIndexOperationsHelper.java
index 8350141153..b92dc2815d 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryIndexOperationsHelper.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryIndexOperationsHelper.java
@@ -158,7 +158,8 @@ public abstract class SecondaryIndexOperationsHelper implements ISecondaryIndexO
     private static int getSortNumFrames(MetadataProvider metadataProvider, SourceLocation sourceLoc)
             throws AlgebricksException {
         return OptimizationConfUtil.getSortNumFrames(metadataProvider.getApplicationContext().getCompilerProperties(),
-                metadataProvider.getConfig(), sourceLoc);
+                metadataProvider.getConfig(), sourceLoc,
+                metadataProvider.getApplicationContext().getCompilerProperties().getFrameSize());
     }
 
     public static ISecondaryIndexOperationsHelper createIndexOperationsHelper(Dataset dataset, Index index,


(asterixdb) 01/03: [ASTERIXDB-3690][COMP] Fixing Index-Only Query Plan when using LIKE in UDF or with SET

Posted by im...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit b553fc3831591062b7b9329aa8d7f732b62a06f2
Author: Shahrzad Shirazi <Sh...@couchbase.com>
AuthorDate: Mon Jan 5 11:17:28 2026 -0800

    [ASTERIXDB-3690][COMP] Fixing Index-Only Query Plan when using LIKE in UDF or with SET
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details: This change ensures that an index-only query plan is used when applicable for LIKE predicates in a UDF or with a SET variable.
    
    
    Ext-ref: MB-69660
    
    
    Change-Id: I8387141bc0edf36195934ae4452ad530c63bb4bf
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20764
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Peeyush Gupta <pe...@couchbase.com>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
---
 .../optimizerts/results/ASTERIXDB-2402.plan        | 168 ++---
 .../ASTERIXDB-3682-field-access-in-join.plan       | 208 +++---
 .../resources/optimizerts/results/ch2/ch2_q16.plan |  86 +--
 .../resources/optimizerts/results/ch2/ch2_q20.plan | 142 ++--
 .../resources/optimizerts/results/ch2/ch2_q22.plan | 108 +--
 .../resources/optimizerts/results/nested_loj2.plan |  58 +-
 .../optimizerts/results/subquery/exists.plan       | 150 ++---
 .../optimizerts/results/subquery/in_let_3.plan     |  78 +--
 .../optimizerts/results/subquery/not_exists.plan   |  82 +--
 .../tpcds/query-ASTERIXDB-1581-correlated.plan     | 722 ++++++++++-----------
 .../optimizerts/results_cbo/ASTERIXDB-2402.plan    | 158 ++---
 .../optimizerts/results_cbo/ch2/ch2_q16.plan       | 102 +--
 .../optimizerts/results_cbo/nested_loj2.plan       |  52 +-
 .../udf-with-like-in/udf-with-like-in.01.ddl.sqlpp |  35 +
 .../udf-with-like-in.02.update.sqlpp               |  22 +
 .../udf-with-like-in.03.query.sqlpp                |  23 +
 .../udf-with-like-in.04.query.sqlpp                |  23 +
 .../temporal/001/{001.005.adm => 001.005.plan}     |   0
 .../temporal/001/{001.006.adm => 001.006.plan}     |   0
 .../temporal/001/{001.007.adm => 001.007.plan}     |   0
 .../results/profile/plansleep/sleep.3.regexjson    |  46 +-
 .../udf-with-like-in/udf-with-like-in.03.plan      |  30 +
 .../udf-with-like-in/udf-with-like-in.04.plan      |  30 +
 .../lang/sqlpp/rewrites/SqlppQueryRewriter.java    |  16 +-
 .../rewrites/visitor/LikeFunctionCallVisitor.java  |  72 ++
 .../visitor/OperatorExpressionVisitor.java         |  32 +-
 26 files changed, 1354 insertions(+), 1089 deletions(-)

diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan
index a2c89b4a47..94beaf77b7 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan
@@ -1,168 +1,168 @@
-distribute result [$$237]
+distribute result [$$253]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    project ([$$237])
+    project ([$$253])
     -- STREAM_PROJECT  |PARTITIONED|
       subplan {
-                aggregate [$$237] <- [listify($$236)]
+                aggregate [$$253] <- [listify($$252)]
                 -- AGGREGATE  |LOCAL|
-                  assign [$$236] <- [{"channelExecutionTime": $$267, "result": $$268, "BrokerEndpoint": $$BrokerEndpoint}]
+                  assign [$$252] <- [{"channelExecutionTime": $$283, "result": $$284, "BrokerEndpoint": $$BrokerEndpoint}]
                   -- ASSIGN  |LOCAL|
-                    group by ([$$BrokerEndpoint := $$240]) decor ([$$267 := $$269; $$268 := $$270]) {
+                    group by ([$$BrokerEndpoint := $$256]) decor ([$$283 := $$285; $$284 := $$286]) {
                               aggregate [] <- []
                               -- AGGREGATE  |LOCAL|
                                 nested tuple source
                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                            }
-                    -- MICRO_PRE_CLUSTERED_GROUP_BY[$$240]  |LOCAL|
-                      order (ASC, $$240)
-                      -- MICRO_STABLE_SORT [$$240(ASC)]  |LOCAL|
-                        assign [$$240] <- [$$sub.getField("BrokerEndpoint")] project: [$$270, $$269, $$240]
+                    -- MICRO_PRE_CLUSTERED_GROUP_BY[$$256]  |LOCAL|
+                      order (ASC, $$256)
+                      -- MICRO_STABLE_SORT [$$256(ASC)]  |LOCAL|
+                        assign [$$256] <- [$$sub.getField("BrokerEndpoint")] project: [$$286, $$285, $$256]
                         -- ASSIGN  |LOCAL|
-                          unnest $$sub <- scan-collection($$229) project: [$$270, $$269, $$sub]
+                          unnest $$sub <- scan-collection($$245) project: [$$286, $$285, $$sub]
                           -- UNNEST  |LOCAL|
-                            project ([$$270, $$269, $$229])
+                            project ([$$286, $$285, $$245])
                             -- STREAM_PROJECT  |LOCAL|
                               subplan {
-                                        aggregate [$$229] <- [listify($$228)]
+                                        aggregate [$$245] <- [listify($$244)]
                                         -- AGGREGATE  |LOCAL|
-                                          assign [$$228] <- [{"sub": $$sub}]
+                                          assign [$$244] <- [{"sub": $$sub}]
                                           -- ASSIGN  |LOCAL|
-                                            unnest $$sub <- scan-collection($$266) project: [$$sub]
+                                            unnest $$sub <- scan-collection($$282) project: [$$sub]
                                             -- UNNEST  |LOCAL|
-                                              project ([$$266])
+                                              project ([$$282])
                                               -- STREAM_PROJECT  |LOCAL|
                                                 nested tuple source
                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                      }
                               -- SUBPLAN  |LOCAL|
-                                project ([$$270, $$269, $$266])
+                                project ([$$286, $$285, $$282])
                                 -- STREAM_PROJECT  |LOCAL|
                                   nested tuple source
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
              }
       -- SUBPLAN  |PARTITIONED|
-        project ([$$270, $$269, $$266])
+        project ([$$286, $$285, $$282])
         -- STREAM_PROJECT  |PARTITIONED|
           commit
           -- COMMIT  |PARTITIONED|
-            project ([$$270, $$269, $$266, $$224])
+            project ([$$286, $$285, $$282, $$240])
             -- STREAM_PROJECT  |PARTITIONED|
               exchange
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                insert into channels.EmergenciesNearMeChannelResults from record: $$241 partitioned by [$$224]
+                insert into channels.EmergenciesNearMeChannelResults from record: $$257 partitioned by [$$240]
                 -- INSERT_DELETE  |PARTITIONED|
                   exchange
-                  -- HASH_PARTITION_EXCHANGE [$$224]  |PARTITIONED|
-                    assign [$$270, $$269, $$266, $$224] <- [$$241.getField("result"), $$241.getField("channelExecutionTime"), $$241.getField("brokerSubIds"), $$241.getField(0)]
+                  -- HASH_PARTITION_EXCHANGE [$$240]  |PARTITIONED|
+                    assign [$$286, $$285, $$282, $$240] <- [$$257.getField("result"), $$257.getField("channelExecutionTime"), $$257.getField("brokerSubIds"), $$257.getField(0)]
                     -- ASSIGN  |PARTITIONED|
-                      assign [$$241] <- [cast(check-unknown(put-autogenerated-key($$222, "resultId")))] project: [$$241]
+                      assign [$$257] <- [cast(check-unknown(put-autogenerated-key($$238, "resultId")))] project: [$$257]
                       -- ASSIGN  |PARTITIONED|
-                        assign [$$222] <- [{"result": $$result, "channelExecutionTime": current-datetime(), "channelSubId": $$276, "deliveryTime": current-datetime(), "brokerSubIds": $$221}] project: [$$222]
+                        assign [$$238] <- [{"result": $$result, "channelExecutionTime": current-datetime(), "channelSubId": $$292, "deliveryTime": current-datetime(), "brokerSubIds": $$237}] project: [$$238]
                         -- ASSIGN  |PARTITIONED|
-                          project ([$$221, $$276, $$result])
+                          project ([$$237, $$292, $$result])
                           -- STREAM_PROJECT  |PARTITIONED|
                             exchange
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              group by ([$$279 := $$277]) decor ([$$276; $$result]) {
-                                        aggregate [$$221] <- [listify({"BrokerEndPoint": $$263, "brokerSubId": $$248})]
+                              group by ([$$295 := $$293]) decor ([$$292; $$result]) {
+                                        aggregate [$$237] <- [listify({"BrokerEndPoint": $$279, "brokerSubId": $$264})]
                                         -- AGGREGATE  |LOCAL|
-                                          select (not(is-missing($$278)))
+                                          select (not(is-missing($$294)))
                                           -- STREAM_SELECT  |LOCAL|
-                                            project ([$$263, $$248, $$278])
+                                            project ([$$279, $$264, $$294])
                                             -- STREAM_PROJECT  |LOCAL|
                                               nested tuple source
                                               -- NESTED_TUPLE_SOURCE  |LOCAL|
                                      }
-                              -- PRE_CLUSTERED_GROUP_BY[$$277]  |PARTITIONED|
+                              -- PRE_CLUSTERED_GROUP_BY[$$293]  |PARTITIONED|
                                 exchange
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  order (ASC, $$277)
-                                  -- STABLE_SORT [$$277(ASC)]  |PARTITIONED|
+                                  order (ASC, $$293)
+                                  -- STABLE_SORT [$$293(ASC)]  |PARTITIONED|
                                     exchange
-                                    -- HASH_PARTITION_EXCHANGE [$$277]  |PARTITIONED|
-                                      project ([$$result, $$276, $$263, $$248, $$278, $$277])
+                                    -- HASH_PARTITION_EXCHANGE [$$293]  |PARTITIONED|
+                                      project ([$$result, $$292, $$279, $$264, $$294, $$293])
                                       -- STREAM_PROJECT  |PARTITIONED|
                                         exchange
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          left outer join (eq($$247, $$276))
-                                          -- HYBRID_HASH_JOIN [$$276][$$247]  |PARTITIONED|
+                                          left outer join (eq($$263, $$292))
+                                          -- HYBRID_HASH_JOIN [$$292][$$263]  |PARTITIONED|
                                             exchange
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              running-aggregate [$$277] <- [create-query-uid()]
+                                              running-aggregate [$$293] <- [create-query-uid()]
                                               -- RUNNING_AGGREGATE  |PARTITIONED|
-                                                unnest $$result <- scan-collection($$201) project: [$$result, $$276]
+                                                unnest $$result <- scan-collection($$217) project: [$$result, $$292]
                                                 -- UNNEST  |PARTITIONED|
                                                   exchange
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    group by ([$$276 := $$243]) decor ([]) {
-                                                              aggregate [$$201] <- [listify({"report": $$r, "shelters": $$191})]
+                                                    group by ([$$292 := $$259]) decor ([]) {
+                                                              aggregate [$$217] <- [listify({"report": $$r, "shelters": $$207})]
                                                               -- AGGREGATE  |LOCAL|
-                                                                group by ([$$272 := $$244; $$273 := $$245]) decor ([$$243; $$262; $$sub; $$r; $$u; $$252; $$253; $$254]) {
-                                                                          aggregate [$$191] <- [listify({"location": $$242})]
+                                                                group by ([$$288 := $$260; $$289 := $$261]) decor ([$$r; $$u; $$259; $$278; $$268; $$269; $$270; $$sub]) {
+                                                                          aggregate [$$207] <- [listify({"location": $$258})]
                                                                           -- AGGREGATE  |LOCAL|
-                                                                            select (not(is-missing($$246)))
+                                                                            select (not(is-missing($$262)))
                                                                             -- STREAM_SELECT  |LOCAL|
-                                                                              project ([$$246, $$242])
+                                                                              project ([$$262, $$258])
                                                                               -- STREAM_PROJECT  |LOCAL|
                                                                                 nested tuple source
                                                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                                        }
-                                                                -- MICRO_PRE_CLUSTERED_GROUP_BY[$$244, $$245]  |LOCAL|
-                                                                  select (and(not(is-missing($$274)), not(is-missing($$275))))
+                                                                -- MICRO_PRE_CLUSTERED_GROUP_BY[$$260, $$261]  |LOCAL|
+                                                                  select (and(not(is-missing($$290)), not(is-missing($$291))))
                                                                   -- STREAM_SELECT  |LOCAL|
                                                                     nested tuple source
                                                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                            }
-                                                    -- PRE_CLUSTERED_GROUP_BY[$$243]  |PARTITIONED|
+                                                    -- PRE_CLUSTERED_GROUP_BY[$$259]  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        order (ASC, $$243) (ASC, $$244) (ASC, $$245)
-                                                        -- STABLE_SORT [$$243(ASC), $$244(ASC), $$245(ASC)]  |PARTITIONED|
+                                                        order (ASC, $$259) (ASC, $$260) (ASC, $$261)
+                                                        -- STABLE_SORT [$$259(ASC), $$260(ASC), $$261(ASC)]  |PARTITIONED|
                                                           exchange
-                                                          -- HASH_PARTITION_EXCHANGE [$$243]  |PARTITIONED|
-                                                            select (spatial-intersect($$242, $$254)) retain-untrue ($$246 <- missing)
+                                                          -- HASH_PARTITION_EXCHANGE [$$259]  |PARTITIONED|
+                                                            select (spatial-intersect($$258, $$270)) retain-untrue ($$262 <- missing)
                                                             -- STREAM_SELECT  |PARTITIONED|
-                                                              assign [$$242] <- [$$s.getField(1)] project: [$$243, $$sub, $$252, $$244, $$r, $$253, $$262, $$274, $$245, $$u, $$275, $$254, $$246, $$242]
+                                                              assign [$$258] <- [$$s.getField(1)] project: [$$259, $$sub, $$268, $$260, $$r, $$269, $$278, $$290, $$261, $$u, $$291, $$270, $$262, $$258]
                                                               -- ASSIGN  |PARTITIONED|
-                                                                project ([$$243, $$sub, $$252, $$244, $$r, $$253, $$262, $$274, $$245, $$u, $$275, $$254, $$246, $$s])
+                                                                project ([$$259, $$sub, $$268, $$260, $$r, $$269, $$278, $$290, $$261, $$u, $$291, $$270, $$262, $$s])
                                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                                   exchange
                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                    left-outer-unnest-map [$$246, $$s] <- index-search("Shelters", 0, "Default", "channels", "Shelters", true, false, 1, $$302, 1, $$302, true, true, true)
+                                                                    left-outer-unnest-map [$$262, $$s] <- index-search("Shelters", 0, "Default", "channels", "Shelters", true, false, 1, $$318, 1, $$318, true, true, true)
                                                                     -- BTREE_SEARCH  |PARTITIONED|
                                                                       exchange
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        order (ASC, $$302)
-                                                                        -- STABLE_SORT [$$302(ASC)]  |PARTITIONED|
+                                                                        order (ASC, $$318)
+                                                                        -- STABLE_SORT [$$318(ASC)]  |PARTITIONED|
                                                                           exchange
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            project ([$$243, $$sub, $$252, $$244, $$r, $$253, $$262, $$274, $$245, $$u, $$275, $$254, $$302])
+                                                                            project ([$$259, $$sub, $$268, $$260, $$r, $$269, $$278, $$290, $$261, $$u, $$291, $$270, $$318])
                                                                             -- STREAM_PROJECT  |PARTITIONED|
                                                                               exchange
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                left-outer-unnest-map [$$298, $$299, $$300, $$301, $$302] <- index-search("s_location", 1, "Default", "channels", "Shelters", true, true, 4, $$294, $$295, $$296, $$297)
+                                                                                left-outer-unnest-map [$$314, $$315, $$316, $$317, $$318] <- index-search("s_location", 1, "Default", "channels", "Shelters", true, true, 4, $$310, $$311, $$312, $$313)
                                                                                 -- RTREE_SEARCH  |PARTITIONED|
                                                                                   exchange
                                                                                   -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                                    assign [$$294, $$295, $$296, $$297] <- [create-mbr($$254, 2, 0), create-mbr($$254, 2, 1), create-mbr($$254, 2, 2), create-mbr($$254, 2, 3)]
+                                                                                    assign [$$310, $$311, $$312, $$313] <- [create-mbr($$270, 2, 0), create-mbr($$270, 2, 1), create-mbr($$270, 2, 2), create-mbr($$270, 2, 3)]
                                                                                     -- ASSIGN  |PARTITIONED|
                                                                                       exchange
                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                        left outer join (and(spatial-intersect($$253, $$254), eq($$245, $$252)))
-                                                                                        -- HYBRID_HASH_JOIN [$$252][$$245]  |PARTITIONED|
+                                                                                        left outer join (and(spatial-intersect($$269, $$270), eq($$261, $$268)))
+                                                                                        -- HYBRID_HASH_JOIN [$$268][$$261]  |PARTITIONED|
                                                                                           exchange
-                                                                                          -- HASH_PARTITION_EXCHANGE [$$252]  |PARTITIONED|
+                                                                                          -- HASH_PARTITION_EXCHANGE [$$268]  |PARTITIONED|
                                                                                             left outer join (true)
                                                                                             -- NESTED_LOOP  |PARTITIONED|
                                                                                               exchange
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                assign [$$252] <- [$$sub.getField("param0")]
+                                                                                                assign [$$268] <- [$$sub.getField("param0")]
                                                                                                 -- ASSIGN  |PARTITIONED|
                                                                                                   exchange
                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                    data-scan []<-[$$243, $$sub] <- channels.EmergenciesNearMeChannelChannelSubscriptions
+                                                                                                    data-scan []<-[$$259, $$sub] <- channels.EmergenciesNearMeChannelChannelSubscriptions
                                                                                                     -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                       exchange
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -170,63 +170,63 @@ distribute result [$$237]
                                                                                                         -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                                               exchange
                                                                                               -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                                                assign [$$274] <- [true]
+                                                                                                assign [$$290] <- [true]
                                                                                                 -- ASSIGN  |PARTITIONED|
-                                                                                                  select (gt($$262, numeric-subtract(current-datetime(), day_time_duration: {PT10S })))
+                                                                                                  select (gt($$278, numeric-subtract(current-datetime(), day_time_duration: {PT10S })))
                                                                                                   -- STREAM_SELECT  |PARTITIONED|
-                                                                                                    assign [$$253, $$262] <- [$$r.getField(2), $$r.getField(3)]
+                                                                                                    assign [$$269, $$278] <- [$$r.getField(2), $$r.getField(3)]
                                                                                                     -- ASSIGN  |PARTITIONED|
                                                                                                       exchange
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                        unnest-map [$$244, $$r] <- index-search("Reports", 0, "Default", "channels", "Reports", false, false, 1, $$284, 1, $$284, true, true, true)
+                                                                                                        unnest-map [$$260, $$r] <- index-search("Reports", 0, "Default", "channels", "Reports", false, false, 1, $$300, 1, $$300, true, true, true)
                                                                                                         -- BTREE_SEARCH  |PARTITIONED|
                                                                                                           exchange
                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                            order (ASC, $$284)
-                                                                                                            -- STABLE_SORT [$$284(ASC)]  |PARTITIONED|
+                                                                                                            order (ASC, $$300)
+                                                                                                            -- STABLE_SORT [$$300(ASC)]  |PARTITIONED|
                                                                                                               exchange
                                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                project ([$$284])
+                                                                                                                project ([$$300])
                                                                                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                                                                                   exchange
                                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                    unnest-map [$$283, $$284] <- index-search("report_time", 0, "Default", "channels", "Reports", false, false, 1, $$282, 0, false, true, false)
+                                                                                                                    unnest-map [$$299, $$300] <- index-search("report_time", 0, "Default", "channels", "Reports", false, false, 1, $$298, 0, false, true, false)
                                                                                                                     -- BTREE_SEARCH  |PARTITIONED|
                                                                                                                       exchange
                                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                        assign [$$282] <- [numeric-subtract(current-datetime(), day_time_duration: {PT10S })]
+                                                                                                                        assign [$$298] <- [numeric-subtract(current-datetime(), day_time_duration: {PT10S })]
                                                                                                                         -- ASSIGN  |PARTITIONED|
                                                                                                                           empty-tuple-source
                                                                                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                                           exchange
                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                            assign [$$275, $$254] <- [true, $$u.getField(0)]
+                                                                                            assign [$$291, $$270] <- [true, $$u.getField(0)]
                                                                                             -- ASSIGN  |PARTITIONED|
                                                                                               exchange
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                data-scan []<-[$$245, $$u] <- channels.UserLocations
+                                                                                                data-scan []<-[$$261, $$u] <- channels.UserLocations
                                                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                   exchange
                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                                     empty-tuple-source
                                                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                             exchange
-                                            -- HASH_PARTITION_EXCHANGE [$$247]  |PARTITIONED|
-                                              assign [$$278] <- [true]
+                                            -- HASH_PARTITION_EXCHANGE [$$263]  |PARTITIONED|
+                                              assign [$$294] <- [true]
                                               -- ASSIGN  |PARTITIONED|
-                                                project ([$$248, $$247, $$263])
+                                                project ([$$264, $$263, $$279])
                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                   exchange
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    join (and(eq($$258, $$249), eq($$260, $$250)))
-                                                    -- HYBRID_HASH_JOIN [$$258, $$260][$$249, $$250]  |PARTITIONED|
+                                                    join (and(eq($$274, $$265), eq($$276, $$266)))
+                                                    -- HYBRID_HASH_JOIN [$$274, $$276][$$265, $$266]  |PARTITIONED|
                                                       exchange
-                                                      -- HASH_PARTITION_EXCHANGE [$$258, $$260]  |PARTITIONED|
-                                                        assign [$$260, $$258] <- [$$bs.getField("BrokerName"), $$bs.getField("DataverseName")] project: [$$248, $$247, $$258, $$260]
+                                                      -- HASH_PARTITION_EXCHANGE [$$274, $$276]  |PARTITIONED|
+                                                        assign [$$276, $$274] <- [$$bs.getField("BrokerName"), $$bs.getField("DataverseName")] project: [$$264, $$263, $$274, $$276]
                                                         -- ASSIGN  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            data-scan []<-[$$247, $$248, $$bs] <- channels.EmergenciesNearMeChannelBrokerSubscriptions
+                                                            data-scan []<-[$$263, $$264, $$bs] <- channels.EmergenciesNearMeChannelBrokerSubscriptions
                                                             -- DATASOURCE_SCAN  |PARTITIONED|
                                                               exchange
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -234,11 +234,11 @@ distribute result [$$237]
                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        assign [$$263] <- [$$b.getField("BrokerEndPoint")] project: [$$263, $$249, $$250]
+                                                        assign [$$279] <- [$$b.getField("BrokerEndPoint")] project: [$$279, $$265, $$266]
                                                         -- ASSIGN  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            data-scan []<-[$$249, $$250, $$b] <- channels.Broker
+                                                            data-scan []<-[$$265, $$266, $$b] <- channels.Broker
                                                             -- DATASOURCE_SCAN  |PARTITIONED|
                                                               exchange
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-3682-field-access-in-join.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-3682-field-access-in-join.plan
index d1a7b0e8d9..6c942aec07 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-3682-field-access-in-join.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-3682-field-access-in-join.plan
@@ -1,138 +1,138 @@
-distribute result [$$462]
+distribute result [$$485]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$462] <- [to-object-var-str($$609)] project: [$$462]
+    assign [$$485] <- [to-object-var-str($$632)] project: [$$485]
     -- ASSIGN  |PARTITIONED|
-      project ([$$609])
+      project ([$$632])
       -- STREAM_PROJECT  |PARTITIONED|
         exchange
-        -- SORT_MERGE_EXCHANGE [$$544(ASC), $$545(ASC), $$546(ASC), $$547(ASC) ]  |PARTITIONED|
-          order (ASC, $$544) (ASC, $$545) (ASC, $$546) (ASC, $$547)
-          -- STABLE_SORT [$$544(ASC), $$545(ASC), $$546(ASC), $$547(ASC)]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$567(ASC), $$568(ASC), $$569(ASC), $$570(ASC) ]  |PARTITIONED|
+          order (ASC, $$567) (ASC, $$568) (ASC, $$569) (ASC, $$570)
+          -- STABLE_SORT [$$567(ASC), $$568(ASC), $$569(ASC), $$570(ASC)]  |PARTITIONED|
             exchange
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              assign [$$544, $$545, $$546, $$547] <- [$$609.getField("join_key2"), $$609.getField("wsc"), $$609.getField("lcd"), $$609.getField("wsd")]
+              assign [$$567, $$568, $$569, $$570] <- [$$632.getField("join_key2"), $$632.getField("wsc"), $$632.getField("lcd"), $$632.getField("wsd")]
               -- ASSIGN  |PARTITIONED|
-                select (and(like($$471, "%"), not(is-missing($$471)))) project: [$$609]
+                select (and(like($$494, "%"), not(is-missing($$494)))) project: [$$632]
                 -- STREAM_SELECT  |PARTITIONED|
-                  assign [$$471] <- [$$609.getField("bco")]
+                  assign [$$494] <- [$$632.getField("bco")]
                   -- ASSIGN  |PARTITIONED|
-                    assign [$$609] <- [object-concat-strict(to-object-var-str($$343), {"lov_cKey": $$481, "wsd": $$620, "wsm": $$621, "wsc": $$528, "scKey": $$619, "wpdi": $$524, "bch": $$540, "omaa": $$541, "bco": uppercase(substring($$540, 0, position($$540, "_")))})] project: [$$609]
+                    assign [$$632] <- [object-concat-strict(to-object-var-str($$366), {"lov_cKey": $$504, "wsd": $$643, "wsm": $$644, "wsc": $$551, "scKey": $$642, "wpdi": $$547, "bch": $$563, "omaa": $$564, "bco": uppercase(substring($$563, 0, position($$563, "_")))})] project: [$$632]
                     -- ASSIGN  |PARTITIONED|
-                      select (and(like(object-concat-strict(to-object-var-str($$343), {"lov_cKey": $$481, "wsd": $$408.getField(3), "wsm": $$408.getField(4), "wsc": $$408.getField("wsc"), "scKey": $$619, "wpdi": $$524, "bch": $$540, "omaa": $$541, "bco": uppercase(substring($$540, 0, position($$540, "_")))}).getField("bch"), "%"), like(object-concat-strict(to-object-var-str($$343), {"lov_cKey": $$481, "wsd": $$408.getField(3), "wsm": $$408.getField(4), "wsc": $$408.getField("wsc"), "scKe [...]
+                      select (and(like(object-concat-strict(to-object-var-str($$366), {"lov_cKey": $$504, "wsd": $$431.getField(3), "wsm": $$431.getField(4), "wsc": $$431.getField("wsc"), "scKey": $$642, "wpdi": $$547, "bch": $$563, "omaa": $$564, "bco": uppercase(substring($$563, 0, position($$563, "_")))}).getField("bch"), "%"), like(object-concat-strict(to-object-var-str($$366), {"lov_cKey": $$504, "wsd": $$431.getField(3), "wsm": $$431.getField(4), "wsc": $$431.getField("wsc"), "scKe [...]
                       -- STREAM_SELECT  |PARTITIONED|
-                        project ([$$343, $$481, $$620, $$621, $$528, $$619, $$524, $$408, $$540, $$541])
+                        project ([$$366, $$504, $$643, $$644, $$551, $$642, $$547, $$431, $$563, $$564])
                         -- STREAM_PROJECT  |PARTITIONED|
                           exchange
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            join (eq($$491, $$524))
-                            -- HYBRID_HASH_JOIN [$$524][$$491]  |PARTITIONED|
+                            join (eq($$514, $$547))
+                            -- HYBRID_HASH_JOIN [$$547][$$514]  |PARTITIONED|
                               exchange
-                              -- HASH_PARTITION_EXCHANGE [$$524]  |PARTITIONED|
-                                project ([$$343, $$481, $$620, $$621, $$528, $$619, $$524, $$408])
+                              -- HASH_PARTITION_EXCHANGE [$$547]  |PARTITIONED|
+                                project ([$$366, $$504, $$643, $$644, $$551, $$642, $$547, $$431])
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   exchange
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    join (and(eq($$616, $$618), eq($$481, $$619)))
-                                    -- HYBRID_HASH_JOIN [$$616, $$481][$$618, $$619]  |PARTITIONED|
+                                    join (and(eq($$639, $$641), eq($$504, $$642)))
+                                    -- HYBRID_HASH_JOIN [$$639, $$504][$$641, $$642]  |PARTITIONED|
                                       exchange
-                                      -- HASH_PARTITION_EXCHANGE [$$616, $$481]  |PARTITIONED|
-                                        project ([$$343, $$481, $$616])
+                                      -- HASH_PARTITION_EXCHANGE [$$639, $$504]  |PARTITIONED|
+                                        project ([$$366, $$504, $$639])
                                         -- STREAM_PROJECT  |PARTITIONED|
                                           exchange
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            join (eq($$uniqueID, $$504))
-                                            -- HYBRID_HASH_JOIN [$$504][$$uniqueID]  |PARTITIONED|
+                                            join (eq($$uniqueID, $$527))
+                                            -- HYBRID_HASH_JOIN [$$527][$$uniqueID]  |PARTITIONED|
                                               exchange
-                                              -- HASH_PARTITION_EXCHANGE [$$504]  |PARTITIONED|
-                                                assign [$$343] <- [{"join_key2": $$616, "lov13_wsx1": substring($$480, 0, 7), "lcd": substring($$480, 0, 10), "lov13_name": $$482, "lov13_uunn": $$504, "lov13_t0_dd": $$617, "lov13_t0_ff": substring($$617, 0, 19)}] project: [$$343, $$616, $$504]
+                                              -- HASH_PARTITION_EXCHANGE [$$527]  |PARTITIONED|
+                                                assign [$$366] <- [{"join_key2": $$639, "lov13_wsx1": substring($$503, 0, 7), "lcd": substring($$503, 0, 10), "lov13_name": $$505, "lov13_uunn": $$527, "lov13_t0_dd": $$640, "lov13_t0_ff": substring($$640, 0, 19)}] project: [$$366, $$639, $$527]
                                                 -- ASSIGN  |PARTITIONED|
-                                                  assign [$$617] <- [to-string($$u_val.getField("t0"))] project: [$$480, $$504, $$482, $$616, $$617]
+                                                  assign [$$640] <- [to-string($$u_val.getField("t0"))] project: [$$503, $$527, $$505, $$639, $$640]
                                                   -- ASSIGN  |PARTITIONED|
-                                                    select (not(is-null($$616)))
+                                                    select (not(is-null($$639)))
                                                     -- STREAM_SELECT  |PARTITIONED|
-                                                      assign [$$616] <- [substring(if-missing-or-null(if-missing-or-null($$476.getField("someId1"), $$476.getField("someId2")), $$476.getField("someId3")), 0, 38)] project: [$$480, $$504, $$482, $$u_val, $$616]
+                                                      assign [$$639] <- [substring(if-missing-or-null(if-missing-or-null($$499.getField("someId1"), $$499.getField("someId2")), $$499.getField("someId3")), 0, 38)] project: [$$503, $$527, $$505, $$u_val, $$639]
                                                       -- ASSIGN  |PARTITIONED|
-                                                        assign [$$476] <- [$$u_val.getField("marop")]
+                                                        assign [$$499] <- [$$u_val.getField("marop")]
                                                         -- ASSIGN  |PARTITIONED|
-                                                          unnest $$u_val <- scan-collection($$310) project: [$$480, $$504, $$482, $$u_val]
+                                                          unnest $$u_val <- scan-collection($$333) project: [$$503, $$527, $$505, $$u_val]
                                                           -- UNNEST  |PARTITIONED|
-                                                            project ([$$480, $$504, $$482, $$310])
+                                                            project ([$$503, $$527, $$505, $$333])
                                                             -- STREAM_PROJECT  |PARTITIONED|
                                                               subplan {
-                                                                        aggregate [$$310] <- [listify($$309)]
+                                                                        aggregate [$$333] <- [listify($$332)]
                                                                         -- AGGREGATE  |LOCAL|
-                                                                          assign [$$309] <- [{"marop": $$483, "t0": $$503}]
+                                                                          assign [$$332] <- [{"marop": $$506, "t0": $$526}]
                                                                           -- ASSIGN  |LOCAL|
-                                                                            select (and(eq($$502, "iap"), not(is-unknown($$483)))) project: [$$503, $$483]
+                                                                            select (and(eq($$525, "iap"), not(is-unknown($$506)))) project: [$$526, $$506]
                                                                             -- STREAM_SELECT  |LOCAL|
-                                                                              assign [$$503, $$483, $$502] <- [$$item2.getField("t0"), $$item2.getField("marop"), $$item2.getField("ua")] project: [$$503, $$483, $$502]
+                                                                              assign [$$526, $$506, $$525] <- [$$item2.getField("t0"), $$item2.getField("marop"), $$item2.getField("ua")] project: [$$526, $$506, $$525]
                                                                               -- ASSIGN  |LOCAL|
-                                                                                unnest $$item2 <- scan-collection($$501) project: [$$item2]
+                                                                                unnest $$item2 <- scan-collection($$524) project: [$$item2]
                                                                                 -- UNNEST  |LOCAL|
-                                                                                  project ([$$501])
+                                                                                  project ([$$524])
                                                                                   -- STREAM_PROJECT  |LOCAL|
                                                                                     nested tuple source
                                                                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                                      }
                                                               -- SUBPLAN  |PARTITIONED|
-                                                                select (not(or(eq($$482, "p1"), eq($$482, "p2"), eq($$482, "p3"))))
+                                                                select (not(or(eq($$505, "p1"), eq($$505, "p2"), eq($$505, "p3"))))
                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                  project ([$$480, $$504, $$501, $$482])
+                                                                  project ([$$503, $$527, $$524, $$505])
                                                                   -- STREAM_PROJECT  |PARTITIONED|
                                                                     exchange
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      join (eq($$485, $$295))
-                                                                      -- HYBRID_HASH_JOIN [$$295][$$485]  |PARTITIONED|
+                                                                      join (eq($$508, $$318))
+                                                                      -- HYBRID_HASH_JOIN [$$318][$$508]  |PARTITIONED|
                                                                         exchange
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          assign [$$295] <- [get-item(split($$482, " "), 0)]
+                                                                          assign [$$318] <- [get-item(split($$505, " "), 0)]
                                                                           -- ASSIGN  |PARTITIONED|
-                                                                            assign [$$501, $$482] <- [$$item.getField("value"), $$item.getField("name")] project: [$$480, $$504, $$501, $$482]
+                                                                            assign [$$524, $$505] <- [$$item.getField("value"), $$item.getField("name")] project: [$$503, $$527, $$524, $$505]
                                                                             -- ASSIGN  |PARTITIONED|
-                                                                              unnest $$item <- scan-collection(object-pairs($$492)) project: [$$480, $$504, $$item]
+                                                                              unnest $$item <- scan-collection(object-pairs($$515)) project: [$$503, $$527, $$item]
                                                                               -- UNNEST  |PARTITIONED|
-                                                                                select ($$282) project: [$$480, $$504, $$492]
+                                                                                select ($$305) project: [$$515, $$503, $$527]
                                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                                  project ([$$282, $$480, $$504, $$492])
+                                                                                  project ([$$305, $$515, $$503, $$527])
                                                                                   -- STREAM_PROJECT  |PARTITIONED|
                                                                                     exchange
                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                      group by ([$$566 := $$472]) decor ([$$480; $$504; $$492]) {
-                                                                                                aggregate [$$282] <- [non-empty-stream()]
+                                                                                      group by ([$$589 := $$495]) decor ([$$515; $$503; $$527]) {
+                                                                                                aggregate [$$305] <- [non-empty-stream()]
                                                                                                 -- AGGREGATE  |LOCAL|
-                                                                                                  select (not(is-missing($$565)))
+                                                                                                  select (not(is-missing($$588)))
                                                                                                   -- STREAM_SELECT  |LOCAL|
-                                                                                                    project ([$$565])
+                                                                                                    project ([$$588])
                                                                                                     -- STREAM_PROJECT  |LOCAL|
                                                                                                       nested tuple source
                                                                                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                                                              }
-                                                                                      -- PRE_CLUSTERED_GROUP_BY[$$472]  |PARTITIONED|
+                                                                                      -- PRE_CLUSTERED_GROUP_BY[$$495]  |PARTITIONED|
                                                                                         exchange
                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                          order (ASC, $$472)
-                                                                                          -- STABLE_SORT [$$472(ASC)]  |PARTITIONED|
+                                                                                          order (ASC, $$495)
+                                                                                          -- STABLE_SORT [$$495(ASC)]  |PARTITIONED|
                                                                                             exchange
                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                              project ([$$504, $$480, $$492, $$565, $$472])
+                                                                                              project ([$$527, $$503, $$515, $$588, $$495])
                                                                                               -- STREAM_PROJECT  |PARTITIONED|
                                                                                                 exchange
                                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                  left outer join (eq($$472, $$564))
-                                                                                                  -- HYBRID_HASH_JOIN [$$472][$$564]  |PARTITIONED|
+                                                                                                  left outer join (eq($$495, $$587))
+                                                                                                  -- HYBRID_HASH_JOIN [$$495][$$587]  |PARTITIONED|
                                                                                                     exchange
                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                      select (and(eq($$b.getField("t"), "lovStat"), not(and(eq(len($$614), 1), eq(get-item($$614, 0), "some_str"))))) project: [$$504, $$480, $$492, $$472]
+                                                                                                      select (and(eq($$b.getField("t"), "lovStat"), not(and(eq(len($$637), 1), eq(get-item($$637, 0), "some_str"))))) project: [$$527, $$503, $$515, $$495]
                                                                                                       -- STREAM_SELECT  |PARTITIONED|
-                                                                                                        assign [$$614] <- [object-names($$492)]
+                                                                                                        assign [$$637] <- [object-names($$515)]
                                                                                                         -- ASSIGN  |PARTITIONED|
-                                                                                                          assign [$$504, $$480, $$492] <- [$$b.getField("uunn"), $$b.getField("qwer"), $$b.getField("ihsaa")]
+                                                                                                          assign [$$527, $$503, $$515] <- [$$b.getField("uunn"), $$b.getField("qwer"), $$b.getField("ihsaa")]
                                                                                                           -- ASSIGN  |PARTITIONED|
                                                                                                             exchange
                                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                              data-scan []<-[$$472, $$b] <- test.col2
+                                                                                                              data-scan []<-[$$495, $$b] <- test.col2
                                                                                                               -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                                 exchange
                                                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -140,48 +140,48 @@ distribute result [$$462]
                                                                                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                                                     exchange
                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                      assign [$$565] <- [true]
+                                                                                                      assign [$$588] <- [true]
                                                                                                       -- ASSIGN  |PARTITIONED|
-                                                                                                        project ([$$564])
+                                                                                                        project ([$$587])
                                                                                                         -- STREAM_PROJECT  |PARTITIONED|
                                                                                                           exchange
                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                            join (eq($$484, $$271))
-                                                                                                            -- HYBRID_HASH_JOIN [$$271][$$484]  |PARTITIONED|
+                                                                                                            join (eq($$507, $$294))
+                                                                                                            -- HYBRID_HASH_JOIN [$$294][$$507]  |PARTITIONED|
                                                                                                               exchange
                                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                select ($$280) project: [$$564, $$271]
+                                                                                                                select ($$303) project: [$$587, $$294]
                                                                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                                                                  project ([$$564, $$271, $$280])
+                                                                                                                  project ([$$587, $$294, $$303])
                                                                                                                   -- STREAM_PROJECT  |PARTITIONED|
                                                                                                                     subplan {
-                                                                                                                              aggregate [$$280] <- [non-empty-stream()]
+                                                                                                                              aggregate [$$303] <- [non-empty-stream()]
                                                                                                                               -- AGGREGATE  |LOCAL|
-                                                                                                                                select (and(eq($$499, "iap"), not(is-unknown($$498))))
+                                                                                                                                select (and(eq($$522, "iap"), not(is-unknown($$521))))
                                                                                                                                 -- STREAM_SELECT  |LOCAL|
-                                                                                                                                  assign [$$499, $$498] <- [$$item2.getField("ua"), $$item2.getField("marop")] project: [$$499, $$498]
+                                                                                                                                  assign [$$522, $$521] <- [$$item2.getField("ua"), $$item2.getField("marop")] project: [$$522, $$521]
                                                                                                                                   -- ASSIGN  |LOCAL|
-                                                                                                                                    unnest $$item2 <- scan-collection($$497) project: [$$item2]
+                                                                                                                                    unnest $$item2 <- scan-collection($$520) project: [$$item2]
                                                                                                                                     -- UNNEST  |LOCAL|
-                                                                                                                                      project ([$$497])
+                                                                                                                                      project ([$$520])
                                                                                                                                       -- STREAM_PROJECT  |LOCAL|
                                                                                                                                         nested tuple source
                                                                                                                                         -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                                                                                            }
                                                                                                                     -- SUBPLAN  |PARTITIONED|
-                                                                                                                      assign [$$271, $$497] <- [get-item(split($$item.getField("name"), " "), 0), $$item.getField("value")] project: [$$564, $$271, $$497]
+                                                                                                                      assign [$$294, $$520] <- [get-item(split($$item.getField("name"), " "), 0), $$item.getField("value")] project: [$$587, $$294, $$520]
                                                                                                                       -- ASSIGN  |PARTITIONED|
-                                                                                                                        unnest $$item <- scan-collection(object-pairs($$560)) project: [$$564, $$item]
+                                                                                                                        unnest $$item <- scan-collection(object-pairs($$583)) project: [$$587, $$item]
                                                                                                                         -- UNNEST  |PARTITIONED|
-                                                                                                                          select (and(not(and(eq(len($$615), 1), eq(get-item($$615, 0), "some_str"))), eq($$561.getField("t"), "lovStat"))) project: [$$564, $$560]
+                                                                                                                          select (and(not(and(eq(len($$638), 1), eq(get-item($$638, 0), "some_str"))), eq($$584.getField("t"), "lovStat"))) project: [$$587, $$583]
                                                                                                                           -- STREAM_SELECT  |PARTITIONED|
-                                                                                                                            assign [$$615] <- [object-names($$560)]
+                                                                                                                            assign [$$638] <- [object-names($$583)]
                                                                                                                             -- ASSIGN  |PARTITIONED|
-                                                                                                                              assign [$$560] <- [$$561.getField("ihsaa")]
+                                                                                                                              assign [$$583] <- [$$584.getField("ihsaa")]
                                                                                                                               -- ASSIGN  |PARTITIONED|
                                                                                                                                 exchange
                                                                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                  data-scan []<-[$$564, $$561] <- test.col2
+                                                                                                                                  data-scan []<-[$$587, $$584] <- test.col2
                                                                                                                                   -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                                                     exchange
                                                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -189,25 +189,25 @@ distribute result [$$462]
                                                                                                                                       -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                                                               exchange
                                                                                                               -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                                                                unnest $$484 <- scan-collection(array: [ "X", "Y" ])
+                                                                                                                unnest $$507 <- scan-collection(array: [ "X", "Y" ])
                                                                                                                 -- UNNEST  |UNPARTITIONED|
                                                                                                                   empty-tuple-source
                                                                                                                   -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
                                                                         exchange
                                                                         -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                          unnest $$485 <- scan-collection(array: [ "X", "Y" ])
+                                                                          unnest $$508 <- scan-collection(array: [ "X", "Y" ])
                                                                           -- UNNEST  |UNPARTITIONED|
                                                                             empty-tuple-source
                                                                             -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
                                               exchange
                                               -- HASH_PARTITION_EXCHANGE [$$uniqueID]  |PARTITIONED|
-                                                unnest $$uniqueID <- scan-collection($$520) project: [$$481, $$uniqueID]
+                                                unnest $$uniqueID <- scan-collection($$543) project: [$$504, $$uniqueID]
                                                 -- UNNEST  |PARTITIONED|
-                                                  assign [$$520] <- [array-star($$p.getField("members")).getField("uniqueID")] project: [$$481, $$520]
+                                                  assign [$$543] <- [array-star($$p.getField("members")).getField("uniqueID")] project: [$$504, $$543]
                                                   -- ASSIGN  |PARTITIONED|
-                                                    select (and(eq($$p.getField("r"), "uuu"), eq($$p.getField("t"), "ccc"), not(is-missing($$481))))
+                                                    select (and(eq($$p.getField("r"), "uuu"), eq($$p.getField("t"), "ccc"), not(is-missing($$504))))
                                                     -- STREAM_SELECT  |PARTITIONED|
-                                                      assign [$$481] <- [$$p.getField("cKey")]
+                                                      assign [$$504] <- [$$p.getField("cKey")]
                                                       -- ASSIGN  |PARTITIONED|
                                                         assign [$$p] <- [$$p2] project: [$$p]
                                                         -- ASSIGN  |PARTITIONED|
@@ -221,46 +221,46 @@ distribute result [$$462]
                                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                                   exchange
                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                    data-scan []<-[$$474, $$p2] <- test.col1
+                                                                    data-scan []<-[$$497, $$p2] <- test.col1
                                                                     -- DATASOURCE_SCAN  |PARTITIONED|
                                                                       exchange
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                         empty-tuple-source
                                                                         -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                       exchange
-                                      -- HASH_PARTITION_EXCHANGE [$$618, $$619]  |PARTITIONED|
-                                        assign [$$408] <- [{"join_key1": $$618, "wpdi": $$524, "wsc": $$528, "scKey": $$619, "wwlps": $$401, "wsd": $$620, "wsm": $$621}] project: [$$620, $$621, $$528, $$619, $$524, $$408, $$618]
+                                      -- HASH_PARTITION_EXCHANGE [$$641, $$642]  |PARTITIONED|
+                                        assign [$$431] <- [{"join_key1": $$641, "wpdi": $$547, "wsc": $$551, "scKey": $$642, "wwlps": $$424, "wsd": $$643, "wsm": $$644}] project: [$$643, $$644, $$551, $$642, $$547, $$431, $$641]
                                         -- ASSIGN  |PARTITIONED|
-                                          assign [$$621, $$620, $$619, $$618] <- [substring($$531, 0, 7), substring($$531, 0, 10), uppercase(substring($$528, 0, position($$528, "_"))), substring($$526, 0, 38)] project: [$$528, $$524, $$401, $$621, $$620, $$619, $$618]
+                                          assign [$$644, $$643, $$642, $$641] <- [substring($$554, 0, 7), substring($$554, 0, 10), uppercase(substring($$551, 0, position($$551, "_"))), substring($$549, 0, 38)] project: [$$551, $$547, $$424, $$644, $$643, $$642, $$641]
                                           -- ASSIGN  |PARTITIONED|
-                                            project ([$$528, $$524, $$531, $$526, $$401])
+                                            project ([$$551, $$547, $$554, $$549, $$424])
                                             -- STREAM_PROJECT  |PARTITIONED|
                                               subplan {
-                                                        aggregate [$$401] <- [listify($$400)]
+                                                        aggregate [$$424] <- [listify($$423)]
                                                         -- AGGREGATE  |LOCAL|
-                                                          assign [$$400] <- [$$item.getField("wkps")]
+                                                          assign [$$423] <- [$$item.getField("wkps")]
                                                           -- ASSIGN  |LOCAL|
-                                                            unnest $$item <- scan-collection($$525) project: [$$item]
+                                                            unnest $$item <- scan-collection($$548) project: [$$item]
                                                             -- UNNEST  |LOCAL|
-                                                              project ([$$525])
+                                                              project ([$$548])
                                                               -- STREAM_PROJECT  |LOCAL|
                                                                 nested tuple source
                                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                      }
                                               -- SUBPLAN  |PARTITIONED|
-                                                project ([$$528, $$524, $$531, $$526, $$525])
+                                                project ([$$551, $$547, $$554, $$549, $$548])
                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                   exchange
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    join (eq($$488, $$373))
-                                                    -- HYBRID_HASH_JOIN [$$373][$$488]  |PARTITIONED|
+                                                    join (eq($$511, $$396))
+                                                    -- HYBRID_HASH_JOIN [$$396][$$511]  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        select (and(eq($$p2.getField("t"), "ak1"), not(is-missing($$524)), not(is-missing($$556)))) project: [$$528, $$524, $$531, $$526, $$525, $$373]
+                                                        select (and(eq($$p2.getField("t"), "ak1"), not(is-missing($$547)), not(is-missing($$579)))) project: [$$551, $$547, $$554, $$549, $$548, $$396]
                                                         -- STREAM_SELECT  |PARTITIONED|
-                                                          assign [$$531, $$528, $$526, $$525, $$524] <- [$$556.getField("ssatt"), $$556.getField("stchk"), $$p2.getField("ed"), $$556.getField("intib"), $$556.getField("coaed")]
+                                                          assign [$$554, $$551, $$549, $$548, $$547] <- [$$579.getField("ssatt"), $$579.getField("stchk"), $$p2.getField("ed"), $$579.getField("intib"), $$579.getField("coaed")]
                                                           -- ASSIGN  |PARTITIONED|
-                                                            assign [$$373, $$556] <- [$$p2.getField("ha"), $$p2.getField("kat")]
+                                                            assign [$$396, $$579] <- [$$p2.getField("ha"), $$p2.getField("kat")]
                                                             -- ASSIGN  |PARTITIONED|
                                                               exchange
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -272,7 +272,7 @@ distribute result [$$462]
                                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                                       exchange
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        data-scan []<-[$$474, $$p2] <- test.col1
+                                                                        data-scan []<-[$$497, $$p2] <- test.col1
                                                                         -- DATASOURCE_SCAN  |PARTITIONED|
                                                                           exchange
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -280,17 +280,17 @@ distribute result [$$462]
                                                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                       exchange
                                                       -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                        unnest $$488 <- scan-collection(array: [ "l1", "l2" ])
+                                                        unnest $$511 <- scan-collection(array: [ "l1", "l2" ])
                                                         -- UNNEST  |UNPARTITIONED|
                                                           empty-tuple-source
                                                           -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
                               exchange
-                              -- HASH_PARTITION_EXCHANGE [$$491]  |PARTITIONED|
-                                assign [$$541, $$540] <- [$$470.getField("omaa"), $$470.getField("qaz")] project: [$$540, $$541, $$491]
+                              -- HASH_PARTITION_EXCHANGE [$$514]  |PARTITIONED|
+                                assign [$$564, $$563] <- [$$493.getField("omaa"), $$493.getField("qaz")] project: [$$563, $$564, $$514]
                                 -- ASSIGN  |PARTITIONED|
-                                  select (not(is-missing($$470)))
+                                  select (not(is-missing($$493)))
                                   -- STREAM_SELECT  |PARTITIONED|
-                                    assign [$$491, $$470] <- [$$sbr.getField("ed"), $$sbr.getField("tohac")] project: [$$491, $$470]
+                                    assign [$$514, $$493] <- [$$sbr.getField("ed"), $$sbr.getField("tohac")] project: [$$514, $$493]
                                     -- ASSIGN  |PARTITIONED|
                                       assign [$$sbr] <- [$$p2] project: [$$sbr]
                                       -- ASSIGN  |PARTITIONED|
@@ -304,7 +304,7 @@ distribute result [$$462]
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 exchange
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  data-scan []<-[$$474, $$p2] <- test.col1
+                                                  data-scan []<-[$$497, $$p2] <- test.col1
                                                   -- DATASOURCE_SCAN  |PARTITIONED|
                                                     exchange
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q16.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q16.plan
index cf8178dc84..8a2ed67a55 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q16.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q16.plan
@@ -1,96 +1,96 @@
-distribute result [$$128]
+distribute result [$$149]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$128] <- [{"i_name": $$i_name, "brand": $#1, "i_price": $$i_price, "supplier_cnt": $$139}] project: [$$128]
+    assign [$$149] <- [{"i_name": $$i_name, "brand": $#1, "i_price": $$i_price, "supplier_cnt": $$160}] project: [$$149]
     -- ASSIGN  |PARTITIONED|
       exchange
-      -- SORT_MERGE_EXCHANGE [$$139(DESC) ]  |PARTITIONED|
-        order (DESC, $$139)
-        -- STABLE_SORT [$$139(DESC)]  |PARTITIONED|
+      -- SORT_MERGE_EXCHANGE [$$160(DESC) ]  |PARTITIONED|
+        order (DESC, $$160)
+        -- STABLE_SORT [$$160(DESC)]  |PARTITIONED|
           exchange
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            group by ([$$i_name := $$129; $#1 := $$130; $$i_price := $$131]) decor ([]) {
-                      aggregate [$$139] <- [agg-sql-count($$150)]
+            group by ([$$i_name := $$150; $#1 := $$151; $$i_price := $$152]) decor ([]) {
+                      aggregate [$$160] <- [agg-sql-count($$171)]
                       -- AGGREGATE  |LOCAL|
-                        distinct ([$$150])
+                        distinct ([$$171])
                         -- MICRO_PRE_SORTED_DISTINCT_BY  |LOCAL|
-                          order (ASC, $$150)
-                          -- MICRO_STABLE_SORT [$$150(ASC)]  |LOCAL|
-                            assign [$$150] <- [numeric-mod(numeric-multiply($$143, $$144), 10000)] project: [$$150]
+                          order (ASC, $$171)
+                          -- MICRO_STABLE_SORT [$$171(ASC)]  |LOCAL|
+                            assign [$$171] <- [numeric-mod(numeric-multiply($$164, $$165), 10000)] project: [$$171]
                             -- ASSIGN  |LOCAL|
-                              project ([$$143, $$144])
+                              project ([$$164, $$165])
                               -- STREAM_PROJECT  |LOCAL|
                                 nested tuple source
                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                    }
-            -- PRE_CLUSTERED_GROUP_BY[$$129, $$130, $$131]  |PARTITIONED|
+            -- PRE_CLUSTERED_GROUP_BY[$$150, $$151, $$152]  |PARTITIONED|
               exchange
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                order (ASC, $$129) (ASC, $$130) (ASC, $$131)
-                -- STABLE_SORT [$$129(ASC), $$130(ASC), $$131(ASC)]  |PARTITIONED|
+                order (ASC, $$150) (ASC, $$151) (ASC, $$152)
+                -- STABLE_SORT [$$150(ASC), $$151(ASC), $$152(ASC)]  |PARTITIONED|
                   exchange
-                  -- HASH_PARTITION_EXCHANGE [$$129, $$130, $$131]  |PARTITIONED|
-                    assign [$$130] <- [substring1($$132, 1, 3)] project: [$$143, $$144, $$129, $$130, $$131]
+                  -- HASH_PARTITION_EXCHANGE [$$150, $$151, $$152]  |PARTITIONED|
+                    assign [$$151] <- [substring1($$153, 1, 3)] project: [$$164, $$165, $$150, $$151, $$152]
                     -- ASSIGN  |PARTITIONED|
-                      select ($$111) project: [$$129, $$131, $$132, $$144, $$143]
+                      select ($$132) project: [$$150, $$152, $$153, $$165, $$164]
                       -- STREAM_SELECT  |PARTITIONED|
-                        project ([$$111, $$129, $$131, $$132, $$144, $$143])
+                        project ([$$132, $$150, $$152, $$153, $$165, $$164])
                         -- STREAM_PROJECT  |PARTITIONED|
                           exchange
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            group by ([$$146 := $$133; $$147 := $$134]) decor ([$$129; $$131; $$132; $$144 := $$138; $$143 := $$141]) {
-                                      aggregate [$$111] <- [empty-stream()]
+                            group by ([$$167 := $$154; $$168 := $$155]) decor ([$$150; $$152; $$153; $$165 := $$159; $$164 := $$162]) {
+                                      aggregate [$$132] <- [empty-stream()]
                                       -- AGGREGATE  |LOCAL|
-                                        select (not(is-missing($$145)))
+                                        select (not(is-missing($$166)))
                                         -- STREAM_SELECT  |LOCAL|
-                                          project ([$$145])
+                                          project ([$$166])
                                           -- STREAM_PROJECT  |LOCAL|
                                             nested tuple source
                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
                                    }
-                            -- PRE_CLUSTERED_GROUP_BY[$$133, $$134]  |PARTITIONED|
+                            -- PRE_CLUSTERED_GROUP_BY[$$154, $$155]  |PARTITIONED|
                               exchange
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                order (ASC, $$133) (ASC, $$134)
-                                -- STABLE_SORT [$$133(ASC), $$134(ASC)]  |PARTITIONED|
+                                order (ASC, $$154) (ASC, $$155)
+                                -- STABLE_SORT [$$154(ASC), $$155(ASC)]  |PARTITIONED|
                                   exchange
-                                  -- HASH_PARTITION_EXCHANGE [$$133, $$134]  |PARTITIONED|
-                                    project ([$$129, $$131, $$132, $$145, $$133, $$134, $$138, $$141])
+                                  -- HASH_PARTITION_EXCHANGE [$$154, $$155]  |PARTITIONED|
+                                    project ([$$150, $$152, $$153, $$166, $$154, $$155, $$159, $$162])
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       exchange
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        left outer join (not(if-missing-or-null(neq(numeric-mod(numeric-multiply($$141, $$138), 10000), $$105), false)))
+                                        left outer join (not(if-missing-or-null(neq(numeric-mod(numeric-multiply($$162, $$159), 10000), $$126), false)))
                                         -- NESTED_LOOP  |PARTITIONED|
                                           exchange
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            project ([$$129, $$131, $$132, $$133, $$134, $$138, $$141])
+                                            project ([$$150, $$152, $$153, $$154, $$155, $$159, $$162])
                                             -- STREAM_PROJECT  |PARTITIONED|
                                               exchange
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                join (eq($$137, $$138))
-                                                -- HYBRID_HASH_JOIN [$$138][$$137]  |PARTITIONED|
+                                                join (eq($$158, $$159))
+                                                -- HYBRID_HASH_JOIN [$$159][$$158]  |PARTITIONED|
                                                   exchange
-                                                  -- HASH_PARTITION_EXCHANGE [$$138]  |PARTITIONED|
-                                                    assign [$$138, $$141] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$133, $$138, $$141]
+                                                  -- HASH_PARTITION_EXCHANGE [$$159]  |PARTITIONED|
+                                                    assign [$$159, $$162] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$154, $$159, $$162]
                                                     -- ASSIGN  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        data-scan []<-[$$133, $$s] <- test.stock
+                                                        data-scan []<-[$$154, $$s] <- test.stock
                                                         -- DATASOURCE_SCAN  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                             empty-tuple-source
                                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                   exchange
-                                                  -- HASH_PARTITION_EXCHANGE [$$137]  |PARTITIONED|
-                                                    select (not(like($$132, "zz%")))
+                                                  -- HASH_PARTITION_EXCHANGE [$$158]  |PARTITIONED|
+                                                    select (not(and(ge($$153, "zz"), lt($$153, "z{"))))
                                                     -- STREAM_SELECT  |PARTITIONED|
-                                                      assign [$$131, $$129, $$132, $$137] <- [$$i.getField("i_price"), $$i.getField("i_name"), $$i.getField("i_data"), $$i.getField("i_id")] project: [$$134, $$131, $$129, $$132, $$137]
+                                                      assign [$$152, $$150, $$153, $$158] <- [$$i.getField("i_price"), $$i.getField("i_name"), $$i.getField("i_data"), $$i.getField("i_id")] project: [$$155, $$152, $$150, $$153, $$158]
                                                       -- ASSIGN  |PARTITIONED|
                                                         exchange
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          data-scan []<-[$$134, $$i] <- test.item
+                                                          data-scan []<-[$$155, $$i] <- test.item
                                                           -- DATASOURCE_SCAN  |PARTITIONED|
                                                             exchange
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -98,17 +98,17 @@ distribute result [$$128]
                                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                           exchange
                                           -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                            assign [$$145] <- [true]
+                                            assign [$$166] <- [true]
                                             -- ASSIGN  |PARTITIONED|
-                                              select (like($$su.getField("su_comment"), "%Customer%Complaints%")) project: [$$105]
+                                              select (like($$su.getField("su_comment"), "%Customer%Complaints%")) project: [$$126]
                                               -- STREAM_SELECT  |PARTITIONED|
-                                                assign [$$105] <- [$$su.getField("su_suppkey")]
+                                                assign [$$126] <- [$$su.getField("su_suppkey")]
                                                 -- ASSIGN  |PARTITIONED|
                                                   project ([$$su])
                                                   -- STREAM_PROJECT  |PARTITIONED|
                                                     exchange
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      data-scan []<-[$$135, $$su] <- test.supplier
+                                                      data-scan []<-[$$156, $$su] <- test.supplier
                                                       -- DATASOURCE_SCAN  |PARTITIONED|
                                                         exchange
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q20.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q20.plan
index a0e0b52fa2..b1df10baf2 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q20.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q20.plan
@@ -1,190 +1,190 @@
-distribute result [$$180]
+distribute result [$$193]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$180] <- [{"su_name": $$201, "su_address": $$203}] project: [$$180]
+    assign [$$193] <- [{"su_name": $$214, "su_address": $$216}] project: [$$193]
     -- ASSIGN  |PARTITIONED|
       exchange
-      -- SORT_MERGE_EXCHANGE [$$201(ASC) ]  |PARTITIONED|
-        order (ASC, $$201)
-        -- STABLE_SORT [$$201(ASC)]  |PARTITIONED|
+      -- SORT_MERGE_EXCHANGE [$$214(ASC) ]  |PARTITIONED|
+        order (ASC, $$214)
+        -- STABLE_SORT [$$214(ASC)]  |PARTITIONED|
           exchange
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            project ([$$201, $$203])
+            project ([$$214, $$216])
             -- STREAM_PROJECT  |PARTITIONED|
               exchange
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                join (eq($$196, $$197))
-                -- HYBRID_HASH_JOIN [$$196][$$197]  |PARTITIONED|
+                join (eq($$209, $$210))
+                -- HYBRID_HASH_JOIN [$$209][$$210]  |PARTITIONED|
                   exchange
-                  -- HASH_PARTITION_EXCHANGE [$$196]  |PARTITIONED|
-                    select ($$170) project: [$$201, $$203, $$196]
+                  -- HASH_PARTITION_EXCHANGE [$$209]  |PARTITIONED|
+                    select ($$183) project: [$$214, $$216, $$209]
                     -- STREAM_SELECT  |PARTITIONED|
-                      project ([$$170, $$196, $$201, $$203])
+                      project ([$$183, $$209, $$214, $$216])
                       -- STREAM_PROJECT  |PARTITIONED|
                         exchange
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          group by ([$$208 := $$187]) decor ([$$196; $$201; $$203]) {
-                                    aggregate [$$170] <- [non-empty-stream()]
+                          group by ([$$221 := $$200]) decor ([$$209; $$214; $$216]) {
+                                    aggregate [$$183] <- [non-empty-stream()]
                                     -- AGGREGATE  |LOCAL|
-                                      select (not(is-missing($$207)))
+                                      select (not(is-missing($$220)))
                                       -- STREAM_SELECT  |LOCAL|
-                                        project ([$$207])
+                                        project ([$$220])
                                         -- STREAM_PROJECT  |LOCAL|
                                           nested tuple source
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                  }
-                          -- PRE_CLUSTERED_GROUP_BY[$$187]  |PARTITIONED|
+                          -- PRE_CLUSTERED_GROUP_BY[$$200]  |PARTITIONED|
                             exchange
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              order (ASC, $$187)
-                              -- STABLE_SORT [$$187(ASC)]  |PARTITIONED|
+                              order (ASC, $$200)
+                              -- STABLE_SORT [$$200(ASC)]  |PARTITIONED|
                                 exchange
-                                -- HASH_PARTITION_EXCHANGE [$$187]  |PARTITIONED|
-                                  project ([$$201, $$203, $$196, $$207, $$187])
+                                -- HASH_PARTITION_EXCHANGE [$$200]  |PARTITIONED|
+                                  project ([$$214, $$216, $$209, $$220, $$200])
                                   -- STREAM_PROJECT  |PARTITIONED|
                                     exchange
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      left outer join (eq($$195, $$166))
-                                      -- HYBRID_HASH_JOIN [$$195][$$166]  |PARTITIONED|
+                                      left outer join (eq($$208, $$179))
+                                      -- HYBRID_HASH_JOIN [$$208][$$179]  |PARTITIONED|
                                         exchange
-                                        -- HASH_PARTITION_EXCHANGE [$$195]  |PARTITIONED|
-                                          assign [$$203, $$201, $$196, $$195] <- [$$su.getField("su_address"), $$su.getField("su_name"), $$su.getField("su_nationkey"), $$su.getField("su_suppkey")] project: [$$201, $$203, $$196, $$187, $$195]
+                                        -- HASH_PARTITION_EXCHANGE [$$208]  |PARTITIONED|
+                                          assign [$$216, $$214, $$209, $$208] <- [$$su.getField("su_address"), $$su.getField("su_name"), $$su.getField("su_nationkey"), $$su.getField("su_suppkey")] project: [$$214, $$216, $$209, $$200, $$208]
                                           -- ASSIGN  |PARTITIONED|
                                             exchange
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              data-scan []<-[$$187, $$su] <- test.supplier
+                                              data-scan []<-[$$200, $$su] <- test.supplier
                                               -- DATASOURCE_SCAN  |PARTITIONED|
                                                 exchange
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                   empty-tuple-source
                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                         exchange
-                                        -- HASH_PARTITION_EXCHANGE [$$166]  |PARTITIONED|
-                                          assign [$$207, $$166] <- [true, numeric-mod(numeric-multiply($$s_i_id, $$s_w_id), 10000)] project: [$$207, $$166]
+                                        -- HASH_PARTITION_EXCHANGE [$$179]  |PARTITIONED|
+                                          assign [$$220, $$179] <- [true, numeric-mod(numeric-multiply($$s_i_id, $$s_w_id), 10000)] project: [$$220, $$179]
                                           -- ASSIGN  |PARTITIONED|
-                                            select (gt(numeric-multiply(20, $$s_quantity), $$193)) project: [$$s_i_id, $$s_w_id]
+                                            select (gt(numeric-multiply(20, $$s_quantity), $$206)) project: [$$s_i_id, $$s_w_id]
                                             -- STREAM_SELECT  |PARTITIONED|
                                               exchange
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                group by ([$$s_i_id := $$210; $$s_w_id := $$211; $$s_quantity := $$212]) decor ([]) {
-                                                          aggregate [$$193] <- [agg-global-sql-sum($$209)]
+                                                group by ([$$s_i_id := $$223; $$s_w_id := $$224; $$s_quantity := $$225]) decor ([]) {
+                                                          aggregate [$$206] <- [agg-global-sql-sum($$222)]
                                                           -- AGGREGATE  |LOCAL|
                                                             nested tuple source
                                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                        }
-                                                -- SORT_GROUP_BY[$$210, $$211, $$212]  |PARTITIONED|
+                                                -- SORT_GROUP_BY[$$223, $$224, $$225]  |PARTITIONED|
                                                   exchange
-                                                  -- HASH_PARTITION_EXCHANGE [$$210, $$211, $$212]  |PARTITIONED|
-                                                    group by ([$$210 := $$194; $$211 := $$183; $$212 := $$184]) decor ([]) {
-                                                              aggregate [$$209] <- [agg-local-sql-sum($$162)]
+                                                  -- HASH_PARTITION_EXCHANGE [$$223, $$224, $$225]  |PARTITIONED|
+                                                    group by ([$$223 := $$207; $$224 := $$196; $$225 := $$197]) decor ([]) {
+                                                              aggregate [$$222] <- [agg-local-sql-sum($$175)]
                                                               -- AGGREGATE  |LOCAL|
                                                                 nested tuple source
                                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                            }
-                                                    -- SORT_GROUP_BY[$$194, $$183, $$184]  |PARTITIONED|
+                                                    -- SORT_GROUP_BY[$$207, $$196, $$197]  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        project ([$$162, $$194, $$183, $$184])
+                                                        project ([$$175, $$207, $$196, $$197])
                                                         -- STREAM_PROJECT  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            join (eq($$198, $$194))
-                                                            -- HYBRID_HASH_JOIN [$$194][$$198]  |PARTITIONED|
+                                                            join (eq($$211, $$207))
+                                                            -- HYBRID_HASH_JOIN [$$207][$$211]  |PARTITIONED|
                                                               exchange
-                                                              -- HASH_PARTITION_EXCHANGE [$$194]  |PARTITIONED|
-                                                                select ($$144) project: [$$194, $$183, $$184]
+                                                              -- HASH_PARTITION_EXCHANGE [$$207]  |PARTITIONED|
+                                                                select ($$157) project: [$$207, $$196, $$197]
                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                  project ([$$144, $$194, $$183, $$184])
+                                                                  project ([$$157, $$196, $$197, $$207])
                                                                   -- STREAM_PROJECT  |PARTITIONED|
                                                                     exchange
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      group by ([$$206 := $$189]) decor ([$$194; $$183; $$184]) {
-                                                                                aggregate [$$144] <- [non-empty-stream()]
+                                                                      group by ([$$219 := $$202]) decor ([$$196; $$197; $$207]) {
+                                                                                aggregate [$$157] <- [non-empty-stream()]
                                                                                 -- AGGREGATE  |LOCAL|
-                                                                                  select (not(is-missing($$205)))
+                                                                                  select (not(is-missing($$218)))
                                                                                   -- STREAM_SELECT  |LOCAL|
-                                                                                    project ([$$205])
+                                                                                    project ([$$218])
                                                                                     -- STREAM_PROJECT  |LOCAL|
                                                                                       nested tuple source
                                                                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                                              }
-                                                                      -- PRE_CLUSTERED_GROUP_BY[$$189]  |PARTITIONED|
+                                                                      -- PRE_CLUSTERED_GROUP_BY[$$202]  |PARTITIONED|
                                                                         exchange
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          order (ASC, $$189)
-                                                                          -- STABLE_SORT [$$189(ASC)]  |PARTITIONED|
+                                                                          order (ASC, $$202)
+                                                                          -- STABLE_SORT [$$202(ASC)]  |PARTITIONED|
                                                                             exchange
-                                                                            -- HASH_PARTITION_EXCHANGE [$$189]  |PARTITIONED|
-                                                                              project ([$$194, $$183, $$184, $$205, $$189])
+                                                                            -- HASH_PARTITION_EXCHANGE [$$202]  |PARTITIONED|
+                                                                              project ([$$207, $$196, $$197, $$218, $$202])
                                                                               -- STREAM_PROJECT  |PARTITIONED|
                                                                                 exchange
                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                  left outer join (eq($$194, $$140))
-                                                                                  -- HYBRID_HASH_JOIN [$$194][$$140]  |PARTITIONED|
+                                                                                  left outer join (eq($$207, $$153))
+                                                                                  -- HYBRID_HASH_JOIN [$$207][$$153]  |PARTITIONED|
                                                                                     exchange
-                                                                                    -- HASH_PARTITION_EXCHANGE [$$194]  |PARTITIONED|
-                                                                                      assign [$$184, $$183, $$194] <- [$$s.getField("s_quantity"), $$s.getField("s_w_id"), $$s.getField("s_i_id")] project: [$$194, $$183, $$184, $$189]
+                                                                                    -- HASH_PARTITION_EXCHANGE [$$207]  |PARTITIONED|
+                                                                                      assign [$$197, $$196, $$207] <- [$$s.getField("s_quantity"), $$s.getField("s_w_id"), $$s.getField("s_i_id")] project: [$$207, $$196, $$197, $$202]
                                                                                       -- ASSIGN  |PARTITIONED|
                                                                                         exchange
                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                          data-scan []<-[$$189, $$s] <- test.stock
+                                                                                          data-scan []<-[$$202, $$s] <- test.stock
                                                                                           -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                             exchange
                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                               empty-tuple-source
                                                                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                                     exchange
-                                                                                    -- HASH_PARTITION_EXCHANGE [$$140]  |PARTITIONED|
-                                                                                      assign [$$205] <- [true]
+                                                                                    -- HASH_PARTITION_EXCHANGE [$$153]  |PARTITIONED|
+                                                                                      assign [$$218] <- [true]
                                                                                       -- ASSIGN  |PARTITIONED|
-                                                                                        select (and(ge($$192, "co"), lt($$192, "cp"))) project: [$$140]
+                                                                                        select (and(ge($$205, "co"), lt($$205, "cp"))) project: [$$153]
                                                                                         -- STREAM_SELECT  |PARTITIONED|
-                                                                                          assign [$$140, $$192] <- [$$i.getField("i_id"), $$i.getField("i_data")] project: [$$140, $$192]
+                                                                                          assign [$$153, $$205] <- [$$i.getField("i_id"), $$i.getField("i_data")] project: [$$153, $$205]
                                                                                           -- ASSIGN  |PARTITIONED|
                                                                                             project ([$$i])
                                                                                             -- STREAM_PROJECT  |PARTITIONED|
                                                                                               exchange
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                data-scan []<-[$$191, $$i] <- test.item
+                                                                                                data-scan []<-[$$204, $$i] <- test.item
                                                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                   exchange
                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                                     empty-tuple-source
                                                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                               exchange
-                                                              -- HASH_PARTITION_EXCHANGE [$$198]  |PARTITIONED|
-                                                                select (and(ge($$185, "2016-01-01 12:00:00"), lt($$185, "2017-01-01 12:00:00"))) project: [$$162, $$198]
+                                                              -- HASH_PARTITION_EXCHANGE [$$211]  |PARTITIONED|
+                                                                select (and(ge($$198, "2016-01-01 12:00:00"), lt($$198, "2017-01-01 12:00:00"))) project: [$$175, $$211]
                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                  assign [$$162, $$198, $$185] <- [$$ol.getField("ol_quantity"), $$ol.getField("ol_i_id"), $$ol.getField("ol_delivery_d")] project: [$$162, $$198, $$185]
+                                                                  assign [$$175, $$211, $$198] <- [$$ol.getField("ol_quantity"), $$ol.getField("ol_i_id"), $$ol.getField("ol_delivery_d")] project: [$$175, $$211, $$198]
                                                                   -- ASSIGN  |PARTITIONED|
-                                                                    unnest $$ol <- scan-collection($$199) project: [$$ol]
+                                                                    unnest $$ol <- scan-collection($$212) project: [$$ol]
                                                                     -- UNNEST  |PARTITIONED|
-                                                                      assign [$$199] <- [$$o.getField("o_orderline")] project: [$$199]
+                                                                      assign [$$212] <- [$$o.getField("o_orderline")] project: [$$212]
                                                                       -- ASSIGN  |PARTITIONED|
                                                                         project ([$$o])
                                                                         -- STREAM_PROJECT  |PARTITIONED|
                                                                           exchange
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            data-scan []<-[$$190, $$o] <- test.orders
+                                                                            data-scan []<-[$$203, $$o] <- test.orders
                                                                             -- DATASOURCE_SCAN  |PARTITIONED|
                                                                               exchange
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                 empty-tuple-source
                                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                   exchange
-                  -- HASH_PARTITION_EXCHANGE [$$197]  |PARTITIONED|
-                    select (eq($$n.getField("n_name"), "Germany")) project: [$$197]
+                  -- HASH_PARTITION_EXCHANGE [$$210]  |PARTITIONED|
+                    select (eq($$n.getField("n_name"), "Germany")) project: [$$210]
                     -- STREAM_SELECT  |PARTITIONED|
-                      assign [$$197] <- [$$n.getField("n_nationkey")]
+                      assign [$$210] <- [$$n.getField("n_nationkey")]
                       -- ASSIGN  |PARTITIONED|
                         project ([$$n])
                         -- STREAM_PROJECT  |PARTITIONED|
                           exchange
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            data-scan []<-[$$188, $$n] <- test.nation
+                            data-scan []<-[$$201, $$n] <- test.nation
                             -- DATASOURCE_SCAN  |PARTITIONED|
                               exchange
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                 empty-tuple-source
-                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
+                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q22.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q22.plan
index 8420b45890..13b02c5e1e 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q22.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q22.plan
@@ -1,90 +1,90 @@
-distribute result [$$147]
+distribute result [$$158]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$147] <- [{"country": $#1, "numcust": $$156, "totacctbal": $$157}] project: [$$147]
+    assign [$$158] <- [{"country": $#1, "numcust": $$167, "totacctbal": $$168}] project: [$$158]
     -- ASSIGN  |PARTITIONED|
       exchange
       -- SORT_MERGE_EXCHANGE [$#1(ASC) ]  |PARTITIONED|
-        group by ([$#1 := $$180]) decor ([]) {
-                  aggregate [$$156, $$157] <- [agg-sql-sum($$178), agg-global-sql-sum($$179)]
+        group by ([$#1 := $$191]) decor ([]) {
+                  aggregate [$$167, $$168] <- [agg-sql-sum($$189), agg-global-sql-sum($$190)]
                   -- AGGREGATE  |LOCAL|
                     nested tuple source
                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                }
-        -- SORT_GROUP_BY[$$180]  |PARTITIONED|
+        -- SORT_GROUP_BY[$$191]  |PARTITIONED|
           exchange
-          -- HASH_PARTITION_EXCHANGE [$$180]  |PARTITIONED|
-            group by ([$$180 := $$148]) decor ([]) {
-                      aggregate [$$178, $$179] <- [agg-sql-count(1), agg-local-sql-sum($$158)]
+          -- HASH_PARTITION_EXCHANGE [$$191]  |PARTITIONED|
+            group by ([$$191 := $$159]) decor ([]) {
+                      aggregate [$$189, $$190] <- [agg-sql-count(1), agg-local-sql-sum($$169)]
                       -- AGGREGATE  |LOCAL|
                         nested tuple source
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
                    }
-            -- SORT_GROUP_BY[$$148]  |PARTITIONED|
+            -- SORT_GROUP_BY[$$159]  |PARTITIONED|
               exchange
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                assign [$$148] <- [substring1($$169, 1, 1)] project: [$$158, $$148]
+                assign [$$159] <- [substring1($$180, 1, 1)] project: [$$169, $$159]
                 -- ASSIGN  |PARTITIONED|
-                  select (not(neq($$155, 0))) project: [$$169, $$158]
+                  select (not(neq($$166, 0))) project: [$$169, $$180]
                   -- STREAM_SELECT  |PARTITIONED|
-                    project ([$$155, $$169, $$158])
+                    project ([$$166, $$169, $$180])
                     -- STREAM_PROJECT  |PARTITIONED|
                       exchange
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        group by ([$$174 := $$177]) decor ([$$169; $$158]) {
-                                  aggregate [$$155] <- [agg-sum($$176)]
+                        group by ([$$185 := $$188]) decor ([$$169; $$180]) {
+                                  aggregate [$$166] <- [agg-sum($$187)]
                                   -- AGGREGATE  |LOCAL|
                                     nested tuple source
                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                                }
-                        -- SORT_GROUP_BY[$$177]  |PARTITIONED|
+                        -- SORT_GROUP_BY[$$188]  |PARTITIONED|
                           exchange
-                          -- HASH_PARTITION_EXCHANGE [$$177]  |PARTITIONED|
-                            group by ([$$177 := $$172]) decor ([$$169; $$158]) {
-                                      aggregate [$$176] <- [agg-count(1)]
+                          -- HASH_PARTITION_EXCHANGE [$$188]  |PARTITIONED|
+                            group by ([$$188 := $$183]) decor ([$$169; $$180]) {
+                                      aggregate [$$187] <- [agg-count(1)]
                                       -- AGGREGATE  |LOCAL|
-                                        select (not(is-missing($$173)))
+                                        select (not(is-missing($$184)))
                                         -- STREAM_SELECT  |LOCAL|
-                                          project ([$$173])
+                                          project ([$$184])
                                           -- STREAM_PROJECT  |LOCAL|
                                             nested tuple source
                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
                                    }
-                            -- PRE_CLUSTERED_GROUP_BY[$$172]  |PARTITIONED|
+                            -- PRE_CLUSTERED_GROUP_BY[$$183]  |PARTITIONED|
                               exchange
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                order (ASC, $$172)
-                                -- STABLE_SORT [$$172(ASC)]  |PARTITIONED|
+                                order (ASC, $$183)
+                                -- STABLE_SORT [$$183(ASC)]  |PARTITIONED|
                                   exchange
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    project ([$$158, $$169, $$173, $$172])
+                                    project ([$$169, $$180, $$184, $$183])
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       exchange
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        left outer join (and(eq($$160, $$161), eq($$162, $$163), eq($$164, $$165)))
-                                        -- HYBRID_HASH_JOIN [$$161, $$163, $$165][$$160, $$162, $$164]  |PARTITIONED|
+                                        left outer join (and(eq($$171, $$172), eq($$173, $$174), eq($$175, $$176)))
+                                        -- HYBRID_HASH_JOIN [$$172, $$174, $$176][$$171, $$173, $$175]  |PARTITIONED|
                                           exchange
-                                          -- HASH_PARTITION_EXCHANGE [$$161, $$163, $$165]  |PARTITIONED|
-                                            running-aggregate [$$172] <- [create-query-uid()]
+                                          -- HASH_PARTITION_EXCHANGE [$$172, $$174, $$176]  |PARTITIONED|
+                                            running-aggregate [$$183] <- [create-query-uid()]
                                             -- RUNNING_AGGREGATE  |PARTITIONED|
-                                              project ([$$158, $$169, $$161, $$163, $$165])
+                                              project ([$$169, $$180, $$172, $$174, $$176])
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 exchange
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (gt($$158, $$159))
+                                                  join (gt($$169, $$170))
                                                   -- NESTED_LOOP  |PARTITIONED|
                                                     exchange
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      project ([$$158, $$169, $$161, $$163, $$165])
+                                                      project ([$$169, $$180, $$172, $$174, $$176])
                                                       -- STREAM_PROJECT  |PARTITIONED|
                                                         exchange
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          join (eq($$153, $$91))
-                                                          -- HYBRID_HASH_JOIN [$$91][$$153]  |PARTITIONED|
+                                                          join (eq($$164, $$102))
+                                                          -- HYBRID_HASH_JOIN [$$102][$$164]  |PARTITIONED|
                                                             exchange
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              assign [$$91, $$169, $$165, $$163, $$161, $$158] <- [substring1($$c.getField("c_phone"), 1, 1), $$c.getField("c_state"), $$c.getField("c_w_id"), $$c.getField("c_id"), $$c.getField("c_d_id"), $$c.getField("c_balance")] project: [$$158, $$169, $$161, $$163, $$165, $$91]
+                                                              assign [$$102, $$180, $$176, $$174, $$172, $$169] <- [substring1($$c.getField("c_phone"), 1, 1), $$c.getField("c_state"), $$c.getField("c_w_id"), $$c.getField("c_id"), $$c.getField("c_d_id"), $$c.getField("c_balance")] project: [$$169, $$180, $$172, $$174, $$176, $$102]
                                                               -- ASSIGN  |PARTITIONED|
                                                                 assign [$$c] <- [$$c1] project: [$$c]
                                                                 -- ASSIGN  |PARTITIONED|
@@ -98,7 +98,7 @@ distribute result [$$147]
                                                                         -- STREAM_PROJECT  |PARTITIONED|
                                                                           exchange
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            data-scan []<-[$$151, $$c1] <- test.customer
+                                                                            data-scan []<-[$$162, $$c1] <- test.customer
                                                                             -- DATASOURCE_SCAN  |PARTITIONED|
                                                                               exchange
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -106,7 +106,7 @@ distribute result [$$147]
                                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                             exchange
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              assign [$$153] <- [$$154] project: [$$153]
+                                                              assign [$$164] <- [$$165] project: [$$164]
                                                               -- ASSIGN  |PARTITIONED|
                                                                 exchange
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -114,35 +114,35 @@ distribute result [$$147]
                                                                   -- REPLICATE  |PARTITIONED|
                                                                     exchange
                                                                     -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                      unnest $$154 <- scan-collection(array: [ "1", "2", "3", "4", "5", "6", "7" ])
+                                                                      unnest $$165 <- scan-collection(array: [ "1", "2", "3", "4", "5", "6", "7" ])
                                                                       -- UNNEST  |UNPARTITIONED|
                                                                         empty-tuple-source
                                                                         -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
                                                     exchange
                                                     -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                      assign [$$159] <- [get-item($$110, 0)] project: [$$159]
+                                                      assign [$$170] <- [get-item($$121, 0)] project: [$$170]
                                                       -- ASSIGN  |UNPARTITIONED|
-                                                        aggregate [$$110] <- [listify($$175)]
+                                                        aggregate [$$121] <- [listify($$186)]
                                                         -- AGGREGATE  |UNPARTITIONED|
-                                                          aggregate [$$175] <- [agg-global-sql-avg($$181)]
+                                                          aggregate [$$186] <- [agg-global-sql-avg($$192)]
                                                           -- AGGREGATE  |UNPARTITIONED|
                                                             exchange
                                                             -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
-                                                              aggregate [$$181] <- [agg-local-sql-avg($$167)]
+                                                              aggregate [$$192] <- [agg-local-sql-avg($$178)]
                                                               -- AGGREGATE  |PARTITIONED|
-                                                                project ([$$167])
+                                                                project ([$$178])
                                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                                   exchange
                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                    join (eq($$154, $$99))
-                                                                    -- HYBRID_HASH_JOIN [$$99][$$154]  |PARTITIONED|
+                                                                    join (eq($$165, $$110))
+                                                                    -- HYBRID_HASH_JOIN [$$110][$$165]  |PARTITIONED|
                                                                       exchange
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        assign [$$99] <- [substring1($$c1.getField("c_phone"), 1, 1)] project: [$$167, $$99]
+                                                                        assign [$$110] <- [substring1($$c1.getField("c_phone"), 1, 1)] project: [$$178, $$110]
                                                                         -- ASSIGN  |PARTITIONED|
-                                                                          select (gt($$167, 0.0))
+                                                                          select (gt($$178, 0.0))
                                                                           -- STREAM_SELECT  |PARTITIONED|
-                                                                            assign [$$167] <- [$$c1.getField("c_balance")]
+                                                                            assign [$$178] <- [$$c1.getField("c_balance")]
                                                                             -- ASSIGN  |PARTITIONED|
                                                                               exchange
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -154,7 +154,7 @@ distribute result [$$147]
                                                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                                                       exchange
                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                        data-scan []<-[$$151, $$c1] <- test.customer
+                                                                                        data-scan []<-[$$162, $$c1] <- test.customer
                                                                                         -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                           exchange
                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -166,23 +166,23 @@ distribute result [$$147]
                                                                         -- REPLICATE  |PARTITIONED|
                                                                           exchange
                                                                           -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                            unnest $$154 <- scan-collection(array: [ "1", "2", "3", "4", "5", "6", "7" ])
+                                                                            unnest $$165 <- scan-collection(array: [ "1", "2", "3", "4", "5", "6", "7" ])
                                                                             -- UNNEST  |UNPARTITIONED|
                                                                               empty-tuple-source
                                                                               -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
                                           exchange
-                                          -- HASH_PARTITION_EXCHANGE [$$160, $$162, $$164]  |PARTITIONED|
-                                            assign [$$173] <- [true]
+                                          -- HASH_PARTITION_EXCHANGE [$$171, $$173, $$175]  |PARTITIONED|
+                                            assign [$$184] <- [true]
                                             -- ASSIGN  |PARTITIONED|
-                                              select (and(ge($$149, "2013-12-01 00:00:00"), le($$149, "2013-12-31 00:00:00"))) project: [$$164, $$162, $$160]
+                                              select (and(ge($$160, "2013-12-01 00:00:00"), le($$160, "2013-12-31 00:00:00"))) project: [$$175, $$173, $$171]
                                               -- STREAM_SELECT  |PARTITIONED|
-                                                assign [$$164, $$162, $$160, $$149] <- [$$o.getField("o_w_id"), $$o.getField("o_c_id"), $$o.getField("o_d_id"), $$o.getField("o_entry_d")] project: [$$164, $$162, $$160, $$149]
+                                                assign [$$175, $$173, $$171, $$160] <- [$$o.getField("o_w_id"), $$o.getField("o_c_id"), $$o.getField("o_d_id"), $$o.getField("o_entry_d")] project: [$$175, $$173, $$171, $$160]
                                                 -- ASSIGN  |PARTITIONED|
                                                   project ([$$o])
                                                   -- STREAM_PROJECT  |PARTITIONED|
                                                     exchange
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      data-scan []<-[$$152, $$o] <- test.orders
+                                                      data-scan []<-[$$163, $$o] <- test.orders
                                                       -- DATASOURCE_SCAN  |PARTITIONED|
                                                         exchange
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nested_loj2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nested_loj2.plan
index b093dc7ae8..fa0664575d 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nested_loj2.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nested_loj2.plan
@@ -1,78 +1,78 @@
-distribute result [$$75]
+distribute result [$$80]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$75] <- [{"cust": $$c, "orders": $$73}] project: [$$75]
+    assign [$$80] <- [{"cust": $$c, "orders": $$78}] project: [$$80]
     -- ASSIGN  |PARTITIONED|
-      project ([$$73, $$c])
+      project ([$$78, $$c])
       -- STREAM_PROJECT  |PARTITIONED|
         exchange
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-          group by ([$$87 := $$76]) decor ([$$c]) {
-                    aggregate [$$73] <- [listify({"order": $$o, "items": $$67})]
+          group by ([$$92 := $$81]) decor ([$$c]) {
+                    aggregate [$$78] <- [listify({"order": $$o, "items": $$72})]
                     -- AGGREGATE  |LOCAL|
-                      group by ([$$85 := $$77]) decor ([$$80; $$c; $$o; $$76]) {
-                                aggregate [$$67] <- [listify($$l)]
+                      group by ([$$90 := $$82]) decor ([$$81; $$85; $$c; $$o]) {
+                                aggregate [$$72] <- [listify($$l)]
                                 -- AGGREGATE  |LOCAL|
-                                  select (not(is-missing($$84)))
+                                  select (not(is-missing($$89)))
                                   -- STREAM_SELECT  |LOCAL|
-                                    project ([$$l, $$84])
+                                    project ([$$l, $$89])
                                     -- STREAM_PROJECT  |LOCAL|
                                       nested tuple source
                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                              }
-                      -- MICRO_PRE_CLUSTERED_GROUP_BY[$$77]  |LOCAL|
-                        select (not(is-missing($$86)))
+                      -- MICRO_PRE_CLUSTERED_GROUP_BY[$$82]  |LOCAL|
+                        select (not(is-missing($$91)))
                         -- STREAM_SELECT  |LOCAL|
                           nested tuple source
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                  }
-          -- PRE_CLUSTERED_GROUP_BY[$$76]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$81]  |PARTITIONED|
             exchange
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              order (ASC, $$76) (ASC, $$77)
-              -- STABLE_SORT [$$76(ASC), $$77(ASC)]  |PARTITIONED|
+              order (ASC, $$81) (ASC, $$82)
+              -- STABLE_SORT [$$81(ASC), $$82(ASC)]  |PARTITIONED|
                 exchange
-                -- HASH_PARTITION_EXCHANGE [$$76]  |PARTITIONED|
-                  project ([$$c, $$o, $$l, $$84, $$77, $$80, $$76, $$86])
+                -- HASH_PARTITION_EXCHANGE [$$81]  |PARTITIONED|
+                  project ([$$c, $$o, $$l, $$89, $$82, $$81, $$85, $$91])
                   -- STREAM_PROJECT  |PARTITIONED|
                     exchange
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      left outer join (eq($$78, $$77))
-                      -- HYBRID_HASH_JOIN [$$77][$$78]  |PARTITIONED|
+                      left outer join (eq($$83, $$82))
+                      -- HYBRID_HASH_JOIN [$$82][$$83]  |PARTITIONED|
                         exchange
-                        -- HASH_PARTITION_EXCHANGE [$$77]  |PARTITIONED|
-                          left outer join (eq($$80, $$76))
-                          -- HYBRID_HASH_JOIN [$$76][$$80]  |PARTITIONED|
+                        -- HASH_PARTITION_EXCHANGE [$$82]  |PARTITIONED|
+                          left outer join (eq($$85, $$81))
+                          -- HYBRID_HASH_JOIN [$$81][$$85]  |PARTITIONED|
                             exchange
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              data-scan []<-[$$76, $$c] <- tpch.Customers
+                              data-scan []<-[$$81, $$c] <- tpch.Customers
                               -- DATASOURCE_SCAN  |PARTITIONED|
                                 exchange
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                   empty-tuple-source
                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                             exchange
-                            -- HASH_PARTITION_EXCHANGE [$$80]  |PARTITIONED|
-                              assign [$$86, $$80] <- [true, $$o.getField(1)]
+                            -- HASH_PARTITION_EXCHANGE [$$85]  |PARTITIONED|
+                              assign [$$91, $$85] <- [true, $$o.getField(1)]
                               -- ASSIGN  |PARTITIONED|
                                 exchange
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  data-scan []<-[$$77, $$o] <- tpch.Orders
+                                  data-scan []<-[$$82, $$o] <- tpch.Orders
                                   -- DATASOURCE_SCAN  |PARTITIONED|
                                     exchange
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                       empty-tuple-source
                                       -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                         exchange
-                        -- HASH_PARTITION_EXCHANGE [$$78]  |PARTITIONED|
-                          assign [$$84] <- [true]
+                        -- HASH_PARTITION_EXCHANGE [$$83]  |PARTITIONED|
+                          assign [$$89] <- [true]
                           -- ASSIGN  |PARTITIONED|
-                            project ([$$78, $$l])
+                            project ([$$83, $$l])
                             -- STREAM_PROJECT  |PARTITIONED|
                               exchange
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                data-scan []<-[$$78, $$79, $$l] <- tpch.LineItems
+                                data-scan []<-[$$83, $$84, $$l] <- tpch.LineItems
                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                   exchange
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan
index 3b747a6415..2768d4ae2d 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan
@@ -1,126 +1,126 @@
-distribute result [$$179]
+distribute result [$$189] [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange
+  exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$179] <- [{"cntrycode": $$cntrycode, "numcust": $$182, "totacctbal": $$183}] project: [$$179]
+    assign [$$189] <- [{"cntrycode": $$cntrycode, "numcust": $$192, "totacctbal": $$193}] project: [$$189] [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
     -- ASSIGN  |PARTITIONED|
-      exchange
+      exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
       -- SORT_MERGE_EXCHANGE [$$cntrycode(ASC) ]  |PARTITIONED|
-        group by ([$$cntrycode := $$205]) decor ([]) {
-                  aggregate [$$182, $$183] <- [agg-sql-sum($$203), agg-global-sql-sum($$204)]
+        group by ([$$cntrycode := $$215]) decor ([]) {
+                  aggregate [$$192, $$193] <- [agg-sql-sum($$213), agg-global-sql-sum($$214)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                   -- AGGREGATE  |LOCAL|
-                    nested tuple source
+                    nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-               }
-        -- SORT_GROUP_BY[$$205]  |PARTITIONED|
-          exchange
-          -- HASH_PARTITION_EXCHANGE [$$205]  |PARTITIONED|
-            group by ([$$205 := $$180]) decor ([]) {
-                      aggregate [$$203, $$204] <- [agg-sql-count($$140), agg-local-sql-sum($$191)]
+               } [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+        -- SORT_GROUP_BY[$$215]  |PARTITIONED|
+          exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+          -- HASH_PARTITION_EXCHANGE [$$215]  |PARTITIONED|
+            group by ([$$215 := $$190]) decor ([]) {
+                      aggregate [$$213, $$214] <- [agg-sql-count($$150), agg-local-sql-sum($$201)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |LOCAL|
-                        nested tuple source
+                        nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                   }
-            -- SORT_GROUP_BY[$$180]  |PARTITIONED|
-              exchange
+                   } [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+            -- SORT_GROUP_BY[$$190]  |PARTITIONED|
+              exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                assign [$$180] <- [substring($$193, 0, 2)] project: [$$140, $$191, $$180]
+                assign [$$190] <- [substring($$203, 0, 2)] project: [$$150, $$201, $$190] [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                 -- ASSIGN  |PARTITIONED|
-                  select (neq($$181, 0)) project: [$$193, $$140, $$191]
+                  select (neq($$191, 0)) project: [$$150, $$201, $$203] [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                   -- STREAM_SELECT  |PARTITIONED|
-                    project ([$$181, $$193, $$140, $$191])
+                    project ([$$191, $$150, $$201, $$203]) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                     -- STREAM_PROJECT  |PARTITIONED|
-                      exchange
+                      exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        group by ([$$198 := $$202]) decor ([$$193; $$140; $$191]) {
-                                  aggregate [$$181] <- [agg-sum($$201)]
+                        group by ([$$208 := $$212]) decor ([$$150; $$201; $$203]) {
+                                  aggregate [$$191] <- [agg-sum($$211)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- AGGREGATE  |LOCAL|
-                                    nested tuple source
+                                    nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-                               }
-                        -- SORT_GROUP_BY[$$202]  |PARTITIONED|
-                          exchange
-                          -- HASH_PARTITION_EXCHANGE [$$202]  |PARTITIONED|
-                            group by ([$$202 := $$196]) decor ([$$193; $$140; $$191]) {
-                                      aggregate [$$201] <- [agg-count({"o": $$o})]
+                               } [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+                        -- SORT_GROUP_BY[$$212]  |PARTITIONED|
+                          exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+                          -- HASH_PARTITION_EXCHANGE [$$212]  |PARTITIONED|
+                            group by ([$$212 := $$206]) decor ([$$150; $$201; $$203]) {
+                                      aggregate [$$211] <- [agg-count({"o": $$o})] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                       -- AGGREGATE  |LOCAL|
-                                        select (not(is-missing($$197)))
+                                        select (not(is-missing($$207))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                         -- STREAM_SELECT  |LOCAL|
-                                          project ([$$o, $$197])
+                                          project ([$$o, $$207]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- STREAM_PROJECT  |LOCAL|
-                                            nested tuple source
+                                            nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                   }
-                            -- PRE_CLUSTERED_GROUP_BY[$$196]  |PARTITIONED|
-                              exchange
+                                   } [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+                            -- PRE_CLUSTERED_GROUP_BY[$$206]  |PARTITIONED|
+                              exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                order (ASC, $$196)
-                                -- STABLE_SORT [$$196(ASC)]  |PARTITIONED|
-                                  exchange
+                                order (ASC, $$206) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+                                -- STABLE_SORT [$$206(ASC)]  |PARTITIONED|
+                                  exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    project ([$$140, $$191, $$193, $$o, $$197, $$196])
+                                    project ([$$150, $$201, $$203, $$o, $$207, $$206]) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                                     -- STREAM_PROJECT  |PARTITIONED|
-                                      exchange
+                                      exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        left outer join (eq($$189, $$192))
-                                        -- HYBRID_HASH_JOIN [$$192][$$189]  |PARTITIONED|
-                                          exchange
-                                          -- HASH_PARTITION_EXCHANGE [$$192]  |PARTITIONED|
-                                            running-aggregate [$$196] <- [create-query-uid()]
+                                        left outer join (eq($$199, $$202)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- HYBRID_HASH_JOIN [$$202][$$199]  |PARTITIONED|
+                                          exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
+                                          -- HASH_PARTITION_EXCHANGE [$$202]  |PARTITIONED|
+                                            running-aggregate [$$206] <- [create-query-uid()] [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                                             -- RUNNING_AGGREGATE  |PARTITIONED|
-                                              project ([$$140, $$191, $$193, $$192])
+                                              project ([$$150, $$201, $$203, $$202]) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                                               -- STREAM_PROJECT  |PARTITIONED|
-                                                exchange
+                                                exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.000006E12]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (gt($$191, $$188))
+                                                  join (gt($$201, $$198)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 1.0E12, total-cost: 1.000006E12]
                                                   -- NESTED_LOOP  |PARTITIONED|
-                                                    exchange
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      assign [$$140] <- [{"c_acctbal": $$191, "c_custkey": $$192, "cntrycode": substring($$193, 0, 2)}]
+                                                      assign [$$150] <- [{"c_acctbal": $$201, "c_custkey": $$202, "cntrycode": substring($$203, 0, 2)}] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- ASSIGN  |PARTITIONED|
-                                                        assign [$$193, $$192, $$191] <- [$$Customer.getField(4), $$Customer.getField(0), $$Customer.getField(5)] project: [$$193, $$192, $$191]
+                                                        assign [$$203, $$202, $$201] <- [$$Customer.getField(4), $$Customer.getField(0), $$Customer.getField(5)] project: [$$203, $$202, $$201] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                         -- ASSIGN  |PARTITIONED|
-                                                          exchange
+                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            data-scan []<-[$$Customer] <- test.Customer
+                                                            data-scan []<-[$$Customer] <- test.Customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- DATASOURCE_SCAN  |PARTITIONED|
-                                                              exchange
+                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                empty-tuple-source
+                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                    exchange
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                      assign [$$188] <- [get-item($$154, 0)] project: [$$188]
+                                                      assign [$$198] <- [get-item($$164, 0)] project: [$$198] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- ASSIGN  |UNPARTITIONED|
-                                                        aggregate [$$154] <- [listify($$200)]
+                                                        aggregate [$$164] <- [listify($$210)] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                         -- AGGREGATE  |UNPARTITIONED|
-                                                          aggregate [$$200] <- [agg-global-sql-avg($$206)]
+                                                          aggregate [$$210] <- [agg-global-sql-avg($$216)] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                           -- AGGREGATE  |UNPARTITIONED|
-                                                            exchange
+                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
-                                                              aggregate [$$206] <- [agg-local-sql-avg($$194)]
+                                                              aggregate [$$216] <- [agg-local-sql-avg($$204)] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                               -- AGGREGATE  |PARTITIONED|
-                                                                select (gt($$194, 0.0))
+                                                                select (gt($$204, 0.0)) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                  assign [$$194] <- [$$186.getField(5)] project: [$$194]
+                                                                  assign [$$204] <- [$$196.getField(5)] project: [$$204] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                   -- ASSIGN  |PARTITIONED|
-                                                                    exchange
+                                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      data-scan []<-[$$186] <- test.Customer
+                                                                      data-scan []<-[$$196] <- test.Customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                       -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                        exchange
+                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          empty-tuple-source
+                                                                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                          exchange
-                                          -- HASH_PARTITION_EXCHANGE [$$189]  |PARTITIONED|
-                                            assign [$$197, $$189] <- [true, $$o.getField(1)]
+                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                          -- HASH_PARTITION_EXCHANGE [$$199]  |PARTITIONED|
+                                            assign [$$207, $$199] <- [true, $$o.getField(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- ASSIGN  |PARTITIONED|
-                                              exchange
+                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                data-scan []<-[$$o] <- test.Orders
+                                                data-scan []<-[$$o] <- test.Orders [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                 -- DATASOURCE_SCAN  |PARTITIONED|
-                                                  exchange
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    empty-tuple-source
+                                                    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/optimizerts/results/subquery/in_let_3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in_let_3.plan
index c1c9da3374..52a5567f65 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in_let_3.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in_let_3.plan
@@ -1,55 +1,55 @@
-distribute result [$$102]
+distribute result [$$110]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$102] <- [{"cid": $$113, "pid": $$109, "ts": $$105}] project: [$$102]
+    assign [$$110] <- [{"cid": $$121, "pid": $$117, "ts": $$113}] project: [$$110]
     -- ASSIGN  |PARTITIONED|
       exchange
-      -- SORT_MERGE_EXCHANGE [$$113(ASC) ]  |PARTITIONED|
-        order (ASC, $$113)
-        -- STABLE_SORT [$$113(ASC)]  |PARTITIONED|
+      -- SORT_MERGE_EXCHANGE [$$121(ASC) ]  |PARTITIONED|
+        order (ASC, $$121)
+        -- STABLE_SORT [$$121(ASC)]  |PARTITIONED|
           exchange
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            select ($$96) project: [$$113, $$109, $$105]
+            select ($$104) project: [$$121, $$117, $$113]
             -- STREAM_SELECT  |PARTITIONED|
-              project ([$$96, $$113, $$105, $$109])
+              project ([$$104, $$113, $$117, $$121])
               -- STREAM_PROJECT  |PARTITIONED|
                 exchange
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  group by ([$$118 := $$116]) decor ([$$113; $$105; $$109]) {
-                            aggregate [$$96] <- [non-empty-stream()]
+                  group by ([$$126 := $$124]) decor ([$$113; $$117; $$121]) {
+                            aggregate [$$104] <- [non-empty-stream()]
                             -- AGGREGATE  |LOCAL|
-                              select (not(is-missing($$117)))
+                              select (not(is-missing($$125)))
                               -- STREAM_SELECT  |LOCAL|
-                                project ([$$117])
+                                project ([$$125])
                                 -- STREAM_PROJECT  |LOCAL|
                                   nested tuple source
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
                          }
-                  -- PRE_CLUSTERED_GROUP_BY[$$116]  |PARTITIONED|
+                  -- PRE_CLUSTERED_GROUP_BY[$$124]  |PARTITIONED|
                     exchange
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      order (ASC, $$116)
-                      -- STABLE_SORT [$$116(ASC)]  |PARTITIONED|
+                      order (ASC, $$124)
+                      -- STABLE_SORT [$$124(ASC)]  |PARTITIONED|
                         exchange
-                        -- HASH_PARTITION_EXCHANGE [$$116]  |PARTITIONED|
-                          project ([$$113, $$109, $$105, $$117, $$116])
+                        -- HASH_PARTITION_EXCHANGE [$$124]  |PARTITIONED|
+                          project ([$$121, $$117, $$113, $$125, $$124])
                           -- STREAM_PROJECT  |PARTITIONED|
                             exchange
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              left outer join (eq($$109, $$pid))
-                              -- HYBRID_HASH_JOIN [$$109][$$pid]  |PARTITIONED|
+                              left outer join (eq($$117, $$pid))
+                              -- HYBRID_HASH_JOIN [$$117][$$pid]  |PARTITIONED|
                                 exchange
-                                -- HASH_PARTITION_EXCHANGE [$$109]  |PARTITIONED|
-                                  select (ge($$105, 2000))
+                                -- HASH_PARTITION_EXCHANGE [$$117]  |PARTITIONED|
+                                  select (ge($$113, 2000))
                                   -- STREAM_SELECT  |PARTITIONED|
-                                    running-aggregate [$$116] <- [create-query-uid()]
+                                    running-aggregate [$$124] <- [create-query-uid()]
                                     -- RUNNING_AGGREGATE  |PARTITIONED|
-                                      assign [$$105, $$109] <- [$$i1.getField("ts"), $$i1.getField("pid")] project: [$$113, $$109, $$105]
+                                      assign [$$113, $$117] <- [$$i1.getField("ts"), $$i1.getField("pid")] project: [$$121, $$117, $$113]
                                       -- ASSIGN  |PARTITIONED|
-                                        unnest $$i1 <- scan-collection($$110) project: [$$113, $$i1]
+                                        unnest $$i1 <- scan-collection($$118) project: [$$121, $$i1]
                                         -- UNNEST  |PARTITIONED|
-                                          assign [$$113, $$110] <- [$$c1.getField("cid"), $$c1.getField("items")] project: [$$113, $$110]
+                                          assign [$$121, $$118] <- [$$c1.getField("cid"), $$c1.getField("items")] project: [$$121, $$118]
                                           -- ASSIGN  |PARTITIONED|
                                             assign [$$c1] <- [$$c2] project: [$$c1]
                                             -- ASSIGN  |PARTITIONED|
@@ -63,7 +63,7 @@ distribute result [$$102]
                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        data-scan []<-[$$107, $$c2] <- test.cart
+                                                        data-scan []<-[$$115, $$c2] <- test.cart
                                                         -- DATASOURCE_SCAN  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -71,37 +71,37 @@ distribute result [$$102]
                                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                 exchange
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  assign [$$117] <- [true]
+                                  assign [$$125] <- [true]
                                   -- ASSIGN  |PARTITIONED|
-                                    select (gt($$108, 1)) project: [$$pid]
+                                    select (gt($$116, 1)) project: [$$pid]
                                     -- STREAM_SELECT  |PARTITIONED|
                                       exchange
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        group by ([$$pid := $$120]) decor ([]) {
-                                                  aggregate [$$108] <- [agg-sql-sum($$119)]
+                                        group by ([$$pid := $$128]) decor ([]) {
+                                                  aggregate [$$116] <- [agg-sql-sum($$127)]
                                                   -- AGGREGATE  |LOCAL|
                                                     nested tuple source
                                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                }
-                                        -- SORT_GROUP_BY[$$120]  |PARTITIONED|
+                                        -- SORT_GROUP_BY[$$128]  |PARTITIONED|
                                           exchange
-                                          -- HASH_PARTITION_EXCHANGE [$$120]  |PARTITIONED|
-                                            group by ([$$120 := $$104]) decor ([]) {
-                                                      aggregate [$$119] <- [agg-sql-count(1)]
+                                          -- HASH_PARTITION_EXCHANGE [$$128]  |PARTITIONED|
+                                            group by ([$$128 := $$112]) decor ([]) {
+                                                      aggregate [$$127] <- [agg-sql-count(1)]
                                                       -- AGGREGATE  |LOCAL|
                                                         nested tuple source
                                                         -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                    }
-                                            -- SORT_GROUP_BY[$$104]  |PARTITIONED|
+                                            -- SORT_GROUP_BY[$$112]  |PARTITIONED|
                                               exchange
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                select (ge($$i2.getField("ts"), 2000)) project: [$$104]
+                                                select (ge($$i2.getField("ts"), 2000)) project: [$$112]
                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                  assign [$$104] <- [$$i2.getField("pid")]
+                                                  assign [$$112] <- [$$i2.getField("pid")]
                                                   -- ASSIGN  |PARTITIONED|
-                                                    unnest $$i2 <- scan-collection($$111) project: [$$i2]
+                                                    unnest $$i2 <- scan-collection($$119) project: [$$i2]
                                                     -- UNNEST  |PARTITIONED|
-                                                      assign [$$111] <- [$$c2.getField("items")] project: [$$111]
+                                                      assign [$$119] <- [$$c2.getField("items")] project: [$$119]
                                                       -- ASSIGN  |PARTITIONED|
                                                         exchange
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -113,7 +113,7 @@ distribute result [$$102]
                                                               -- STREAM_PROJECT  |PARTITIONED|
                                                                 exchange
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  data-scan []<-[$$107, $$c2] <- test.cart
+                                                                  data-scan []<-[$$115, $$c2] <- test.cart
                                                                   -- DATASOURCE_SCAN  |PARTITIONED|
                                                                     exchange
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan
index 66267ed64a..31d05817ec 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan
@@ -1,84 +1,84 @@
-distribute result [$$180]
+distribute result [$$190]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$180] <- [{"cntrycode": $$cntrycode, "numcust": $$183, "totacctbal": $$184}] project: [$$180]
+    assign [$$190] <- [{"cntrycode": $$cntrycode, "numcust": $$193, "totacctbal": $$194}] project: [$$190]
     -- ASSIGN  |PARTITIONED|
       exchange
       -- SORT_MERGE_EXCHANGE [$$cntrycode(ASC) ]  |PARTITIONED|
-        group by ([$$cntrycode := $$206]) decor ([]) {
-                  aggregate [$$183, $$184] <- [agg-sql-sum($$204), agg-global-sql-sum($$205)]
+        group by ([$$cntrycode := $$216]) decor ([]) {
+                  aggregate [$$193, $$194] <- [agg-sql-sum($$214), agg-global-sql-sum($$215)]
                   -- AGGREGATE  |LOCAL|
                     nested tuple source
                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                }
-        -- SORT_GROUP_BY[$$206]  |PARTITIONED|
+        -- SORT_GROUP_BY[$$216]  |PARTITIONED|
           exchange
-          -- HASH_PARTITION_EXCHANGE [$$206]  |PARTITIONED|
-            group by ([$$206 := $$181]) decor ([]) {
-                      aggregate [$$204, $$205] <- [agg-sql-count($$140), agg-local-sql-sum($$192)]
+          -- HASH_PARTITION_EXCHANGE [$$216]  |PARTITIONED|
+            group by ([$$216 := $$191]) decor ([]) {
+                      aggregate [$$214, $$215] <- [agg-sql-count($$150), agg-local-sql-sum($$202)]
                       -- AGGREGATE  |LOCAL|
                         nested tuple source
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
                    }
-            -- SORT_GROUP_BY[$$181]  |PARTITIONED|
+            -- SORT_GROUP_BY[$$191]  |PARTITIONED|
               exchange
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                assign [$$181] <- [substring($$194, 0, 2)] project: [$$140, $$192, $$181]
+                assign [$$191] <- [substring($$204, 0, 2)] project: [$$150, $$202, $$191]
                 -- ASSIGN  |PARTITIONED|
-                  select (not(neq($$182, 0))) project: [$$192, $$194, $$140]
+                  select (not(neq($$192, 0))) project: [$$150, $$202, $$204]
                   -- STREAM_SELECT  |PARTITIONED|
-                    project ([$$182, $$192, $$194, $$140])
+                    project ([$$192, $$150, $$202, $$204])
                     -- STREAM_PROJECT  |PARTITIONED|
                       exchange
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        group by ([$$199 := $$203]) decor ([$$192; $$194; $$140]) {
-                                  aggregate [$$182] <- [agg-sum($$202)]
+                        group by ([$$209 := $$213]) decor ([$$150; $$202; $$204]) {
+                                  aggregate [$$192] <- [agg-sum($$212)]
                                   -- AGGREGATE  |LOCAL|
                                     nested tuple source
                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                                }
-                        -- SORT_GROUP_BY[$$203]  |PARTITIONED|
+                        -- SORT_GROUP_BY[$$213]  |PARTITIONED|
                           exchange
-                          -- HASH_PARTITION_EXCHANGE [$$203]  |PARTITIONED|
-                            group by ([$$203 := $$197]) decor ([$$192; $$194; $$140]) {
-                                      aggregate [$$202] <- [agg-count({"o": $$o})]
+                          -- HASH_PARTITION_EXCHANGE [$$213]  |PARTITIONED|
+                            group by ([$$213 := $$207]) decor ([$$150; $$202; $$204]) {
+                                      aggregate [$$212] <- [agg-count({"o": $$o})]
                                       -- AGGREGATE  |LOCAL|
-                                        select (not(is-missing($$198)))
+                                        select (not(is-missing($$208)))
                                         -- STREAM_SELECT  |LOCAL|
-                                          project ([$$o, $$198])
+                                          project ([$$o, $$208])
                                           -- STREAM_PROJECT  |LOCAL|
                                             nested tuple source
                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
                                    }
-                            -- PRE_CLUSTERED_GROUP_BY[$$197]  |PARTITIONED|
+                            -- PRE_CLUSTERED_GROUP_BY[$$207]  |PARTITIONED|
                               exchange
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                order (ASC, $$197)
-                                -- STABLE_SORT [$$197(ASC)]  |PARTITIONED|
+                                order (ASC, $$207)
+                                -- STABLE_SORT [$$207(ASC)]  |PARTITIONED|
                                   exchange
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    project ([$$140, $$192, $$194, $$o, $$198, $$197])
+                                    project ([$$150, $$202, $$204, $$o, $$208, $$207])
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       exchange
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        left outer join (eq($$190, $$193))
-                                        -- HYBRID_HASH_JOIN [$$193][$$190]  |PARTITIONED|
+                                        left outer join (eq($$200, $$203))
+                                        -- HYBRID_HASH_JOIN [$$203][$$200]  |PARTITIONED|
                                           exchange
-                                          -- HASH_PARTITION_EXCHANGE [$$193]  |PARTITIONED|
-                                            running-aggregate [$$197] <- [create-query-uid()]
+                                          -- HASH_PARTITION_EXCHANGE [$$203]  |PARTITIONED|
+                                            running-aggregate [$$207] <- [create-query-uid()]
                                             -- RUNNING_AGGREGATE  |PARTITIONED|
-                                              project ([$$140, $$192, $$194, $$193])
+                                              project ([$$150, $$202, $$204, $$203])
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 exchange
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (gt($$192, $$189))
+                                                  join (gt($$202, $$199))
                                                   -- NESTED_LOOP  |PARTITIONED|
                                                     exchange
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      assign [$$140] <- [{"c_acctbal": $$192, "c_custkey": $$193, "cntrycode": substring($$194, 0, 2)}]
+                                                      assign [$$150] <- [{"c_acctbal": $$202, "c_custkey": $$203, "cntrycode": substring($$204, 0, 2)}]
                                                       -- ASSIGN  |PARTITIONED|
-                                                        assign [$$194, $$193, $$192] <- [$$Customer.getField(4), $$Customer.getField(0), $$Customer.getField(5)] project: [$$194, $$193, $$192]
+                                                        assign [$$204, $$203, $$202] <- [$$Customer.getField(4), $$Customer.getField(0), $$Customer.getField(5)] project: [$$204, $$203, $$202]
                                                         -- ASSIGN  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -90,31 +90,31 @@ distribute result [$$180]
                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                     exchange
                                                     -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                      assign [$$189] <- [get-item($$154, 0)] project: [$$189]
+                                                      assign [$$199] <- [get-item($$164, 0)] project: [$$199]
                                                       -- ASSIGN  |UNPARTITIONED|
-                                                        aggregate [$$154] <- [listify($$201)]
+                                                        aggregate [$$164] <- [listify($$211)]
                                                         -- AGGREGATE  |UNPARTITIONED|
-                                                          aggregate [$$201] <- [agg-global-sql-avg($$207)]
+                                                          aggregate [$$211] <- [agg-global-sql-avg($$217)]
                                                           -- AGGREGATE  |UNPARTITIONED|
                                                             exchange
                                                             -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
-                                                              aggregate [$$207] <- [agg-local-sql-avg($$195)]
+                                                              aggregate [$$217] <- [agg-local-sql-avg($$205)]
                                                               -- AGGREGATE  |PARTITIONED|
-                                                                select (gt($$195, 0.0))
+                                                                select (gt($$205, 0.0))
                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                  assign [$$195] <- [$$187.getField(5)] project: [$$195]
+                                                                  assign [$$205] <- [$$197.getField(5)] project: [$$205]
                                                                   -- ASSIGN  |PARTITIONED|
                                                                     exchange
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      data-scan []<-[$$187] <- test.Customer
+                                                                      data-scan []<-[$$197] <- test.Customer
                                                                       -- DATASOURCE_SCAN  |PARTITIONED|
                                                                         exchange
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                           empty-tuple-source
                                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                           exchange
-                                          -- HASH_PARTITION_EXCHANGE [$$190]  |PARTITIONED|
-                                            assign [$$198, $$190] <- [true, $$o.getField(1)]
+                                          -- HASH_PARTITION_EXCHANGE [$$200]  |PARTITIONED|
+                                            assign [$$208, $$200] <- [true, $$o.getField(1)]
                                             -- ASSIGN  |PARTITIONED|
                                               exchange
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581-correlated.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581-correlated.plan
index 500690592b..bda3724246 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581-correlated.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581-correlated.plan
@@ -1,615 +1,615 @@
-distribute result [$$150]
+distribute result [$$160] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange
+  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$150] <- [{"bucket1": $$148}] project: [$$150]
+    assign [$$160] <- [{"bucket1": $$158}] project: [$$160] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
     -- ASSIGN  |PARTITIONED|
-      unnest $$148 <- scan-collection($$147) project: [$$148]
+      unnest $$158 <- scan-collection($$157) project: [$$158] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
       -- UNNEST  |PARTITIONED|
-        assign [$$147] <- [switch-case(true, lt(get-item($$114, 0), 25437), cast($$131), cast($$146))] project: [$$147]
+        assign [$$157] <- [switch-case(true, lt(get-item($$124, 0), 25437), cast($$141), cast($$156))] project: [$$157] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
         -- ASSIGN  |PARTITIONED|
-          project ([$$146, $$114, $$131])
+          project ([$$156, $$124, $$141]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
           -- STREAM_PROJECT  |PARTITIONED|
-            exchange
+            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              group by ([$$231 := $$187]) decor ([$$114; $$131]) {
-                        aggregate [$$146] <- [listify($$145)]
+              group by ([$$241 := $$197]) decor ([$$124; $$141]) {
+                        aggregate [$$156] <- [listify($$155)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- AGGREGATE  |LOCAL|
-                          aggregate [$$145] <- [listify($$144)]
+                          aggregate [$$155] <- [listify($$154)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- AGGREGATE  |LOCAL|
-                            select (not(is-missing($$230)))
+                            select (not(is-missing($$240))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- STREAM_SELECT  |LOCAL|
-                              project ([$$144, $$230])
+                              project ([$$154, $$240]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- STREAM_PROJECT  |LOCAL|
-                                nested tuple source
+                                nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
-                     }
-              -- PRE_CLUSTERED_GROUP_BY[$$187]  |PARTITIONED|
-                exchange
+                     } [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+              -- PRE_CLUSTERED_GROUP_BY[$$197]  |PARTITIONED|
+                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  order (ASC, $$187)
-                  -- STABLE_SORT [$$187(ASC)]  |PARTITIONED|
-                    exchange
+                  order (ASC, $$197) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                  -- STABLE_SORT [$$197(ASC)]  |PARTITIONED|
+                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      project ([$$114, $$131, $$144, $$230, $$187])
+                      project ([$$124, $$141, $$154, $$240, $$197]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                       -- STREAM_PROJECT  |PARTITIONED|
-                        exchange
+                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          left outer join (eq($$187, $$229))
-                          -- HYBRID_HASH_JOIN [$$187][$$229]  |PARTITIONED|
-                            exchange
+                          left outer join (eq($$197, $$239)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- HYBRID_HASH_JOIN [$$197][$$239]  |PARTITIONED|
+                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              group by ([$$187 := $$171]) decor ([$$114]) {
-                                        aggregate [$$131] <- [listify($$130)]
+                              group by ([$$197 := $$181]) decor ([$$124]) {
+                                        aggregate [$$141] <- [listify($$140)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                         -- AGGREGATE  |LOCAL|
-                                          aggregate [$$130] <- [listify($$129)]
+                                          aggregate [$$140] <- [listify($$139)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- AGGREGATE  |LOCAL|
-                                            select (not(is-missing($$186)))
+                                            select (not(is-missing($$196))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- STREAM_SELECT  |LOCAL|
-                                              project ([$$129, $$186])
+                                              project ([$$139, $$196]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- STREAM_PROJECT  |LOCAL|
-                                                nested tuple source
+                                                nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                     }
-                              -- PRE_CLUSTERED_GROUP_BY[$$171]  |PARTITIONED|
-                                exchange
+                                     } [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- PRE_CLUSTERED_GROUP_BY[$$181]  |PARTITIONED|
+                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  project ([$$114, $$129, $$186, $$171])
+                                  project ([$$124, $$139, $$196, $$181]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                   -- STREAM_PROJECT  |PARTITIONED|
-                                    exchange
+                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      left outer join (eq($$171, $$185))
-                                      -- HYBRID_HASH_JOIN [$$171][$$185]  |PARTITIONED|
-                                        exchange
+                                      left outer join (eq($$181, $$195)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- HYBRID_HASH_JOIN [$$181][$$195]  |PARTITIONED|
+                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          group by ([$$171 := $$151]) decor ([]) {
-                                                    aggregate [$$114] <- [listify($$158)]
+                                          group by ([$$181 := $$161]) decor ([]) {
+                                                    aggregate [$$124] <- [listify($$168)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                     -- AGGREGATE  |LOCAL|
-                                                      aggregate [$$158] <- [agg-sql-count(1)]
+                                                      aggregate [$$168] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                       -- AGGREGATE  |LOCAL|
-                                                        select (not(is-missing($$170)))
+                                                        select (not(is-missing($$180))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                         -- STREAM_SELECT  |LOCAL|
-                                                          project ([$$170])
+                                                          project ([$$180]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- STREAM_PROJECT  |LOCAL|
-                                                            nested tuple source
+                                                            nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                 }
-                                          -- PRE_CLUSTERED_GROUP_BY[$$151]  |PARTITIONED|
-                                            exchange
+                                                 } [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- PRE_CLUSTERED_GROUP_BY[$$161]  |PARTITIONED|
+                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              order (ASC, $$151)
-                                              -- STABLE_SORT [$$151(ASC)]  |PARTITIONED|
-                                                exchange
+                                              order (ASC, $$161) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- STABLE_SORT [$$161(ASC)]  |PARTITIONED|
+                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  project ([$$170, $$151])
+                                                  project ([$$180, $$161]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                   -- STREAM_PROJECT  |PARTITIONED|
-                                                    exchange
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      left outer join (eq($$161, $$151))
-                                                      -- HYBRID_HASH_JOIN [$$151][$$161]  |PARTITIONED|
-                                                        exchange
+                                                      left outer join (eq($$171, $$161)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                      -- HYBRID_HASH_JOIN [$$161][$$171]  |PARTITIONED|
+                                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          assign [$$151, $$item] <- [$$213, $$211] project: [$$151]
+                                                          assign [$$161, $$item] <- [$$223, $$219] project: [$$161] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                           -- ASSIGN  |PARTITIONED|
-                                                            exchange
+                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              replicate
+                                                              replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                               -- REPLICATE  |PARTITIONED|
-                                                                exchange
+                                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  unnest-map [$$213, $$211] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$254, 1, $$255, true, true, true)
+                                                                  unnest-map [$$223, $$219] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$264, 1, $$265, true, true, true) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                   -- BTREE_SEARCH  |PARTITIONED|
-                                                                    exchange
+                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      assign [$$254, $$255] <- [1, 1]
+                                                                      assign [$$264, $$265] <- [1, 1] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                       -- ASSIGN  |PARTITIONED|
-                                                                        empty-tuple-source
+                                                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                         -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                        exchange
+                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          assign [$$170, $$161] <- [$$220, $$212] project: [$$170, $$161]
+                                                          assign [$$180, $$171] <- [$$230, $$222] project: [$$180, $$171] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- ASSIGN  |PARTITIONED|
-                                                            exchange
+                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              replicate
+                                                              replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- REPLICATE  |PARTITIONED|
-                                                                exchange
-                                                                -- HASH_PARTITION_EXCHANGE [$$212]  |PARTITIONED|
-                                                                  assign [$$220, $$212] <- [true, $$221.getField(10)] project: [$$220, $$212]
+                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                -- HASH_PARTITION_EXCHANGE [$$222]  |PARTITIONED|
+                                                                  assign [$$230, $$222] <- [true, $$231.getField(10)] project: [$$230, $$222] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                   -- ASSIGN  |PARTITIONED|
-                                                                    assign [$$221] <- [$$store_sales] project: [$$221]
+                                                                    assign [$$231] <- [$$store_sales] project: [$$231] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ASSIGN  |PARTITIONED|
-                                                                      exchange
+                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        replicate
+                                                                        replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                         -- REPLICATE  |PARTITIONED|
-                                                                          exchange
+                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            project ([$$store_sales])
+                                                                            project ([$$store_sales]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                             -- STREAM_PROJECT  |PARTITIONED|
-                                                                              exchange
+                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                data-scan []<-[$$154, $$155, $$store_sales] <- tpcds.store_sales
+                                                                                data-scan []<-[$$164, $$165, $$store_sales] <- tpcds.store_sales [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                  exchange
+                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                    empty-tuple-source
+                                                                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                        exchange
-                                        -- HASH_PARTITION_EXCHANGE [$$185]  |PARTITIONED|
-                                          assign [$$186, $$129] <- [true, {"$1": $$159}] project: [$$129, $$186, $$185]
+                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- HASH_PARTITION_EXCHANGE [$$195]  |PARTITIONED|
+                                          assign [$$196, $$139] <- [true, {"$1": $$169}] project: [$$139, $$196, $$195] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- ASSIGN  |PARTITIONED|
-                                            project ([$$159, $$185])
+                                            project ([$$169, $$195]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- STREAM_PROJECT  |PARTITIONED|
-                                              exchange
+                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                group by ([$$174 := $$234; $$185 := $$235]) decor ([]) {
-                                                          aggregate [$$159] <- [agg-global-sql-avg($$233)]
+                                                group by ([$$184 := $$244; $$195 := $$245]) decor ([]) {
+                                                          aggregate [$$169] <- [agg-global-sql-avg($$243)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- AGGREGATE  |LOCAL|
-                                                            nested tuple source
+                                                            nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                       }
-                                                -- SORT_GROUP_BY[$$234, $$235]  |PARTITIONED|
-                                                  exchange
-                                                  -- HASH_PARTITION_EXCHANGE [$$234, $$235]  |PARTITIONED|
-                                                    group by ([$$234 := $$172; $$235 := $$175]) decor ([]) {
-                                                              aggregate [$$233] <- [agg-local-sql-avg($$127)]
+                                                       } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                -- SORT_GROUP_BY[$$244, $$245]  |PARTITIONED|
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                  -- HASH_PARTITION_EXCHANGE [$$244, $$245]  |PARTITIONED|
+                                                    group by ([$$244 := $$182; $$245 := $$185]) decor ([]) {
+                                                              aggregate [$$243] <- [agg-local-sql-avg($$137)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- AGGREGATE  |LOCAL|
-                                                                select (not(is-missing($$173)))
+                                                                select (not(is-missing($$183))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- STREAM_SELECT  |LOCAL|
-                                                                  project ([$$127, $$173])
+                                                                  project ([$$137, $$183]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                   -- STREAM_PROJECT  |LOCAL|
-                                                                    nested tuple source
+                                                                    nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                           }
-                                                    -- PRE_CLUSTERED_GROUP_BY[$$172, $$175]  |PARTITIONED|
-                                                      exchange
+                                                           } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    -- PRE_CLUSTERED_GROUP_BY[$$182, $$185]  |PARTITIONED|
+                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        order (ASC, $$172) (ASC, $$175)
-                                                        -- STABLE_SORT [$$172(ASC), $$175(ASC)]  |PARTITIONED|
-                                                          exchange
+                                                        order (ASC, $$182) (ASC, $$185) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                        -- STABLE_SORT [$$182(ASC), $$185(ASC)]  |PARTITIONED|
+                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            project ([$$127, $$173, $$172, $$175])
+                                                            project ([$$137, $$183, $$182, $$185]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- STREAM_PROJECT  |PARTITIONED|
-                                                              exchange
+                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                left outer join (eq($$163, $$164))
-                                                                -- HYBRID_HASH_JOIN [$$164][$$163]  |PARTITIONED|
-                                                                  exchange
+                                                                left outer join (eq($$173, $$174)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                -- HYBRID_HASH_JOIN [$$174][$$173]  |PARTITIONED|
+                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                    assign [$$175, $$164, $$172] <- [$$208, $$210, $$207] project: [$$175, $$164, $$172]
+                                                                    assign [$$185, $$174, $$182] <- [$$218, $$221, $$217] project: [$$185, $$174, $$182] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ASSIGN  |PARTITIONED|
-                                                                      exchange
+                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        replicate
+                                                                        replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                         -- REPLICATE  |PARTITIONED|
-                                                                          exchange
-                                                                          -- HASH_PARTITION_EXCHANGE [$$210]  |PARTITIONED|
-                                                                            running-aggregate [$$207] <- [create-query-uid()]
+                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                          -- HASH_PARTITION_EXCHANGE [$$221]  |PARTITIONED|
+                                                                            running-aggregate [$$217] <- [create-query-uid()] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                             -- RUNNING_AGGREGATE  |PARTITIONED|
-                                                                              assign [$$210] <- [$$211.getField(0)] project: [$$208, $$210]
+                                                                              assign [$$221] <- [$$219.getField(0)] project: [$$218, $$221] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                               -- ASSIGN  |PARTITIONED|
-                                                                                select (lt(get-item($$209, 0), 25437)) project: [$$208, $$211]
+                                                                                select (lt(get-item($$220, 0), 25437)) project: [$$218, $$219] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                                  exchange
+                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                    replicate
+                                                                                    replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                     -- REPLICATE  |PARTITIONED|
-                                                                                      exchange
+                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                        group by ([$$208 := $$213]) decor ([$$211]) {
-                                                                                                  aggregate [$$209] <- [listify($$219)]
+                                                                                        group by ([$$218 := $$223]) decor ([$$219]) {
+                                                                                                  aggregate [$$220] <- [listify($$229)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                   -- AGGREGATE  |LOCAL|
-                                                                                                    aggregate [$$219] <- [agg-sql-count(1)]
+                                                                                                    aggregate [$$229] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                     -- AGGREGATE  |LOCAL|
-                                                                                                      select (not(is-missing($$215)))
+                                                                                                      select (not(is-missing($$225))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- STREAM_SELECT  |LOCAL|
-                                                                                                        project ([$$215])
+                                                                                                        project ([$$225]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                         -- STREAM_PROJECT  |LOCAL|
-                                                                                                          nested tuple source
+                                                                                                          nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                                               }
-                                                                                        -- PRE_CLUSTERED_GROUP_BY[$$213]  |PARTITIONED|
-                                                                                          exchange
+                                                                                               } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                        -- PRE_CLUSTERED_GROUP_BY[$$223]  |PARTITIONED|
+                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                            order (ASC, $$213)
-                                                                                            -- STABLE_SORT [$$213(ASC)]  |PARTITIONED|
-                                                                                              exchange
+                                                                                            order (ASC, $$223) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                            -- STABLE_SORT [$$223(ASC)]  |PARTITIONED|
+                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                project ([$$211, $$215, $$213])
+                                                                                                project ([$$219, $$225, $$223]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                 -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                  exchange
+                                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                    left outer join (eq($$214, $$213))
-                                                                                                    -- HYBRID_HASH_JOIN [$$213][$$214]  |PARTITIONED|
-                                                                                                      exchange
+                                                                                                    left outer join (eq($$224, $$223)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                                                                    -- HYBRID_HASH_JOIN [$$223][$$224]  |PARTITIONED|
+                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                        replicate
+                                                                                                        replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                         -- REPLICATE  |PARTITIONED|
-                                                                                                          exchange
+                                                                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                            unnest-map [$$213, $$211] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$254, 1, $$255, true, true, true)
+                                                                                                            unnest-map [$$223, $$219] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$264, 1, $$265, true, true, true) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                             -- BTREE_SEARCH  |PARTITIONED|
-                                                                                                              exchange
+                                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                assign [$$254, $$255] <- [1, 1]
+                                                                                                                assign [$$264, $$265] <- [1, 1] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                 -- ASSIGN  |PARTITIONED|
-                                                                                                                  empty-tuple-source
+                                                                                                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                                                      exchange
+                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                        assign [$$215, $$214] <- [$$220, $$212] project: [$$215, $$214]
+                                                                                                        assign [$$225, $$224] <- [$$230, $$222] project: [$$225, $$224] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                         -- ASSIGN  |PARTITIONED|
-                                                                                                          exchange
+                                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                            replicate
+                                                                                                            replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                             -- REPLICATE  |PARTITIONED|
-                                                                                                              exchange
-                                                                                                              -- HASH_PARTITION_EXCHANGE [$$212]  |PARTITIONED|
-                                                                                                                assign [$$220, $$212] <- [true, $$221.getField(10)] project: [$$220, $$212]
+                                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                              -- HASH_PARTITION_EXCHANGE [$$222]  |PARTITIONED|
+                                                                                                                assign [$$230, $$222] <- [true, $$231.getField(10)] project: [$$230, $$222] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                 -- ASSIGN  |PARTITIONED|
-                                                                                                                  assign [$$221] <- [$$store_sales] project: [$$221]
+                                                                                                                  assign [$$231] <- [$$store_sales] project: [$$231] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                   -- ASSIGN  |PARTITIONED|
-                                                                                                                    exchange
+                                                                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                      replicate
+                                                                                                                      replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                       -- REPLICATE  |PARTITIONED|
-                                                                                                                        exchange
+                                                                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                          project ([$$store_sales])
+                                                                                                                          project ([$$store_sales]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                           -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                                            exchange
+                                                                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                              data-scan []<-[$$154, $$155, $$store_sales] <- tpcds.store_sales
+                                                                                                                              data-scan []<-[$$164, $$165, $$store_sales] <- tpcds.store_sales [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                               -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                                                                exchange
+                                                                                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                  empty-tuple-source
+                                                                                                                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                  exchange
-                                                                  -- HASH_PARTITION_EXCHANGE [$$163]  |PARTITIONED|
-                                                                    assign [$$173, $$127, $$163] <- [true, $$store_sales.getField(14), $$store_sales.getField(10)] project: [$$127, $$173, $$163]
+                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                  -- HASH_PARTITION_EXCHANGE [$$173]  |PARTITIONED|
+                                                                    assign [$$183, $$137, $$173] <- [true, $$store_sales.getField(14), $$store_sales.getField(10)] project: [$$137, $$183, $$173] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ASSIGN  |PARTITIONED|
-                                                                      exchange
+                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        replicate
+                                                                        replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                         -- REPLICATE  |PARTITIONED|
-                                                                          exchange
+                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            project ([$$store_sales])
+                                                                            project ([$$store_sales]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                             -- STREAM_PROJECT  |PARTITIONED|
-                                                                              exchange
+                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                data-scan []<-[$$154, $$155, $$store_sales] <- tpcds.store_sales
+                                                                                data-scan []<-[$$164, $$165, $$store_sales] <- tpcds.store_sales [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                  exchange
+                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                    empty-tuple-source
+                                                                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                            exchange
-                            -- HASH_PARTITION_EXCHANGE [$$229]  |PARTITIONED|
-                              assign [$$230, $$144] <- [true, {"$2": $$160}] project: [$$144, $$230, $$229]
+                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- HASH_PARTITION_EXCHANGE [$$239]  |PARTITIONED|
+                              assign [$$240, $$154] <- [true, {"$2": $$170}] project: [$$154, $$240, $$239] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- ASSIGN  |PARTITIONED|
-                                project ([$$160, $$229])
+                                project ([$$170, $$239]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- STREAM_PROJECT  |PARTITIONED|
-                                  exchange
+                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    group by ([$$190 := $$240; $$229 := $$241]) decor ([]) {
-                                              aggregate [$$160] <- [agg-global-sql-avg($$239)]
+                                    group by ([$$200 := $$250; $$239 := $$251]) decor ([]) {
+                                              aggregate [$$170] <- [agg-global-sql-avg($$249)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- AGGREGATE  |LOCAL|
-                                                nested tuple source
+                                                nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                           }
-                                    -- SORT_GROUP_BY[$$240, $$241]  |PARTITIONED|
-                                      exchange
-                                      -- HASH_PARTITION_EXCHANGE [$$240, $$241]  |PARTITIONED|
-                                        group by ([$$240 := $$188; $$241 := $$191]) decor ([]) {
-                                                  aggregate [$$239] <- [agg-local-sql-avg($$142)]
+                                           } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                    -- SORT_GROUP_BY[$$250, $$251]  |PARTITIONED|
+                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- HASH_PARTITION_EXCHANGE [$$250, $$251]  |PARTITIONED|
+                                        group by ([$$250 := $$198; $$251 := $$201]) decor ([]) {
+                                                  aggregate [$$249] <- [agg-local-sql-avg($$152)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                   -- AGGREGATE  |LOCAL|
-                                                    select (not(is-missing($$189)))
+                                                    select (not(is-missing($$199))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                     -- STREAM_SELECT  |LOCAL|
-                                                      project ([$$142, $$189])
+                                                      project ([$$152, $$199]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                       -- STREAM_PROJECT  |LOCAL|
-                                                        nested tuple source
+                                                        nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                               }
-                                        -- PRE_CLUSTERED_GROUP_BY[$$188, $$191]  |PARTITIONED|
-                                          exchange
+                                               } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- PRE_CLUSTERED_GROUP_BY[$$198, $$201]  |PARTITIONED|
+                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            order (ASC, $$188) (ASC, $$191)
-                                            -- STABLE_SORT [$$188(ASC), $$191(ASC)]  |PARTITIONED|
-                                              exchange
+                                            order (ASC, $$198) (ASC, $$201) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                            -- STABLE_SORT [$$198(ASC), $$201(ASC)]  |PARTITIONED|
+                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                project ([$$142, $$189, $$188, $$191])
+                                                project ([$$152, $$199, $$198, $$201]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                 -- STREAM_PROJECT  |PARTITIONED|
-                                                  exchange
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    left outer join (eq($$165, $$166))
-                                                    -- HYBRID_HASH_JOIN [$$166][$$165]  |PARTITIONED|
-                                                      exchange
-                                                      -- HASH_PARTITION_EXCHANGE [$$166]  |PARTITIONED|
-                                                        running-aggregate [$$188] <- [create-query-uid()]
+                                                    left outer join (eq($$175, $$176)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    -- HYBRID_HASH_JOIN [$$176][$$175]  |PARTITIONED|
+                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                      -- HASH_PARTITION_EXCHANGE [$$176]  |PARTITIONED|
+                                                        running-aggregate [$$198] <- [create-query-uid()] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                         -- RUNNING_AGGREGATE  |PARTITIONED|
-                                                          assign [$$166] <- [$$194.getField(0)] project: [$$191, $$166]
+                                                          assign [$$176] <- [$$203.getField(0)] project: [$$201, $$176] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- ASSIGN  |PARTITIONED|
-                                                            select (not(or(and($$258, not(is-unknown($$258)))))) project: [$$191, $$194]
+                                                            select (not(or(and($$268, not(is-unknown($$268)))))) project: [$$201, $$203] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- STREAM_SELECT  |PARTITIONED|
-                                                              assign [$$258] <- [lt(get-item($$193, 0), 25437)] project: [$$191, $$194, $$258]
+                                                              assign [$$268] <- [lt(get-item($$204, 0), 25437)] project: [$$201, $$203, $$268] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- ASSIGN  |PARTITIONED|
-                                                                exchange
+                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  group by ([$$191 := $$192]) decor ([$$193; $$194]) {
-                                                                            aggregate [] <- []
+                                                                  group by ([$$201 := $$202]) decor ([$$203; $$204]) {
+                                                                            aggregate [] <- [] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                             -- AGGREGATE  |LOCAL|
-                                                                              aggregate [] <- []
+                                                                              aggregate [] <- [] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                               -- AGGREGATE  |LOCAL|
-                                                                                select (not(is-missing($$203)))
+                                                                                select (not(is-missing($$213))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                 -- STREAM_SELECT  |LOCAL|
-                                                                                  project ([$$203])
+                                                                                  project ([$$213]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                   -- STREAM_PROJECT  |LOCAL|
-                                                                                    nested tuple source
+                                                                                    nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                         }
-                                                                  -- PRE_CLUSTERED_GROUP_BY[$$192]  |PARTITIONED|
-                                                                    exchange
+                                                                         } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                  -- PRE_CLUSTERED_GROUP_BY[$$202]  |PARTITIONED|
+                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      project ([$$194, $$193, $$203, $$192])
+                                                                      project ([$$203, $$204, $$213, $$202]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                       -- STREAM_PROJECT  |PARTITIONED|
-                                                                        exchange
+                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          left outer join (eq($$192, $$195))
-                                                                          -- HYBRID_HASH_JOIN [$$192][$$195]  |PARTITIONED|
-                                                                            exchange
+                                                                          left outer join (eq($$202, $$205)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                          -- HYBRID_HASH_JOIN [$$202][$$205]  |PARTITIONED|
+                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                              assign [$$193, $$192, $$194] <- [$$209, $$208, $$211] project: [$$193, $$192, $$194]
+                                                                              assign [$$204, $$202, $$203] <- [$$220, $$218, $$219] project: [$$204, $$202, $$203] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                               -- ASSIGN  |PARTITIONED|
-                                                                                exchange
+                                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                  replicate
+                                                                                  replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                   -- REPLICATE  |PARTITIONED|
-                                                                                    exchange
+                                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                      group by ([$$208 := $$213]) decor ([$$211]) {
-                                                                                                aggregate [$$209] <- [listify($$219)]
+                                                                                      group by ([$$218 := $$223]) decor ([$$219]) {
+                                                                                                aggregate [$$220] <- [listify($$229)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                 -- AGGREGATE  |LOCAL|
-                                                                                                  aggregate [$$219] <- [agg-sql-count(1)]
+                                                                                                  aggregate [$$229] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                   -- AGGREGATE  |LOCAL|
-                                                                                                    select (not(is-missing($$215)))
+                                                                                                    select (not(is-missing($$225))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                     -- STREAM_SELECT  |LOCAL|
-                                                                                                      project ([$$215])
+                                                                                                      project ([$$225]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- STREAM_PROJECT  |LOCAL|
-                                                                                                        nested tuple source
+                                                                                                        nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                                             }
-                                                                                      -- PRE_CLUSTERED_GROUP_BY[$$213]  |PARTITIONED|
-                                                                                        exchange
+                                                                                             } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                      -- PRE_CLUSTERED_GROUP_BY[$$223]  |PARTITIONED|
+                                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                          order (ASC, $$213)
-                                                                                          -- STABLE_SORT [$$213(ASC)]  |PARTITIONED|
-                                                                                            exchange
+                                                                                          order (ASC, $$223) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                          -- STABLE_SORT [$$223(ASC)]  |PARTITIONED|
+                                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                              project ([$$211, $$215, $$213])
+                                                                                              project ([$$219, $$225, $$223]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                               -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                exchange
+                                                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                  left outer join (eq($$214, $$213))
-                                                                                                  -- HYBRID_HASH_JOIN [$$213][$$214]  |PARTITIONED|
-                                                                                                    exchange
+                                                                                                  left outer join (eq($$224, $$223)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                                                                  -- HYBRID_HASH_JOIN [$$223][$$224]  |PARTITIONED|
+                                                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                      replicate
+                                                                                                      replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                       -- REPLICATE  |PARTITIONED|
-                                                                                                        exchange
+                                                                                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                          unnest-map [$$213, $$211] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$254, 1, $$255, true, true, true)
+                                                                                                          unnest-map [$$223, $$219] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$264, 1, $$265, true, true, true) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                           -- BTREE_SEARCH  |PARTITIONED|
-                                                                                                            exchange
+                                                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                              assign [$$254, $$255] <- [1, 1]
+                                                                                                              assign [$$264, $$265] <- [1, 1] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                               -- ASSIGN  |PARTITIONED|
-                                                                                                                empty-tuple-source
+                                                                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                                                    exchange
+                                                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                      assign [$$215, $$214] <- [$$220, $$212] project: [$$215, $$214]
+                                                                                                      assign [$$225, $$224] <- [$$230, $$222] project: [$$225, $$224] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- ASSIGN  |PARTITIONED|
-                                                                                                        exchange
+                                                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                          replicate
+                                                                                                          replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                           -- REPLICATE  |PARTITIONED|
-                                                                                                            exchange
-                                                                                                            -- HASH_PARTITION_EXCHANGE [$$212]  |PARTITIONED|
-                                                                                                              assign [$$220, $$212] <- [true, $$221.getField(10)] project: [$$220, $$212]
+                                                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                            -- HASH_PARTITION_EXCHANGE [$$222]  |PARTITIONED|
+                                                                                                              assign [$$230, $$222] <- [true, $$231.getField(10)] project: [$$230, $$222] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                               -- ASSIGN  |PARTITIONED|
-                                                                                                                assign [$$221] <- [$$store_sales] project: [$$221]
+                                                                                                                assign [$$231] <- [$$store_sales] project: [$$231] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                 -- ASSIGN  |PARTITIONED|
-                                                                                                                  exchange
+                                                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                    replicate
+                                                                                                                    replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                     -- REPLICATE  |PARTITIONED|
-                                                                                                                      exchange
+                                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                        project ([$$store_sales])
+                                                                                                                        project ([$$store_sales]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                         -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                                          exchange
+                                                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                            data-scan []<-[$$154, $$155, $$store_sales] <- tpcds.store_sales
+                                                                                                                            data-scan []<-[$$164, $$165, $$store_sales] <- tpcds.store_sales [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                             -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                                                              exchange
+                                                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                empty-tuple-source
+                                                                                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                            exchange
-                                                                            -- HASH_PARTITION_EXCHANGE [$$195]  |PARTITIONED|
-                                                                              assign [$$203] <- [true]
+                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                            -- HASH_PARTITION_EXCHANGE [$$205]  |PARTITIONED|
+                                                                              assign [$$213] <- [true] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                               -- ASSIGN  |PARTITIONED|
-                                                                                project ([$$195])
+                                                                                project ([$$205]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                 -- STREAM_PROJECT  |PARTITIONED|
-                                                                                  exchange
+                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                    group by ([$$206 := $$237; $$195 := $$238]) decor ([]) {
-                                                                                              aggregate [] <- []
+                                                                                    group by ([$$216 := $$247; $$205 := $$248]) decor ([]) {
+                                                                                              aggregate [] <- [] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                               -- AGGREGATE  |LOCAL|
-                                                                                                nested tuple source
+                                                                                                nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                                           }
-                                                                                    -- SORT_GROUP_BY[$$237, $$238]  |PARTITIONED|
-                                                                                      exchange
-                                                                                      -- HASH_PARTITION_EXCHANGE [$$237, $$238]  |PARTITIONED|
-                                                                                        group by ([$$237 := $$207; $$238 := $$208]) decor ([]) {
-                                                                                                  aggregate [] <- []
+                                                                                           } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                    -- SORT_GROUP_BY[$$247, $$248]  |PARTITIONED|
+                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                      -- HASH_PARTITION_EXCHANGE [$$247, $$248]  |PARTITIONED|
+                                                                                        group by ([$$247 := $$217; $$248 := $$218]) decor ([]) {
+                                                                                                  aggregate [] <- [] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                   -- AGGREGATE  |LOCAL|
-                                                                                                    select (not(is-missing($$220)))
+                                                                                                    select (not(is-missing($$230))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                     -- STREAM_SELECT  |LOCAL|
-                                                                                                      project ([$$220])
+                                                                                                      project ([$$230]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- STREAM_PROJECT  |LOCAL|
-                                                                                                        nested tuple source
+                                                                                                        nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                                               }
-                                                                                        -- PRE_CLUSTERED_GROUP_BY[$$207, $$208]  |PARTITIONED|
-                                                                                          exchange
+                                                                                               } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                        -- PRE_CLUSTERED_GROUP_BY[$$217, $$218]  |PARTITIONED|
+                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                            order (ASC, $$207) (ASC, $$208)
-                                                                                            -- STABLE_SORT [$$207(ASC), $$208(ASC)]  |PARTITIONED|
-                                                                                              exchange
+                                                                                            order (ASC, $$217) (ASC, $$218) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                            -- STABLE_SORT [$$217(ASC), $$218(ASC)]  |PARTITIONED|
+                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                project ([$$220, $$207, $$208])
+                                                                                                project ([$$230, $$217, $$218]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                 -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                  exchange
+                                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                    left outer join (eq($$212, $$210))
-                                                                                                    -- HYBRID_HASH_JOIN [$$210][$$212]  |PARTITIONED|
-                                                                                                      exchange
+                                                                                                    left outer join (eq($$222, $$221)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                    -- HYBRID_HASH_JOIN [$$221][$$222]  |PARTITIONED|
+                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                        replicate
+                                                                                                        replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                         -- REPLICATE  |PARTITIONED|
-                                                                                                          exchange
-                                                                                                          -- HASH_PARTITION_EXCHANGE [$$210]  |PARTITIONED|
-                                                                                                            running-aggregate [$$207] <- [create-query-uid()]
+                                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                          -- HASH_PARTITION_EXCHANGE [$$221]  |PARTITIONED|
+                                                                                                            running-aggregate [$$217] <- [create-query-uid()] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                             -- RUNNING_AGGREGATE  |PARTITIONED|
-                                                                                                              assign [$$210] <- [$$211.getField(0)] project: [$$208, $$210]
+                                                                                                              assign [$$221] <- [$$219.getField(0)] project: [$$218, $$221] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                               -- ASSIGN  |PARTITIONED|
-                                                                                                                select (lt(get-item($$209, 0), 25437)) project: [$$208, $$211]
+                                                                                                                select (lt(get-item($$220, 0), 25437)) project: [$$218, $$219] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                 -- STREAM_SELECT  |PARTITIONED|
-                                                                                                                  exchange
+                                                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                    replicate
+                                                                                                                    replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                     -- REPLICATE  |PARTITIONED|
-                                                                                                                      exchange
+                                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                        group by ([$$208 := $$213]) decor ([$$211]) {
-                                                                                                                                  aggregate [$$209] <- [listify($$219)]
+                                                                                                                        group by ([$$218 := $$223]) decor ([$$219]) {
+                                                                                                                                  aggregate [$$220] <- [listify($$229)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                   -- AGGREGATE  |LOCAL|
-                                                                                                                                    aggregate [$$219] <- [agg-sql-count(1)]
+                                                                                                                                    aggregate [$$229] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                     -- AGGREGATE  |LOCAL|
-                                                                                                                                      select (not(is-missing($$215)))
+                                                                                                                                      select (not(is-missing($$225))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                       -- STREAM_SELECT  |LOCAL|
-                                                                                                                                        project ([$$215])
+                                                                                                                                        project ([$$225]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                         -- STREAM_PROJECT  |LOCAL|
-                                                                                                                                          nested tuple source
+                                                                                                                                          nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                                                                               }
-                                                                                                                        -- PRE_CLUSTERED_GROUP_BY[$$213]  |PARTITIONED|
-                                                                                                                          exchange
+                                                                                                                               } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                                        -- PRE_CLUSTERED_GROUP_BY[$$223]  |PARTITIONED|
+                                                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                            order (ASC, $$213)
-                                                                                                                            -- STABLE_SORT [$$213(ASC)]  |PARTITIONED|
-                                                                                                                              exchange
+                                                                                                                            order (ASC, $$223) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                                            -- STABLE_SORT [$$223(ASC)]  |PARTITIONED|
+                                                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                project ([$$211, $$215, $$213])
+                                                                                                                                project ([$$219, $$225, $$223]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                 -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                                                  exchange
+                                                                                                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                    left outer join (eq($$214, $$213))
-                                                                                                                                    -- HYBRID_HASH_JOIN [$$213][$$214]  |PARTITIONED|
-                                                                                                                                      exchange
+                                                                                                                                    left outer join (eq($$224, $$223)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                                                                                                    -- HYBRID_HASH_JOIN [$$223][$$224]  |PARTITIONED|
+                                                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                        replicate
+                                                                                                                                        replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                                                         -- REPLICATE  |PARTITIONED|
-                                                                                                                                          exchange
+                                                                                                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                            unnest-map [$$213, $$211] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$254, 1, $$255, true, true, true)
+                                                                                                                                            unnest-map [$$223, $$219] <- index-search("item", 0, "Default", "tpcds", "item", false, false, 1, $$264, 1, $$265, true, true, true) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                                                                                             -- BTREE_SEARCH  |PARTITIONED|
-                                                                                                                                              exchange
+                                                                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                                assign [$$254, $$255] <- [1, 1]
+                                                                                                                                                assign [$$264, $$265] <- [1, 1] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                 -- ASSIGN  |PARTITIONED|
-                                                                                                                                                  empty-tuple-source
+                                                                                                                                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                                                                                      exchange
+                                                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                        assign [$$215, $$214] <- [$$220, $$212] project: [$$215, $$214]
+                                                                                                                                        assign [$$225, $$224] <- [$$230, $$222] project: [$$225, $$224] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                         -- ASSIGN  |PARTITIONED|
-                                                                                                                                          exchange
+                                                                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                            replicate
+                                                                                                                                            replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                             -- REPLICATE  |PARTITIONED|
-                                                                                                                                              exchange
-                                                                                                                                              -- HASH_PARTITION_EXCHANGE [$$212]  |PARTITIONED|
-                                                                                                                                                assign [$$220, $$212] <- [true, $$221.getField(10)] project: [$$220, $$212]
+                                                                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                                                              -- HASH_PARTITION_EXCHANGE [$$222]  |PARTITIONED|
+                                                                                                                                                assign [$$230, $$222] <- [true, $$231.getField(10)] project: [$$230, $$222] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                 -- ASSIGN  |PARTITIONED|
-                                                                                                                                                  assign [$$221] <- [$$store_sales] project: [$$221]
+                                                                                                                                                  assign [$$231] <- [$$store_sales] project: [$$231] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                   -- ASSIGN  |PARTITIONED|
-                                                                                                                                                    exchange
+                                                                                                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                                      replicate
+                                                                                                                                                      replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                       -- REPLICATE  |PARTITIONED|
-                                                                                                                                                        exchange
+                                                                                                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                                          project ([$$store_sales])
+                                                                                                                                                          project ([$$store_sales]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                           -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                                                                            exchange
+                                                                                                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                                              data-scan []<-[$$154, $$155, $$store_sales] <- tpcds.store_sales
+                                                                                                                                                              data-scan []<-[$$164, $$165, $$store_sales] <- tpcds.store_sales [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                               -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                                                                                                exchange
+                                                                                                                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                                                                  empty-tuple-source
+                                                                                                                                                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                                                      exchange
+                                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                        replicate
+                                                                                                        replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                         -- REPLICATE  |PARTITIONED|
-                                                                                                          exchange
-                                                                                                          -- HASH_PARTITION_EXCHANGE [$$212]  |PARTITIONED|
-                                                                                                            assign [$$220, $$212] <- [true, $$221.getField(10)] project: [$$220, $$212]
+                                                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                          -- HASH_PARTITION_EXCHANGE [$$222]  |PARTITIONED|
+                                                                                                            assign [$$230, $$222] <- [true, $$231.getField(10)] project: [$$230, $$222] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                             -- ASSIGN  |PARTITIONED|
-                                                                                                              assign [$$221] <- [$$store_sales] project: [$$221]
+                                                                                                              assign [$$231] <- [$$store_sales] project: [$$231] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                               -- ASSIGN  |PARTITIONED|
-                                                                                                                exchange
+                                                                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                  replicate
+                                                                                                                  replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                   -- REPLICATE  |PARTITIONED|
-                                                                                                                    exchange
+                                                                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                      project ([$$store_sales])
+                                                                                                                      project ([$$store_sales]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                       -- STREAM_PROJECT  |PARTITIONED|
-                                                                                                                        exchange
+                                                                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                          data-scan []<-[$$154, $$155, $$store_sales] <- tpcds.store_sales
+                                                                                                                          data-scan []<-[$$164, $$165, $$store_sales] <- tpcds.store_sales [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                           -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                                                            exchange
+                                                                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                                              empty-tuple-source
+                                                                                                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                      exchange
-                                                      -- HASH_PARTITION_EXCHANGE [$$165]  |PARTITIONED|
-                                                        assign [$$189, $$142, $$165] <- [true, $$store_sales.getField(22), $$store_sales.getField(10)] project: [$$142, $$189, $$165]
+                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                      -- HASH_PARTITION_EXCHANGE [$$175]  |PARTITIONED|
+                                                        assign [$$199, $$152, $$175] <- [true, $$store_sales.getField(22), $$store_sales.getField(10)] project: [$$152, $$199, $$175] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                         -- ASSIGN  |PARTITIONED|
-                                                          assign [$$store_sales] <- [$$store_sales] project: [$$store_sales]
+                                                          assign [$$store_sales] <- [$$store_sales] project: [$$store_sales] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- ASSIGN  |PARTITIONED|
-                                                            exchange
+                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              replicate
+                                                              replicate [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- REPLICATE  |PARTITIONED|
-                                                                exchange
+                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  project ([$$store_sales])
+                                                                  project ([$$store_sales]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                   -- STREAM_PROJECT  |PARTITIONED|
-                                                                    exchange
+                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      data-scan []<-[$$154, $$155, $$store_sales] <- tpcds.store_sales
+                                                                      data-scan []<-[$$164, $$165, $$store_sales] <- tpcds.store_sales [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                       -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                        exchange
+                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          empty-tuple-source
+                                                                          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/optimizerts/results_cbo/ASTERIXDB-2402.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ASTERIXDB-2402.plan
index 957048d362..8569ca1db9 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ASTERIXDB-2402.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ASTERIXDB-2402.plan
@@ -1,168 +1,168 @@
-distribute result [$$237]
+distribute result [$$253]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    project ([$$237])
+    project ([$$253])
     -- STREAM_PROJECT  |PARTITIONED|
       subplan {
-                aggregate [$$237] <- [listify($$236)]
+                aggregate [$$253] <- [listify($$252)]
                 -- AGGREGATE  |LOCAL|
-                  assign [$$236] <- [{"channelExecutionTime": $$267, "result": $$268, "BrokerEndpoint": $$BrokerEndpoint}]
+                  assign [$$252] <- [{"channelExecutionTime": $$283, "result": $$284, "BrokerEndpoint": $$BrokerEndpoint}]
                   -- ASSIGN  |LOCAL|
-                    group by ([$$BrokerEndpoint := $$240]) decor ([$$267 := $$269; $$268 := $$270]) {
+                    group by ([$$BrokerEndpoint := $$256]) decor ([$$283 := $$285; $$284 := $$286]) {
                               aggregate [] <- []
                               -- AGGREGATE  |LOCAL|
                                 nested tuple source
                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                            }
-                    -- MICRO_PRE_CLUSTERED_GROUP_BY[$$240]  |LOCAL|
-                      order (ASC, $$240)
-                      -- MICRO_STABLE_SORT [$$240(ASC)]  |LOCAL|
-                        assign [$$240] <- [$$sub.getField("BrokerEndpoint")] project: [$$270, $$269, $$240]
+                    -- MICRO_PRE_CLUSTERED_GROUP_BY[$$256]  |LOCAL|
+                      order (ASC, $$256)
+                      -- MICRO_STABLE_SORT [$$256(ASC)]  |LOCAL|
+                        assign [$$256] <- [$$sub.getField("BrokerEndpoint")] project: [$$286, $$285, $$256]
                         -- ASSIGN  |LOCAL|
-                          unnest $$sub <- scan-collection($$229) project: [$$270, $$269, $$sub]
+                          unnest $$sub <- scan-collection($$245) project: [$$286, $$285, $$sub]
                           -- UNNEST  |LOCAL|
-                            project ([$$270, $$269, $$229])
+                            project ([$$286, $$285, $$245])
                             -- STREAM_PROJECT  |LOCAL|
                               subplan {
-                                        aggregate [$$229] <- [listify($$228)]
+                                        aggregate [$$245] <- [listify($$244)]
                                         -- AGGREGATE  |LOCAL|
-                                          assign [$$228] <- [{"sub": $$sub}]
+                                          assign [$$244] <- [{"sub": $$sub}]
                                           -- ASSIGN  |LOCAL|
-                                            unnest $$sub <- scan-collection($$266) project: [$$sub]
+                                            unnest $$sub <- scan-collection($$282) project: [$$sub]
                                             -- UNNEST  |LOCAL|
-                                              project ([$$266])
+                                              project ([$$282])
                                               -- STREAM_PROJECT  |LOCAL|
                                                 nested tuple source
                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                      }
                               -- SUBPLAN  |LOCAL|
-                                project ([$$270, $$269, $$266])
+                                project ([$$286, $$285, $$282])
                                 -- STREAM_PROJECT  |LOCAL|
                                   nested tuple source
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
              }
       -- SUBPLAN  |PARTITIONED|
-        project ([$$270, $$269, $$266])
+        project ([$$286, $$285, $$282])
         -- STREAM_PROJECT  |PARTITIONED|
           commit
           -- COMMIT  |PARTITIONED|
-            project ([$$270, $$269, $$266, $$224])
+            project ([$$286, $$285, $$282, $$240])
             -- STREAM_PROJECT  |PARTITIONED|
               exchange
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                insert into channels.EmergenciesNearMeChannelResults from record: $$241 partitioned by [$$224]
+                insert into channels.EmergenciesNearMeChannelResults from record: $$257 partitioned by [$$240]
                 -- INSERT_DELETE  |PARTITIONED|
                   exchange
-                  -- HASH_PARTITION_EXCHANGE [$$224]  |PARTITIONED|
-                    assign [$$270, $$269, $$266, $$224] <- [$$241.getField("result"), $$241.getField("channelExecutionTime"), $$241.getField("brokerSubIds"), $$241.getField(0)]
+                  -- HASH_PARTITION_EXCHANGE [$$240]  |PARTITIONED|
+                    assign [$$286, $$285, $$282, $$240] <- [$$257.getField("result"), $$257.getField("channelExecutionTime"), $$257.getField("brokerSubIds"), $$257.getField(0)]
                     -- ASSIGN  |PARTITIONED|
-                      assign [$$241] <- [cast(check-unknown(put-autogenerated-key($$222, "resultId")))] project: [$$241]
+                      assign [$$257] <- [cast(check-unknown(put-autogenerated-key($$238, "resultId")))] project: [$$257]
                       -- ASSIGN  |PARTITIONED|
-                        assign [$$222] <- [{"result": $$result, "channelExecutionTime": current-datetime(), "channelSubId": $$276, "deliveryTime": current-datetime(), "brokerSubIds": $$221}] project: [$$222]
+                        assign [$$238] <- [{"result": $$result, "channelExecutionTime": current-datetime(), "channelSubId": $$292, "deliveryTime": current-datetime(), "brokerSubIds": $$237}] project: [$$238]
                         -- ASSIGN  |PARTITIONED|
-                          project ([$$221, $$276, $$result])
+                          project ([$$237, $$292, $$result])
                           -- STREAM_PROJECT  |PARTITIONED|
                             exchange
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              group by ([$$279 := $$277]) decor ([$$276; $$result]) {
-                                        aggregate [$$221] <- [listify({"BrokerEndPoint": $$263, "brokerSubId": $$248})]
+                              group by ([$$295 := $$293]) decor ([$$292; $$result]) {
+                                        aggregate [$$237] <- [listify({"BrokerEndPoint": $$279, "brokerSubId": $$264})]
                                         -- AGGREGATE  |LOCAL|
-                                          select (not(is-missing($$278)))
+                                          select (not(is-missing($$294)))
                                           -- STREAM_SELECT  |LOCAL|
-                                            project ([$$263, $$248, $$278])
+                                            project ([$$279, $$264, $$294])
                                             -- STREAM_PROJECT  |LOCAL|
                                               nested tuple source
                                               -- NESTED_TUPLE_SOURCE  |LOCAL|
                                      }
-                              -- PRE_CLUSTERED_GROUP_BY[$$277]  |PARTITIONED|
+                              -- PRE_CLUSTERED_GROUP_BY[$$293]  |PARTITIONED|
                                 exchange
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  order (ASC, $$277)
-                                  -- STABLE_SORT [$$277(ASC)]  |PARTITIONED|
+                                  order (ASC, $$293)
+                                  -- STABLE_SORT [$$293(ASC)]  |PARTITIONED|
                                     exchange
-                                    -- HASH_PARTITION_EXCHANGE [$$277]  |PARTITIONED|
-                                      project ([$$result, $$276, $$263, $$248, $$278, $$277])
+                                    -- HASH_PARTITION_EXCHANGE [$$293]  |PARTITIONED|
+                                      project ([$$result, $$292, $$279, $$264, $$294, $$293])
                                       -- STREAM_PROJECT  |PARTITIONED|
                                         exchange
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          left outer join (eq($$247, $$276))
-                                          -- HYBRID_HASH_JOIN [$$276][$$247]  |PARTITIONED|
+                                          left outer join (eq($$263, $$292))
+                                          -- HYBRID_HASH_JOIN [$$292][$$263]  |PARTITIONED|
                                             exchange
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              running-aggregate [$$277] <- [create-query-uid()]
+                                              running-aggregate [$$293] <- [create-query-uid()]
                                               -- RUNNING_AGGREGATE  |PARTITIONED|
-                                                unnest $$result <- scan-collection($$201) project: [$$result, $$276]
+                                                unnest $$result <- scan-collection($$217) project: [$$result, $$292]
                                                 -- UNNEST  |PARTITIONED|
                                                   exchange
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    group by ([$$276 := $$243]) decor ([]) {
-                                                              aggregate [$$201] <- [listify({"report": $$r, "shelters": $$191})]
+                                                    group by ([$$292 := $$259]) decor ([]) {
+                                                              aggregate [$$217] <- [listify({"report": $$r, "shelters": $$207})]
                                                               -- AGGREGATE  |LOCAL|
-                                                                group by ([$$272 := $$244; $$273 := $$245]) decor ([$$243; $$262; $$sub; $$r; $$u; $$252; $$253; $$254]) {
-                                                                          aggregate [$$191] <- [listify({"location": $$242})]
+                                                                group by ([$$288 := $$260; $$289 := $$261]) decor ([$$r; $$u; $$259; $$278; $$268; $$269; $$270; $$sub]) {
+                                                                          aggregate [$$207] <- [listify({"location": $$258})]
                                                                           -- AGGREGATE  |LOCAL|
-                                                                            select (not(is-missing($$246)))
+                                                                            select (not(is-missing($$262)))
                                                                             -- STREAM_SELECT  |LOCAL|
-                                                                              project ([$$246, $$242])
+                                                                              project ([$$262, $$258])
                                                                               -- STREAM_PROJECT  |LOCAL|
                                                                                 nested tuple source
                                                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                                        }
-                                                                -- MICRO_PRE_CLUSTERED_GROUP_BY[$$244, $$245]  |LOCAL|
-                                                                  select (and(not(is-missing($$274)), not(is-missing($$275))))
+                                                                -- MICRO_PRE_CLUSTERED_GROUP_BY[$$260, $$261]  |LOCAL|
+                                                                  select (and(not(is-missing($$290)), not(is-missing($$291))))
                                                                   -- STREAM_SELECT  |LOCAL|
                                                                     nested tuple source
                                                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                            }
-                                                    -- PRE_CLUSTERED_GROUP_BY[$$243]  |PARTITIONED|
+                                                    -- PRE_CLUSTERED_GROUP_BY[$$259]  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        order (ASC, $$243) (ASC, $$244) (ASC, $$245)
-                                                        -- STABLE_SORT [$$243(ASC), $$244(ASC), $$245(ASC)]  |PARTITIONED|
+                                                        order (ASC, $$259) (ASC, $$260) (ASC, $$261)
+                                                        -- STABLE_SORT [$$259(ASC), $$260(ASC), $$261(ASC)]  |PARTITIONED|
                                                           exchange
-                                                          -- HASH_PARTITION_EXCHANGE [$$243]  |PARTITIONED|
-                                                            select (spatial-intersect($$242, $$254)) retain-untrue ($$246 <- missing)
+                                                          -- HASH_PARTITION_EXCHANGE [$$259]  |PARTITIONED|
+                                                            select (spatial-intersect($$258, $$270)) retain-untrue ($$262 <- missing)
                                                             -- STREAM_SELECT  |PARTITIONED|
-                                                              assign [$$242] <- [$$s.getField(1)] project: [$$243, $$sub, $$252, $$244, $$r, $$253, $$262, $$274, $$245, $$u, $$275, $$254, $$246, $$242]
+                                                              assign [$$258] <- [$$s.getField(1)] project: [$$259, $$sub, $$268, $$260, $$r, $$269, $$278, $$290, $$261, $$u, $$291, $$270, $$262, $$258]
                                                               -- ASSIGN  |PARTITIONED|
-                                                                project ([$$243, $$sub, $$252, $$244, $$r, $$253, $$262, $$274, $$245, $$u, $$275, $$254, $$246, $$s])
+                                                                project ([$$259, $$sub, $$268, $$260, $$r, $$269, $$278, $$290, $$261, $$u, $$291, $$270, $$262, $$s])
                                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                                   exchange
                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                    left-outer-unnest-map [$$246, $$s] <- index-search("Shelters", 0, "Default", "channels", "Shelters", true, false, 1, $$299, 1, $$299, true, true, true)
+                                                                    left-outer-unnest-map [$$262, $$s] <- index-search("Shelters", 0, "Default", "channels", "Shelters", true, false, 1, $$315, 1, $$315, true, true, true)
                                                                     -- BTREE_SEARCH  |PARTITIONED|
                                                                       exchange
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        order (ASC, $$299)
-                                                                        -- STABLE_SORT [$$299(ASC)]  |PARTITIONED|
+                                                                        order (ASC, $$315)
+                                                                        -- STABLE_SORT [$$315(ASC)]  |PARTITIONED|
                                                                           exchange
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            project ([$$243, $$sub, $$252, $$244, $$r, $$253, $$262, $$274, $$245, $$u, $$275, $$254, $$299])
+                                                                            project ([$$259, $$sub, $$268, $$260, $$r, $$269, $$278, $$290, $$261, $$u, $$291, $$270, $$315])
                                                                             -- STREAM_PROJECT  |PARTITIONED|
                                                                               exchange
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                left-outer-unnest-map [$$295, $$296, $$297, $$298, $$299] <- index-search("s_location", 1, "Default", "channels", "Shelters", true, true, 4, $$291, $$292, $$293, $$294)
+                                                                                left-outer-unnest-map [$$311, $$312, $$313, $$314, $$315] <- index-search("s_location", 1, "Default", "channels", "Shelters", true, true, 4, $$307, $$308, $$309, $$310)
                                                                                 -- RTREE_SEARCH  |PARTITIONED|
                                                                                   exchange
                                                                                   -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                                    assign [$$291, $$292, $$293, $$294] <- [create-mbr($$254, 2, 0), create-mbr($$254, 2, 1), create-mbr($$254, 2, 2), create-mbr($$254, 2, 3)]
+                                                                                    assign [$$307, $$308, $$309, $$310] <- [create-mbr($$270, 2, 0), create-mbr($$270, 2, 1), create-mbr($$270, 2, 2), create-mbr($$270, 2, 3)]
                                                                                     -- ASSIGN  |PARTITIONED|
                                                                                       exchange
                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                        left outer join (and(spatial-intersect($$253, $$254), eq($$245, $$252)))
-                                                                                        -- HYBRID_HASH_JOIN [$$252][$$245]  |PARTITIONED|
+                                                                                        left outer join (and(spatial-intersect($$269, $$270), eq($$261, $$268)))
+                                                                                        -- HYBRID_HASH_JOIN [$$268][$$261]  |PARTITIONED|
                                                                                           exchange
-                                                                                          -- HASH_PARTITION_EXCHANGE [$$252]  |PARTITIONED|
+                                                                                          -- HASH_PARTITION_EXCHANGE [$$268]  |PARTITIONED|
                                                                                             left outer join (true)
                                                                                             -- NESTED_LOOP  |PARTITIONED|
                                                                                               exchange
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                assign [$$252] <- [$$sub.getField("param0")]
+                                                                                                assign [$$268] <- [$$sub.getField("param0")]
                                                                                                 -- ASSIGN  |PARTITIONED|
                                                                                                   exchange
                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                    data-scan []<-[$$243, $$sub] <- channels.EmergenciesNearMeChannelChannelSubscriptions
+                                                                                                    data-scan []<-[$$259, $$sub] <- channels.EmergenciesNearMeChannelChannelSubscriptions
                                                                                                     -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                       exchange
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -170,15 +170,15 @@ distribute result [$$237]
                                                                                                         -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                                               exchange
                                                                                               -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                                                assign [$$274] <- [true]
+                                                                                                assign [$$290] <- [true]
                                                                                                 -- ASSIGN  |PARTITIONED|
-                                                                                                  select (gt($$262, numeric-subtract(current-datetime(), day_time_duration: {PT10S })))
+                                                                                                  select (gt($$278, numeric-subtract(current-datetime(), day_time_duration: {PT10S })))
                                                                                                   -- STREAM_SELECT  |PARTITIONED|
-                                                                                                    assign [$$253, $$262] <- [$$r.getField(2), $$r.getField(3)]
+                                                                                                    assign [$$269, $$278] <- [$$r.getField(2), $$r.getField(3)]
                                                                                                     -- ASSIGN  |PARTITIONED|
                                                                                                       exchange
                                                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                        data-scan []<-[$$244, $$r] <- channels.Reports
+                                                                                                        data-scan []<-[$$260, $$r] <- channels.Reports
                                                                                                         -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                           exchange
                                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -186,33 +186,33 @@ distribute result [$$237]
                                                                                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                                           exchange
                                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                            assign [$$275, $$254] <- [true, $$u.getField(0)]
+                                                                                            assign [$$291, $$270] <- [true, $$u.getField(0)]
                                                                                             -- ASSIGN  |PARTITIONED|
                                                                                               exchange
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                data-scan []<-[$$245, $$u] <- channels.UserLocations
+                                                                                                data-scan []<-[$$261, $$u] <- channels.UserLocations
                                                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                                   exchange
                                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                                     empty-tuple-source
                                                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                             exchange
-                                            -- HASH_PARTITION_EXCHANGE [$$247]  |PARTITIONED|
-                                              assign [$$278] <- [true]
+                                            -- HASH_PARTITION_EXCHANGE [$$263]  |PARTITIONED|
+                                              assign [$$294] <- [true]
                                               -- ASSIGN  |PARTITIONED|
-                                                project ([$$248, $$247, $$263])
+                                                project ([$$264, $$263, $$279])
                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                   exchange
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    join (and(eq($$258, $$249), eq($$260, $$250)))
-                                                    -- HYBRID_HASH_JOIN [$$258, $$260][$$249, $$250]  |PARTITIONED|
+                                                    join (and(eq($$274, $$265), eq($$276, $$266)))
+                                                    -- HYBRID_HASH_JOIN [$$274, $$276][$$265, $$266]  |PARTITIONED|
                                                       exchange
-                                                      -- HASH_PARTITION_EXCHANGE [$$258, $$260]  |PARTITIONED|
-                                                        assign [$$260, $$258] <- [$$bs.getField("BrokerName"), $$bs.getField("DataverseName")] project: [$$248, $$247, $$258, $$260]
+                                                      -- HASH_PARTITION_EXCHANGE [$$274, $$276]  |PARTITIONED|
+                                                        assign [$$276, $$274] <- [$$bs.getField("BrokerName"), $$bs.getField("DataverseName")] project: [$$264, $$263, $$274, $$276]
                                                         -- ASSIGN  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            data-scan []<-[$$247, $$248, $$bs] <- channels.EmergenciesNearMeChannelBrokerSubscriptions
+                                                            data-scan []<-[$$263, $$264, $$bs] <- channels.EmergenciesNearMeChannelBrokerSubscriptions
                                                             -- DATASOURCE_SCAN  |PARTITIONED|
                                                               exchange
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -220,11 +220,11 @@ distribute result [$$237]
                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                       exchange
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        assign [$$263] <- [$$b.getField("BrokerEndPoint")] project: [$$263, $$249, $$250]
+                                                        assign [$$279] <- [$$b.getField("BrokerEndPoint")] project: [$$279, $$265, $$266]
                                                         -- ASSIGN  |PARTITIONED|
                                                           exchange
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            data-scan []<-[$$249, $$250, $$b] <- channels.Broker
+                                                            data-scan []<-[$$265, $$266, $$b] <- channels.Broker
                                                             -- DATASOURCE_SCAN  |PARTITIONED|
                                                               exchange
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q16.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q16.plan
index d2a0c9b250..f727f5716d 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q16.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q16.plan
@@ -1,82 +1,82 @@
-distribute result [$$128] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+distribute result [$$149] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+  exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$128] <- [{"i_name": $$i_name, "brand": $#1, "i_price": $$i_price, "supplier_cnt": $$139}] project: [$$128] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+    assign [$$149] <- [{"i_name": $$i_name, "brand": $#1, "i_price": $$i_price, "supplier_cnt": $$160}] project: [$$149] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
-      -- SORT_MERGE_EXCHANGE [$$139(DESC) ]  |PARTITIONED|
-        order (DESC, $$139) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
-        -- STABLE_SORT [$$139(DESC)]  |PARTITIONED|
-          exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+      exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
+      -- SORT_MERGE_EXCHANGE [$$160(DESC) ]  |PARTITIONED|
+        order (DESC, $$160) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
+        -- STABLE_SORT [$$160(DESC)]  |PARTITIONED|
+          exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            group by ([$$i_name := $$129; $#1 := $$130; $$i_price := $$131]) decor ([]) {
-                      aggregate [$$139] <- [agg-sql-count($$150)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+            group by ([$$i_name := $$150; $#1 := $$151; $$i_price := $$152]) decor ([]) {
+                      aggregate [$$160] <- [agg-sql-count($$171)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |LOCAL|
-                        distinct ([$$150]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                        distinct ([$$171]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- MICRO_PRE_SORTED_DISTINCT_BY  |LOCAL|
-                          order (ASC, $$150) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                          -- MICRO_STABLE_SORT [$$150(ASC)]  |LOCAL|
-                            assign [$$150] <- [numeric-mod(numeric-multiply($$143, $$144), 10000)] project: [$$150] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          order (ASC, $$171) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- MICRO_STABLE_SORT [$$171(ASC)]  |LOCAL|
+                            assign [$$171] <- [numeric-mod(numeric-multiply($$164, $$165), 10000)] project: [$$171] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- ASSIGN  |LOCAL|
-                              project ([$$143, $$144]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                              project ([$$164, $$165]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- STREAM_PROJECT  |LOCAL|
                                 nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
-                   } [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
-            -- PRE_CLUSTERED_GROUP_BY[$$129, $$130, $$131]  |PARTITIONED|
-              exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                   } [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
+            -- PRE_CLUSTERED_GROUP_BY[$$150, $$151, $$152]  |PARTITIONED|
+              exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                order (ASC, $$129) (ASC, $$130) (ASC, $$131) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
-                -- STABLE_SORT [$$129(ASC), $$130(ASC), $$131(ASC)]  |PARTITIONED|
-                  exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
-                  -- HASH_PARTITION_EXCHANGE [$$129, $$130, $$131]  |PARTITIONED|
-                    assign [$$130] <- [substring1($$132, 1, 3)] project: [$$143, $$144, $$129, $$130, $$131] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                order (ASC, $$150) (ASC, $$151) (ASC, $$152) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
+                -- STABLE_SORT [$$150(ASC), $$151(ASC), $$152(ASC)]  |PARTITIONED|
+                  exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
+                  -- HASH_PARTITION_EXCHANGE [$$150, $$151, $$152]  |PARTITIONED|
+                    assign [$$151] <- [substring1($$153, 1, 3)] project: [$$164, $$165, $$150, $$151, $$152] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                     -- ASSIGN  |PARTITIONED|
-                      select ($$111) project: [$$129, $$131, $$132, $$144, $$143] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                      select ($$132) project: [$$150, $$152, $$153, $$165, $$164] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                       -- STREAM_SELECT  |PARTITIONED|
-                        project ([$$111, $$129, $$131, $$132, $$144, $$143]) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                        project ([$$132, $$150, $$152, $$153, $$165, $$164]) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                         -- STREAM_PROJECT  |PARTITIONED|
-                          exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                          exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            group by ([$$146 := $$133; $$147 := $$134]) decor ([$$129; $$131; $$132; $$144 := $$138; $$143 := $$141]) {
-                                      aggregate [$$111] <- [empty-stream()] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            group by ([$$167 := $$154; $$168 := $$155]) decor ([$$150; $$152; $$153; $$165 := $$159; $$164 := $$162]) {
+                                      aggregate [$$132] <- [empty-stream()] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                       -- AGGREGATE  |LOCAL|
-                                        select (not(is-missing($$145))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        select (not(is-missing($$166))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                         -- STREAM_SELECT  |LOCAL|
-                                          project ([$$145]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                          project ([$$166]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- STREAM_PROJECT  |LOCAL|
                                             nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                   } [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
-                            -- PRE_CLUSTERED_GROUP_BY[$$133, $$134]  |PARTITIONED|
-                              exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                                   } [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
+                            -- PRE_CLUSTERED_GROUP_BY[$$154, $$155]  |PARTITIONED|
+                              exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                order (ASC, $$133) (ASC, $$134) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
-                                -- STABLE_SORT [$$133(ASC), $$134(ASC)]  |PARTITIONED|
-                                  exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                                order (ASC, $$154) (ASC, $$155) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
+                                -- STABLE_SORT [$$154(ASC), $$155(ASC)]  |PARTITIONED|
+                                  exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    project ([$$129, $$131, $$132, $$145, $$133, $$134, $$138, $$141]) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                                    project ([$$150, $$152, $$153, $$166, $$154, $$155, $$159, $$162]) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                                     -- STREAM_PROJECT  |PARTITIONED|
-                                      exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.000015E12]
+                                      exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.500015E12]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        join (eq($$137, $$138)) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 1.000004E12, total-cost: 2.000015E12]
-                                        -- HYBRID_HASH_JOIN [$$138][$$137]  |PARTITIONED|
+                                        join (eq($$158, $$159)) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 5.00004E11, total-cost: 1.500015E12]
+                                        -- HYBRID_HASH_JOIN [$$159][$$158]  |PARTITIONED|
                                           exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            project ([$$145, $$133, $$138, $$141]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            project ([$$166, $$154, $$159, $$162]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                             -- STREAM_PROJECT  |PARTITIONED|
                                               exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                left outer join (not(if-missing-or-null(neq(numeric-mod(numeric-multiply($$141, $$138), 10000), $$105), false))) [cardinality: 1.0E12, doc-size: -2.0, op-cost: 1.0E12, total-cost: 1.000006E12]
+                                                left outer join (not(if-missing-or-null(neq(numeric-mod(numeric-multiply($$162, $$159), 10000), $$126), false))) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 1.0E12, total-cost: 1.000006E12]
                                                 -- NESTED_LOOP  |PARTITIONED|
                                                   exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    assign [$$138, $$141] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$133, $$138, $$141] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    assign [$$159, $$162] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$154, $$159, $$162] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- ASSIGN  |PARTITIONED|
                                                       exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        data-scan []<-[$$133, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        data-scan []<-[$$154, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                         -- DATASOURCE_SCAN  |PARTITIONED|
                                                           exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -84,17 +84,17 @@ distribute result [$$128] [cardinality: 9.223372036854776E16, doc-size: -3.0, op
                                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                   exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                   -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                    assign [$$145] <- [true] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    assign [$$166] <- [true] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                     -- ASSIGN  |PARTITIONED|
-                                                      select (like($$su.getField("su_comment"), "%Customer%Complaints%")) project: [$$105] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      select (like($$su.getField("su_comment"), "%Customer%Complaints%")) project: [$$126] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- STREAM_SELECT  |PARTITIONED|
-                                                        assign [$$105] <- [$$su.getField("su_suppkey")] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                        assign [$$126] <- [$$su.getField("su_suppkey")] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                         -- ASSIGN  |PARTITIONED|
                                                           project ([$$su]) [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|
-                                                              data-scan []<-[$$135, $$su] <- test.supplier [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                              data-scan []<-[$$156, $$su] <- test.supplier [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
                                                               -- DATASOURCE_SCAN  |PARTITIONED|
                                                                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -102,13 +102,13 @@ distribute result [$$128] [cardinality: 9.223372036854776E16, doc-size: -3.0, op
                                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                           exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                           -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                            select (not(like($$132, "zz%"))) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            select (not(and(ge($$153, "zz"), lt($$153, "z{")))) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                             -- STREAM_SELECT  |PARTITIONED|
-                                              assign [$$131, $$129, $$132, $$137] <- [$$i.getField("i_price"), $$i.getField("i_name"), $$i.getField("i_data"), $$i.getField("i_id")] project: [$$134, $$131, $$129, $$132, $$137] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              assign [$$152, $$150, $$153, $$158] <- [$$i.getField("i_price"), $$i.getField("i_name"), $$i.getField("i_data"), $$i.getField("i_id")] project: [$$155, $$152, $$150, $$153, $$158] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                               -- ASSIGN  |PARTITIONED|
                                                 exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  data-scan []<-[$$134, $$i] <- test.item [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  data-scan []<-[$$155, $$i] <- test.item [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                   -- DATASOURCE_SCAN  |PARTITIONED|
                                                     exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested_loj2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested_loj2.plan
index 5ba84d5276..2e92af9218 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested_loj2.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested_loj2.plan
@@ -1,64 +1,64 @@
-distribute result [$$75] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+distribute result [$$80] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
   exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$75] <- [{"cust": $$c, "orders": $$73}] project: [$$75] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+    assign [$$80] <- [{"cust": $$c, "orders": $$78}] project: [$$80] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
     -- ASSIGN  |PARTITIONED|
-      project ([$$73, $$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+      project ([$$78, $$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
       -- STREAM_PROJECT  |PARTITIONED|
         exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-          group by ([$$87 := $$76]) decor ([$$c]) {
-                    aggregate [$$73] <- [listify({"order": $$o, "items": $$67})] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+          group by ([$$92 := $$81]) decor ([$$c]) {
+                    aggregate [$$78] <- [listify({"order": $$o, "items": $$72})] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- AGGREGATE  |LOCAL|
-                      group by ([$$85 := $$77]) decor ([$$80; $$c; $$o; $$76]) {
-                                aggregate [$$67] <- [listify($$l)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                      group by ([$$90 := $$82]) decor ([$$81; $$85; $$c; $$o]) {
+                                aggregate [$$72] <- [listify($$l)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- AGGREGATE  |LOCAL|
-                                  select (not(is-missing($$84))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                  select (not(is-missing($$89))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- STREAM_SELECT  |LOCAL|
-                                    project ([$$l, $$84]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                    project ([$$l, $$89]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                     -- STREAM_PROJECT  |LOCAL|
                                       nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                              } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                      -- MICRO_PRE_CLUSTERED_GROUP_BY[$$77]  |LOCAL|
-                        select (not(is-missing($$86))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                      -- MICRO_PRE_CLUSTERED_GROUP_BY[$$82]  |LOCAL|
+                        select (not(is-missing($$91))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- STREAM_SELECT  |LOCAL|
                           nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                  } [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-          -- PRE_CLUSTERED_GROUP_BY[$$76]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$81]  |PARTITIONED|
             exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              order (ASC, $$76) (ASC, $$77) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-              -- STABLE_SORT [$$76(ASC), $$77(ASC)]  |PARTITIONED|
+              order (ASC, $$81) (ASC, $$82) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+              -- STABLE_SORT [$$81(ASC), $$82(ASC)]  |PARTITIONED|
                 exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  project ([$$c, $$o, $$l, $$84, $$77, $$80, $$76, $$86]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                  project ([$$c, $$o, $$l, $$89, $$82, $$81, $$85, $$91]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                   -- STREAM_PROJECT  |PARTITIONED|
                     exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      left outer join (eq($$78, $$77)) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 5.00004E11, total-cost: 5.00015E11]
-                      -- HYBRID_HASH_JOIN [$$77][$$78]  |PARTITIONED|
+                      left outer join (eq($$83, $$82)) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 5.00004E11, total-cost: 5.00015E11]
+                      -- HYBRID_HASH_JOIN [$$82][$$83]  |PARTITIONED|
                         exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          left outer join (eq($$80, $$76)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                          -- HYBRID_HASH_JOIN [$$76][$$80]  |PARTITIONED|
+                          left outer join (eq($$85, $$81)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                          -- HYBRID_HASH_JOIN [$$81][$$85]  |PARTITIONED|
                             exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              data-scan []<-[$$76, $$c] <- tpch.Customers [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              data-scan []<-[$$81, $$c] <- tpch.Customers [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                               -- DATASOURCE_SCAN  |PARTITIONED|
                                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                   empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                             exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                            -- HASH_PARTITION_EXCHANGE [$$80]  |PARTITIONED|
-                              assign [$$86, $$80] <- [true, $$o.getField(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- HASH_PARTITION_EXCHANGE [$$85]  |PARTITIONED|
+                              assign [$$91, $$85] <- [true, $$o.getField(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- ASSIGN  |PARTITIONED|
                                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  data-scan []<-[$$77, $$o] <- tpch.Orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                  data-scan []<-[$$82, $$o] <- tpch.Orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
                                   -- DATASOURCE_SCAN  |PARTITIONED|
                                     exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -66,13 +66,13 @@ distribute result [$$75] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0,
                                       -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                         exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- BROADCAST_EXCHANGE  |PARTITIONED|
-                          assign [$$84] <- [true] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          assign [$$89] <- [true] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- ASSIGN  |PARTITIONED|
-                            project ([$$78, $$l]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            project ([$$83, $$l]) [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|
-                                data-scan []<-[$$78, $$79, $$l] <- tpch.LineItems [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                data-scan []<-[$$83, $$84, $$l] <- tpch.LineItems [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                   exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.01.ddl.sqlpp
new file mode 100644
index 0000000000..d8c0b04276
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.01.ddl.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+drop dataverse experiments if exists;
+create dataverse experiments;
+use experiments;
+
+CREATE TYPE dsType AS {id: int};
+CREATE DATASET ds(dsType) primary key id;
+
+create index n on ds(name);
+
+CREATE FUNCTION is_name_equal(hotel, val) {
+    hotel.name= val
+};
+CREATE FUNCTION is_name_like(hotel, pattern) {
+    hotel.`name` LIKE pattern
+};
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.02.update.sqlpp
new file mode 100644
index 0000000000..0900514f57
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.02.update.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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 experiments;
+
+UPSERT INTO ds {"id": 1, "name": "Alec Boehms"};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.03.query.sqlpp
new file mode 100644
index 0000000000..80c50278bf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.03.query.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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 experiments;
+
+
+explain SELECT h.name FROM ds AS h WHERE is_name_equal(h, "Alec Boehm");
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.04.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.04.query.sqlpp
new file mode 100644
index 0000000000..4425907891
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/udf-with-like-in/udf-with-like-in.04.query.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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 experiments;
+
+
+explain SELECT h.name FROM ds AS h WHERE is_name_like(h, "Alec Boehm");
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.005.plan
similarity index 100%
rename from asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.005.adm
rename to asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.005.plan
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.006.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.006.plan
similarity index 100%
rename from asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.006.adm
rename to asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.006.plan
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.007.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.007.plan
similarity index 100%
rename from asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.007.adm
rename to asterixdb/asterix-app/src/test/resources/runtimets/results/column/temporal/001/001.007.plan
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/plansleep/sleep.3.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/plansleep/sleep.3.regexjson
index 22ca8afe57..4ac19e8f4c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/plansleep/sleep.3.regexjson
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/plansleep/sleep.3.regexjson
@@ -2,7 +2,7 @@
   "optimizedLogicalPlan": {
     "operator": "distribute-result",
     "expressions": [
-      "$$51"
+      "$$55"
     ],
     "operatorId": "1.1",
     "runtime-id": "R{.+}",
@@ -33,7 +33,7 @@
           {
             "operator": "project",
             "variables": [
-              "$$51"
+              "$$55"
             ],
             "operatorId": "1.3",
             "runtime-id": "R{.+}",
@@ -66,7 +66,7 @@
                 "min-cardinality": "R{[0-9.]+}",
                 "max-cardinality": "R{[0-9.]+}",
                 "total-cardinality": "R{[0-9.]+}",
-                "physical-operator": "SORT_MERGE_EXCHANGE [$$52(ASC) ]",
+                "physical-operator": "SORT_MERGE_EXCHANGE [$$56(ASC) ]",
                 "execution-mode": "PARTITIONED",
                 "optimizer-estimates": {
                   "cardinality": "R{[0-9.]+}",
@@ -80,7 +80,7 @@
                     "order-by-list": [
                       {
                         "order": "ASC",
-                        "expression": "$$52"
+                        "expression": "$$56"
                       }
                     ],
                     "operatorId": "1.5",
@@ -108,7 +108,7 @@
                         "tuple-bytes": "175 bytes"
                       }
                     ],
-                    "physical-operator": "STABLE_SORT [$$52(ASC)]",
+                    "physical-operator": "STABLE_SORT [$$56(ASC)]",
                     "execution-mode": "PARTITIONED",
                     "optimizer-estimates": {
                       "cardinality": "R{[0-9.]+}",
@@ -133,14 +133,14 @@
                           {
                             "operator": "assign",
                             "variables": [
-                              "$$52"
+                              "$$56"
                             ],
                             "expressions": [
                               "sleep($$city, 1700)"
                             ],
                             "project-variables": [
-                              "$$51",
-                              "$$52"
+                              "$$55",
+                              "$$56"
                             ],
                             "operatorId": "1.7",
                             "runtime-id": "R{.+}",
@@ -167,14 +167,14 @@
                               {
                                 "operator": "assign",
                                 "variables": [
-                                  "$$51"
+                                  "$$55"
                                 ],
                                 "expressions": [
-                                  "{\"customers\": $$55, \"city\": $$city}"
+                                  "{\"customers\": $$59, \"city\": $$city}"
                                 ],
                                 "project-variables": [
                                   "$$city",
-                                  "$$51"
+                                  "$$55"
                                 ],
                                 "operatorId": "1.8",
                                 "runtime-id": "R{.+}",
@@ -216,17 +216,17 @@
                                         "group-by-list": [
                                           {
                                             "variable": "$$city",
-                                            "expression": "$$59"
+                                            "expression": "$$63"
                                           }
                                         ],
                                         "subplan": [
                                           {
                                             "operator": "aggregate",
                                             "variables": [
-                                              "$$55"
+                                              "$$59"
                                             ],
                                             "expressions": [
-                                              "agg-sql-sum($$58)"
+                                              "agg-sql-sum($$62)"
                                             ],
                                             "operatorId": "1.9.1",
                                             "physical-operator": "AGGREGATE",
@@ -266,7 +266,7 @@
                                             "tuple-bytes": "89 bytes"
                                           }
                                         ],
-                                        "physical-operator": "SORT_GROUP_BY[$$59]",
+                                        "physical-operator": "SORT_GROUP_BY[$$63]",
                                         "execution-mode": "PARTITIONED",
                                         "optimizer-estimates": {
                                           "cardinality": "R{[0-9.]+}",
@@ -284,7 +284,7 @@
                                             "min-cardinality": 3,
                                             "max-cardinality": 3,
                                             "total-cardinality": 3,
-                                            "physical-operator": "HASH_PARTITION_EXCHANGE [$$59]",
+                                            "physical-operator": "HASH_PARTITION_EXCHANGE [$$63]",
                                             "execution-mode": "PARTITIONED",
                                             "optimizer-estimates": {
                                               "cardinality": "R{[0-9.]+}",
@@ -297,15 +297,15 @@
                                                 "operator": "group-by",
                                                 "group-by-list": [
                                                   {
-                                                    "variable": "$$59",
-                                                    "expression": "$$53"
+                                                    "variable": "$$63",
+                                                    "expression": "$$57"
                                                   }
                                                 ],
                                                 "subplan": [
                                                   {
                                                     "operator": "aggregate",
                                                     "variables": [
-                                                      "$$58"
+                                                      "$$62"
                                                     ],
                                                     "expressions": [
                                                       "agg-sql-count(1)"
@@ -348,7 +348,7 @@
                                                     "tuple-bytes": "89 bytes"
                                                   }
                                                 ],
-                                                "physical-operator": "SORT_GROUP_BY[$$53]",
+                                                "physical-operator": "SORT_GROUP_BY[$$57]",
                                                 "execution-mode": "PARTITIONED",
                                                 "optimizer-estimates": {
                                                   "cardinality": "R{[0-9.]+}",
@@ -373,13 +373,13 @@
                                                       {
                                                         "operator": "assign",
                                                         "variables": [
-                                                          "$$53"
+                                                          "$$57"
                                                         ],
                                                         "expressions": [
                                                           "$$c.getField(3).getField(2)"
                                                         ],
                                                         "project-variables": [
-                                                          "$$53"
+                                                          "$$57"
                                                         ],
                                                         "operatorId": "1.14",
                                                         "runtime-id": "R{.+}",
@@ -471,7 +471,7 @@
                                                                       {
                                                                         "operator": "data-scan",
                                                                         "variables": [
-                                                                          "$$54",
+                                                                          "$$58",
                                                                           "$$c"
                                                                         ],
                                                                         "data-source": "test.Customers",
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/udf-with-like-in/udf-with-like-in.03.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results/udf-with-like-in/udf-with-like-in.03.plan
new file mode 100644
index 0000000000..34d5618080
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/udf-with-like-in/udf-with-like-in.03.plan
@@ -0,0 +1,30 @@
+distribute result [$$21] [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 [$$21] <- [{"name": $$22}] project: [$$21] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$22]) [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 ([$$27]) [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, $$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($$22, "Alec Boehm")) [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 [$$22, $$27] <- index-search("d", 0, "Default", "experiments", "ds", false, false, 1, $$24, 1, $$25, 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 [$$24, $$25] <- ["Alec Boehm", "Alec Boehm"] [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/udf-with-like-in/udf-with-like-in.04.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results/udf-with-like-in/udf-with-like-in.04.plan
new file mode 100644
index 0000000000..34d5618080
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/udf-with-like-in/udf-with-like-in.04.plan
@@ -0,0 +1,30 @@
+distribute result [$$21] [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 [$$21] <- [{"name": $$22}] project: [$$21] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$22]) [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 ([$$27]) [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, $$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($$22, "Alec Boehm")) [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 [$$22, $$27] <- index-search("d", 0, "Default", "experiments", "ds", false, false, 1, $$24, 1, $$25, 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 [$$24, $$25] <- ["Alec Boehm", "Alec Boehm"] [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-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index f36d953493..36d9898539 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -59,6 +59,7 @@ import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.GenerateColumnNameVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.InlineColumnAliasVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.InlineWithExpressionVisitor;
+import org.apache.asterix.lang.sqlpp.rewrites.visitor.LikeFunctionCallVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.OperatorExpressionVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SelectExcludeRewriteSugarVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SetOperationVisitor;
@@ -191,7 +192,10 @@ public class SqlppQueryRewriter implements IQueryRewriter {
         // Rewrites window expression aggregations.
         rewriteWindowAggregationSugar();
 
-        // Rewrites like/not-like expressions.
+        // Rewrites like/not-like/in/not-in/concat/between/not-between operators into function calls.
+        // For LIKE operators: if the pattern expression is not a constant value, we keep it as an operator
+        // to allow other rewrites (e.g., inlining UDFs and WITH clauses) to process it first.
+        // The LIKE operator is then converted to a function call in rewritLikeOperator().
         rewriteOperatorExpression();
 
         // Normalizes CASE expressions and rewrites simple ones into switch-case()
@@ -225,6 +229,8 @@ public class SqlppQueryRewriter implements IQueryRewriter {
         // and external UDFs, therefore need to inline SQL++ UDFs to check the deterministic property.
         inlineWithExpressions();
 
+        rewritLikeOperator();
+
         // Sets the var counter of the query.
         topStatement.setVarCounter(context.getVarCounter().get());
     }
@@ -294,6 +300,12 @@ public class SqlppQueryRewriter implements IQueryRewriter {
         rewriteTopExpr(operatorExpressionVisitor, null);
     }
 
+    protected void rewritLikeOperator() throws CompilationException {
+        // Rewrites like operators into function call expression.
+        LikeFunctionCallVisitor likeFunctionCallVisitor = new LikeFunctionCallVisitor(context);
+        rewriteTopExpr(likeFunctionCallVisitor, null);
+    }
+
     protected void inlineColumnAlias() throws CompilationException {
         // Inline column aliases.
         InlineColumnAliasVisitor inlineColumnAliasVisitor = new InlineColumnAliasVisitor(context);
@@ -688,4 +700,4 @@ public class SqlppQueryRewriter implements IQueryRewriter {
         resultExpr.setSourceLocation(sourceLoc);
         return resultExpr;
     }
-}
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/LikeFunctionCallVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/LikeFunctionCallVisitor.java
new file mode 100644
index 0000000000..4d78522407
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/LikeFunctionCallVisitor.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+package org.apache.asterix.lang.sqlpp.rewrites.visitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
+import org.apache.asterix.lang.common.expression.OperatorExpr;
+import org.apache.asterix.lang.common.literal.StringLiteral;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.struct.OperatorType;
+import org.apache.asterix.lang.common.util.ExpressionUtils;
+
+public class LikeFunctionCallVisitor extends OperatorExpressionVisitor {
+
+    public LikeFunctionCallVisitor(LangRewritingContext context) {
+        super(context);
+    }
+
+    @Override
+    public Expression visit(OperatorExpr operatorExpr, ILangExpression arg) throws CompilationException {
+        List<Expression> newExprList = new ArrayList<>();
+        for (Expression expr : operatorExpr.getExprList()) {
+            newExprList.add(expr.accept(this, operatorExpr));
+        }
+        operatorExpr.setExprList(newExprList);
+        OperatorType opType = operatorExpr.getOpList().get(0);
+        if (opType == OperatorType.LIKE) {
+            return processLikeOperator(operatorExpr);
+        }
+        return operatorExpr;
+    }
+
+    private Expression processLikeOperator(OperatorExpr operatorExpr) throws CompilationException {
+        Expression target = operatorExpr.getExprList().get(0);
+        Expression patternExpr = operatorExpr.getExprList().get(1);
+        String patternStr = ExpressionUtils.getStringLiteral(patternExpr);
+        if (patternStr != null) {
+            StringBuilder likePatternStr = new StringBuilder();
+            LikePattern likePattern = processPattern(patternStr, likePatternStr);
+            if (likePattern == LikePattern.PREFIX) {
+                return convertLikeToRange(operatorExpr, target, likePatternStr.toString());
+            } else if (likePattern == LikePattern.EQUAL) {
+                Expression processedExpr = new LiteralExpr(new StringLiteral(likePatternStr.toString()));
+                return createOperatorExpression(OperatorType.EQ, target, processedExpr, operatorExpr.getHints(),
+                        operatorExpr.getSourceLocation());
+            }
+        }
+        return createLikeExpression(operatorExpr);
+    }
+}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java
index 50c4ac9d8d..e28fdd5765 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java
@@ -40,6 +40,7 @@ import org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.QuantifiedExpression.Quantifier;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.literal.FalseLiteral;
+import org.apache.asterix.lang.common.literal.NullLiteral;
 import org.apache.asterix.lang.common.literal.StringLiteral;
 import org.apache.asterix.lang.common.literal.TrueLiteral;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
@@ -106,11 +107,28 @@ public class OperatorExpressionVisitor extends AbstractSqlppExpressionScopingVis
                         return createOperatorExpression(OperatorType.EQ, target, processedExpr, operatorExpr.getHints(),
                                 operatorExpr.getSourceLocation());
                     }
+                    return createLikeExpression(operatorExpr);
                 }
-                return createLikeExpression(operatorExpr);
+                if (patternExpr.getKind() == Expression.Kind.LITERAL_EXPRESSION
+                        && ((LiteralExpr) patternExpr).getValue().getValue() == NullLiteral.INSTANCE.getValue()) {
+                    return createLikeExpression(operatorExpr);
+                }
+                return operatorExpr;
             case NOT_LIKE:
+                // Convert NOT_LIKE to NOT(LIKE operator) by first processing as LIKE, then wrapping with NOT
+                // Create a LIKE operator with the same operands
+                OperatorExpr likeOperatorExpr = new OperatorExpr();
+                likeOperatorExpr.setExprList(new ArrayList<>(operatorExpr.getExprList()));
+                likeOperatorExpr.addOperator(OperatorType.LIKE);
+                if (operatorExpr.hasHints()) {
+                    likeOperatorExpr.addHints(operatorExpr.getHints());
+                }
+                likeOperatorExpr.setSourceLocation(operatorExpr.getSourceLocation());
+                // Process the LIKE operator through the LIKE case logic (handles prefix patterns, etc.)
+                Expression processedLikeExpr = processLikeOperator(likeOperatorExpr, OperatorType.LIKE);
+                // Wrap the processed result with NOT function call
                 CallExpr notLikeExpr = new CallExpr(new FunctionSignature(BuiltinFunctions.NOT),
-                        new ArrayList<>(Collections.singletonList(createLikeExpression(operatorExpr))));
+                        new ArrayList<>(Collections.singletonList(processedLikeExpr)));
                 notLikeExpr.setSourceLocation(operatorExpr.getSourceLocation());
                 return notLikeExpr;
             default:
@@ -254,7 +272,7 @@ public class OperatorExpressionVisitor extends AbstractSqlppExpressionScopingVis
         }
     }
 
-    private Expression createOperatorExpression(OperatorType opType, Expression lhs, Expression rhs,
+    protected Expression createOperatorExpression(OperatorType opType, Expression lhs, Expression rhs,
             List<IExpressionAnnotation> hints, SourceLocation sourceLoc) {
         OperatorExpr comparison = new OperatorExpr();
         comparison.addOperand(lhs);
@@ -284,7 +302,7 @@ public class OperatorExpressionVisitor extends AbstractSqlppExpressionScopingVis
         return andExpr;
     }
 
-    private Expression convertLikeToRange(OperatorExpr operatorExpr, Expression target, String prefix)
+    protected Expression convertLikeToRange(OperatorExpr operatorExpr, Expression target, String prefix)
             throws CompilationException {
         int lastCodePoint = prefix.codePointAt(prefix.length() - 1);
         String incrementedLastChar = new String(Character.toChars(lastCodePoint + 1));
@@ -294,7 +312,7 @@ public class OperatorExpressionVisitor extends AbstractSqlppExpressionScopingVis
         return createRangeExpression(target, OperatorType.GE, left, right, OperatorType.LT, operatorExpr);
     }
 
-    private static CallExpr createLikeExpression(OperatorExpr operatorExpr) {
+    protected static CallExpr createLikeExpression(OperatorExpr operatorExpr) {
         CallExpr likeExpr =
                 new CallExpr(new FunctionSignature(BuiltinFunctions.STRING_LIKE), operatorExpr.getExprList());
         likeExpr.addHints(operatorExpr.getHints());
@@ -302,7 +320,7 @@ public class OperatorExpressionVisitor extends AbstractSqlppExpressionScopingVis
         return likeExpr;
     }
 
-    private static LikePattern processPattern(String pattern, StringBuilder likePatternStr) {
+    protected static LikePattern processPattern(String pattern, StringBuilder likePatternStr) {
         // note: similar logic is applied in StringLikeDescriptor
         if (pattern.equals(String.valueOf(PERCENT))) {
             return null;
@@ -334,4 +352,4 @@ public class OperatorExpressionVisitor extends AbstractSqlppExpressionScopingVis
         PREFIX,
         EQUAL
     }
-}
+}
\ No newline at end of file