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

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

commit 15ae69e9306e6245d1832354d6991c31bc07cedb
Merge: 83a47bc642 ceb62bead4
Author: Murtadha Hubail <[email protected]>
AuthorDate: Sun Apr 13 18:23:30 2025 +0300

    Merge branch 'ionic' into 'master'
    
    Change-Id: Ia2a193ecfeb7df3a8f0da9203b065493cf92c3b0

 .../rules/PushValueAccessAndFilterDownRule.java    |    2 +
 .../optimizer/rules/pushdown/PushdownContext.java  |   13 +-
 .../rules/pushdown/PushdownProcessorsExecutor.java |    8 +
 .../ParquetDatasetScanDefineDescriptor.java        |   45 +
 .../processor/AbstractFilterPushdownProcessor.java |   22 +-
 .../processor/ColumnFilterPushdownProcessor.java   |   13 +-
 .../ColumnRangeFilterPushdownProcessor.java        |   11 +-
 .../DeltaTableFilterPushdownProcessor.java         |    6 +-
 .../ExternalDatasetFilterPushdownProcessor.java    |    6 +-
 ...or.java => ParquetFilterPushdownProcessor.java} |   39 +-
 .../asterix/translator/AbstractLangTranslator.java |    2 +-
 .../csv/csv-params/quote-escape/quote-escape.csv   |    4 +
 asterixdb/asterix-app/pom.xml                      |    3 +-
 .../api/http/server/NCQueryServiceServlet.java     |   11 +-
 .../app/active/ActiveEntityEventsListener.java     |    4 +-
 .../external/ExternalCredentialsCacheUpdater.java  |    9 +-
 .../asterix/app/translator/QueryTranslator.java    |    6 +-
 ...Test.java => CloudStorageCancellationTest.java} |   51 +-
 .../test/cloud_storage/CloudStorageTest.java       |   24 +-
 .../test/common/CancellationTestExecutor.java      |    8 +
 .../java/org/apache/asterix/test/dml/DmlTest.java  |    2 +
 .../external_dataset/ExternalDatasetTestUtils.java |    1 +
 .../asterix/test/runtime/NullMissingTest.java      |    5 -
 .../asterix/test/runtime/TPCExecutionTest.java     |    2 +
 .../column-filter/ASTERIXDB-3595.001.sqlpp}        |   32 +-
 .../results/column-filter/ASTERIXDB-3595.001.plan  |   38 +
 .../double-precision.001.ddl.sqlpp}                |   26 +-
 .../double-precision.002.update.sqlpp              |   39 +
 .../double-precision.003.query.sqlpp               |   16 +-
 .../filter/double/double.001.ddl.sqlpp}            |   26 +-
 .../column/filter/double/double.002.update.sqlpp   |   86 ++
 .../column/filter/double/double.003.query.sqlpp    |   16 +-
 .../csv/simple-csv/simple-csv.03.update.sqlpp      |    2 +-
 .../csv/simple-csv/simple-csv.11.update.sqlpp      |    2 +-
 .../test.000.update.sqlpp}                         |   22 +-
 .../parquet-error-checks.17.update.sqlpp           |    2 +-
 ...ate.sqlpp => parquet-error-checks.18.ddl.sqlpp} |   18 +-
 ....sqlpp => parquet-error-checks.19.update.sqlpp} |   11 +-
 ....sqlpp => parquet-error-checks.20.update.sqlpp} |   11 +-
 ....sqlpp => parquet-error-checks.21.update.sqlpp} |   11 +-
 ....sqlpp => parquet-error-checks.22.update.sqlpp} |   11 +-
 .../parquet-file-writers.01.ddl.sqlpp}             |   23 +-
 .../parquet-file-writers.02.update.sqlpp           |  121 +++
 .../parquet-file-writers.03.update.sqlpp}          |   17 +-
 .../parquet-file-writers.04.ddl.sqlpp}             |   30 +-
 .../parquet-file-writers.05.query.sqlpp            |   16 +-
 .../parquet-type-hierarchy.01.ddl.sqlpp}           |   23 +-
 .../parquet-type-hierarchy.02.update.sqlpp         |   39 +
 .../parquet-type-hierarchy.03.update.sqlpp}        |   16 +-
 .../parquet-type-hierarchy.04.update.sqlpp}        |   26 +-
 .../parquet-type-hierarchy.05.query.sqlpp          |   16 +-
 .../limit_after_offset.1.query.sqlpp               |   14 +-
 .../api/cluster_state_1/cluster_state_1.1.regexadm |    2 +
 .../cluster_state_1_full.1.regexadm                |    2 +
 .../cluster_state_1_less.1.regexadm                |    2 +
 .../double-precision/double-precision.003.adm      |   12 +
 .../results/column/filter/double/double.003.adm    |    3 +
 .../results/comparison/missingif/missingif.1.adm   |    2 +-
 .../runtimets/results/comparison/nanif/nanif.1.adm |    2 +-
 .../results/comparison/neginfif/neginfif.1.adm     |    2 +-
 .../results/comparison/nullif/nullif.1.adm         |    2 +-
 .../results/comparison/posinfif/posinfif.1.adm     |    2 +-
 .../parquet-file-writers.05.adm                    | 1001 ++++++++++++++++++++
 .../parquet-type-hierarchy.05.adm                  |   11 +
 .../parquet/embed-one-value/one-field.011.plan     |    2 +-
 .../parquet/embed-one-value/one-field.021.plan     |    2 +-
 .../parquet/embed-one-value/one-field.031.plan     |    2 +-
 .../parquet/embed-one-value/one-field.121.plan     |    2 +-
 .../parquet/one-field/one-field.011.plan           |    2 +-
 .../parquet/one-field/one-field.021.plan           |    2 +-
 .../parquet/one-field/one-field.031.plan           |    2 +-
 .../parquet/one-field/one-field.121.plan           |    2 +-
 .../parquet/pushdown-plans/pushdown-plans.03.plan  |    2 +-
 .../parquet/pushdown-plans/pushdown-plans.04.plan  |    2 +-
 .../parquet/pushdown-plans/pushdown-plans.05.plan  |    2 +-
 .../parquet/pushdown-plans/pushdown-plans.08.plan  |    4 +-
 .../parquet/pushdown-plans/pushdown-plans.09.plan  |    4 +-
 .../limit_after_offset/limit_after_offset.1.adm    |    0
 .../runtimets/results/numeric/ifinf/ifinf.1.adm    |    6 +-
 .../src/test/resources/runtimets/sqlpp_queries.xml |   15 +
 .../runtimets/testsuite_external_dataset_s3.xml    |   35 +
 .../runtimets/testsuite_single_partition_sqlpp.xml |   10 +
 .../resources/runtimets/testsuite_sqlpp_hdfs.xml   |    4 +
 asterixdb/asterix-cloud/pom.xml                    |    4 +
 .../asterix/cloud/clients/ICloudGuardian.java      |   21 +
 .../cloud/clients/aws/s3/S3ClientConfig.java       |   12 +-
 .../cloud/clients/aws/s3/S3CloudClient.java        |    5 +
 .../parquet/ParquetSchemaInferPoolWriter.java      |   36 +-
 .../parquet/ParquetSinkExternalWriterRuntime.java  |    6 +-
 .../AbstractCloudExternalFileWriterFactory.java    |   36 +-
 .../writer/AzureExternalFileWriterFactory.java     |   16 +-
 .../cloud/writer/GCSExternalFileWriterFactory.java |   19 +-
 .../cloud/writer/S3ExternalFileWriterFactory.java  |   15 +-
 .../assembler/AbstractPrimitiveValueAssembler.java |    4 +
 .../column/filter/FalseColumnFilterEvaluator.java  |    8 +-
 .../column/filter/TrueColumnFilterEvaluator.java   |    8 +-
 .../iterable/IColumnIterableFilterEvaluator.java   |    5 +-
 .../evaluator/AbstractIterableFilterEvaluator.java |   28 +-
 .../evaluator/ColumnIterableFilterEvaluator.java   |    9 +-
 .../ColumnarRepeatedIterableFilterEvaluator.java   |    5 -
 .../AbstractColumnFilterComparatorFactory.java     |    5 +
 .../compartor/GEColumnFilterEvaluatorFactory.java  |    5 +
 .../compartor/GTColumnFilterEvaluatorFactory.java  |    5 +
 .../compartor/LEColumnFilterEvaluatorFactory.java  |    5 +
 .../compartor/LTColumnFilterEvaluatorFactory.java  |    5 +
 .../operation/lsm/flush/FlushColumnMetadata.java   |    2 +-
 .../column/operation/query/ColumnAssembler.java    |   14 +
 .../column/tuple/MergeColumnTupleReference.java    |   11 +-
 .../column/tuple/QueryColumnTupleReference.java    |   56 +-
 .../tuple/QueryColumnWithMetaTupleReference.java   |   63 +-
 .../values/reader/AbstractColumnValuesReader.java  |   11 +-
 .../values/reader/PrimitiveColumnValuesReader.java |    2 +-
 .../asterix/common/config/CloudProperties.java     |   10 +-
 .../asterix/common/config/ExternalProperties.java  |   12 +-
 .../common/config/OptimizationConfUtil.java        |    6 +-
 .../apache/asterix/common/context/DatasetInfo.java |   24 +
 .../common/context/DatasetLifecycleManager.java    |    2 +
 .../common/exceptions/AsterixException.java        |   37 +-
 .../common/exceptions/CompilationException.java    |   27 +-
 .../asterix/common/exceptions/ErrorCode.java       |    3 +
 .../common/exceptions/MetadataException.java       |   16 +-
 .../ioopcallbacks/LSMIOOperationCallback.java      |    1 +
 .../asterix/common/storage/StorageIOStats.java     |   18 +
 .../apache/asterix/common/utils/CSVConstants.java} |   32 +-
 .../src/main/resources/asx_errormsg/en.properties  |    3 +
 .../filter/ParquetFilterEvaluatorFactory.java      |   55 ++
 .../converter/CSVWithRecordConverterFactory.java   |    7 +-
 .../input/record/reader/aws/AwsS3InputStream.java  |    6 +-
 .../aws/parquet/AwsS3ParquetReaderFactory.java     |   10 +
 .../parquet/AzureBlobParquetReaderFactory.java     |   10 +
 .../parquet/AzureDataLakeParquetReaderFactory.java |   10 +
 .../input/record/reader/gcs/GCSInputStream.java    |    9 +-
 .../record/reader/gcs/GCSInputStreamFactory.java   |    8 +-
 .../reader/gcs/delta/GCSDeltaReaderFactory.java    |    4 +-
 .../gcs/parquet/GCSParquetReaderFactory.java       |   17 +-
 .../reader/stream/QuotedLineRecordReader.java      |    7 +-
 .../parser/factory/DelimitedDataParserFactory.java |    4 +-
 .../external/util/ExternalDataConstants.java       |    9 -
 .../asterix/external/util/ExternalDataUtils.java   |   33 +-
 .../external/util/WriterValidationUtil.java        |   12 +-
 .../asterix/external/util/aws/s3/S3AuthUtils.java  |   74 +-
 .../external/util/google/gcs/GCSAuthUtils.java     |  294 ++++++
 .../external/util/google/gcs/GCSConstants.java     |   13 +-
 .../asterix/external/util/google/gcs/GCSUtils.java |  165 +---
 .../writer/printer/ParquetExternalFilePrinter.java |    7 +-
 .../printer/ParquetExternalFilePrinterFactory.java |   13 +-
 .../printer/parquet/AsterixParquetTypeMap.java     |    8 +
 .../printer/parquet/ParquetSchemaLazyVisitor.java  |   23 +-
 .../writer/printer/parquet/ParquetSchemaTree.java  |   31 +-
 .../printer/parquet/SchemaCheckerLazyVisitor.java  |    4 +-
 .../external/parser/test/RecordWithMetaTest.java   |    7 +-
 .../test/StreamRecordReaderProviderTest.java       |    4 +-
 .../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj    |    1 +
 .../functions/ExternalFunctionCompilerUtil.java    |    2 +-
 .../apache/asterix/metadata/utils/DatasetUtil.java |    5 +
 .../apache/asterix/metadata/utils/IndexUtil.java   |   23 +
 .../utils/filter/ColumnRangeFilterBuilder.java     |    8 +
 .../utils/filter/ParquetFilterBuilder.java         |  220 +++++
 .../data/common/ExpressionTypeComputer.java        |    7 +-
 .../printers/csv/AObjectPrinterFactory.java        |   17 +-
 .../printers/csv/AStringPrinterFactory.java        |    6 +-
 .../data/nontagged/printers/csv/CSVUtils.java      |   21 +-
 .../nontagged/CSVPrinterFactoryProvider.java       |   12 +-
 .../asterix/om/functions/BuiltinFunctions.java     |    2 +-
 .../om/typecomputer/impl/DoubleIfTypeComputer.java |   38 +-
 .../typecomputer/impl/IfNanOrInfTypeComputer.java  |   14 +-
 .../typecomputer/impl/MissingIfTypeComputer.java   |    5 +
 .../om/typecomputer/impl/NullIfTypeComputer.java   |    5 +
 .../test/om/typecomputer/TypeComputerTest.java     |   13 +-
 .../comparisons/AbstractComparisonEvaluator.java   |    6 +-
 .../comparisons/AbstractIfEqualsEvaluator.java     |   24 +-
 .../AbstractValueComparisonEvaluator.java          |    2 +-
 .../comparisons/MissingIfEqualsDescriptor.java     |    2 -
 .../comparisons/NanIfEqualsDescriptor.java         |    2 -
 .../comparisons/NegInfIfEqualsDescriptor.java      |    2 -
 .../comparisons/NullIfEqualsDescriptor.java        |    2 -
 .../comparisons/PosInfIfEqualsDescriptor.java      |    2 -
 .../evaluators/functions/IfInfDescriptor.java      |    7 +-
 .../evaluators/functions/IfNanDescriptor.java      |    2 +-
 .../evaluators/functions/IfNanOrInfDescriptor.java |   11 +-
 .../ExternalDatasetProjectionFiltrationInfo.java   |    2 +-
 ...uetExternalDatasetProjectionFiltrationInfo.java |   86 ++
 asterixdb/pom.xml                                  |    5 +
 .../common/exceptions/AlgebricksException.java     |   52 +-
 .../LogicalOperatorPrettyPrintVisitorJson.java     |    2 +-
 .../core/rewriter/base/AbstractRuleController.java |    6 +-
 .../core/rewriter/base/HeuristicOptimizer.java     |    2 +-
 .../algebricks/algebricks-runtime/pom.xml          |    5 +
 .../meta/AlgebricksMetaOperatorDescriptor.java     |   21 +-
 .../runtime/SuperActivityOperatorNodePushable.java |    2 +-
 .../apache/hyracks/api/util/ExceptionUtils.java    |   42 +-
 .../org/apache/hyracks/api/util/InvokeUtil.java    |   64 ++
 .../hyracks/cloud/io/request/ICloudRequest.java    |    7 +
 .../cloud/util/CloudRetryableRequestUtil.java      |   54 +-
 .../java/org/apache/hyracks/control/nc/Task.java   |   35 +-
 .../VariableDeletableTupleMemoryManager.java       |    4 +-
 .../std/group/HashSpillableTableFactory.java       |   12 +-
 .../std/join/NestedLoopJoinOperatorDescriptor.java |    6 +-
 .../OptimizedHybridHashJoinOperatorDescriptor.java |   78 +-
 .../org/apache/hyracks/http/server/WebManager.java |    8 +-
 .../lsm/btree/column/api/IColumnTupleIterator.java |   23 +-
 .../btree/column/error/ColumnarValueException.java |    4 +
 .../impls/lsm/LSMColumnBTreeRangeSearchCursor.java |    4 +-
 .../lsm/tuples/AbstractColumnTupleReference.java   |   19 +-
 .../lsm/btree/impls/LSMBTreePointSearchCursor.java |    7 +-
 .../am/lsm/common/impls/LSMIndexSearchCursor.java  |    7 +-
 .../am/lsm/common/impls/LSMTreeIndexAccessor.java  |   17 +-
 .../impls/LSMInvertedIndexAccessor.java            |   17 +-
 .../hyracks/util/ExponentialRetryPolicy.java       |   17 +-
 .../java/org/apache/hyracks/util/IRetryPolicy.java |    3 +-
 210 files changed, 3533 insertions(+), 1145 deletions(-)

diff --cc 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
index 73f0606660,dac71ce271..8980688760
--- 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
@@@ -49,11 -49,18 +49,19 @@@ public class CancellationTestExecutor e
  
      private final ExecutorService executor = 
Executors.newSingleThreadExecutor();
  
+     public CancellationTestExecutor() {
+         super();
+     }
+ 
+     public CancellationTestExecutor(String deltaPath) {
+         super(deltaPath);
+     }
+ 
      @Override
      public InputStream executeQueryService(String str, 
TestCaseContext.OutputFormat fmt, URI uri,
 -            List<TestCase.CompilationUnit.Parameter> params, boolean 
jsonEncoded, Charset responseCharset,
 -            Predicate<Integer> responseCodeValidator, boolean cancellable) 
throws Exception {
 +            List<TestCase.CompilationUnit.Parameter> params, 
List<TestCase.CompilationUnit.Placeholder> placeholders,
 +            boolean jsonEncoded, Charset responseCharset, Predicate<Integer> 
responseCodeValidator, boolean cancellable)
 +            throws Exception {
          cancellable = cancellable && !containsClientContextID(str);
          String clientContextId = UUID.randomUUID().toString();
          final List<TestCase.CompilationUnit.Parameter> newParams =
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.011.plan
index 83c24b28b6,805b9aa53a..ac64aa48b5
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.011.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.011.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$17(ASC) ]  |PARTITIONED|
 -        order (ASC, $$17) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$17) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$17(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (eq($$d.getField("department"), "accounting")) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +            select (eq($$d.getField("department"), "accounting")) 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$17] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$17] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") embed-filter-value: true 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") embed-filter-value: true 
row-group-filter on: eq($$d.getField("department"), "accounting") [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") embed-filter-value: true 
row-group-filter on: eq($$d.getField("department"), "accounting") [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.021.plan
index e4a5101930,a57424cf57..bb6e9b343e
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.021.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.021.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$22(ASC) ]  |PARTITIONED|
 -        order (ASC, $$22) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$22) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$22(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +            select (and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") embed-filter-value: true 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") embed-filter-value: true 
row-group-filter on: and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") embed-filter-value: true 
row-group-filter on: and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.031.plan
index 30bf3f8c3a,5e231767ca..5ba75b1ccc
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.031.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.031.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$22(ASC) ]  |PARTITIONED|
 -        order (ASC, $$22) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$22) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$22(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +            select (or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.Department embed-filter-value: 
true [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.Department embed-filter-value: 
true row-group-filter on: or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.Department embed-filter-value: 
true row-group-filter on: or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.121.plan
index 3609b5db52,5832f4f1dc..e4f848b6b2
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.121.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/embed-one-value/one-field.121.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$18(ASC) ]  |PARTITIONED|
 -        order (ASC, $$18) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$18) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$18(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (eq($$d.getField("name").getField("last"), "Jones")) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +            select (eq($$d.getField("name").getField("last"), "Jones")) 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$18] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$18] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.LastName prefix-filter on: 
eq($$d.getField("name").getField("last"), "Jones") embed-filter-value: true 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.LastName prefix-filter on: 
eq($$d.getField("name").getField("last"), "Jones") embed-filter-value: true 
row-group-filter on: eq($$d.getField("name").getField("last"), "Jones") 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.LastName prefix-filter on: 
eq($$d.getField("name").getField("last"), "Jones") embed-filter-value: true 
row-group-filter on: eq($$d.getField("name").getField("last"), "Jones") 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.011.plan
index fb724717d5,ecbd5ee343..6c49ee6c3c
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.011.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.011.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$17(ASC) ]  |PARTITIONED|
 -        order (ASC, $$17) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$17) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$17(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (eq($$d.getField("department"), "accounting")) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +            select (eq($$d.getField("department"), "accounting")) 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$17] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$17] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") row-group-filter on: 
eq($$d.getField("department"), "accounting") [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") row-group-filter on: 
eq($$d.getField("department"), "accounting") [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.021.plan
index 3cafbadc44,35da9483fb..8900a937a3
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.021.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.021.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$22(ASC) ]  |PARTITIONED|
 -        order (ASC, $$22) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$22) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$22(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +            select (and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") row-group-filter on: 
and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.Department prefix-filter on: 
eq($$d.getField("department"), "accounting") row-group-filter on: 
and(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.031.plan
index 520adefffb,23892f1f71..a05ff5f375
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.031.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.031.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$22(ASC) ]  |PARTITIONED|
 -        order (ASC, $$22) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$22) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$22(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +            select (or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith"))) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$22] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.Department [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.Department row-group-filter on: 
or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.Department row-group-filter on: 
or(eq($$d.getField("department"), "accounting"), 
eq($$d.getField("name").getField("last"), "Smith")) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.121.plan
index 3275b9e0a4,9fb8ee15f8..a8469c77b7
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.121.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/dynamic-prefixes/parquet/one-field/one-field.121.plan
@@@ -1,24 -1,24 +1,24 @@@
 -distribute result [$$d] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$d] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    project ([$$d]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    project ([$$d]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- STREAM_PROJECT  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- SORT_MERGE_EXCHANGE [$$18(ASC) ]  |PARTITIONED|
 -        order (ASC, $$18) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$18) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$18(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -            select (eq($$d.getField("name").getField("last"), "Jones")) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +            select (eq($$d.getField("name").getField("last"), "Jones")) 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              assign [$$18] <- [$$d.getField("id")] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +              assign [$$18] <- [$$d.getField("id")] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                -- ASSIGN  |PARTITIONED|
 -                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                   data-scan []<-[$$d] <- test.LastName prefix-filter on: 
eq($$d.getField("name").getField("last"), "Jones") [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
 -                  data-scan []<-[$$d] <- test.LastName prefix-filter on: 
eq($$d.getField("name").getField("last"), "Jones") row-group-filter on: 
eq($$d.getField("name").getField("last"), "Jones") [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
++                  data-scan []<-[$$d] <- test.LastName prefix-filter on: 
eq($$d.getField("name").getField("last"), "Jones") row-group-filter on: 
eq($$d.getField("name").getField("last"), "Jones") [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
                    -- DATASOURCE_SCAN  |PARTITIONED|
 -                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    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, op-cost: 0.0, 
total-cost: 0.0]
 +                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.03.plan
index 6ceee91262,9dab9c1dc3..000b1f3dc9
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.03.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.03.plan
@@@ -1,22 -1,22 +1,22 @@@
 -distribute result [$$p1] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$p1] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    distinct ([$$p1]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    distinct ([$$p1]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
      -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -        order (ASC, $$p1) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        order (ASC, $$p1) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
          -- STABLE_SORT [$$p1(ASC)]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- HASH_PARTITION_EXCHANGE [$$p1]  |PARTITIONED|
 -            select (gt($$p1.getField("id"), 10)) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
 +            select (gt($$p1.getField("id"), 10)) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                 data-scan []<-[$$p1] <- test.ParquetDataset1 [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
 -                data-scan []<-[$$p1] <- test.ParquetDataset1 row-group-filter 
on: gt($$p1.getField("id"), 10) [cardinality: 0.0, op-cost: 0.0, total-cost: 
0.0]
++                data-scan []<-[$$p1] <- test.ParquetDataset1 row-group-filter 
on: gt($$p1.getField("id"), 10) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                  -- DATASOURCE_SCAN  |PARTITIONED|
 -                  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                  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, op-cost: 0.0, 
total-cost: 0.0]
 +                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.04.plan
index 304a098a20,2fca35d399..a17f99b954
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.04.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.04.plan
@@@ -1,44 -1,44 +1,44 @@@
 -distribute result [$$69] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$69] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    assign [$$69] <- [{"text": $$text, "$1": $$72}] project: [$$69] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    assign [$$69] <- [{"text": $$text, "$1": $$72}] project: [$$69] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
      -- ASSIGN  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
          group by ([$$text := $$80]) decor ([]) {
 -                  aggregate [$$72] <- [agg-global-sql-sum($$79)] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                  aggregate [$$72] <- [agg-global-sql-sum($$79)] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- AGGREGATE  |LOCAL|
 -                    nested tuple source [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                    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, op-cost: 0.0, total-cost: 0.0]
 +               } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
          -- SORT_GROUP_BY[$$80]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- HASH_PARTITION_EXCHANGE [$$80]  |PARTITIONED|
              group by ([$$80 := $$71]) decor ([]) {
 -                      aggregate [$$79] <- 
[agg-local-sql-sum(array-distinct($$74))] [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                      aggregate [$$79] <- 
[agg-local-sql-sum(array-distinct($$74))] [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                        -- AGGREGATE  |LOCAL|
 -                        nested tuple source [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                        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, op-cost: 0.0, total-cost: 0.0]
 +                   } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
              -- SORT_GROUP_BY[$$71]  |PARTITIONED|
 -              exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -                select (eq(lowercase($$71), "string")) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +                select (eq(lowercase($$71), "string")) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                  -- STREAM_SELECT  |PARTITIONED|
 -                  assign [$$71] <- [$$ht.getField("text")] project: [$$74, 
$$71] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                  assign [$$71] <- [$$ht.getField("text")] project: [$$74, 
$$71] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- ASSIGN  |PARTITIONED|
 -                    unnest $$ht <- scan-collection($$74) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +                    unnest $$ht <- scan-collection($$74) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                      -- UNNEST  |PARTITIONED|
 -                      assign [$$74] <- 
[$$p1.getField("entities").getField("hashtags")] project: [$$74] [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
 +                      assign [$$74] <- 
[$$p1.getField("entities").getField("hashtags")] project: [$$74] [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                        -- ASSIGN  |PARTITIONED|
 -                        select (gt($$p1.getField("id"), 10)) [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
 +                        select (gt($$p1.getField("id"), 10)) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                          -- STREAM_SELECT  |PARTITIONED|
 -                          exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                             data-scan []<-[$$p1] <- test.ParquetDataset1 
project ({entities:{hashtags:any},id:any}) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 -                            data-scan []<-[$$p1] <- test.ParquetDataset1 
project ({entities:{hashtags:any},id:any}) row-group-filter on: 
gt($$p1.getField("id"), 10) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
++                            data-scan []<-[$$p1] <- test.ParquetDataset1 
project ({entities:{hashtags:any},id:any}) row-group-filter on: 
gt($$p1.getField("id"), 10) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                              -- DATASOURCE_SCAN  |PARTITIONED|
 -                              exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                              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, 
op-cost: 0.0, total-cost: 0.0]
 +                                empty-tuple-source [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.05.plan
index 71c1ed48e3,945f2da54c..52650d761c
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.05.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.05.plan
@@@ -1,44 -1,44 +1,44 @@@
 -distribute result [$$68] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$68] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |PARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -    assign [$$68] <- [{"text": $$text, "$1": $$71}] project: [$$68] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +    assign [$$68] <- [{"text": $$text, "$1": $$71}] project: [$$68] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
      -- ASSIGN  |PARTITIONED|
 -      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
          group by ([$$text := $$78]) decor ([]) {
 -                  aggregate [$$71] <- [agg-global-sql-sum($$77)] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                  aggregate [$$71] <- [agg-global-sql-sum($$77)] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                    -- AGGREGATE  |LOCAL|
 -                    nested tuple source [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                    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, op-cost: 0.0, total-cost: 0.0]
 +               } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
          -- SORT_GROUP_BY[$$78]  |PARTITIONED|
 -          exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
            -- HASH_PARTITION_EXCHANGE [$$78]  |PARTITIONED|
              group by ([$$78 := $$70]) decor ([]) {
 -                      aggregate [$$77] <- [agg-local-sql-sum(sql-sum($$74))] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                      aggregate [$$77] <- [agg-local-sql-sum(sql-sum($$74))] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                        -- AGGREGATE  |LOCAL|
 -                        nested tuple source [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                        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, op-cost: 0.0, total-cost: 0.0]
 +                   } [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
              -- SORT_GROUP_BY[$$70]  |PARTITIONED|
 -              exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
 -                select (eq(lowercase($$70), "string")) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +                select (eq(lowercase($$70), "string")) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                  -- STREAM_SELECT  |PARTITIONED|
 -                  assign [$$74, $$70] <- [$$ht.getField("indices"), 
$$ht.getField("text")] project: [$$74, $$70] [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                  assign [$$74, $$70] <- [$$ht.getField("indices"), 
$$ht.getField("text")] project: [$$74, $$70] [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                    -- ASSIGN  |PARTITIONED|
 -                    unnest $$ht <- scan-collection($$73) project: [$$ht] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    unnest $$ht <- scan-collection($$73) project: [$$ht] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                      -- UNNEST  |PARTITIONED|
 -                      assign [$$73] <- 
[$$p1.getField("entities").getField("hashtags")] project: [$$73] [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
 +                      assign [$$73] <- 
[$$p1.getField("entities").getField("hashtags")] project: [$$73] [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                        -- ASSIGN  |PARTITIONED|
 -                        select (gt($$p1.getField("id"), 10)) [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
 +                        select (gt($$p1.getField("id"), 10)) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                          -- STREAM_SELECT  |PARTITIONED|
 -                          exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                             data-scan []<-[$$p1] <- test.ParquetDataset1 
project ({entities:{hashtags:[{indices:any,text:any}]},id:any}) [cardinality: 
0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
 -                            data-scan []<-[$$p1] <- test.ParquetDataset1 
project ({entities:{hashtags:[{indices:any,text:any}]},id:any}) 
row-group-filter on: gt($$p1.getField("id"), 10) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
++                            data-scan []<-[$$p1] <- test.ParquetDataset1 
project ({entities:{hashtags:[{indices:any,text:any}]},id:any}) 
row-group-filter on: gt($$p1.getField("id"), 10) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
                              -- DATASOURCE_SCAN  |PARTITIONED|
 -                              exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                              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, 
op-cost: 0.0, total-cost: 0.0]
 +                                empty-tuple-source [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.08.plan
index efe3c69c02,694172004e..1645245ef2
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.08.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.08.plan
@@@ -1,56 -1,52 +1,56 @@@
 -distribute result [$$65] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$65] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |UNPARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
 -    assign [$$65] <- [{"$1": $$66}] project: [$$65] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +    assign [$$65] <- [{"$1": $$66}] project: [$$65] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
      -- ASSIGN  |UNPARTITIONED|
 -      aggregate [$$66] <- [agg-sql-sum($$75)] [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
 +      aggregate [$$66] <- [agg-sql-sum($$75)] [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
        -- AGGREGATE  |UNPARTITIONED|
 -        exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
          -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
 -          aggregate [$$75] <- [agg-sql-count(1)] [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
 +          aggregate [$$75] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
            -- AGGREGATE  |PARTITIONED|
 -            select (or($$53, $$57)) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +            select (or($$53, $$57)) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              project ([$$53, $$57]) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +              project ([$$53, $$57]) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                -- STREAM_PROJECT  |PARTITIONED|
                  subplan {
 -                          aggregate [$$57] <- [non-empty-stream()] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                          aggregate [$$57] <- [non-empty-stream()] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                            -- AGGREGATE  |LOCAL|
 -                            select (eq($$70, 2)) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
 +                            select (eq($$70, 2)) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
                              -- STREAM_SELECT  |LOCAL|
 -                              assign [$$70] <- [$$e.getField("x")] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                              assign [$$70] <- [$$e.getField("x")] project: 
[$$70] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                -- ASSIGN  |LOCAL|
 -                                unnest $$e <- scan-collection($$67) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                unnest $$e <- scan-collection($$67) project: 
[$$e] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                  -- UNNEST  |LOCAL|
 -                                  nested tuple source [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 -                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
 -                       } [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                  project ([$$67]) [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]
                  -- SUBPLAN  |PARTITIONED|
                    subplan {
 -                            aggregate [$$53] <- [non-empty-stream()] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                            aggregate [$$53] <- [non-empty-stream()] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                              -- AGGREGATE  |LOCAL|
 -                              select (eq($$68, 1)) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +                              select (eq($$68, 1)) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                -- STREAM_SELECT  |LOCAL|
 -                                assign [$$68] <- [$$e.getField("x")] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                assign [$$68] <- [$$e.getField("x")] project: 
[$$68] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                  -- ASSIGN  |LOCAL|
 -                                  unnest $$e <- scan-collection($$67) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                  unnest $$e <- scan-collection($$67) 
project: [$$e] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                    -- UNNEST  |LOCAL|
 -                                    nested tuple source [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 -                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
 -                         } [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                    project ([$$67]) [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]
                    -- SUBPLAN  |PARTITIONED|
 -                    assign [$$67] <- [$$p.getField("val1")] project: [$$67] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    assign [$$67] <- [$$p.getField("val1")] project: [$$67] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                      -- ASSIGN  |PARTITIONED|
 -                      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 
0.0]
 +                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                         data-scan []<-[$$p] <- test.ParquetDataset1 project 
({val1:[{x:any}]}) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
 -                        data-scan []<-[$$p] <- test.ParquetDataset1 project 
({val1:[{x:any}]}) row-group-filter on: 
or(eq(scan-collection($$p.getField("val1")).getField("x"), 1), 
eq(scan-collection($$p.getField("val1")).getField("x"), 2)) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
++                        data-scan []<-[$$p] <- test.ParquetDataset1 project 
({val1:[{x:any}]}) row-group-filter on: 
or(eq(scan-collection($$p.getField("val1")).getField("x"), 1), 
eq(scan-collection($$p.getField("val1")).getField("x"), 2)) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                          -- DATASOURCE_SCAN  |PARTITIONED|
 -                          exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                          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, op-cost: 
0.0, total-cost: 0.0]
 -                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
 +                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
-                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
++                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.09.plan
index 0fd326505d,316e465ef1..82f52b8fdf
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.09.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/common/parquet/pushdown-plans/pushdown-plans.09.plan
@@@ -1,56 -1,52 +1,56 @@@
 -distribute result [$$65] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +distribute result [$$65] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
  -- DISTRIBUTE_RESULT  |UNPARTITIONED|
 -  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
    -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
 -    assign [$$65] <- [{"$1": $$66}] project: [$$65] [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +    assign [$$65] <- [{"$1": $$66}] project: [$$65] [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
      -- ASSIGN  |UNPARTITIONED|
 -      aggregate [$$66] <- [agg-sql-sum($$75)] [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
 +      aggregate [$$66] <- [agg-sql-sum($$75)] [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
        -- AGGREGATE  |UNPARTITIONED|
 -        exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 
0.0]
          -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
 -          aggregate [$$75] <- [agg-sql-count(1)] [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
 +          aggregate [$$75] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
            -- AGGREGATE  |PARTITIONED|
 -            select (or($$53, $$57)) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +            select (or($$53, $$57)) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
              -- STREAM_SELECT  |PARTITIONED|
 -              project ([$$53, $$57]) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +              project ([$$53, $$57]) [cardinality: 0.0, doc-size: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                -- STREAM_PROJECT  |PARTITIONED|
                  subplan {
 -                          aggregate [$$57] <- [non-empty-stream()] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                          aggregate [$$57] <- [non-empty-stream()] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                            -- AGGREGATE  |LOCAL|
 -                            select (eq($$70, 2)) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
 +                            select (eq($$70, 2)) [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
                              -- STREAM_SELECT  |LOCAL|
 -                              assign [$$70] <- [$$e.getField("y")] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                              assign [$$70] <- [$$e.getField("y")] project: 
[$$70] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                -- ASSIGN  |LOCAL|
 -                                unnest $$e <- scan-collection($$67) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                unnest $$e <- scan-collection($$67) project: 
[$$e] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                  -- UNNEST  |LOCAL|
 -                                  nested tuple source [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 -                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
 -                       } [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                  project ([$$67]) [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]
                  -- SUBPLAN  |PARTITIONED|
                    subplan {
 -                            aggregate [$$53] <- [non-empty-stream()] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                            aggregate [$$53] <- [non-empty-stream()] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                              -- AGGREGATE  |LOCAL|
 -                              select (eq($$68, 1)) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 +                              select (eq($$68, 1)) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                -- STREAM_SELECT  |LOCAL|
 -                                assign [$$68] <- [$$e.getField("x")] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                assign [$$68] <- [$$e.getField("x")] project: 
[$$68] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                  -- ASSIGN  |LOCAL|
 -                                  unnest $$e <- scan-collection($$67) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                  unnest $$e <- scan-collection($$67) 
project: [$$e] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                    -- UNNEST  |LOCAL|
 -                                    nested tuple source [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
 -                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
 -                         } [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                                    project ([$$67]) [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]
                    -- SUBPLAN  |PARTITIONED|
 -                    assign [$$67] <- [$$p.getField("val1")] project: [$$67] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 +                    assign [$$67] <- [$$p.getField("val1")] project: [$$67] 
[cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                      -- ASSIGN  |PARTITIONED|
 -                      exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 
0.0]
 +                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 
0.0, total-cost: 0.0]
                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                         data-scan []<-[$$p] <- test.ParquetDataset1 project 
({val1:[{x:any,y:any}]}) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 -                        data-scan []<-[$$p] <- test.ParquetDataset1 project 
({val1:[{x:any,y:any}]}) row-group-filter on: 
or(eq(scan-collection($$p.getField("val1")).getField("x"), 1), 
eq(scan-collection($$p.getField("val1")).getField("y"), 2)) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
++                        data-scan []<-[$$p] <- test.ParquetDataset1 project 
({val1:[{x:any,y:any}]}) row-group-filter on: 
or(eq(scan-collection($$p.getField("val1")).getField("x"), 1), 
eq(scan-collection($$p.getField("val1")).getField("y"), 2)) [cardinality: 0.0, 
doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                          -- DATASOURCE_SCAN  |PARTITIONED|
 -                          exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
 +                          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, op-cost: 
0.0, total-cost: 0.0]
 -                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
 +                            empty-tuple-source [cardinality: 0.0, doc-size: 
0.0, op-cost: 0.0, total-cost: 0.0]
-                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
++                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --cc 
asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset_s3.xml
index 8555c813e9,38ebf01c97..308266184c
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset_s3.xml
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset_s3.xml
@@@ -139,13 -144,18 +149,23 @@@
          <output-dir compare="Text">parquet-empty-array</output-dir>
        </compilation-unit>
      </test-case>
+     <test-case FilePath="copy-to">
+       <compilation-unit name="parquet-type-hierarchy">
+         <placeholder name="adapter" value="S3" />
+         <placeholder name="pathprefix" value="" />
+         <placeholder name="path_prefix" value="" />
+         <placeholder name="additionalProperties" 
value='"container":"playground",' />
+         <placeholder name="additional_Properties" 
value='("container"="playground")' />
+         <output-dir compare="Text">parquet-type-hierarchy</output-dir>
+       </compilation-unit>
+     </test-case>
      <test-case FilePath="copy-to">
        <compilation-unit name="empty-path">
 +        <placeholder name="adapter" value="S3" />
 +        <placeholder name="pathprefix" value="" />
 +        <placeholder name="path_prefix" value="" />
 +        <placeholder name="additionalProperties" 
value='"container":"playground",' />
 +        <placeholder name="additional_Properties" 
value='("container"="playground")' />
          <output-dir compare="Text">empty-path</output-dir>
        </compilation-unit>
      </test-case>
diff --cc 
asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AbstractCloudExternalFileWriterFactory.java
index 7c8ea03e5f,1de64d0031..977f90a1a7
--- 
a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AbstractCloudExternalFileWriterFactory.java
+++ 
b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AbstractCloudExternalFileWriterFactory.java
@@@ -63,13 -63,15 +63,19 @@@ abstract class AbstractCloudExternalFil
  
      abstract ICloudClient createCloudClient(IApplicationContext appCtx) 
throws CompilationException;
  
 +    abstract String getAdapterName();
 +
 +    abstract int getPathMaxLengthInBytes();
 +
-     abstract boolean isNoContainerFoundException(IOException e);
- 
-     abstract boolean isSdkException(Throwable e);
+     /**
+      * Certain failures are wrapped in our exceptions as IO failures, this 
method checks if the original failure
+      * is reported from the external SDK, and if so, returns it. This is to 
ensure that the failure
+      * reported by the external SDK is the one reported back as the issue.
+      *
+      * @param ex failure thrown
+      * @return the throwable if it is an SDK exception, null otherwise
+      */
+     abstract Optional<T> getSdkException(Throwable ex);
  
      final void buildClient(IApplicationContext appCtx) throws 
HyracksDataException {
          try {
diff --cc 
asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AzureExternalFileWriterFactory.java
index 3a2923d3f3,42f7fbbd0f..fd71ffc63c
--- 
a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AzureExternalFileWriterFactory.java
+++ 
b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AzureExternalFileWriterFactory.java
@@@ -40,12 -39,11 +40,11 @@@ import org.apache.hyracks.api.context.I
  import org.apache.hyracks.api.context.IHyracksTaskContext;
  import org.apache.hyracks.api.exceptions.HyracksDataException;
  import org.apache.hyracks.api.exceptions.IWarningCollector;
+ import org.apache.hyracks.api.util.ExceptionUtils;
  
 -import software.amazon.awssdk.core.exception.SdkException;
 +import com.azure.core.exception.AzureException;
  
- import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
- 
- public final class AzureExternalFileWriterFactory extends 
AbstractCloudExternalFileWriterFactory {
 -public final class S3ExternalFileWriterFactory extends 
AbstractCloudExternalFileWriterFactory<SdkException> {
++public final class AzureExternalFileWriterFactory extends 
AbstractCloudExternalFileWriterFactory<AzureException> {
      private static final long serialVersionUID = 4551318140901866805L;
      static final char SEPARATOR = '/';
      public static final IExternalFileWriterFactoryProvider PROVIDER = new 
IExternalFileWriterFactoryProvider() {
@@@ -73,23 -71,8 +72,18 @@@
      }
  
      @Override
 -    Optional<SdkException> getSdkException(Throwable ex) {
 -        return ExceptionUtils.getCauseOfType(ex, SdkException.class);
 +    String getAdapterName() {
 +        return ExternalDataConstants.KEY_ADAPTER_NAME_AZURE_BLOB;
 +    }
 +
 +    @Override
 +    int getPathMaxLengthInBytes() {
 +        return AzureConstants.MAX_KEY_LENGTH_IN_BYTES;
 +    }
 +
 +    @Override
-     boolean isNoContainerFoundException(IOException e) {
-         return e.getCause() instanceof NoSuchBucketException;
-     }
- 
-     @Override
-     boolean isSdkException(Throwable e) {
-         return e instanceof AzureException;
++    Optional<AzureException> getSdkException(Throwable ex) {
++        return ExceptionUtils.getCauseOfType(ex, AzureException.class);
      }
  
      @Override
diff --cc 
asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/GCSExternalFileWriterFactory.java
index eddf66c63f,49946a2e14..dcf9166218
--- 
a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/GCSExternalFileWriterFactory.java
+++ 
b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/GCSExternalFileWriterFactory.java
@@@ -27,8 -27,7 +27,8 @@@ import org.apache.asterix.cloud.clients
  import org.apache.asterix.common.api.IApplicationContext;
  import org.apache.asterix.common.exceptions.CompilationException;
  import org.apache.asterix.external.util.ExternalDataConstants;
+ import org.apache.asterix.external.util.google.gcs.GCSAuthUtils;
 +import org.apache.asterix.external.util.google.gcs.GCSConstants;
- import org.apache.asterix.external.util.google.gcs.GCSUtils;
  import org.apache.asterix.runtime.writer.ExternalFileWriterConfiguration;
  import org.apache.asterix.runtime.writer.IExternalFileWriter;
  import org.apache.asterix.runtime.writer.IExternalFileWriterFactory;
@@@ -71,24 -70,9 +71,19 @@@ public final class GCSExternalFileWrite
                  ICloudGuardian.NoOpCloudGuardian.INSTANCE);
      }
  
 +    @Override
 +    String getAdapterName() {
 +        return ExternalDataConstants.KEY_ADAPTER_NAME_GCS;
 +    }
 +
 +    @Override
 +    int getPathMaxLengthInBytes() {
 +        return GCSConstants.MAX_KEY_LENGTH_IN_BYTES;
 +    }
 +
      @Override
-     boolean isNoContainerFoundException(IOException e) {
-         return e.getCause() instanceof StorageException;
-     }
- 
-     @Override
-     boolean isSdkException(Throwable e) {
-         return e instanceof BaseServiceException;
+     Optional<BaseServiceException> getSdkException(Throwable ex) {
+         return ExceptionUtils.getCauseOfType(ex, BaseServiceException.class);
      }
  
      @Override
diff --cc 
asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/S3ExternalFileWriterFactory.java
index 97e6051720,42f7fbbd0f..b3747468cf
--- 
a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/S3ExternalFileWriterFactory.java
+++ 
b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/S3ExternalFileWriterFactory.java
@@@ -71,24 -70,9 +71,19 @@@ public final class S3ExternalFileWriter
                  ICloudGuardian.NoOpCloudGuardian.INSTANCE);
      }
  
 +    @Override
 +    String getAdapterName() {
 +        return ExternalDataConstants.KEY_ADAPTER_NAME_AWS_S3;
 +    }
 +
 +    @Override
 +    int getPathMaxLengthInBytes() {
 +        return S3Constants.MAX_KEY_LENGTH_IN_BYTES;
 +    }
 +
      @Override
-     boolean isNoContainerFoundException(IOException e) {
-         return e.getCause() instanceof NoSuchBucketException;
-     }
- 
-     @Override
-     boolean isSdkException(Throwable e) {
-         return e instanceof SdkException;
+     Optional<SdkException> getSdkException(Throwable ex) {
+         return ExceptionUtils.getCauseOfType(ex, SdkException.class);
      }
  
      @Override
diff --cc 
asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/google/gcs/GCSConstants.java
index 8319a80f0a,19fd74fadb..123f039bac
--- 
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/google/gcs/GCSConstants.java
+++ 
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/google/gcs/GCSConstants.java
@@@ -39,10 -39,8 +39,11 @@@ public class GCSConstants 
          throw new AssertionError("do not instantiate");
      }
  
 +    // Key max length
 +    public static final int MAX_KEY_LENGTH_IN_BYTES = 1024;
 +
      public static final String APPLICATION_DEFAULT_CREDENTIALS_FIELD_NAME = 
"applicationDefaultCredentials";
+     public static final String IMPERSONATE_SERVICE_ACCOUNT_FIELD_NAME = 
"impersonateServiceAccount";
      public static final String JSON_CREDENTIALS_FIELD_NAME = 
"jsonCredentials";
      public static final String ENDPOINT_FIELD_NAME = "endpoint";
      public static final String STORAGE_PREFIX = "prefix";

Reply via email to