Merge branch 'gerrit/ionic' into 'master'

Change-Id: Idaae7d6906e39513691a35bd243286638660e72d
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
index f78aa59..98c54e6 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
@@ -61,6 +61,7 @@
         addFunctionAndArgChecker(BuiltinFunctions.IF_NULL, null);
         addFunctionAndArgChecker(BuiltinFunctions.IF_MISSING_OR_NULL, null);
         addFunctionAndArgChecker(BuiltinFunctions.IF_SYSTEM_NULL, null);
+        addFunctionAndArgChecker(BuiltinFunctions.IF_ERROR, null);
     }
 
     // allows the rule to check other functions in addition to the ones specified here
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
index 6813e84..7c9b548 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
@@ -34,7 +34,6 @@
 import org.apache.asterix.metadata.entities.Datatype;
 import org.apache.asterix.metadata.entities.Index;
 import org.apache.asterix.om.types.ARecordType;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.api.exceptions.SourceLocation;
 
 /**
@@ -528,7 +527,7 @@
             return condition;
         }
 
-        public Query getQuery() throws AlgebricksException {
+        public Query getQuery() {
             return query;
         }
 
@@ -605,9 +604,9 @@
         private final List<OrderbyClause.NullOrderModifier> orderByNullModifierList;
         private final List<Expression> keyExpressions;
         private final boolean autogenerated;
-
         private final ARecordType itemType;
         private final ARecordType parquetSchema;
+        private final Map<String, String> formatConfigs;
 
         public CompiledCopyToStatement(CopyToStatement copyToStatement) {
             this.query = copyToStatement.getQuery();
@@ -625,6 +624,7 @@
             this.autogenerated = copyToStatement.isAutogenerated();
             this.itemType = eddDecl.getItemType();
             this.parquetSchema = eddDecl.getParquetSchema();
+            this.formatConfigs = copyToStatement.getFormatConfigs();
         }
 
         @Override
@@ -696,6 +696,10 @@
             return autogenerated;
         }
 
+        public Map<String, String> getFormatConfigs() {
+            return formatConfigs;
+        }
+
         public boolean isFileStoreSink() {
             return keyExpressions.isEmpty() && !autogenerated;
         }
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 6d37447..ed62ba3 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -467,7 +467,7 @@
 
         // Write adapter configuration
         WriteDataSink writeDataSink = new WriteDataSink(copyTo.getAdapter(), copyTo.getProperties(),
-                copyTo.getItemType(), copyTo.getParquetSchema(), expr.getSourceLocation());
+                copyTo.getItemType(), copyTo.getParquetSchema(), copyTo.getFormatConfigs(), expr.getSourceLocation());
 
         // writeOperator
         WriteOperator writeOperator = new WriteOperator(sourceExprRef, new MutableObject<>(fullPathExpr),
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index 3d806a8..31fe950 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -586,6 +586,7 @@
                             outerUnnestMissingValue)
                     : new UnnestOperator(rightVar, new MutableObject<>(pUnnestExpr.first));
         }
+        unnestOp.getAnnotations().put(ARRAY_ACCESS, rightExpr.getKind() == Kind.FIELD_ACCESSOR_EXPRESSION);
         ExternalSubpathAnnotation hint = ((AbstractExpression) rightExpr).findHint(ExternalSubpathAnnotation.class);
         if (hint != null) {
             unnestOp.getAnnotations().put(SUBPATH, hint.getSubPath());
diff --git a/asterixdb/asterix-app/pom.xml b/asterixdb/asterix-app/pom.xml
index 7cd2cb8..81f570a 100644
--- a/asterixdb/asterix-app/pom.xml
+++ b/asterixdb/asterix-app/pom.xml
@@ -185,7 +185,7 @@
             <configuration>
               <includeClassifiers>testlib</includeClassifiers>
               <outputDirectory>target/data/externallib</outputDirectory>
-              <overwrite>true</overwrite>
+              <overWriteIfNewer>true</overWriteIfNewer>
               <stripVersion>true</stripVersion>
             </configuration>
           </execution>
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.5.query.sqlpp
new file mode 100644
index 0000000..96c263b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.5.query.sqlpp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties:( c_w_id ,c_d_id, c_id)
+--  and requirement properties: (o_c_id, o_w_id, o_d_id)
+--  with the following join condition
+--  the expected final required properties of orders will be: (o_w_id, o_d_id, o_c_id)
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+
+
+CREATE TYPE cust_type AS {c_w_id : integer,c_d_id : integer, c_id : integer};
+CREATE DATASET customer(cust_type) PRIMARY KEY c_w_id, c_d_id, c_id;
+
+CREATE TYPE orders_type AS {o_w_id : integer, o_d_id : integer, o_id : integer};
+CREATE DATASET orders(orders_type) PRIMARY KEY o_w_id, o_d_id, o_id;
+
+
+
+
+
+SELECT c.c_id, o.*
+FROM customer c LEFT OUTER JOIN orders o ON (
+    c.c_w_id  = o.o_w_id
+        AND c.c_d_id = o.o_d_id
+        AND c.c_id = o.o_c_id
+        AND o.o_carrier_id > 8);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.7.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.7.query.sqlpp
new file mode 100644
index 0000000..bb0a1be
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.7.query.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+use test;
+
+
+
+SELECT c.c_id, o.*
+FROM customer c LEFT OUTER JOIN orders o ON (
+    c.c_w_id /*+ hash-bcast */  = o.o_w_id
+        AND c.c_d_id = o.o_d_id
+        AND c.c_id = o.o_c_id
+        AND o.o_carrier_id > 8);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.9.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.9.query.sqlpp
new file mode 100644
index 0000000..c0ed3de
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange/hash_join_exchange.9.query.sqlpp
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties: (o_w_id, o_d_id, o_id)
+--  and requirement properties: (o_w_id, o_d_id, o_id)
+--  with the following join condition
+--  the expected final required properties of orders will be: (o_w_id, o_d_id, o_id)
+
+
+use test;
+
+
+
+SELECT o.o_d_id, o.o_w_id, o.o_id, o.c_id, o.o_carrier_id, o.o_ol_cnt, c.*
+FROM orders o LEFT OUTER JOIN customer c ON (
+    c.c_w_id  = o.o_w_id
+        AND c.c_d_id = o.o_d_id
+        AND c.c_id = o.o_c_id
+        AND o.o_carrier_id > 8);
+
+
+
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.11.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.11.query.sqlpp
new file mode 100644
index 0000000..9f01f47
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.11.query.sqlpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties: (a_1, a_0, a_2)
+--  with join condition a_0=b_0, a_1=b_1, a_2=b_2 and equivalence mapping a_0=a_1
+--  the expected final required properties of B will be: (b_0, b_1, b_2) which should be okay.
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+CREATE TYPE A_TYPE AS {a_0 : integer, a_1 : integer, a_2 : integer};
+CREATE DATASET A(A_TYPE) PRIMARY KEY a_0, a_1, a_2;
+
+CREATE TYPE B_TYPE AS {b_0 : integer, b_1 : integer, b_2 : integer};
+CREATE DATASET B(B_TYPE) PRIMARY KEY b_0, b_1, b_2;
+
+
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B   ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1
+        AND A.a_2 = B.b_2)
+WHERE  A.a_0=A.a_2;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.13.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.13.query.sqlpp
new file mode 100644
index 0000000..9e2fbe3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.13.query.sqlpp
@@ -0,0 +1,36 @@
+/*
+* 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.
+*/
+
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first partition properties:( a_0, a_1, a_2)
+--  and requirement properties: (b_0, b_1, b_2)
+--  with the join condition A.a_0  = B.b_0 AND B.b_1 = A.a_1 AND A.a_2 = B.b_2 AND A.a_3 = B.b_3
+--  No extra hash exchanges are required as its already partitioned on (a_0, a_1, a_2, a_3) & (b_0, b_1, b_2, b_3)
+--  As partition on (a_0, a_1, a_2) implies partition on (a_0, a_1, a_2, a_3)
+
+
+use test;
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+        FROM  A  LEFT OUTER JOIN B   ON (
+            A.a_0  = B.b_0
+                AND B.b_1 = A.a_1
+                AND A.a_2 = B.b_2
+                AND A.a_3 = B.b_3);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.5.query.sqlpp
new file mode 100644
index 0000000..ace3520
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.5.query.sqlpp
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties: (a_1, a_0, a_2)
+--  with join condition a_0=b_0, a_1=b_1, a_2=b_2
+--  the expected final required properties of B will be: (b_0, b_1, b_2) which should be okay.
+
+
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+
+
+CREATE TYPE A_TYPE AS {a_0 : integer, a_1 : integer, a_2 : integer};
+CREATE DATASET A(A_TYPE) PRIMARY KEY a_0, a_1, a_2;
+
+CREATE TYPE B_TYPE AS {b_0 : integer, b_1 : integer, b_2 : integer};
+CREATE DATASET B(B_TYPE) PRIMARY KEY b_0, b_1, b_2;
+
+
+
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B   ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1
+        AND A.a_2 = B.b_2);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.7.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.7.query.sqlpp
new file mode 100644
index 0000000..1a364fc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.7.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties:( a_3 ,a_0, a_1)
+--  and requirement properties: (b_3, b_0, b_1)
+--  with the following join condition
+--  the expected final required properties of orders will be: (b_3, b_0, b_1)
+
+use test;
+
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B  ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1
+        AND A.a_3 = B.b_3);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.9.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.9.query.sqlpp
new file mode 100644
index 0000000..1aff08c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/hash_join_exchange_1/hash_join_exchange_1.9.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties:( a_0, a_1)
+--  and requirement properties: (b_0, b_1)
+--  with the following join condition
+--  the expected final required properties of orders will be: (b_0, b_1)
+use test;
+
+
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B   ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.5.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.5.query.plan
new file mode 100644
index 0000000..c9c3348
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.5.query.plan
@@ -0,0 +1,40 @@
+distribute result [$$43]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$43] <- [object-concat-strict({"c_id": $$46}, to-object-var-str($$o))] project: [$$43]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$46, $$o])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$46, $$51), eq($$44, $$47), eq($$45, $$48)))
+          -- HYBRID_HASH_JOIN [$$46, $$44, $$45][$$51, $$47, $$48]  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              project ([$$46, $$44, $$45])
+              -- STREAM_PROJECT  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$44, $$45, $$46, $$c] <- test.customer
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- HASH_PARTITION_EXCHANGE [$$47, $$48, $$51]  |PARTITIONED|
+              select (gt($$o.getField("o_carrier_id"), 8))
+              -- STREAM_SELECT  |PARTITIONED|
+                assign [$$51] <- [$$o.getField("o_c_id")]
+                -- ASSIGN  |PARTITIONED|
+                  project ([$$47, $$48, $$o])
+                  -- STREAM_PROJECT  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      data-scan []<-[$$47, $$48, $$49, $$o] <- test.orders
+                      -- DATASOURCE_SCAN  |PARTITIONED|
+                        exchange
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          empty-tuple-source
+                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.7.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.7.query.plan
new file mode 100644
index 0000000..02a3b43
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.7.query.plan
@@ -0,0 +1,40 @@
+distribute result [$$43]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$43] <- [object-concat-strict({"c_id": $$46}, to-object-var-str($$o))] project: [$$43]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$46, $$o])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$46, $$51), eq($$44, $$47), eq($$45, $$48)))
+          -- HYBRID_HASH_JOIN [$$46, $$44, $$45][$$51, $$47, $$48]  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              project ([$$46, $$44, $$45])
+              -- STREAM_PROJECT  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$44, $$45, $$46, $$c] <- test.customer
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- BROADCAST_EXCHANGE  |PARTITIONED|
+              select (gt($$o.getField("o_carrier_id"), 8))
+              -- STREAM_SELECT  |PARTITIONED|
+                assign [$$51] <- [$$o.getField("o_c_id")]
+                -- ASSIGN  |PARTITIONED|
+                  project ([$$47, $$48, $$o])
+                  -- STREAM_PROJECT  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      data-scan []<-[$$47, $$48, $$49, $$o] <- test.orders
+                      -- DATASOURCE_SCAN  |PARTITIONED|
+                        exchange
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          empty-tuple-source
+                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.9.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.9.query.plan
new file mode 100644
index 0000000..4a69a97
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange/hash_join_exchange.9.query.plan
@@ -0,0 +1,54 @@
+distribute result [$$48]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$48] <- [object-concat-strict({"o_d_id": $$50, "o_w_id": $$49, "o_id": $$51, "c_id": $$65, "o_carrier_id": $$61, "o_ol_cnt": $$67}, to-object-var-str($$c))] project: [$$48]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$50, $$49, $$51, $$65, $$61, $$67, $$c])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$49, $$73), eq($$50, $$74), eq($$51, $$75)))
+          -- HYBRID_HASH_JOIN [$$49, $$50, $$51][$$73, $$74, $$75]  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              assign [$$67, $$61, $$65] <- [$$o.getField("o_ol_cnt"), $$o.getField("o_carrier_id"), $$o.getField("c_id")] project: [$$50, $$49, $$51, $$65, $$61, $$67]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$49, $$50, $$51, $$o] <- test.orders
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- HASH_PARTITION_EXCHANGE [$$73, $$74, $$75]  |PARTITIONED|
+              project ([$$c, $$73, $$74, $$75])
+              -- STREAM_PROJECT  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  join (and(eq($$54, $$68), eq($$52, $$73), eq($$53, $$74)))
+                  -- HYBRID_HASH_JOIN [$$68, $$73, $$74][$$54, $$52, $$53]  |PARTITIONED|
+                    exchange
+                    -- HASH_PARTITION_EXCHANGE [$$73, $$74, $$68]  |PARTITIONED|
+                      select (gt($$69.getField("o_carrier_id"), 8)) project: [$$73, $$74, $$75, $$68]
+                      -- STREAM_SELECT  |PARTITIONED|
+                        assign [$$68] <- [$$69.getField("o_c_id")]
+                        -- ASSIGN  |PARTITIONED|
+                          exchange
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            data-scan []<-[$$73, $$74, $$75, $$69] <- test.orders
+                            -- DATASOURCE_SCAN  |PARTITIONED|
+                              exchange
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                empty-tuple-source
+                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      data-scan []<-[$$52, $$53, $$54, $$c] <- test.customer
+                      -- DATASOURCE_SCAN  |PARTITIONED|
+                        exchange
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          empty-tuple-source
+                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.11.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.11.query.plan
new file mode 100644
index 0000000..20fa187
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.11.query.plan
@@ -0,0 +1,38 @@
+distribute result [$$46]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$46] <- [{"a_0": $$49, "a_1": $$50, "a_2": $$51, "a_3": $$62, "b_3": $$63}] project: [$$46]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$49, $$50, $$51, $$62, $$63])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$51, $$54), eq($$49, $$52), eq($$53, $$50)))
+          -- HYBRID_HASH_JOIN [$$51, $$49, $$50][$$54, $$52, $$53]  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              select (eq($$49, $$51))
+              -- STREAM_SELECT  |PARTITIONED|
+                assign [$$62] <- [$$A.getField("a_3")] project: [$$49, $$50, $$51, $$62]
+                -- ASSIGN  |PARTITIONED|
+                  exchange
+                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                    data-scan []<-[$$49, $$50, $$51, $$A] <- test.A
+                    -- DATASOURCE_SCAN  |PARTITIONED|
+                      exchange
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        empty-tuple-source
+                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              assign [$$63] <- [$$B.getField("b_3")] project: [$$63, $$54, $$52, $$53]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$52, $$53, $$54, $$B] <- test.B
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.13.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.13.query.plan
new file mode 100644
index 0000000..f4d6562
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.13.query.plan
@@ -0,0 +1,36 @@
+distribute result [$$46]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$46] <- [{"a_0": $$47, "a_1": $$48, "a_2": $$49, "a_3": $$55, "b_3": $$56}] project: [$$46]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$47, $$48, $$49, $$55, $$56])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$49, $$52), eq($$55, $$56), eq($$47, $$50), eq($$51, $$48)))
+          -- HYBRID_HASH_JOIN [$$49, $$55, $$47, $$48][$$52, $$56, $$50, $$51]  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              assign [$$55] <- [$$A.getField("a_3")] project: [$$47, $$48, $$49, $$55]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$47, $$48, $$49, $$A] <- test.A
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              assign [$$56] <- [$$B.getField("b_3")] project: [$$56, $$52, $$50, $$51]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$50, $$51, $$52, $$B] <- test.B
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.5.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.5.query.plan
new file mode 100644
index 0000000..3bf9f1a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.5.query.plan
@@ -0,0 +1,36 @@
+distribute result [$$43]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$43] <- [{"a_0": $$44, "a_1": $$45, "a_2": $$46, "a_3": $$59, "b_3": $$60}] project: [$$43]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$44, $$45, $$46, $$59, $$60])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$46, $$49), eq($$44, $$47), eq($$48, $$45)))
+          -- HYBRID_HASH_JOIN [$$46, $$44, $$45][$$49, $$47, $$48]  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              assign [$$59] <- [$$A.getField("a_3")] project: [$$44, $$45, $$46, $$59]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$44, $$45, $$46, $$A] <- test.A
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              assign [$$60] <- [$$B.getField("b_3")] project: [$$60, $$49, $$47, $$48]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$47, $$48, $$49, $$B] <- test.B
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.7.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.7.query.plan
new file mode 100644
index 0000000..2751a74
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.7.query.plan
@@ -0,0 +1,38 @@
+distribute result [$$43]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$43] <- [{"a_0": $$44, "a_1": $$45, "a_2": $$46, "a_3": $$50, "b_3": $$51}] project: [$$43]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$44, $$45, $$46, $$50, $$51])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$50, $$51), eq($$44, $$47), eq($$48, $$45)))
+          -- HYBRID_HASH_JOIN [$$50, $$44, $$45][$$51, $$47, $$48]  |PARTITIONED|
+            exchange
+            -- HASH_PARTITION_EXCHANGE [$$50, $$44, $$45]  |PARTITIONED|
+              assign [$$50] <- [$$A.getField("a_3")] project: [$$44, $$45, $$46, $$50]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$44, $$45, $$46, $$A] <- test.A
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- HASH_PARTITION_EXCHANGE [$$51, $$47, $$48]  |PARTITIONED|
+              assign [$$51] <- [$$B.getField("b_3")] project: [$$51, $$47, $$48]
+              -- ASSIGN  |PARTITIONED|
+                project ([$$47, $$48, $$B])
+                -- STREAM_PROJECT  |PARTITIONED|
+                  exchange
+                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                    data-scan []<-[$$47, $$48, $$49, $$B] <- test.B
+                    -- DATASOURCE_SCAN  |PARTITIONED|
+                      exchange
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        empty-tuple-source
+                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.9.query.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.9.query.plan
new file mode 100644
index 0000000..483fdc2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/hash_join_exchange_1/hash_join_exchange_1.9.query.plan
@@ -0,0 +1,38 @@
+distribute result [$$40]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    assign [$$40] <- [{"a_0": $$41, "a_1": $$42, "a_2": $$43, "a_3": $$54, "b_3": $$55}] project: [$$40]
+    -- ASSIGN  |PARTITIONED|
+      project ([$$41, $$42, $$43, $$54, $$55])
+      -- STREAM_PROJECT  |PARTITIONED|
+        exchange
+        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+          left outer join (and(eq($$41, $$44), eq($$45, $$42)))
+          -- HYBRID_HASH_JOIN [$$41, $$42][$$44, $$45]  |PARTITIONED|
+            exchange
+            -- HASH_PARTITION_EXCHANGE [$$41, $$42]  |PARTITIONED|
+              assign [$$54] <- [$$A.getField("a_3")] project: [$$41, $$42, $$43, $$54]
+              -- ASSIGN  |PARTITIONED|
+                exchange
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$41, $$42, $$43, $$A] <- test.A
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange
+            -- HASH_PARTITION_EXCHANGE [$$44, $$45]  |PARTITIONED|
+              assign [$$55] <- [$$B.getField("b_3")] project: [$$55, $$44, $$45]
+              -- ASSIGN  |PARTITIONED|
+                project ([$$44, $$45, $$B])
+                -- STREAM_PROJECT  |PARTITIONED|
+                  exchange
+                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                    data-scan []<-[$$44, $$45, $$46, $$B] <- test.B
+                    -- DATASOURCE_SCAN  |PARTITIONED|
+                      exchange
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        empty-tuple-source
+                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.000.ddl.sqlpp
new file mode 100644
index 0000000..c04056a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.000.ddl.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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 test IF EXISTS;
+CREATE DATAVERSE test;
+
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.030.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.030.update.sqlpp
new file mode 100644
index 0000000..4372e59
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.030.update.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+COPY (
+   select value x FROM [
+   {"id":1, "name":"", "amount":123.2, "accountNumber":345.34, "joinDatetime": datetime("2025-04-25T14:53:54.398"), "joinDate": date("2025-04-25"), "joinTime": time("14:53:54.398")}
+   ] as x
+) toWrite
+TO %adapter%
+PATH (%pathprefix% "copy-to-result", "csv", "simple-csv", "datetime-not-formatted")
+TYPE ( {id: bigint, name: string?, amount: float, accountNumber: double, joinDatetime: datetime, joinDate: date, joinTime: time} )
+WITH {
+    %template_colons%,
+    %additionalProperties%
+    "format":"csv",
+    "header":"true"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.031.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.031.update.sqlpp
new file mode 100644
index 0000000..8adfd8c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.031.update.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License", you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+COPY (
+   select value x FROM [
+   {"id":1, "name":"", "amount":123.2, "accountNumber":345.34, "joinDatetime": datetime("2025-04-25T14:53:54.398")}
+   ] as x
+) toWrite
+TO %adapter%
+PATH (%pathprefix% "copy-to-result", "csv", "simple-csv", "datetime-formatted")
+TYPE ( {id: bigint, name: string?, amount: float, accountNumber: double, joinDatetime: datetime} )
+DATETIME "DD-MM-YYYYTss:mm:hh"
+WITH {
+    %template_colons%,
+    %additionalProperties%
+    "format":"csv",
+    "header":"true"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.032.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.032.update.sqlpp
new file mode 100644
index 0000000..38b0eef
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.032.update.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License", you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+COPY (
+   select value x FROM [
+   {"id":1, "name":"", "amount":123.2, "accountNumber":345.34, "joinDatetime": datetime("2025-04-25T14:53:54.398"), "joinDate": date("2025-04-25")}
+   ] as x
+) toWrite
+TO %adapter%
+PATH (%pathprefix% "copy-to-result", "csv", "simple-csv", "datetime-date-formatted")
+TYPE ( {id: bigint, name: string?, amount: float, accountNumber: double, joinDatetime: datetime, joinDate: date} )
+DATE "DD-MM-YYYY" DATETIME "DD-MM-YYYY"
+WITH {
+    %template_colons%,
+    %additionalProperties%
+    "format":"csv",
+    "header":"true"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.033.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.033.update.sqlpp
new file mode 100644
index 0000000..5628b8e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.033.update.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.
+ */
+
+COPY (
+   select value x FROM [
+   {"id":1, "name":"", "amount":123.2, "accountNumber":345.34, "joinDatetime": datetime("2025-04-25T14:53:54.398"), "joinTime": time("14:53:54.398")}
+   ] as x
+) toWrite
+TO %adapter%
+PATH (%pathprefix% "copy-to-result", "csv", "simple-csv", "datetime-time-formatted")
+TYPE ( {id: bigint, name: string?, amount: float, accountNumber: double, joinDatetime: datetime, joinTime: time} )
+DATETIME "hh:mm:ss.nnna"
+TIME "hh:mm:ss.nnna"
+WITH {
+    %template_colons%,
+    %additionalProperties%
+    "format":"csv",
+    "header":"true"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.034.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.034.update.sqlpp
new file mode 100644
index 0000000..d5044cd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.034.update.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License", you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+COPY (
+   select value x FROM [
+   {"id":1, "name":"", "amount":123.2, "accountNumber":345.34, "joinDatetime": datetime("2025-04-25T14:53:54.398")}
+   ] as x
+) toWrite
+TO %adapter%
+PATH (%pathprefix% "copy-to-result", "csv", "simple-csv", "datetime-formatted-2")
+TYPE ( {id: bigint, name: string?, amount: float, accountNumber: double, joinDatetime: datetime} )
+DATETIME "DD/MM/YYYY ss:mm:hh a"
+WITH {
+    %template_colons%,
+    %additionalProperties%
+    "format":"csv",
+    "header":"true"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.035.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.035.update.sqlpp
new file mode 100644
index 0000000..a80fd43
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.035.update.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License", you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+COPY (
+   select value x FROM [
+   {"id":1, "name":"", "amount":123.2, "accountNumber":345.34, "joinDatetime": datetime("2025-04-25T14:53:54.398")}
+   ] as x
+) toWrite
+TO %adapter%
+PATH (%pathprefix% "copy-to-result", "csv", "simple-csv", "datetime-formatted-with-comma")
+TYPE ( {id: bigint, name: string?, amount: float, accountNumber: double, joinDatetime: datetime} )
+DATETIME "DD/MMM/YYYY, ss:mm:hh a"
+WITH {
+    %template_colons%,
+    %additionalProperties%
+    "format":"csv",
+    "header":"true"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.036.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.036.update.sqlpp
new file mode 100644
index 0000000..26fb57c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.036.update.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+COPY (
+   select value x FROM [
+   {"id":1, "name":"", "amount":123.2, "accountNumber":345.34, "joinDatetime": datetime("2025-04-25T14:53:54.398"), "joinDate": date("2025-04-25"), "joinTime": time("14:53:54.398")}
+   ] as x
+) toWrite
+TO %adapter%
+PATH (%pathprefix% "copy-to-result", "csv", "simple-csv", "datetime-date-time-formatted-with-comma")
+TYPE ( {id: bigint, name: string?, amount: float, accountNumber: double, joinDatetime: datetime, joinDate: date, joinTime: time} )
+DATETIME "DD/MMM/YYYY, ss:mm:hh a"
+TIME "ss:mm:hh a"
+DATE "DD/MMM/YYYY"
+WITH {
+    %template_colons%,
+    %additionalProperties%
+    "format":"csv",
+    "header":"true"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.040.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.040.ddl.sqlpp
new file mode 100644
index 0000000..e8dc8bd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.040.ddl.sqlpp
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+drop dataset datetimeNotFormattedDataset if exists;
+drop dataset datetimeFormattedDataset if exists;
+drop dataset datetimeDateFormattedDataset if exists;
+drop dataset datatimeTimeFormattedDataset if exists;
+drop dataset datetimeFormattedDataset2 if exists;
+drop dataset datetimeFormattedWithCommaDataset if exists;
+drop dataset datetimeDateTimeFormattedWithCommaDataset if exists;
+
+drop type datetimeNotFormattedType if exists;
+drop type datetimeFormattedType if exists;
+drop type datetimeDateFormattedType if exists;
+drop type datatimeTimeFormattedType if exists;
+drop type datetimeFormattedType2 if exists;
+drop type datetimeFormattedWithCommaType if exists;
+drop type datetimeDateTimeFormattedWithCommaType if exists;
+
+CREATE TYPE datetimeNotFormattedType AS { id: bigint, name: string?, amount: float, accountNumber: double, joinDateTime: string, joinDate: string, joinTime: string };
+CREATE TYPE datetimeFormattedType AS { id: bigint, name: string?, amount: float, accountNumber: double, joinDateTime: string };
+CREATE TYPE datetimeDateFormattedType AS { id: bigint, name: string?, amount: float, accountNumber: double, joinDateTime: string, joinDate: string };
+CREATE TYPE datatimeTimeFormattedType AS { id: bigint, name: string?, amount: float, accountNumber: double, joinDateTime: string, joinTime: string };
+CREATE TYPE datetimeFormattedType2 AS { id: bigint, name: string?, amount: float, accountNumber: double, joinDateTime: string };
+CREATE TYPE datetimeFormattedWithCommaType AS { id: bigint, name: string?, amount: float, accountNumber: double, joinDateTime: string };
+CREATE TYPE datetimeDateTimeFormattedWithCommaType AS { id: bigint, name: string?, amount: float, accountNumber: double, joinDateTime: string, joinDate: string, joinTime: string };
+
+CREATE EXTERNAL DATASET datetimeNotFormattedDataset(datetimeNotFormattedType) USING %adapter%
+(
+  %template%,
+  %additional_Properties%,
+  ("header"="true"),
+  ("definition"="%path_prefix%copy-to-result/csv/simple-csv/datetime-not-formatted"),
+  ("format" = "csv")
+);
+
+CREATE EXTERNAL DATASET datetimeFormattedDataset(datetimeFormattedType) USING %adapter%
+(
+  %template%,
+  %additional_Properties%,
+  ("header"="true"),
+  ("definition"="%path_prefix%copy-to-result/csv/simple-csv/datetime-formatted"),
+  ("format" = "csv")
+);
+
+CREATE EXTERNAL DATASET datetimeDateFormattedDataset(datetimeDateFormattedType) USING %adapter%
+(
+  %template%,
+  %additional_Properties%,
+  ("header"="true"),
+  ("definition"="%path_prefix%copy-to-result/csv/simple-csv/datetime-date-formatted"),
+  ("format" = "csv")
+);
+
+CREATE EXTERNAL DATASET datatimeTimeFormattedDataset(datatimeTimeFormattedType) USING %adapter%
+(
+  %template%,
+  %additional_Properties%,
+  ("header"="true"),
+  ("definition"="%path_prefix%copy-to-result/csv/simple-csv/datetime-time-formatted"),
+  ("format" = "csv")
+);
+
+CREATE EXTERNAL DATASET datetimeFormattedDataset2(datetimeFormattedType2) USING %adapter%
+(
+  %template%,
+  %additional_Properties%,
+  ("header"="true"),
+  ("definition"="%path_prefix%copy-to-result/csv/simple-csv/datetime-formatted-2"),
+  ("format" = "csv")
+);
+
+CREATE EXTERNAL DATASET datetimeFormattedWithCommaDataset(datetimeFormattedWithCommaType) USING %adapter%
+(
+  %template%,
+  %additional_Properties%,
+  ("header"="true"),
+  ("definition"="%path_prefix%copy-to-result/csv/simple-csv/datetime-formatted-with-comma"),
+  ("format" = "csv")
+);
+
+CREATE EXTERNAL DATASET datetimeDateTimeFormattedWithCommaDataset(datetimeDateTimeFormattedWithCommaType) USING %adapter%
+(
+  %template%,
+  %additional_Properties%,
+  ("header"="true"),
+  ("definition"="%path_prefix%copy-to-result/csv/simple-csv/datetime-date-time-formatted-with-comma"),
+  ("format" = "csv")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.130.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.130.query.sqlpp
new file mode 100644
index 0000000..4ccbb8d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.130.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT 
+joinDateTime as joinDateTime, get_type(joinDateTime) as joinDateTimeType, datetime(joinDateTime) as joinDateTimeCasted,  get_type(datetime(joinDateTime)) as joinDateTimeCastedType,
+joinDate as joinDate, get_type(joinDate) as joinDateType, date(joinDate) as joinDateCasted,  get_type(date(joinDate)) as joinDateCastedType,
+joinTime as joinTime, get_type(joinTime) as joinTimeType, time(joinTime) as joinTimeCasted,  get_type(time(joinTime)) as joinTimeCastedType
+FROM datetimeNotFormattedDataset;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.131.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.131.query.sqlpp
new file mode 100644
index 0000000..ddd60e6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.131.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT 
+joinDateTime as joinDateTime, get_type(joinDateTime) as joinDateTimeType, parse_datetime(joinDateTime, "DD-MM-YYYYTss:mm:hh") as joinDateTimeCasted,  get_type(parse_datetime(joinDateTime, "DD-MM-YYYYTss:mm:hh")) as joinDateTimeCastedType
+FROM datetimeFormattedDataset;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.132.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.132.query.sqlpp
new file mode 100644
index 0000000..ac6158e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.132.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT 
+joinDateTime as joinDateTime, get_type(joinDateTime) as joinDateTimeType, parse_datetime(joinDateTime, "DD-MM-YYYY") as joinDateTimeCasted, get_type(parse_datetime(joinDateTime, "DD-MM-YYYY")) as joinDateTimeCastedType,
+joinDate as joinDate, get_type(joinDate) as joinDateType, parse_Date(joinDate, "DD-MM-YYYY") as joinDateCasted, get_type(parse_Date(joinDate, "DD-MM-YYYY")) as joinDateCastedType
+FROM datetimeDateFormattedDataset;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.133.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.133.query.sqlpp
new file mode 100644
index 0000000..870e830
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.133.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT 
+joinTime as joinTime, get_type(joinTime) as joinTimeType, parse_time(joinTime, "hh:mm:ss.nnna") as joinTimeCasted, get_type(parse_time(joinTime, "hh:mm:ss.nnna")) as joinTimeCastedType
+FROM datatimeTimeFormattedDataset;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.134.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.134.query.sqlpp
new file mode 100644
index 0000000..332222d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.134.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT 
+joinDateTime as joinDateTime, get_type(joinDateTime) as joinDateTimeType, parse_datetime(joinDateTime, "DD/MM/YYYY ss:mm:hh a") as joinDateTimeCasted, get_type(parse_datetime(joinDateTime, "DD/MM/YYYY ss:mm:hh a")) as joinDateTimeCastedType
+FROM datetimeFormattedDataset2;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.135.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.135.query.sqlpp
new file mode 100644
index 0000000..ffe5b55
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.135.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT 
+joinDateTime as joinDateTime, get_type(joinDateTime) as joinDateTimeType, parse_datetime(joinDateTime, "DD/MMM/YYYY, ss:mm:hh a") as joinDateTimeCasted, get_type(parse_datetime(joinDateTime, "DD/MMM/YYYY, ss:mm:hh a")) as joinDateTimeCastedType
+FROM datetimeFormattedWithCommaDataset;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.136.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.136.query.sqlpp
new file mode 100644
index 0000000..aa3afad
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.136.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT 
+joinDateTime as joinDateTime, get_type(joinDateTime) as joinDateTimeType, parse_datetime(joinDateTime, "DD/MMM/YYYY, ss:mm:hh a") as joinDateTimeCasted, get_type(parse_datetime(joinDateTime, "DD/MMM/YYYY, ss:mm:hh a")) as joinDateTimeCastedType,
+joinDate as joinDate, get_type(joinDate) as joinDateType, parse_Date(joinDate, "DD/MMM/YYYY") as joinDateCasted, get_type(parse_Date(joinDate, "DD/MMM/YYYY")) as joinDateCastedType,
+joinTime as joinTime, get_type(joinTime) as joinTimeType, parse_time(joinTime, "ss:mm:hh a") as joinTimeCasted, get_type(parse_time(joinTime, "ss:mm:hh a")) as joinTimeCastedType
+FROM datetimeDateTimeFormattedWithCommaDataset;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.999.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.999.ddl.sqlpp
new file mode 100644
index 0000000..220c7be
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy-to/csv/datetime/test.999.ddl.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.
+ */
+
+DROP DATAVERSE test IF EXISTS;
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.01.ddl.sqlpp
new file mode 100644
index 0000000..1a3bfb4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.01.ddl.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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 test IF EXISTS;
+CREATE DATAVERSE test;
+USE test;
+
+CREATE TYPE t1 IF NOT EXISTS AS {id: int, f: string?};
+CREATE DATASET ds1(t1) IF NOT EXISTS PRIMARY KEY id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.02.update.sqlpp
new file mode 100644
index 0000000..dbf6daf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.02.update.sqlpp
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+UPSERT INTO ds1 ([
+{"id": 1, "f": "asterix", "f2": "asterix"},
+{"id": 2, "f": "𩸽", "f2": "𩸽"},
+{"id": 3, "f": "a𩸽b", "f2": "a𩸽b"},
+{"id": 4, "f": null, "f2": null},
+{"id": 5},
+{"id": 6, "f2": 1}
+]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.03.query.sqlpp
new file mode 100644
index 0000000..e00b33e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.03.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT sha1_hex(f) a, sha1_hex(f2) b, sha1_base64(f) c, sha1_base64(f2) d
+FROM ds1
+ORDER BY ds1.id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.04.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.04.query.sqlpp
new file mode 100644
index 0000000..3f00c24
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.04.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT sha1_hex("asterix") a, sha1_hex("𩸽") b, sha1_hex("a𩸽b") c, sha1_hex(null) d,
+       sha1_base64("asterix") e, sha1_base64("𩸽") f, sha1_base64("a𩸽b") g, sha1_base64(null) h,
+       sha1_hex(missing) i, sha1_base64(missing) j, sha1_hex(1) k, sha1_base64(1) l;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.99.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.99.ddl.sqlpp
new file mode 100644
index 0000000..36b2bab
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/crypto/sha1/sha1.99.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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 test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.1.ddl.sqlpp
new file mode 100644
index 0000000..2b817b2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.1.ddl.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+CREATE TYPE cust_type AS {c_w_id : integer,c_d_id : integer, c_id : integer};
+CREATE DATASET customer(cust_type) PRIMARY KEY c_w_id, c_d_id, c_id;
+
+CREATE TYPE orders_type AS {o_w_id : integer, o_d_id : integer, o_id : integer};
+CREATE DATASET orders(orders_type) PRIMARY KEY o_w_id, o_d_id, o_id;
+
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.2.update.sqlpp
new file mode 100644
index 0000000..b7042c8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.2.update.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+
+INSERT INTO customer ({"c_id":2,"c_d_id":1,"c_w_id":1,"c_discount":0.3413,"c_credit":"GC","c_first":"jqmoaqly","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":4228533.790000002,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"ingngcunkfzoku","c_street_2":"sihqvjfhhphyd","c_city":"jtflodpnsmtn","c_state":"ps","c_zip":"640711111","c_phone":"8709221552477813","c_since":"2016-04-28 05:24:17","key":"1.1.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":2,"c_w_id":1,"c_discount":0.4472,"c_credit":"GC","c_first":"yupforh","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":2637344.5900000003,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"kfmblhsbdf","c_street_2":"ldmnvpzyzqpjgdldcxd","c_city":"jakerbxcuwmnfvqntd","c_state":"ft","c_zip":"377611111","c_phone":"2594721341099812","c_since":"2019-07-23 11:35:08","key":"1.2.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":3,"c_w_id":1,"c_discount":0.4549,"c_credit":"GC","c_first":"cdchdqts","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":2275392.5500000003,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"emwtajlhjyzigbxtll","c_street_2":"bsxxckrjkxvnx","c_city":"vuthjjchaubyurhxu","c_state":"ae","c_zip":"207611111","c_phone":"2223483665383895","c_since":"2015-01-10 09:13:11","key":"1.3.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":4,"c_w_id":1,"c_discount":0.2902,"c_credit":"BC","c_first":"dbxdynrsxq","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":-10.0,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"cdnrcokhecssszdxy","c_street_2":"owkrknkjxxeh","c_city":"dizrkudapnhlur","c_state":"ne","c_zip":"214211111","c_phone":"9527105621833116","c_since":"2019-09-30 04:41:34","key":"1.4.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":5,"c_w_id":1,"c_discount":0.1233,"c_credit":"GC","c_first":"xvaijyn","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":8318309.3500000015,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"tbjodrhupcwdyhiul","c_street_2":"fvbhntiihftymwkabbr","c_city":"cjlfuvcqvkg","c_state":"ng","c_zip":"417111111","c_phone":"5673180500149103","c_since":"2014-10-20 20:06:32","key":"1.5.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":6,"c_w_id":1,"c_discount":0.4838,"c_credit":"GC","c_first":"ikjojneh","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":6788632.1400000015,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"djtnknodfrkny","c_street_2":"iwarlwscxj","c_city":"eaixkpruvqiuhbqnpasf","c_state":"nl","c_zip":"461611111","c_phone":"7068147293579806","c_since":"2018-08-29 23:19:39","key":"1.6.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":7,"c_w_id":1,"c_discount":0.3469,"c_credit":"GC","c_first":"mqvlqra","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":-10.0,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"rcnecgnkrtpgkzrjap","c_street_2":"voabsdpbfuxusyiqs","c_city":"udtfebydicf","c_state":"am","c_zip":"528111111","c_phone":"3972476735934659","c_since":"2020-02-17 05:48:03","key":"1.7.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":8,"c_w_id":1,"c_discount":0.319,"c_credit":"GC","c_first":"hcmxoxvr","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":3253865.68,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"jrkgfusmekbbjygma","c_street_2":"ljkmhxyzyctxyrtlo","c_city":"uxceeygbpgjh","c_state":"he","c_zip":"111611111","c_phone":"3276574132758646","c_since":"2019-08-03 09:05:23","key":"1.8.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":9,"c_w_id":1,"c_discount":0.1118,"c_credit":"BC","c_first":"horovuvbi","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":-10.0,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"ikznzllcvcejsvsf","c_street_2":"lmaferykvzvnlck","c_city":"xzqhxyxkfwgd","c_state":"eu","c_zip":"130211111","c_phone":"3913647178718934","c_since":"2018-07-13 11:47:36","key":"1.9.2"});
+INSERT INTO customer ({"c_id":2,"c_d_id":10,"c_w_id":1,"c_discount":0.4349,"c_credit":"GC","c_first":"ghoevrth","c_middle":"OE","c_last":"BARBAROUGHT","c_credit_lim":50000.0,"c_balance":-10.0,"c_ytd_payment":10.0,"c_payment_cnt":1,"c_delivery_cnt":0,"c_street_1":"qvyasidzgzxzkf","c_street_2":"yyqlehcjsyoaf","c_city":"svnmulhzkp","c_state":"ni","c_zip":"302111111","c_phone":"0212917484161389","c_since":"2017-04-29 18:46:22","key":"1.10.2"});
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.3.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.3.update.sqlpp
new file mode 100644
index 0000000..5a27699
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.3.update.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+INSERT INTO orders ({"o_id":881,"o_c_id":2,"o_d_id":1,"o_w_id":1,"o_carrier_id":6,"o_ol_cnt":11});
+INSERT INTO orders ({"o_id":525,"o_c_id":2,"o_d_id":2,"o_w_id":1,"o_carrier_id":1,"o_ol_cnt":15});
+INSERT INTO orders ({"o_id":466,"o_c_id":2,"o_d_id":3,"o_w_id":1,"o_carrier_id":10,"o_ol_cnt":14});
+INSERT INTO orders ({"o_id":2449,"o_c_id":2,"o_d_id":4,"o_w_id":1,"o_carrier_id":0,"o_ol_cnt":15});
+INSERT INTO orders ({"o_id":1652,"o_c_id":2,"o_d_id":5,"o_w_id":1,"o_carrier_id":10,"o_ol_cnt":7});
+INSERT INTO orders ({"o_id":1350,"o_c_id":2,"o_d_id":6,"o_w_id":1,"o_carrier_id":8,"o_ol_cnt":9});
+INSERT INTO orders ({"o_id":2822,"o_c_id":2,"o_d_id":7,"o_w_id":1,"o_carrier_id":0,"o_ol_cnt":12});
+INSERT INTO orders ({"o_id":677,"o_c_id":2,"o_d_id":8,"o_w_id":1,"o_carrier_id":6,"o_ol_cnt":6});
+INSERT INTO orders ({"o_id":2851,"o_c_id":2,"o_d_id":9,"o_w_id":1,"o_carrier_id":0,"o_ol_cnt":12});
+INSERT INTO orders ({"o_id":2841,"o_c_id":2,"o_d_id":10,"o_w_id":1,"o_carrier_id":0,"o_ol_cnt":9});
+
+
+
+
+
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.4.query.sqlpp
new file mode 100644
index 0000000..a878aa5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.4.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+
+
+
+SELECT c.c_id, o.*
+FROM customer c LEFT OUTER JOIN orders o ON (
+    c.c_w_id  = o.o_w_id
+        AND c.c_d_id = o.o_d_id
+        AND c.c_id = o.o_c_id
+        AND o.o_carrier_id > 8)
+ORDER BY o.o_d_id, o.o_id;
+
+
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.6.query.sqlpp
new file mode 100644
index 0000000..f9572a1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.6.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT c.c_id, o.*
+FROM customer c LEFT OUTER JOIN orders o ON (
+    c.c_w_id /*+ hash-bcast */  = o.o_w_id
+        AND c.c_d_id = o.o_d_id
+        AND c.c_id = o.o_c_id
+        AND o.o_carrier_id > 8)
+ORDER BY o.o_d_id, o.o_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.8.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.8.query.sqlpp
new file mode 100644
index 0000000..c77148b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange/hash_join_exchange.8.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+
+
+SELECT o.o_d_id, o.o_w_id, o.o_id, o.c_id, o.o_carrier_id, o.o_ol_cnt, c.*
+FROM orders o LEFT OUTER JOIN customer c ON (
+    c.c_w_id  = o.o_w_id
+        AND c.c_d_id = o.o_d_id
+        AND c.c_id = o.o_c_id
+        AND o.o_carrier_id > 8)
+ORDER BY o.o_d_id, o.o_w_id, o.o_id, o.c_id, o.o_carrier_id, o.o_ol_cnt;
+
+
+
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.1.ddl.sqlpp
new file mode 100644
index 0000000..c12c22d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.1.ddl.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+
+CREATE TYPE A_TYPE AS {a_0 : integer, a_1 : integer, a_2 : integer};
+CREATE DATASET A(A_TYPE) PRIMARY KEY a_0, a_1, a_2;
+
+CREATE TYPE B_TYPE AS {b_0 : integer, b_1 : integer, b_2 : integer};
+CREATE DATASET B(B_TYPE) PRIMARY KEY b_0, b_1, b_2;
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.10.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.10.query.sqlpp
new file mode 100644
index 0000000..07bf929
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.10.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties: (a_1, a_0, a_2)
+--  with join condition a_0=b_0, a_1=b_1, a_2=b_2 and equivalence mapping a_0=a_1
+--  the expected final required properties of B will be: (b_0, b_1, b_2) which should be okay.
+
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B   ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1
+        AND A.a_2 = B.b_2)
+WHERE  A.a_0=A.a_2
+ORDER BY  A.a_0, A.a_1, A.a_2, A.a_3, B.b_3;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.12.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.12.query.sqlpp
new file mode 100644
index 0000000..42a62ef
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.12.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B   ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1
+        AND A.a_2 = B.b_2
+        AND A.a_3 = B.b_3)
+ORDER BY  A.a_0, A.a_1, A.a_2, A.a_3, B.b_3;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.2.update.sqlpp
new file mode 100644
index 0000000..c8f69c8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.2.update.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+
+INSERT INTO A(
+    SELECT VALUE    {"a_0": i, "a_1": i, "a_2": i, "a_3": i}
+    FROM range(1, 100) i
+);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.3.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.3.update.sqlpp
new file mode 100644
index 0000000..074d554
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.3.update.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+
+
+INSERT INTO B(
+    SELECT VALUE    {"b_0": i, "b_1": i, "b_2": i, "b_3": i}
+    FROM range(51, 150) i
+);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.4.query.sqlpp
new file mode 100644
index 0000000..c50b573
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.4.query.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+--  This Test is intended to test the IPartitioningRequirementsCoordinator for outer join
+--  in the case where the first delivered properties: (a_1, a_0, a_2)
+--  with join condition a_0=b_0, a_1=b_1, a_2=b_2
+--  the expected final required properties of B will be: (b_0, b_1, b_2) which should be okay.
+
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B   ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1
+        AND A.a_2 = B.b_2)
+ORDER BY  A.a_0, A.a_1, A.a_2, A.a_3, B.b_3;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.6.query.sqlpp
new file mode 100644
index 0000000..b7d7196
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.6.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B  ON (
+        A.a_0  = B.b_0
+            AND B.b_1 = A.a_1
+            AND A.a_3 = B.b_3)
+ORDER BY  A.a_0, A.a_1, A.a_2, A.a_3, B.b_3;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.8.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.8.query.sqlpp
new file mode 100644
index 0000000..605e70f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/join/hash_join_exchange_1/hash_join_exchange_1.8.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+SELECT A.a_0, A.a_1, A.a_2, A.a_3, B.b_3
+FROM  A  LEFT OUTER JOIN B   ON (
+    A.a_0  = B.b_0
+        AND B.b_1 = A.a_1)
+ORDER BY  A.a_0, A.a_1, A.a_2, A.a_3, B.b_3;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/handle_error_fun/handle_error_fun.01.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/handle_error_fun/handle_error_fun.01.query.sqlpp
new file mode 100644
index 0000000..c47e3f5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/handle_error_fun/handle_error_fun.01.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+SET `import-private-functions` `true`;
+SELECT VALUE t
+FROM [
+{"id": 1, "f": "fine doc"},
+{"id": 2, "f": "problematic doc"}
+] AS t
+WHERE if_error(inject_failure("", t.id = 2), true) = true;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.01.ddl.sqlpp
new file mode 100644
index 0000000..1a3bfb4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.01.ddl.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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 test IF EXISTS;
+CREATE DATAVERSE test;
+USE test;
+
+CREATE TYPE t1 IF NOT EXISTS AS {id: int, f: string?};
+CREATE DATASET ds1(t1) IF NOT EXISTS PRIMARY KEY id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.02.update.sqlpp
new file mode 100644
index 0000000..0eeb028
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.02.update.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// testing base 16
+USE test;
+
+UPSERT INTO ds1 ([
+{"id": 1, "f": "1", "f2": "1"}, // 1
+{"id": 2, "f": "A", "f2": "A"}, // 10
+{"id": 3, "f": "10", "f2": "10"}, // 16
+{"id": 4, "f": null, "f2": null},
+{"id": 5},
+{"id": 6, "f": "35BC6C28BCA27FB", "f2": "35BC6C28BCA27FB"}, // 242005543865690107
+{"id": 7, "f": "35BC6C28BCA27FBECC144761D32D09986876438F", "f2": "35BC6C28BCA27FBECC144761D32D09986876438F"}, // does not fit in a 64-bit integer
+{"id": 8, "f2": 1} // should return null for non-string inputs
+]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.03.query.sqlpp
new file mode 100644
index 0000000..c4e4b7b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.03.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+USE test;
+
+SELECT from_base(f, 16) a, from_base(f2, 16) b
+FROM ds1
+ORDER BY ds1.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.04.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.04.query.sqlpp
new file mode 100644
index 0000000..bbd27aa
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.04.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+SELECT from_base("1", 16) a, from_base("A", 16) b, from_base("10", 16) c, from_base("35BC6C28BCA27FB", 16) d,
+       from_base("35BC6C28BCA27FBECC144761D32D09986876438F", 16) e,
+       from_base(null, 16) f, from_base(missing, 16) g,
+       from_base("A", null) h, from_base("A", missing) i,
+       from_base("A", -1) j, from_base("A", 1) k, from_base("A", 46) l, from_base(1, 16) m;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.05.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.05.query.sqlpp
new file mode 100644
index 0000000..94f5707
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.05.query.sqlpp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+SELECT from_base("1", 10) a, from_base("10", 10) b, from_base("A", 10) c,
+       from_base("1", 2) d, from_base("10", 2) e, from_base("11", 2) f;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.99.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.99.ddl.sqlpp
new file mode 100644
index 0000000..36b2bab
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/from_base/from_base.99.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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 test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.00.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.00.ddl.sqlpp
new file mode 100644
index 0000000..897aac5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.00.ddl.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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 dataset padding_example if exists;
+create dataset padding_example primary key (id:int);
+upsert into padding_example ([
+{"id":1, "f":"Hi", "f1": "👩"},
+{"id":2, "f": "-7262.98", "f1": "👨‍"},
+{"id":3, "f": "a𩸽b", "f1": "🎉"},
+{"id":4, "f": "👩‍👩‍👧‍👦", "f1": "✓✓✓"},
+{"id":5, "f": null, "f1" : null}
+]);
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.01.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.01.query.sqlpp
new file mode 100644
index 0000000..9b3f0bf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.01.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+
+SELECT id, f, f1,
+    lpad(f, 10, '$') AS f_padded_with_dollar_to_10_codepoints,
+    lpad(f, 2, '$') AS f_truncated_or_padded_to_2_codepoints,
+    lpad(f, 10, '👩‍👩‍👧‍👦') AS f_padded_with_emoji_to_10_codepoints,
+    lpad(f1, 4, '%%') AS f1_padded_to_4_codepoints
+FROM padding_example
+ORDER BY id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.02.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.02.query.sqlpp
new file mode 100644
index 0000000..a1383e6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.02.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+SELECT
+    lpad('asterix', 11, '$&^') AS padded_to_11_codepoints,
+    lpad('👩‍👩‍👧‍', 2, '$') AS truncated_to_2_codepoints,
+    lpad('👩‍👩‍👧‍', 10, '👩‍👩‍👧‍👦') AS padded_to_10_codepoints,
+    lpad(null, 4, '%%') AS padded_to_null_is_null,
+    lpad(22, 11, 'y') AS padded_non_str,
+    lpad('abcd', -2, 'y') AS negative_length;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.03.query.sqlpp
new file mode 100644
index 0000000..5adab87
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.03.query.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.
+ */
+
+SELECT lpad(repeat('a', 228),  240, '$') AS padded_long_input,
+       lpad(repeat('u', 310) || '你8世界🌍', 1000, repeat('彩2', 150) || 'END') AS very_long_unicode_test,
+       lpad(repeat('s', 95) || '©®™§¶你好世界🌍', 100, '$') AS very_long_truncation_with_unicode_result;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.00.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.00.ddl.sqlpp
new file mode 100644
index 0000000..897aac5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.00.ddl.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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 dataset padding_example if exists;
+create dataset padding_example primary key (id:int);
+upsert into padding_example ([
+{"id":1, "f":"Hi", "f1": "👩"},
+{"id":2, "f": "-7262.98", "f1": "👨‍"},
+{"id":3, "f": "a𩸽b", "f1": "🎉"},
+{"id":4, "f": "👩‍👩‍👧‍👦", "f1": "✓✓✓"},
+{"id":5, "f": null, "f1" : null}
+]);
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.01.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.01.query.sqlpp
new file mode 100644
index 0000000..a95ec0b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.01.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+
+SELECT id, f, f1,
+    rpad(f, 10, '$') AS f_padded_with_dollar_to_10_codepoints,
+    rpad(f, 2, '$') AS f_truncated_or_padded_to_2_codepoints,
+    rpad(f, 10, '👩‍👩‍👧‍👦') AS f_padded_with_emoji_to_10_codepoints,
+    rpad(f1, 4, '%%') AS f1_padded_to_4_codepoints
+FROM padding_example
+ORDER BY id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.02.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.02.query.sqlpp
new file mode 100644
index 0000000..c0d1316
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.02.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT
+    rpad('asterix', 11, '$&^') AS padded_to_11_codepoints,
+    rpad('👩‍👩‍👧‍', 2, '$') AS truncated_to_2_codepoints,
+    rpad('👩‍👩‍👧‍', 10, '👩‍👩‍👧‍👦') AS padded_to_10_codepoints,
+    rpad(null, 4, '%%') AS padded_to_null_is_null,
+    rpad(22, 11, 'y') AS padded_non_str;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.03.query.sqlpp
new file mode 100644
index 0000000..701d36b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.03.query.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.
+ */
+
+SELECT rpad(repeat('a', 228),  240, '$') AS padded_long_input,
+       rpad(repeat('u', 310) || '你8世界🌍', 1000, repeat('彩2', 150) || 'END') AS very_long_unicode_test,
+       rpad(repeat('s', 95) || '©®™§¶你好世界🌍', 100, '$') AS very_long_truncation_with_unicode_result;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.130.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.130.adm
new file mode 100644
index 0000000..b6a231a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.130.adm
@@ -0,0 +1 @@
+{ "joinDateTime": "2025-04-25T14:53:54.398", "joinDateTimeType": "string", "joinDateTimeCasted": datetime("2025-04-25T14:53:54.398"), "joinDateTimeCastedType": "datetime", "joinDate": "2025-04-25", "joinDateType": "string", "joinDateCasted": date("2025-04-25"), "joinDateCastedType": "date", "joinTime": "14:53:54.398", "joinTimeType": "string", "joinTimeCasted": time("14:53:54.398"), "joinTimeCastedType": "time" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.131.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.131.adm
new file mode 100644
index 0000000..74c33cc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.131.adm
@@ -0,0 +1 @@
+{ "joinDateTime": "25-04-2025T54:53:14", "joinDateTimeType": "string", "joinDateTimeCasted": datetime("2025-04-25T14:53:54.000"), "joinDateTimeCastedType": "datetime" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.132.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.132.adm
new file mode 100644
index 0000000..1f221d1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.132.adm
@@ -0,0 +1 @@
+{ "joinDateTime": "25-04-2025", "joinDateTimeType": "string", "joinDateTimeCasted": datetime("2025-04-25T00:00:00.000"), "joinDateTimeCastedType": "datetime", "joinDate": "25-04-2025", "joinDateType": "string", "joinDateCasted": date("2025-04-25"), "joinDateCastedType": "date" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.133.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.133.adm
new file mode 100644
index 0000000..2e3cb97
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.133.adm
@@ -0,0 +1 @@
+{ "joinTime": "02:53:54.398PM", "joinTimeType": "string", "joinTimeCasted": time("14:53:54.398"), "joinTimeCastedType": "time" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.134.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.134.adm
new file mode 100644
index 0000000..59d3024
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.134.adm
@@ -0,0 +1 @@
+{ "joinDateTime": "25/04/2025 54:53:02 PM", "joinDateTimeType": "string", "joinDateTimeCasted": datetime("2025-04-25T14:53:54.000"), "joinDateTimeCastedType": "datetime" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.135.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.135.adm
new file mode 100644
index 0000000..84e241a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.135.adm
@@ -0,0 +1 @@
+{ "joinDateTime": "25/APR/2025, 54:53:02 PM", "joinDateTimeType": "string", "joinDateTimeCasted": datetime("2025-04-25T14:53:54.000"), "joinDateTimeCastedType": "datetime" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.136.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.136.adm
new file mode 100644
index 0000000..3d29643
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/copy-to/csv/datetime/result.136.adm
@@ -0,0 +1 @@
+{ "joinDateTime": "25/APR/2025, 54:53:02 PM", "joinDateTimeType": "string", "joinDateTimeCasted": datetime("2025-04-25T14:53:54.000"), "joinDateTimeCastedType": "datetime", "joinDate": "25/APR/2025", "joinDateType": "string", "joinDateCasted": date("2025-04-25"), "joinDateCastedType": "date", "joinTime": "54:53:02 PM", "joinTimeType": "string", "joinTimeCasted": time("14:53:54.000"), "joinTimeCastedType": "time" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/crypto/sha1/sha1.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/crypto/sha1/sha1.03.adm
new file mode 100644
index 0000000..9063191
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/crypto/sha1/sha1.03.adm
@@ -0,0 +1,6 @@
+{ "a": "35BC6C28BCA27FBECC144761D32D09986876438F", "b": "35BC6C28BCA27FBECC144761D32D09986876438F", "c": "NbxsKLyif77MFEdh0y0JmGh2Q48=", "d": "NbxsKLyif77MFEdh0y0JmGh2Q48=" }
+{ "a": "93315873BA703F909C19493045450FE0FDF84AD7", "b": "93315873BA703F909C19493045450FE0FDF84AD7", "c": "kzFYc7pwP5CcGUkwRUUP4P34Stc=", "d": "kzFYc7pwP5CcGUkwRUUP4P34Stc=" }
+{ "a": "AA20F3C74E59734035C2B11EF4C90F3E8521DC9E", "b": "AA20F3C74E59734035C2B11EF4C90F3E8521DC9E", "c": "qiDzx05Zc0A1wrEe9MkPPoUh3J4=", "d": "qiDzx05Zc0A1wrEe9MkPPoUh3J4=" }
+{ "a": null, "b": null, "c": null, "d": null }
+{  }
+{ "b": null, "d": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/crypto/sha1/sha1.04.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/crypto/sha1/sha1.04.adm
new file mode 100644
index 0000000..5f77732
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/crypto/sha1/sha1.04.adm
@@ -0,0 +1 @@
+{ "a": "35BC6C28BCA27FBECC144761D32D09986876438F", "b": "93315873BA703F909C19493045450FE0FDF84AD7", "c": "AA20F3C74E59734035C2B11EF4C90F3E8521DC9E", "d": null, "e": "NbxsKLyif77MFEdh0y0JmGh2Q48=", "f": "kzFYc7pwP5CcGUkwRUUP4P34Stc=", "g": "qiDzx05Zc0A1wrEe9MkPPoUh3J4=", "h": null, "k": null, "l": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.4.adm
new file mode 100644
index 0000000..097f737
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.4.adm
@@ -0,0 +1,10 @@
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "o_w_id": 1, "o_d_id": 3, "o_id": 466, "o_c_id": 2, "o_carrier_id": 10, "o_ol_cnt": 14, "c_id": 2 }
+{ "o_w_id": 1, "o_d_id": 5, "o_id": 1652, "o_c_id": 2, "o_carrier_id": 10, "o_ol_cnt": 7, "c_id": 2 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.6.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.6.adm
new file mode 100644
index 0000000..097f737
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.6.adm
@@ -0,0 +1,10 @@
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "c_id": 2 }
+{ "o_w_id": 1, "o_d_id": 3, "o_id": 466, "o_c_id": 2, "o_carrier_id": 10, "o_ol_cnt": 14, "c_id": 2 }
+{ "o_w_id": 1, "o_d_id": 5, "o_id": 1652, "o_c_id": 2, "o_carrier_id": 10, "o_ol_cnt": 7, "c_id": 2 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.8.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.8.adm
new file mode 100644
index 0000000..113d305
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange/hash_join_exchange.8.adm
@@ -0,0 +1,10 @@
+{ "o_d_id": 1, "o_w_id": 1, "o_id": 881, "o_carrier_id": 6, "o_ol_cnt": 11 }
+{ "o_d_id": 2, "o_w_id": 1, "o_id": 525, "o_carrier_id": 1, "o_ol_cnt": 15 }
+{ "c_w_id": 1, "c_d_id": 3, "c_id": 2, "c_discount": 0.4549, "c_credit": "GC", "c_first": "cdchdqts", "c_middle": "OE", "c_last": "BARBAROUGHT", "c_credit_lim": 50000.0, "c_balance": 2275392.5500000003, "c_ytd_payment": 10.0, "c_payment_cnt": 1, "c_delivery_cnt": 0, "c_street_1": "emwtajlhjyzigbxtll", "c_street_2": "bsxxckrjkxvnx", "c_city": "vuthjjchaubyurhxu", "c_state": "ae", "c_zip": "207611111", "c_phone": "2223483665383895", "c_since": "2015-01-10 09:13:11", "key": "1.3.2", "o_d_id": 3, "o_w_id": 1, "o_id": 466, "o_carrier_id": 10, "o_ol_cnt": 14 }
+{ "o_d_id": 4, "o_w_id": 1, "o_id": 2449, "o_carrier_id": 0, "o_ol_cnt": 15 }
+{ "c_w_id": 1, "c_d_id": 5, "c_id": 2, "c_discount": 0.1233, "c_credit": "GC", "c_first": "xvaijyn", "c_middle": "OE", "c_last": "BARBAROUGHT", "c_credit_lim": 50000.0, "c_balance": 8318309.3500000015, "c_ytd_payment": 10.0, "c_payment_cnt": 1, "c_delivery_cnt": 0, "c_street_1": "tbjodrhupcwdyhiul", "c_street_2": "fvbhntiihftymwkabbr", "c_city": "cjlfuvcqvkg", "c_state": "ng", "c_zip": "417111111", "c_phone": "5673180500149103", "c_since": "2014-10-20 20:06:32", "key": "1.5.2", "o_d_id": 5, "o_w_id": 1, "o_id": 1652, "o_carrier_id": 10, "o_ol_cnt": 7 }
+{ "o_d_id": 6, "o_w_id": 1, "o_id": 1350, "o_carrier_id": 8, "o_ol_cnt": 9 }
+{ "o_d_id": 7, "o_w_id": 1, "o_id": 2822, "o_carrier_id": 0, "o_ol_cnt": 12 }
+{ "o_d_id": 8, "o_w_id": 1, "o_id": 677, "o_carrier_id": 6, "o_ol_cnt": 6 }
+{ "o_d_id": 9, "o_w_id": 1, "o_id": 2851, "o_carrier_id": 0, "o_ol_cnt": 12 }
+{ "o_d_id": 10, "o_w_id": 1, "o_id": 2841, "o_carrier_id": 0, "o_ol_cnt": 9 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.10.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.10.adm
new file mode 100644
index 0000000..497b339
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.10.adm
@@ -0,0 +1,100 @@
+{ "a_0": 1, "a_1": 1, "a_2": 1, "a_3": 1 }
+{ "a_0": 2, "a_1": 2, "a_2": 2, "a_3": 2 }
+{ "a_0": 3, "a_1": 3, "a_2": 3, "a_3": 3 }
+{ "a_0": 4, "a_1": 4, "a_2": 4, "a_3": 4 }
+{ "a_0": 5, "a_1": 5, "a_2": 5, "a_3": 5 }
+{ "a_0": 6, "a_1": 6, "a_2": 6, "a_3": 6 }
+{ "a_0": 7, "a_1": 7, "a_2": 7, "a_3": 7 }
+{ "a_0": 8, "a_1": 8, "a_2": 8, "a_3": 8 }
+{ "a_0": 9, "a_1": 9, "a_2": 9, "a_3": 9 }
+{ "a_0": 10, "a_1": 10, "a_2": 10, "a_3": 10 }
+{ "a_0": 11, "a_1": 11, "a_2": 11, "a_3": 11 }
+{ "a_0": 12, "a_1": 12, "a_2": 12, "a_3": 12 }
+{ "a_0": 13, "a_1": 13, "a_2": 13, "a_3": 13 }
+{ "a_0": 14, "a_1": 14, "a_2": 14, "a_3": 14 }
+{ "a_0": 15, "a_1": 15, "a_2": 15, "a_3": 15 }
+{ "a_0": 16, "a_1": 16, "a_2": 16, "a_3": 16 }
+{ "a_0": 17, "a_1": 17, "a_2": 17, "a_3": 17 }
+{ "a_0": 18, "a_1": 18, "a_2": 18, "a_3": 18 }
+{ "a_0": 19, "a_1": 19, "a_2": 19, "a_3": 19 }
+{ "a_0": 20, "a_1": 20, "a_2": 20, "a_3": 20 }
+{ "a_0": 21, "a_1": 21, "a_2": 21, "a_3": 21 }
+{ "a_0": 22, "a_1": 22, "a_2": 22, "a_3": 22 }
+{ "a_0": 23, "a_1": 23, "a_2": 23, "a_3": 23 }
+{ "a_0": 24, "a_1": 24, "a_2": 24, "a_3": 24 }
+{ "a_0": 25, "a_1": 25, "a_2": 25, "a_3": 25 }
+{ "a_0": 26, "a_1": 26, "a_2": 26, "a_3": 26 }
+{ "a_0": 27, "a_1": 27, "a_2": 27, "a_3": 27 }
+{ "a_0": 28, "a_1": 28, "a_2": 28, "a_3": 28 }
+{ "a_0": 29, "a_1": 29, "a_2": 29, "a_3": 29 }
+{ "a_0": 30, "a_1": 30, "a_2": 30, "a_3": 30 }
+{ "a_0": 31, "a_1": 31, "a_2": 31, "a_3": 31 }
+{ "a_0": 32, "a_1": 32, "a_2": 32, "a_3": 32 }
+{ "a_0": 33, "a_1": 33, "a_2": 33, "a_3": 33 }
+{ "a_0": 34, "a_1": 34, "a_2": 34, "a_3": 34 }
+{ "a_0": 35, "a_1": 35, "a_2": 35, "a_3": 35 }
+{ "a_0": 36, "a_1": 36, "a_2": 36, "a_3": 36 }
+{ "a_0": 37, "a_1": 37, "a_2": 37, "a_3": 37 }
+{ "a_0": 38, "a_1": 38, "a_2": 38, "a_3": 38 }
+{ "a_0": 39, "a_1": 39, "a_2": 39, "a_3": 39 }
+{ "a_0": 40, "a_1": 40, "a_2": 40, "a_3": 40 }
+{ "a_0": 41, "a_1": 41, "a_2": 41, "a_3": 41 }
+{ "a_0": 42, "a_1": 42, "a_2": 42, "a_3": 42 }
+{ "a_0": 43, "a_1": 43, "a_2": 43, "a_3": 43 }
+{ "a_0": 44, "a_1": 44, "a_2": 44, "a_3": 44 }
+{ "a_0": 45, "a_1": 45, "a_2": 45, "a_3": 45 }
+{ "a_0": 46, "a_1": 46, "a_2": 46, "a_3": 46 }
+{ "a_0": 47, "a_1": 47, "a_2": 47, "a_3": 47 }
+{ "a_0": 48, "a_1": 48, "a_2": 48, "a_3": 48 }
+{ "a_0": 49, "a_1": 49, "a_2": 49, "a_3": 49 }
+{ "a_0": 50, "a_1": 50, "a_2": 50, "a_3": 50 }
+{ "a_0": 51, "a_1": 51, "a_2": 51, "a_3": 51, "b_3": 51 }
+{ "a_0": 52, "a_1": 52, "a_2": 52, "a_3": 52, "b_3": 52 }
+{ "a_0": 53, "a_1": 53, "a_2": 53, "a_3": 53, "b_3": 53 }
+{ "a_0": 54, "a_1": 54, "a_2": 54, "a_3": 54, "b_3": 54 }
+{ "a_0": 55, "a_1": 55, "a_2": 55, "a_3": 55, "b_3": 55 }
+{ "a_0": 56, "a_1": 56, "a_2": 56, "a_3": 56, "b_3": 56 }
+{ "a_0": 57, "a_1": 57, "a_2": 57, "a_3": 57, "b_3": 57 }
+{ "a_0": 58, "a_1": 58, "a_2": 58, "a_3": 58, "b_3": 58 }
+{ "a_0": 59, "a_1": 59, "a_2": 59, "a_3": 59, "b_3": 59 }
+{ "a_0": 60, "a_1": 60, "a_2": 60, "a_3": 60, "b_3": 60 }
+{ "a_0": 61, "a_1": 61, "a_2": 61, "a_3": 61, "b_3": 61 }
+{ "a_0": 62, "a_1": 62, "a_2": 62, "a_3": 62, "b_3": 62 }
+{ "a_0": 63, "a_1": 63, "a_2": 63, "a_3": 63, "b_3": 63 }
+{ "a_0": 64, "a_1": 64, "a_2": 64, "a_3": 64, "b_3": 64 }
+{ "a_0": 65, "a_1": 65, "a_2": 65, "a_3": 65, "b_3": 65 }
+{ "a_0": 66, "a_1": 66, "a_2": 66, "a_3": 66, "b_3": 66 }
+{ "a_0": 67, "a_1": 67, "a_2": 67, "a_3": 67, "b_3": 67 }
+{ "a_0": 68, "a_1": 68, "a_2": 68, "a_3": 68, "b_3": 68 }
+{ "a_0": 69, "a_1": 69, "a_2": 69, "a_3": 69, "b_3": 69 }
+{ "a_0": 70, "a_1": 70, "a_2": 70, "a_3": 70, "b_3": 70 }
+{ "a_0": 71, "a_1": 71, "a_2": 71, "a_3": 71, "b_3": 71 }
+{ "a_0": 72, "a_1": 72, "a_2": 72, "a_3": 72, "b_3": 72 }
+{ "a_0": 73, "a_1": 73, "a_2": 73, "a_3": 73, "b_3": 73 }
+{ "a_0": 74, "a_1": 74, "a_2": 74, "a_3": 74, "b_3": 74 }
+{ "a_0": 75, "a_1": 75, "a_2": 75, "a_3": 75, "b_3": 75 }
+{ "a_0": 76, "a_1": 76, "a_2": 76, "a_3": 76, "b_3": 76 }
+{ "a_0": 77, "a_1": 77, "a_2": 77, "a_3": 77, "b_3": 77 }
+{ "a_0": 78, "a_1": 78, "a_2": 78, "a_3": 78, "b_3": 78 }
+{ "a_0": 79, "a_1": 79, "a_2": 79, "a_3": 79, "b_3": 79 }
+{ "a_0": 80, "a_1": 80, "a_2": 80, "a_3": 80, "b_3": 80 }
+{ "a_0": 81, "a_1": 81, "a_2": 81, "a_3": 81, "b_3": 81 }
+{ "a_0": 82, "a_1": 82, "a_2": 82, "a_3": 82, "b_3": 82 }
+{ "a_0": 83, "a_1": 83, "a_2": 83, "a_3": 83, "b_3": 83 }
+{ "a_0": 84, "a_1": 84, "a_2": 84, "a_3": 84, "b_3": 84 }
+{ "a_0": 85, "a_1": 85, "a_2": 85, "a_3": 85, "b_3": 85 }
+{ "a_0": 86, "a_1": 86, "a_2": 86, "a_3": 86, "b_3": 86 }
+{ "a_0": 87, "a_1": 87, "a_2": 87, "a_3": 87, "b_3": 87 }
+{ "a_0": 88, "a_1": 88, "a_2": 88, "a_3": 88, "b_3": 88 }
+{ "a_0": 89, "a_1": 89, "a_2": 89, "a_3": 89, "b_3": 89 }
+{ "a_0": 90, "a_1": 90, "a_2": 90, "a_3": 90, "b_3": 90 }
+{ "a_0": 91, "a_1": 91, "a_2": 91, "a_3": 91, "b_3": 91 }
+{ "a_0": 92, "a_1": 92, "a_2": 92, "a_3": 92, "b_3": 92 }
+{ "a_0": 93, "a_1": 93, "a_2": 93, "a_3": 93, "b_3": 93 }
+{ "a_0": 94, "a_1": 94, "a_2": 94, "a_3": 94, "b_3": 94 }
+{ "a_0": 95, "a_1": 95, "a_2": 95, "a_3": 95, "b_3": 95 }
+{ "a_0": 96, "a_1": 96, "a_2": 96, "a_3": 96, "b_3": 96 }
+{ "a_0": 97, "a_1": 97, "a_2": 97, "a_3": 97, "b_3": 97 }
+{ "a_0": 98, "a_1": 98, "a_2": 98, "a_3": 98, "b_3": 98 }
+{ "a_0": 99, "a_1": 99, "a_2": 99, "a_3": 99, "b_3": 99 }
+{ "a_0": 100, "a_1": 100, "a_2": 100, "a_3": 100, "b_3": 100 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.12.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.12.adm
new file mode 100644
index 0000000..497b339
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.12.adm
@@ -0,0 +1,100 @@
+{ "a_0": 1, "a_1": 1, "a_2": 1, "a_3": 1 }
+{ "a_0": 2, "a_1": 2, "a_2": 2, "a_3": 2 }
+{ "a_0": 3, "a_1": 3, "a_2": 3, "a_3": 3 }
+{ "a_0": 4, "a_1": 4, "a_2": 4, "a_3": 4 }
+{ "a_0": 5, "a_1": 5, "a_2": 5, "a_3": 5 }
+{ "a_0": 6, "a_1": 6, "a_2": 6, "a_3": 6 }
+{ "a_0": 7, "a_1": 7, "a_2": 7, "a_3": 7 }
+{ "a_0": 8, "a_1": 8, "a_2": 8, "a_3": 8 }
+{ "a_0": 9, "a_1": 9, "a_2": 9, "a_3": 9 }
+{ "a_0": 10, "a_1": 10, "a_2": 10, "a_3": 10 }
+{ "a_0": 11, "a_1": 11, "a_2": 11, "a_3": 11 }
+{ "a_0": 12, "a_1": 12, "a_2": 12, "a_3": 12 }
+{ "a_0": 13, "a_1": 13, "a_2": 13, "a_3": 13 }
+{ "a_0": 14, "a_1": 14, "a_2": 14, "a_3": 14 }
+{ "a_0": 15, "a_1": 15, "a_2": 15, "a_3": 15 }
+{ "a_0": 16, "a_1": 16, "a_2": 16, "a_3": 16 }
+{ "a_0": 17, "a_1": 17, "a_2": 17, "a_3": 17 }
+{ "a_0": 18, "a_1": 18, "a_2": 18, "a_3": 18 }
+{ "a_0": 19, "a_1": 19, "a_2": 19, "a_3": 19 }
+{ "a_0": 20, "a_1": 20, "a_2": 20, "a_3": 20 }
+{ "a_0": 21, "a_1": 21, "a_2": 21, "a_3": 21 }
+{ "a_0": 22, "a_1": 22, "a_2": 22, "a_3": 22 }
+{ "a_0": 23, "a_1": 23, "a_2": 23, "a_3": 23 }
+{ "a_0": 24, "a_1": 24, "a_2": 24, "a_3": 24 }
+{ "a_0": 25, "a_1": 25, "a_2": 25, "a_3": 25 }
+{ "a_0": 26, "a_1": 26, "a_2": 26, "a_3": 26 }
+{ "a_0": 27, "a_1": 27, "a_2": 27, "a_3": 27 }
+{ "a_0": 28, "a_1": 28, "a_2": 28, "a_3": 28 }
+{ "a_0": 29, "a_1": 29, "a_2": 29, "a_3": 29 }
+{ "a_0": 30, "a_1": 30, "a_2": 30, "a_3": 30 }
+{ "a_0": 31, "a_1": 31, "a_2": 31, "a_3": 31 }
+{ "a_0": 32, "a_1": 32, "a_2": 32, "a_3": 32 }
+{ "a_0": 33, "a_1": 33, "a_2": 33, "a_3": 33 }
+{ "a_0": 34, "a_1": 34, "a_2": 34, "a_3": 34 }
+{ "a_0": 35, "a_1": 35, "a_2": 35, "a_3": 35 }
+{ "a_0": 36, "a_1": 36, "a_2": 36, "a_3": 36 }
+{ "a_0": 37, "a_1": 37, "a_2": 37, "a_3": 37 }
+{ "a_0": 38, "a_1": 38, "a_2": 38, "a_3": 38 }
+{ "a_0": 39, "a_1": 39, "a_2": 39, "a_3": 39 }
+{ "a_0": 40, "a_1": 40, "a_2": 40, "a_3": 40 }
+{ "a_0": 41, "a_1": 41, "a_2": 41, "a_3": 41 }
+{ "a_0": 42, "a_1": 42, "a_2": 42, "a_3": 42 }
+{ "a_0": 43, "a_1": 43, "a_2": 43, "a_3": 43 }
+{ "a_0": 44, "a_1": 44, "a_2": 44, "a_3": 44 }
+{ "a_0": 45, "a_1": 45, "a_2": 45, "a_3": 45 }
+{ "a_0": 46, "a_1": 46, "a_2": 46, "a_3": 46 }
+{ "a_0": 47, "a_1": 47, "a_2": 47, "a_3": 47 }
+{ "a_0": 48, "a_1": 48, "a_2": 48, "a_3": 48 }
+{ "a_0": 49, "a_1": 49, "a_2": 49, "a_3": 49 }
+{ "a_0": 50, "a_1": 50, "a_2": 50, "a_3": 50 }
+{ "a_0": 51, "a_1": 51, "a_2": 51, "a_3": 51, "b_3": 51 }
+{ "a_0": 52, "a_1": 52, "a_2": 52, "a_3": 52, "b_3": 52 }
+{ "a_0": 53, "a_1": 53, "a_2": 53, "a_3": 53, "b_3": 53 }
+{ "a_0": 54, "a_1": 54, "a_2": 54, "a_3": 54, "b_3": 54 }
+{ "a_0": 55, "a_1": 55, "a_2": 55, "a_3": 55, "b_3": 55 }
+{ "a_0": 56, "a_1": 56, "a_2": 56, "a_3": 56, "b_3": 56 }
+{ "a_0": 57, "a_1": 57, "a_2": 57, "a_3": 57, "b_3": 57 }
+{ "a_0": 58, "a_1": 58, "a_2": 58, "a_3": 58, "b_3": 58 }
+{ "a_0": 59, "a_1": 59, "a_2": 59, "a_3": 59, "b_3": 59 }
+{ "a_0": 60, "a_1": 60, "a_2": 60, "a_3": 60, "b_3": 60 }
+{ "a_0": 61, "a_1": 61, "a_2": 61, "a_3": 61, "b_3": 61 }
+{ "a_0": 62, "a_1": 62, "a_2": 62, "a_3": 62, "b_3": 62 }
+{ "a_0": 63, "a_1": 63, "a_2": 63, "a_3": 63, "b_3": 63 }
+{ "a_0": 64, "a_1": 64, "a_2": 64, "a_3": 64, "b_3": 64 }
+{ "a_0": 65, "a_1": 65, "a_2": 65, "a_3": 65, "b_3": 65 }
+{ "a_0": 66, "a_1": 66, "a_2": 66, "a_3": 66, "b_3": 66 }
+{ "a_0": 67, "a_1": 67, "a_2": 67, "a_3": 67, "b_3": 67 }
+{ "a_0": 68, "a_1": 68, "a_2": 68, "a_3": 68, "b_3": 68 }
+{ "a_0": 69, "a_1": 69, "a_2": 69, "a_3": 69, "b_3": 69 }
+{ "a_0": 70, "a_1": 70, "a_2": 70, "a_3": 70, "b_3": 70 }
+{ "a_0": 71, "a_1": 71, "a_2": 71, "a_3": 71, "b_3": 71 }
+{ "a_0": 72, "a_1": 72, "a_2": 72, "a_3": 72, "b_3": 72 }
+{ "a_0": 73, "a_1": 73, "a_2": 73, "a_3": 73, "b_3": 73 }
+{ "a_0": 74, "a_1": 74, "a_2": 74, "a_3": 74, "b_3": 74 }
+{ "a_0": 75, "a_1": 75, "a_2": 75, "a_3": 75, "b_3": 75 }
+{ "a_0": 76, "a_1": 76, "a_2": 76, "a_3": 76, "b_3": 76 }
+{ "a_0": 77, "a_1": 77, "a_2": 77, "a_3": 77, "b_3": 77 }
+{ "a_0": 78, "a_1": 78, "a_2": 78, "a_3": 78, "b_3": 78 }
+{ "a_0": 79, "a_1": 79, "a_2": 79, "a_3": 79, "b_3": 79 }
+{ "a_0": 80, "a_1": 80, "a_2": 80, "a_3": 80, "b_3": 80 }
+{ "a_0": 81, "a_1": 81, "a_2": 81, "a_3": 81, "b_3": 81 }
+{ "a_0": 82, "a_1": 82, "a_2": 82, "a_3": 82, "b_3": 82 }
+{ "a_0": 83, "a_1": 83, "a_2": 83, "a_3": 83, "b_3": 83 }
+{ "a_0": 84, "a_1": 84, "a_2": 84, "a_3": 84, "b_3": 84 }
+{ "a_0": 85, "a_1": 85, "a_2": 85, "a_3": 85, "b_3": 85 }
+{ "a_0": 86, "a_1": 86, "a_2": 86, "a_3": 86, "b_3": 86 }
+{ "a_0": 87, "a_1": 87, "a_2": 87, "a_3": 87, "b_3": 87 }
+{ "a_0": 88, "a_1": 88, "a_2": 88, "a_3": 88, "b_3": 88 }
+{ "a_0": 89, "a_1": 89, "a_2": 89, "a_3": 89, "b_3": 89 }
+{ "a_0": 90, "a_1": 90, "a_2": 90, "a_3": 90, "b_3": 90 }
+{ "a_0": 91, "a_1": 91, "a_2": 91, "a_3": 91, "b_3": 91 }
+{ "a_0": 92, "a_1": 92, "a_2": 92, "a_3": 92, "b_3": 92 }
+{ "a_0": 93, "a_1": 93, "a_2": 93, "a_3": 93, "b_3": 93 }
+{ "a_0": 94, "a_1": 94, "a_2": 94, "a_3": 94, "b_3": 94 }
+{ "a_0": 95, "a_1": 95, "a_2": 95, "a_3": 95, "b_3": 95 }
+{ "a_0": 96, "a_1": 96, "a_2": 96, "a_3": 96, "b_3": 96 }
+{ "a_0": 97, "a_1": 97, "a_2": 97, "a_3": 97, "b_3": 97 }
+{ "a_0": 98, "a_1": 98, "a_2": 98, "a_3": 98, "b_3": 98 }
+{ "a_0": 99, "a_1": 99, "a_2": 99, "a_3": 99, "b_3": 99 }
+{ "a_0": 100, "a_1": 100, "a_2": 100, "a_3": 100, "b_3": 100 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.4.adm
new file mode 100644
index 0000000..497b339
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.4.adm
@@ -0,0 +1,100 @@
+{ "a_0": 1, "a_1": 1, "a_2": 1, "a_3": 1 }
+{ "a_0": 2, "a_1": 2, "a_2": 2, "a_3": 2 }
+{ "a_0": 3, "a_1": 3, "a_2": 3, "a_3": 3 }
+{ "a_0": 4, "a_1": 4, "a_2": 4, "a_3": 4 }
+{ "a_0": 5, "a_1": 5, "a_2": 5, "a_3": 5 }
+{ "a_0": 6, "a_1": 6, "a_2": 6, "a_3": 6 }
+{ "a_0": 7, "a_1": 7, "a_2": 7, "a_3": 7 }
+{ "a_0": 8, "a_1": 8, "a_2": 8, "a_3": 8 }
+{ "a_0": 9, "a_1": 9, "a_2": 9, "a_3": 9 }
+{ "a_0": 10, "a_1": 10, "a_2": 10, "a_3": 10 }
+{ "a_0": 11, "a_1": 11, "a_2": 11, "a_3": 11 }
+{ "a_0": 12, "a_1": 12, "a_2": 12, "a_3": 12 }
+{ "a_0": 13, "a_1": 13, "a_2": 13, "a_3": 13 }
+{ "a_0": 14, "a_1": 14, "a_2": 14, "a_3": 14 }
+{ "a_0": 15, "a_1": 15, "a_2": 15, "a_3": 15 }
+{ "a_0": 16, "a_1": 16, "a_2": 16, "a_3": 16 }
+{ "a_0": 17, "a_1": 17, "a_2": 17, "a_3": 17 }
+{ "a_0": 18, "a_1": 18, "a_2": 18, "a_3": 18 }
+{ "a_0": 19, "a_1": 19, "a_2": 19, "a_3": 19 }
+{ "a_0": 20, "a_1": 20, "a_2": 20, "a_3": 20 }
+{ "a_0": 21, "a_1": 21, "a_2": 21, "a_3": 21 }
+{ "a_0": 22, "a_1": 22, "a_2": 22, "a_3": 22 }
+{ "a_0": 23, "a_1": 23, "a_2": 23, "a_3": 23 }
+{ "a_0": 24, "a_1": 24, "a_2": 24, "a_3": 24 }
+{ "a_0": 25, "a_1": 25, "a_2": 25, "a_3": 25 }
+{ "a_0": 26, "a_1": 26, "a_2": 26, "a_3": 26 }
+{ "a_0": 27, "a_1": 27, "a_2": 27, "a_3": 27 }
+{ "a_0": 28, "a_1": 28, "a_2": 28, "a_3": 28 }
+{ "a_0": 29, "a_1": 29, "a_2": 29, "a_3": 29 }
+{ "a_0": 30, "a_1": 30, "a_2": 30, "a_3": 30 }
+{ "a_0": 31, "a_1": 31, "a_2": 31, "a_3": 31 }
+{ "a_0": 32, "a_1": 32, "a_2": 32, "a_3": 32 }
+{ "a_0": 33, "a_1": 33, "a_2": 33, "a_3": 33 }
+{ "a_0": 34, "a_1": 34, "a_2": 34, "a_3": 34 }
+{ "a_0": 35, "a_1": 35, "a_2": 35, "a_3": 35 }
+{ "a_0": 36, "a_1": 36, "a_2": 36, "a_3": 36 }
+{ "a_0": 37, "a_1": 37, "a_2": 37, "a_3": 37 }
+{ "a_0": 38, "a_1": 38, "a_2": 38, "a_3": 38 }
+{ "a_0": 39, "a_1": 39, "a_2": 39, "a_3": 39 }
+{ "a_0": 40, "a_1": 40, "a_2": 40, "a_3": 40 }
+{ "a_0": 41, "a_1": 41, "a_2": 41, "a_3": 41 }
+{ "a_0": 42, "a_1": 42, "a_2": 42, "a_3": 42 }
+{ "a_0": 43, "a_1": 43, "a_2": 43, "a_3": 43 }
+{ "a_0": 44, "a_1": 44, "a_2": 44, "a_3": 44 }
+{ "a_0": 45, "a_1": 45, "a_2": 45, "a_3": 45 }
+{ "a_0": 46, "a_1": 46, "a_2": 46, "a_3": 46 }
+{ "a_0": 47, "a_1": 47, "a_2": 47, "a_3": 47 }
+{ "a_0": 48, "a_1": 48, "a_2": 48, "a_3": 48 }
+{ "a_0": 49, "a_1": 49, "a_2": 49, "a_3": 49 }
+{ "a_0": 50, "a_1": 50, "a_2": 50, "a_3": 50 }
+{ "a_0": 51, "a_1": 51, "a_2": 51, "a_3": 51, "b_3": 51 }
+{ "a_0": 52, "a_1": 52, "a_2": 52, "a_3": 52, "b_3": 52 }
+{ "a_0": 53, "a_1": 53, "a_2": 53, "a_3": 53, "b_3": 53 }
+{ "a_0": 54, "a_1": 54, "a_2": 54, "a_3": 54, "b_3": 54 }
+{ "a_0": 55, "a_1": 55, "a_2": 55, "a_3": 55, "b_3": 55 }
+{ "a_0": 56, "a_1": 56, "a_2": 56, "a_3": 56, "b_3": 56 }
+{ "a_0": 57, "a_1": 57, "a_2": 57, "a_3": 57, "b_3": 57 }
+{ "a_0": 58, "a_1": 58, "a_2": 58, "a_3": 58, "b_3": 58 }
+{ "a_0": 59, "a_1": 59, "a_2": 59, "a_3": 59, "b_3": 59 }
+{ "a_0": 60, "a_1": 60, "a_2": 60, "a_3": 60, "b_3": 60 }
+{ "a_0": 61, "a_1": 61, "a_2": 61, "a_3": 61, "b_3": 61 }
+{ "a_0": 62, "a_1": 62, "a_2": 62, "a_3": 62, "b_3": 62 }
+{ "a_0": 63, "a_1": 63, "a_2": 63, "a_3": 63, "b_3": 63 }
+{ "a_0": 64, "a_1": 64, "a_2": 64, "a_3": 64, "b_3": 64 }
+{ "a_0": 65, "a_1": 65, "a_2": 65, "a_3": 65, "b_3": 65 }
+{ "a_0": 66, "a_1": 66, "a_2": 66, "a_3": 66, "b_3": 66 }
+{ "a_0": 67, "a_1": 67, "a_2": 67, "a_3": 67, "b_3": 67 }
+{ "a_0": 68, "a_1": 68, "a_2": 68, "a_3": 68, "b_3": 68 }
+{ "a_0": 69, "a_1": 69, "a_2": 69, "a_3": 69, "b_3": 69 }
+{ "a_0": 70, "a_1": 70, "a_2": 70, "a_3": 70, "b_3": 70 }
+{ "a_0": 71, "a_1": 71, "a_2": 71, "a_3": 71, "b_3": 71 }
+{ "a_0": 72, "a_1": 72, "a_2": 72, "a_3": 72, "b_3": 72 }
+{ "a_0": 73, "a_1": 73, "a_2": 73, "a_3": 73, "b_3": 73 }
+{ "a_0": 74, "a_1": 74, "a_2": 74, "a_3": 74, "b_3": 74 }
+{ "a_0": 75, "a_1": 75, "a_2": 75, "a_3": 75, "b_3": 75 }
+{ "a_0": 76, "a_1": 76, "a_2": 76, "a_3": 76, "b_3": 76 }
+{ "a_0": 77, "a_1": 77, "a_2": 77, "a_3": 77, "b_3": 77 }
+{ "a_0": 78, "a_1": 78, "a_2": 78, "a_3": 78, "b_3": 78 }
+{ "a_0": 79, "a_1": 79, "a_2": 79, "a_3": 79, "b_3": 79 }
+{ "a_0": 80, "a_1": 80, "a_2": 80, "a_3": 80, "b_3": 80 }
+{ "a_0": 81, "a_1": 81, "a_2": 81, "a_3": 81, "b_3": 81 }
+{ "a_0": 82, "a_1": 82, "a_2": 82, "a_3": 82, "b_3": 82 }
+{ "a_0": 83, "a_1": 83, "a_2": 83, "a_3": 83, "b_3": 83 }
+{ "a_0": 84, "a_1": 84, "a_2": 84, "a_3": 84, "b_3": 84 }
+{ "a_0": 85, "a_1": 85, "a_2": 85, "a_3": 85, "b_3": 85 }
+{ "a_0": 86, "a_1": 86, "a_2": 86, "a_3": 86, "b_3": 86 }
+{ "a_0": 87, "a_1": 87, "a_2": 87, "a_3": 87, "b_3": 87 }
+{ "a_0": 88, "a_1": 88, "a_2": 88, "a_3": 88, "b_3": 88 }
+{ "a_0": 89, "a_1": 89, "a_2": 89, "a_3": 89, "b_3": 89 }
+{ "a_0": 90, "a_1": 90, "a_2": 90, "a_3": 90, "b_3": 90 }
+{ "a_0": 91, "a_1": 91, "a_2": 91, "a_3": 91, "b_3": 91 }
+{ "a_0": 92, "a_1": 92, "a_2": 92, "a_3": 92, "b_3": 92 }
+{ "a_0": 93, "a_1": 93, "a_2": 93, "a_3": 93, "b_3": 93 }
+{ "a_0": 94, "a_1": 94, "a_2": 94, "a_3": 94, "b_3": 94 }
+{ "a_0": 95, "a_1": 95, "a_2": 95, "a_3": 95, "b_3": 95 }
+{ "a_0": 96, "a_1": 96, "a_2": 96, "a_3": 96, "b_3": 96 }
+{ "a_0": 97, "a_1": 97, "a_2": 97, "a_3": 97, "b_3": 97 }
+{ "a_0": 98, "a_1": 98, "a_2": 98, "a_3": 98, "b_3": 98 }
+{ "a_0": 99, "a_1": 99, "a_2": 99, "a_3": 99, "b_3": 99 }
+{ "a_0": 100, "a_1": 100, "a_2": 100, "a_3": 100, "b_3": 100 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.6.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.6.adm
new file mode 100644
index 0000000..497b339
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.6.adm
@@ -0,0 +1,100 @@
+{ "a_0": 1, "a_1": 1, "a_2": 1, "a_3": 1 }
+{ "a_0": 2, "a_1": 2, "a_2": 2, "a_3": 2 }
+{ "a_0": 3, "a_1": 3, "a_2": 3, "a_3": 3 }
+{ "a_0": 4, "a_1": 4, "a_2": 4, "a_3": 4 }
+{ "a_0": 5, "a_1": 5, "a_2": 5, "a_3": 5 }
+{ "a_0": 6, "a_1": 6, "a_2": 6, "a_3": 6 }
+{ "a_0": 7, "a_1": 7, "a_2": 7, "a_3": 7 }
+{ "a_0": 8, "a_1": 8, "a_2": 8, "a_3": 8 }
+{ "a_0": 9, "a_1": 9, "a_2": 9, "a_3": 9 }
+{ "a_0": 10, "a_1": 10, "a_2": 10, "a_3": 10 }
+{ "a_0": 11, "a_1": 11, "a_2": 11, "a_3": 11 }
+{ "a_0": 12, "a_1": 12, "a_2": 12, "a_3": 12 }
+{ "a_0": 13, "a_1": 13, "a_2": 13, "a_3": 13 }
+{ "a_0": 14, "a_1": 14, "a_2": 14, "a_3": 14 }
+{ "a_0": 15, "a_1": 15, "a_2": 15, "a_3": 15 }
+{ "a_0": 16, "a_1": 16, "a_2": 16, "a_3": 16 }
+{ "a_0": 17, "a_1": 17, "a_2": 17, "a_3": 17 }
+{ "a_0": 18, "a_1": 18, "a_2": 18, "a_3": 18 }
+{ "a_0": 19, "a_1": 19, "a_2": 19, "a_3": 19 }
+{ "a_0": 20, "a_1": 20, "a_2": 20, "a_3": 20 }
+{ "a_0": 21, "a_1": 21, "a_2": 21, "a_3": 21 }
+{ "a_0": 22, "a_1": 22, "a_2": 22, "a_3": 22 }
+{ "a_0": 23, "a_1": 23, "a_2": 23, "a_3": 23 }
+{ "a_0": 24, "a_1": 24, "a_2": 24, "a_3": 24 }
+{ "a_0": 25, "a_1": 25, "a_2": 25, "a_3": 25 }
+{ "a_0": 26, "a_1": 26, "a_2": 26, "a_3": 26 }
+{ "a_0": 27, "a_1": 27, "a_2": 27, "a_3": 27 }
+{ "a_0": 28, "a_1": 28, "a_2": 28, "a_3": 28 }
+{ "a_0": 29, "a_1": 29, "a_2": 29, "a_3": 29 }
+{ "a_0": 30, "a_1": 30, "a_2": 30, "a_3": 30 }
+{ "a_0": 31, "a_1": 31, "a_2": 31, "a_3": 31 }
+{ "a_0": 32, "a_1": 32, "a_2": 32, "a_3": 32 }
+{ "a_0": 33, "a_1": 33, "a_2": 33, "a_3": 33 }
+{ "a_0": 34, "a_1": 34, "a_2": 34, "a_3": 34 }
+{ "a_0": 35, "a_1": 35, "a_2": 35, "a_3": 35 }
+{ "a_0": 36, "a_1": 36, "a_2": 36, "a_3": 36 }
+{ "a_0": 37, "a_1": 37, "a_2": 37, "a_3": 37 }
+{ "a_0": 38, "a_1": 38, "a_2": 38, "a_3": 38 }
+{ "a_0": 39, "a_1": 39, "a_2": 39, "a_3": 39 }
+{ "a_0": 40, "a_1": 40, "a_2": 40, "a_3": 40 }
+{ "a_0": 41, "a_1": 41, "a_2": 41, "a_3": 41 }
+{ "a_0": 42, "a_1": 42, "a_2": 42, "a_3": 42 }
+{ "a_0": 43, "a_1": 43, "a_2": 43, "a_3": 43 }
+{ "a_0": 44, "a_1": 44, "a_2": 44, "a_3": 44 }
+{ "a_0": 45, "a_1": 45, "a_2": 45, "a_3": 45 }
+{ "a_0": 46, "a_1": 46, "a_2": 46, "a_3": 46 }
+{ "a_0": 47, "a_1": 47, "a_2": 47, "a_3": 47 }
+{ "a_0": 48, "a_1": 48, "a_2": 48, "a_3": 48 }
+{ "a_0": 49, "a_1": 49, "a_2": 49, "a_3": 49 }
+{ "a_0": 50, "a_1": 50, "a_2": 50, "a_3": 50 }
+{ "a_0": 51, "a_1": 51, "a_2": 51, "a_3": 51, "b_3": 51 }
+{ "a_0": 52, "a_1": 52, "a_2": 52, "a_3": 52, "b_3": 52 }
+{ "a_0": 53, "a_1": 53, "a_2": 53, "a_3": 53, "b_3": 53 }
+{ "a_0": 54, "a_1": 54, "a_2": 54, "a_3": 54, "b_3": 54 }
+{ "a_0": 55, "a_1": 55, "a_2": 55, "a_3": 55, "b_3": 55 }
+{ "a_0": 56, "a_1": 56, "a_2": 56, "a_3": 56, "b_3": 56 }
+{ "a_0": 57, "a_1": 57, "a_2": 57, "a_3": 57, "b_3": 57 }
+{ "a_0": 58, "a_1": 58, "a_2": 58, "a_3": 58, "b_3": 58 }
+{ "a_0": 59, "a_1": 59, "a_2": 59, "a_3": 59, "b_3": 59 }
+{ "a_0": 60, "a_1": 60, "a_2": 60, "a_3": 60, "b_3": 60 }
+{ "a_0": 61, "a_1": 61, "a_2": 61, "a_3": 61, "b_3": 61 }
+{ "a_0": 62, "a_1": 62, "a_2": 62, "a_3": 62, "b_3": 62 }
+{ "a_0": 63, "a_1": 63, "a_2": 63, "a_3": 63, "b_3": 63 }
+{ "a_0": 64, "a_1": 64, "a_2": 64, "a_3": 64, "b_3": 64 }
+{ "a_0": 65, "a_1": 65, "a_2": 65, "a_3": 65, "b_3": 65 }
+{ "a_0": 66, "a_1": 66, "a_2": 66, "a_3": 66, "b_3": 66 }
+{ "a_0": 67, "a_1": 67, "a_2": 67, "a_3": 67, "b_3": 67 }
+{ "a_0": 68, "a_1": 68, "a_2": 68, "a_3": 68, "b_3": 68 }
+{ "a_0": 69, "a_1": 69, "a_2": 69, "a_3": 69, "b_3": 69 }
+{ "a_0": 70, "a_1": 70, "a_2": 70, "a_3": 70, "b_3": 70 }
+{ "a_0": 71, "a_1": 71, "a_2": 71, "a_3": 71, "b_3": 71 }
+{ "a_0": 72, "a_1": 72, "a_2": 72, "a_3": 72, "b_3": 72 }
+{ "a_0": 73, "a_1": 73, "a_2": 73, "a_3": 73, "b_3": 73 }
+{ "a_0": 74, "a_1": 74, "a_2": 74, "a_3": 74, "b_3": 74 }
+{ "a_0": 75, "a_1": 75, "a_2": 75, "a_3": 75, "b_3": 75 }
+{ "a_0": 76, "a_1": 76, "a_2": 76, "a_3": 76, "b_3": 76 }
+{ "a_0": 77, "a_1": 77, "a_2": 77, "a_3": 77, "b_3": 77 }
+{ "a_0": 78, "a_1": 78, "a_2": 78, "a_3": 78, "b_3": 78 }
+{ "a_0": 79, "a_1": 79, "a_2": 79, "a_3": 79, "b_3": 79 }
+{ "a_0": 80, "a_1": 80, "a_2": 80, "a_3": 80, "b_3": 80 }
+{ "a_0": 81, "a_1": 81, "a_2": 81, "a_3": 81, "b_3": 81 }
+{ "a_0": 82, "a_1": 82, "a_2": 82, "a_3": 82, "b_3": 82 }
+{ "a_0": 83, "a_1": 83, "a_2": 83, "a_3": 83, "b_3": 83 }
+{ "a_0": 84, "a_1": 84, "a_2": 84, "a_3": 84, "b_3": 84 }
+{ "a_0": 85, "a_1": 85, "a_2": 85, "a_3": 85, "b_3": 85 }
+{ "a_0": 86, "a_1": 86, "a_2": 86, "a_3": 86, "b_3": 86 }
+{ "a_0": 87, "a_1": 87, "a_2": 87, "a_3": 87, "b_3": 87 }
+{ "a_0": 88, "a_1": 88, "a_2": 88, "a_3": 88, "b_3": 88 }
+{ "a_0": 89, "a_1": 89, "a_2": 89, "a_3": 89, "b_3": 89 }
+{ "a_0": 90, "a_1": 90, "a_2": 90, "a_3": 90, "b_3": 90 }
+{ "a_0": 91, "a_1": 91, "a_2": 91, "a_3": 91, "b_3": 91 }
+{ "a_0": 92, "a_1": 92, "a_2": 92, "a_3": 92, "b_3": 92 }
+{ "a_0": 93, "a_1": 93, "a_2": 93, "a_3": 93, "b_3": 93 }
+{ "a_0": 94, "a_1": 94, "a_2": 94, "a_3": 94, "b_3": 94 }
+{ "a_0": 95, "a_1": 95, "a_2": 95, "a_3": 95, "b_3": 95 }
+{ "a_0": 96, "a_1": 96, "a_2": 96, "a_3": 96, "b_3": 96 }
+{ "a_0": 97, "a_1": 97, "a_2": 97, "a_3": 97, "b_3": 97 }
+{ "a_0": 98, "a_1": 98, "a_2": 98, "a_3": 98, "b_3": 98 }
+{ "a_0": 99, "a_1": 99, "a_2": 99, "a_3": 99, "b_3": 99 }
+{ "a_0": 100, "a_1": 100, "a_2": 100, "a_3": 100, "b_3": 100 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.8.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.8.adm
new file mode 100644
index 0000000..497b339
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash_join_exchange_1/hash_join_exchange_1.8.adm
@@ -0,0 +1,100 @@
+{ "a_0": 1, "a_1": 1, "a_2": 1, "a_3": 1 }
+{ "a_0": 2, "a_1": 2, "a_2": 2, "a_3": 2 }
+{ "a_0": 3, "a_1": 3, "a_2": 3, "a_3": 3 }
+{ "a_0": 4, "a_1": 4, "a_2": 4, "a_3": 4 }
+{ "a_0": 5, "a_1": 5, "a_2": 5, "a_3": 5 }
+{ "a_0": 6, "a_1": 6, "a_2": 6, "a_3": 6 }
+{ "a_0": 7, "a_1": 7, "a_2": 7, "a_3": 7 }
+{ "a_0": 8, "a_1": 8, "a_2": 8, "a_3": 8 }
+{ "a_0": 9, "a_1": 9, "a_2": 9, "a_3": 9 }
+{ "a_0": 10, "a_1": 10, "a_2": 10, "a_3": 10 }
+{ "a_0": 11, "a_1": 11, "a_2": 11, "a_3": 11 }
+{ "a_0": 12, "a_1": 12, "a_2": 12, "a_3": 12 }
+{ "a_0": 13, "a_1": 13, "a_2": 13, "a_3": 13 }
+{ "a_0": 14, "a_1": 14, "a_2": 14, "a_3": 14 }
+{ "a_0": 15, "a_1": 15, "a_2": 15, "a_3": 15 }
+{ "a_0": 16, "a_1": 16, "a_2": 16, "a_3": 16 }
+{ "a_0": 17, "a_1": 17, "a_2": 17, "a_3": 17 }
+{ "a_0": 18, "a_1": 18, "a_2": 18, "a_3": 18 }
+{ "a_0": 19, "a_1": 19, "a_2": 19, "a_3": 19 }
+{ "a_0": 20, "a_1": 20, "a_2": 20, "a_3": 20 }
+{ "a_0": 21, "a_1": 21, "a_2": 21, "a_3": 21 }
+{ "a_0": 22, "a_1": 22, "a_2": 22, "a_3": 22 }
+{ "a_0": 23, "a_1": 23, "a_2": 23, "a_3": 23 }
+{ "a_0": 24, "a_1": 24, "a_2": 24, "a_3": 24 }
+{ "a_0": 25, "a_1": 25, "a_2": 25, "a_3": 25 }
+{ "a_0": 26, "a_1": 26, "a_2": 26, "a_3": 26 }
+{ "a_0": 27, "a_1": 27, "a_2": 27, "a_3": 27 }
+{ "a_0": 28, "a_1": 28, "a_2": 28, "a_3": 28 }
+{ "a_0": 29, "a_1": 29, "a_2": 29, "a_3": 29 }
+{ "a_0": 30, "a_1": 30, "a_2": 30, "a_3": 30 }
+{ "a_0": 31, "a_1": 31, "a_2": 31, "a_3": 31 }
+{ "a_0": 32, "a_1": 32, "a_2": 32, "a_3": 32 }
+{ "a_0": 33, "a_1": 33, "a_2": 33, "a_3": 33 }
+{ "a_0": 34, "a_1": 34, "a_2": 34, "a_3": 34 }
+{ "a_0": 35, "a_1": 35, "a_2": 35, "a_3": 35 }
+{ "a_0": 36, "a_1": 36, "a_2": 36, "a_3": 36 }
+{ "a_0": 37, "a_1": 37, "a_2": 37, "a_3": 37 }
+{ "a_0": 38, "a_1": 38, "a_2": 38, "a_3": 38 }
+{ "a_0": 39, "a_1": 39, "a_2": 39, "a_3": 39 }
+{ "a_0": 40, "a_1": 40, "a_2": 40, "a_3": 40 }
+{ "a_0": 41, "a_1": 41, "a_2": 41, "a_3": 41 }
+{ "a_0": 42, "a_1": 42, "a_2": 42, "a_3": 42 }
+{ "a_0": 43, "a_1": 43, "a_2": 43, "a_3": 43 }
+{ "a_0": 44, "a_1": 44, "a_2": 44, "a_3": 44 }
+{ "a_0": 45, "a_1": 45, "a_2": 45, "a_3": 45 }
+{ "a_0": 46, "a_1": 46, "a_2": 46, "a_3": 46 }
+{ "a_0": 47, "a_1": 47, "a_2": 47, "a_3": 47 }
+{ "a_0": 48, "a_1": 48, "a_2": 48, "a_3": 48 }
+{ "a_0": 49, "a_1": 49, "a_2": 49, "a_3": 49 }
+{ "a_0": 50, "a_1": 50, "a_2": 50, "a_3": 50 }
+{ "a_0": 51, "a_1": 51, "a_2": 51, "a_3": 51, "b_3": 51 }
+{ "a_0": 52, "a_1": 52, "a_2": 52, "a_3": 52, "b_3": 52 }
+{ "a_0": 53, "a_1": 53, "a_2": 53, "a_3": 53, "b_3": 53 }
+{ "a_0": 54, "a_1": 54, "a_2": 54, "a_3": 54, "b_3": 54 }
+{ "a_0": 55, "a_1": 55, "a_2": 55, "a_3": 55, "b_3": 55 }
+{ "a_0": 56, "a_1": 56, "a_2": 56, "a_3": 56, "b_3": 56 }
+{ "a_0": 57, "a_1": 57, "a_2": 57, "a_3": 57, "b_3": 57 }
+{ "a_0": 58, "a_1": 58, "a_2": 58, "a_3": 58, "b_3": 58 }
+{ "a_0": 59, "a_1": 59, "a_2": 59, "a_3": 59, "b_3": 59 }
+{ "a_0": 60, "a_1": 60, "a_2": 60, "a_3": 60, "b_3": 60 }
+{ "a_0": 61, "a_1": 61, "a_2": 61, "a_3": 61, "b_3": 61 }
+{ "a_0": 62, "a_1": 62, "a_2": 62, "a_3": 62, "b_3": 62 }
+{ "a_0": 63, "a_1": 63, "a_2": 63, "a_3": 63, "b_3": 63 }
+{ "a_0": 64, "a_1": 64, "a_2": 64, "a_3": 64, "b_3": 64 }
+{ "a_0": 65, "a_1": 65, "a_2": 65, "a_3": 65, "b_3": 65 }
+{ "a_0": 66, "a_1": 66, "a_2": 66, "a_3": 66, "b_3": 66 }
+{ "a_0": 67, "a_1": 67, "a_2": 67, "a_3": 67, "b_3": 67 }
+{ "a_0": 68, "a_1": 68, "a_2": 68, "a_3": 68, "b_3": 68 }
+{ "a_0": 69, "a_1": 69, "a_2": 69, "a_3": 69, "b_3": 69 }
+{ "a_0": 70, "a_1": 70, "a_2": 70, "a_3": 70, "b_3": 70 }
+{ "a_0": 71, "a_1": 71, "a_2": 71, "a_3": 71, "b_3": 71 }
+{ "a_0": 72, "a_1": 72, "a_2": 72, "a_3": 72, "b_3": 72 }
+{ "a_0": 73, "a_1": 73, "a_2": 73, "a_3": 73, "b_3": 73 }
+{ "a_0": 74, "a_1": 74, "a_2": 74, "a_3": 74, "b_3": 74 }
+{ "a_0": 75, "a_1": 75, "a_2": 75, "a_3": 75, "b_3": 75 }
+{ "a_0": 76, "a_1": 76, "a_2": 76, "a_3": 76, "b_3": 76 }
+{ "a_0": 77, "a_1": 77, "a_2": 77, "a_3": 77, "b_3": 77 }
+{ "a_0": 78, "a_1": 78, "a_2": 78, "a_3": 78, "b_3": 78 }
+{ "a_0": 79, "a_1": 79, "a_2": 79, "a_3": 79, "b_3": 79 }
+{ "a_0": 80, "a_1": 80, "a_2": 80, "a_3": 80, "b_3": 80 }
+{ "a_0": 81, "a_1": 81, "a_2": 81, "a_3": 81, "b_3": 81 }
+{ "a_0": 82, "a_1": 82, "a_2": 82, "a_3": 82, "b_3": 82 }
+{ "a_0": 83, "a_1": 83, "a_2": 83, "a_3": 83, "b_3": 83 }
+{ "a_0": 84, "a_1": 84, "a_2": 84, "a_3": 84, "b_3": 84 }
+{ "a_0": 85, "a_1": 85, "a_2": 85, "a_3": 85, "b_3": 85 }
+{ "a_0": 86, "a_1": 86, "a_2": 86, "a_3": 86, "b_3": 86 }
+{ "a_0": 87, "a_1": 87, "a_2": 87, "a_3": 87, "b_3": 87 }
+{ "a_0": 88, "a_1": 88, "a_2": 88, "a_3": 88, "b_3": 88 }
+{ "a_0": 89, "a_1": 89, "a_2": 89, "a_3": 89, "b_3": 89 }
+{ "a_0": 90, "a_1": 90, "a_2": 90, "a_3": 90, "b_3": 90 }
+{ "a_0": 91, "a_1": 91, "a_2": 91, "a_3": 91, "b_3": 91 }
+{ "a_0": 92, "a_1": 92, "a_2": 92, "a_3": 92, "b_3": 92 }
+{ "a_0": 93, "a_1": 93, "a_2": 93, "a_3": 93, "b_3": 93 }
+{ "a_0": 94, "a_1": 94, "a_2": 94, "a_3": 94, "b_3": 94 }
+{ "a_0": 95, "a_1": 95, "a_2": 95, "a_3": 95, "b_3": 95 }
+{ "a_0": 96, "a_1": 96, "a_2": 96, "a_3": 96, "b_3": 96 }
+{ "a_0": 97, "a_1": 97, "a_2": 97, "a_3": 97, "b_3": 97 }
+{ "a_0": 98, "a_1": 98, "a_2": 98, "a_3": 98, "b_3": 98 }
+{ "a_0": 99, "a_1": 99, "a_2": 99, "a_3": 99, "b_3": 99 }
+{ "a_0": 100, "a_1": 100, "a_2": 100, "a_3": 100, "b_3": 100 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/handle_error_fun/handle_error_fun.01.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/handle_error_fun/handle_error_fun.01.adm
new file mode 100644
index 0000000..b9a7cb5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/handle_error_fun/handle_error_fun.01.adm
@@ -0,0 +1 @@
+{ "id": 2, "f": "problematic doc" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.03.adm
new file mode 100644
index 0000000..9b33be8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.03.adm
@@ -0,0 +1,8 @@
+{ "a": 1, "b": 1 }
+{ "a": 10, "b": 10 }
+{ "a": 16, "b": 16 }
+{ "a": null, "b": null }
+{  }
+{ "a": 242005543865690107, "b": 242005543865690107 }
+{ "a": null, "b": null }
+{ "b": null }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.04.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.04.adm
new file mode 100644
index 0000000..8272596
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.04.adm
@@ -0,0 +1 @@
+{ "a": 1, "b": 10, "c": 16, "d": 242005543865690107, "e": null, "f": null, "h": null, "j": null, "k": null, "l": null, "m": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.05.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.05.adm
new file mode 100644
index 0000000..375bff5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/from_base/from_base.05.adm
@@ -0,0 +1 @@
+{ "a": 1, "b": 10, "c": null, "d": 1, "e": 2, "f": 3 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.01.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.01.adm
new file mode 100644
index 0000000..006e70c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.01.adm
@@ -0,0 +1,5 @@
+{ "id": 1, "f_padded_with_dollar_to_10_codepoints": "$$$$$$$$Hi", "f_truncated_or_padded_to_2_codepoints": "Hi", "f_padded_with_emoji_to_10_codepoints": "👩‍👩‍👧‍👦👩Hi", "f1_padded_to_4_codepoints": "%%%👩", "f": "Hi", "f1": "👩" }
+{ "id": 2, "f_padded_with_dollar_to_10_codepoints": "$$-7262.98", "f_truncated_or_padded_to_2_codepoints": "-7", "f_padded_with_emoji_to_10_codepoints": "👩‍-7262.98", "f1_padded_to_4_codepoints": "%%👨‍", "f": "-7262.98", "f1": "👨‍" }
+{ "id": 3, "f_padded_with_dollar_to_10_codepoints": "$$$$$$$a𩸽b", "f_truncated_or_padded_to_2_codepoints": "a𩸽", "f_padded_with_emoji_to_10_codepoints": "👩‍👩‍👧‍👦a𩸽b", "f1_padded_to_4_codepoints": "%%%🎉", "f": "a𩸽b", "f1": "🎉" }
+{ "id": 4, "f_padded_with_dollar_to_10_codepoints": "$$$👩‍👩‍👧‍👦", "f_truncated_or_padded_to_2_codepoints": "👩‍", "f_padded_with_emoji_to_10_codepoints": "👩‍👩👩‍👩‍👧‍👦", "f1_padded_to_4_codepoints": "%✓✓✓", "f": "👩‍👩‍👧‍👦", "f1": "✓✓✓" }
+{ "id": 5, "f_padded_with_dollar_to_10_codepoints": null, "f_truncated_or_padded_to_2_codepoints": null, "f_padded_with_emoji_to_10_codepoints": null, "f1_padded_to_4_codepoints": null, "f": null, "f1": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.02.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.02.adm
new file mode 100644
index 0000000..3f6d3e4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.02.adm
@@ -0,0 +1 @@
+{ "padded_to_11_codepoints": "$&^$asterix", "truncated_to_2_codepoints": "👩‍", "padded_to_10_codepoints": "👩‍👩‍👩‍👩‍👧‍", "padded_to_null_is_null": null, "padded_non_str": null, "negative_length": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.03.adm
new file mode 100644
index 0000000..6ef482b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.03.adm
@@ -0,0 +1 @@
+{ "padded_long_input": "$$$$$$$$$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "very_long_unicode_test": "彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu你8世界🌍", "very_long_truncation_with_unicode_result": "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss©®™§¶" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.01.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.01.adm
new file mode 100644
index 0000000..d534124
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.01.adm
@@ -0,0 +1,5 @@
+{ "id": 1, "f_padded_with_dollar_to_10_codepoints": "Hi$$$$$$$$", "f_truncated_or_padded_to_2_codepoints": "Hi", "f_padded_with_emoji_to_10_codepoints": "Hi👩‍👩‍👧‍👦👩", "f1_padded_to_4_codepoints": "👩%%%", "f": "Hi", "f1": "👩" }
+{ "id": 2, "f_padded_with_dollar_to_10_codepoints": "-7262.98$$", "f_truncated_or_padded_to_2_codepoints": "-7", "f_padded_with_emoji_to_10_codepoints": "-7262.98👩‍", "f1_padded_to_4_codepoints": "👨‍%%", "f": "-7262.98", "f1": "👨‍" }
+{ "id": 3, "f_padded_with_dollar_to_10_codepoints": "a𩸽b$$$$$$$", "f_truncated_or_padded_to_2_codepoints": "a𩸽", "f_padded_with_emoji_to_10_codepoints": "a𩸽b👩‍👩‍👧‍👦", "f1_padded_to_4_codepoints": "🎉%%%", "f": "a𩸽b", "f1": "🎉" }
+{ "id": 4, "f_padded_with_dollar_to_10_codepoints": "👩‍👩‍👧‍👦$$$", "f_truncated_or_padded_to_2_codepoints": "👩‍", "f_padded_with_emoji_to_10_codepoints": "👩‍👩‍👧‍👦👩‍👩", "f1_padded_to_4_codepoints": "✓✓✓%", "f": "👩‍👩‍👧‍👦", "f1": "✓✓✓" }
+{ "id": 5, "f_padded_with_dollar_to_10_codepoints": null, "f_truncated_or_padded_to_2_codepoints": null, "f_padded_with_emoji_to_10_codepoints": null, "f1_padded_to_4_codepoints": null, "f": null, "f1": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.02.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.02.adm
new file mode 100644
index 0000000..ba875f6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.02.adm
@@ -0,0 +1 @@
+{ "padded_to_11_codepoints": "asterix$&^$", "truncated_to_2_codepoints": "👩‍", "padded_to_10_codepoints": "👩‍👩‍👧‍👩‍👩‍", "padded_to_null_is_null": null, "padded_non_str": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.03.adm
new file mode 100644
index 0000000..8f86a8a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.03.adm
@@ -0,0 +1 @@
+{ "padded_long_input": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$$$$$$$$$$", "very_long_unicode_test": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu你8世界🌍彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩", "very_long_truncation_with_unicode_result": "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss©®™§¶" }
\ No newline at end of file
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 a26853b..fadf9df 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
@@ -4019,6 +4019,13 @@
       </compilation-unit>
     </test-case>
   </test-group>
+  <test-group name="crypto">
+    <test-case FilePath="crypto">
+      <compilation-unit name="sha1">
+        <output-dir compare="Text">sha1</output-dir>
+      </compilation-unit>
+    </test-case>
+  </test-group>
   <test-group name="custord">
     <!--
     <test-case FilePath="custord">
@@ -6884,6 +6891,16 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="join">
+      <compilation-unit name="hash_join_exchange">
+        <output-dir compare="Text">hash_join_exchange</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="join">
+      <compilation-unit name="hash_join_exchange_1">
+        <output-dir compare="Text">hash_join_exchange_1</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="join">
       <compilation-unit name="ASTERIXDB-3502">
         <output-dir compare="Text">ASTERIXDB-3502</output-dir>
       </compilation-unit>
@@ -7530,6 +7547,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="misc">
+      <compilation-unit name="handle_error_fun">
+        <output-dir compare="Text">handle_error_fun</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
       <compilation-unit name="query-ASTERIXDB-3299">
         <output-dir compare="Text">query-ASTERIXDB-3299</output-dir>
       </compilation-unit>
@@ -9642,6 +9664,11 @@
         <output-dir compare="Text">unary-minus_double_02</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="numeric">
+      <compilation-unit name="from_base">
+        <output-dir compare="Text">from_base</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="open-closed">
     <!--
@@ -11684,6 +11711,16 @@
         <expected-warn>Function 'position1' failed to evaluate because: Decoding error - got a low surrogate without a leading high surrogate</expected-warn>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="string">
+      <compilation-unit name="pad/lpad">
+        <output-dir compare="Text">pad/lpad</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="string">
+      <compilation-unit name="pad/rpad">
+        <output-dir compare="Text">pad/rpad</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="subquery">
     <test-case FilePath="subquery">
diff --git 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
index e232bc6..810393f 100644
--- 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
@@ -384,6 +384,16 @@
         <expected-error>'||' is not a valid escape. The length of a escape should be 1</expected-error>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="copy-to/csv">
+      <compilation-unit name="datetime">
+        <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">datetime</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="aws-s3-external-dataset">
     <test-case FilePath="external-dataset">
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/ICloudClient.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/ICloudClient.java
index d332944..0baebc7 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/ICloudClient.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/ICloudClient.java
@@ -23,11 +23,13 @@
 import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.asterix.cloud.IWriteBufferProvider;
 import org.apache.asterix.cloud.clients.profiler.IRequestProfilerLimiter;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.FileReference;
+import org.apache.hyracks.cloud.io.request.ICloudRetryPredicate;
 import org.apache.hyracks.control.nc.io.IOManager;
 
 import com.fasterxml.jackson.databind.JsonNode;
@@ -168,4 +170,10 @@
      * Performs any necessary closing and cleaning up
      */
     void close() throws HyracksDataException;
+
+    Predicate<Exception> getObjectNotFoundExceptionPredicate();
+
+    default ICloudRetryPredicate getRetryUnlessNotFound() {
+        return ex -> Predicate.not(getObjectNotFoundExceptionPredicate()).test(ex);
+    }
 }
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/NoopCloudClient.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/NoopCloudClient.java
index fb83aa9..8f37191 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/NoopCloudClient.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/NoopCloudClient.java
@@ -24,6 +24,7 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.asterix.cloud.IWriteBufferProvider;
 import org.apache.asterix.cloud.clients.profiler.IRequestProfilerLimiter;
@@ -117,6 +118,11 @@
     }
 
     @Override
+    public Predicate<Exception> getObjectNotFoundExceptionPredicate() {
+        return e -> true;
+    }
+
+    @Override
     public JsonNode listAsJson(ObjectMapper objectMapper, String bucket) {
         return OBJECT_MAPPER.createArrayNode();
     }
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/UnstableCloudClient.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/UnstableCloudClient.java
index 178984a..d81419b 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/UnstableCloudClient.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/UnstableCloudClient.java
@@ -26,6 +26,7 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Predicate;
 
 import org.apache.asterix.cloud.CloudResettableInputStream;
 import org.apache.asterix.cloud.IWriteBufferProvider;
@@ -143,6 +144,11 @@
         cloudClient.close();
     }
 
+    @Override
+    public Predicate<Exception> getObjectNotFoundExceptionPredicate() {
+        return cloudClient.getObjectNotFoundExceptionPredicate();
+    }
+
     private static void fail() throws HyracksDataException {
         double prob = RANDOM.nextInt(100) / 100.0d;
         if (prob < ERROR_RATE.get()) {
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/aws/s3/S3CloudClient.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/aws/s3/S3CloudClient.java
index fc35792..8a28f53 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/aws/s3/S3CloudClient.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/aws/s3/S3CloudClient.java
@@ -34,6 +34,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.function.Function;
+import java.util.function.Predicate;
 
 import org.apache.asterix.cloud.CloudResettableInputStream;
 import org.apache.asterix.cloud.IWriteBufferProvider;
@@ -328,6 +329,11 @@
         s3Client.close();
     }
 
+    @Override
+    public Predicate<Exception> getObjectNotFoundExceptionPredicate() {
+        return ex -> ex instanceof NoSuchKeyException;
+    }
+
     /**
      * FOR TESTING ONLY
      */
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/azure/blobstorage/AzBlobStorageCloudClient.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/azure/blobstorage/AzBlobStorageCloudClient.java
index 7922fc4..e2bbb5b 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/azure/blobstorage/AzBlobStorageCloudClient.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/azure/blobstorage/AzBlobStorageCloudClient.java
@@ -34,6 +34,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -391,6 +392,11 @@
         // Hence this implementation is a no op.
     }
 
+    @Override
+    public Predicate<Exception> getObjectNotFoundExceptionPredicate() {
+        return ex -> (ex instanceof BlobStorageException bse) && bse.getErrorCode().equals(BlobErrorCode.BLOB_NOT_FOUND);
+    }
+
     private static BlobServiceClient buildClient(AzBlobStorageClientConfig config) {
         BlobServiceClientBuilder blobServiceClientBuilder = new BlobServiceClientBuilder();
         blobServiceClientBuilder.endpoint(getEndpoint(config));
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/google/gcs/GCSCloudClient.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/google/gcs/GCSCloudClient.java
index 62c1835..bd0a044 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/google/gcs/GCSCloudClient.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/clients/google/gcs/GCSCloudClient.java
@@ -32,6 +32,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.asterix.cloud.IWriteBufferProvider;
 import org.apache.asterix.cloud.clients.CloudFile;
@@ -301,6 +302,11 @@
         }
     }
 
+    @Override
+    public Predicate<Exception> getObjectNotFoundExceptionPredicate() {
+        return ex -> (ex instanceof BaseServiceException bse)&& bse.getCode() == 404;
+    }
+
     private static Storage buildClient(GCSClientConfig config) throws HyracksDataException {
         StorageOptions.Builder builder = StorageOptions.newBuilder().setCredentials(config.createCredentialsProvider());
         builder.setStorageRetryStrategy(DEFAULT_NO_RETRY_ON_THREAD_INTERRUPT_STRATEGY);
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/parquet/ParquetSchemaInferPoolWriter.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/parquet/ParquetSchemaInferPoolWriter.java
index 255009e..ca87ced 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/parquet/ParquetSchemaInferPoolWriter.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/parquet/ParquetSchemaInferPoolWriter.java
@@ -29,9 +29,13 @@
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.api.IValueReference;
 import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import org.apache.hyracks.util.LogRedactionUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 // Maintains a pool of Parquet writers holding a file, each with its own schema , and writes values to the appropriate writer based on schema.
 public class ParquetSchemaInferPoolWriter {
+    private static final Logger LOGGER = LogManager.getLogger();
     private final ParquetExternalWriterFactory writerFactory;
     private List<ParquetSchemaTree.SchemaNode> schemaNodes;
     private List<IExternalWriter> writerList;
@@ -65,6 +69,10 @@
         }
 
         if (schemaNodes.size() == maxSchemas) {
+            LOGGER.info("Schema limit exceeded, max schemas allowed: {}", maxSchemas);
+            schemaNodes.forEach(schemaNode -> {
+                LOGGER.info("Inferred schema: {}", LogRedactionUtil.userData(schemaNode.toString()));
+            });
             throw new HyracksDataException(ErrorCode.SCHEMA_LIMIT_EXCEEDED, maxSchemas);
         }
         schemaNodes.add(schemaLazyVisitor.inferSchema(value));
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AbstractCloudExternalFileWriter.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AbstractCloudExternalFileWriter.java
index d02b34e..f93ae92 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AbstractCloudExternalFileWriter.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/writer/AbstractCloudExternalFileWriter.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.cloud.writer;
 
 import static org.apache.hyracks.api.util.ExceptionUtils.getMessageOrToString;
+import static org.apache.hyracks.cloud.util.CloudRetryableRequestUtil.runWithNoRetryOnInterruption;
 
 import org.apache.asterix.cloud.CloudOutputStream;
 import org.apache.asterix.cloud.IWriteBufferProvider;
@@ -33,6 +34,7 @@
 import org.apache.hyracks.api.exceptions.IWarningCollector;
 import org.apache.hyracks.api.exceptions.SourceLocation;
 import org.apache.hyracks.api.exceptions.Warning;
+import org.apache.hyracks.cloud.io.request.ICloudRequest;
 import org.apache.hyracks.data.std.api.IValueReference;
 
 import com.google.common.base.Utf8;
@@ -60,7 +62,7 @@
 
     @Override
     public final void open() throws HyracksDataException {
-        printer.open();
+        runWithRetryIfSdkException(printer::open);
     }
 
     @Override
@@ -69,7 +71,8 @@
             return;
         }
 
-        if (partitionedPath && !cloudClient.isEmptyPrefix(bucket, directory)) {
+        boolean emptyPrefix = runWithNoRetryOnInterruption(() -> cloudClient.isEmptyPrefix(bucket, directory));
+        if (partitionedPath && !emptyPrefix) {
             throw new RuntimeDataException(ErrorCode.DIRECTORY_IS_NOT_EMPTY, pathSourceLocation, directory);
         }
     }
@@ -91,7 +94,7 @@
     @Override
     public final void write(IValueReference value) throws HyracksDataException {
         try {
-            printer.print(value);
+            runWithRetryIfSdkException(() -> printer.print(value));
         } catch (HyracksDataException e) {
             throw e;
         } catch (Exception e) {
@@ -106,9 +109,9 @@
     public final void abort() throws HyracksDataException {
         try {
             if (cloudWriter != null) {
-                cloudWriter.abort();
+                runWithRetryIfSdkException(cloudWriter::abort);
             }
-            printer.close();
+            runWithRetryIfSdkException(printer::close);
         } catch (HyracksDataException e) {
             throw e;
         } catch (Exception e) {
@@ -122,7 +125,7 @@
     @Override
     public final void close() throws HyracksDataException {
         try {
-            printer.close();
+            runWithRetryIfSdkException(printer::close);
         } catch (HyracksDataException e) {
             throw e;
         } catch (Exception e) {
@@ -139,6 +142,10 @@
 
     abstract boolean isSdkException(Exception e);
 
+    private void runWithRetryIfSdkException(ICloudRequest request) throws HyracksDataException {
+        runWithNoRetryOnInterruption(request, this::isSdkException);
+    }
+
     private boolean checkAndWarnExceedingMaxLength(String fullPath) {
         boolean exceeding = isExceedingMaxLength(fullPath, getPathMaxLengthInBytes());
         if (exceeding && warningCollector.shouldWarn()) {
diff --git 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
index 977f90a..c52e2b6 100644
--- 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
@@ -20,6 +20,7 @@
 
 import static org.apache.asterix.cloud.writer.AbstractCloudExternalFileWriter.isExceedingMaxLength;
 import static org.apache.hyracks.api.util.ExceptionUtils.getMessageOrToString;
+import static org.apache.hyracks.cloud.util.CloudRetryableRequestUtil.runWithNoRetryOnInterruption;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -40,6 +41,7 @@
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.cloud.io.request.ICloudReturnableRequest;
 import org.apache.hyracks.data.std.primitive.LongPointable;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -122,7 +124,7 @@
                         staticPath, getPathMaxLengthInBytes(), getAdapterName());
             }
 
-            if (!testClient.isEmptyPrefix(bucket, staticPath)) {
+            if (!runWithNoRetryOnInterruption(() -> testClient.isEmptyPrefix(bucket, staticPath))) {
                 // Ensure that the static path is empty
                 throw new CompilationException(ErrorCode.DIRECTORY_IS_NOT_EMPTY, pathSourceLocation, staticPath);
             }
@@ -138,10 +140,16 @@
         Random random = new Random();
         String pathPrefix = "testFile";
         String path = pathPrefix + random.nextInt();
-        while (testClient.exists(bucket, path)) {
+
+        String existsFinalPath = path;
+        ICloudReturnableRequest<Boolean> existsRequest = () -> testClient.exists(bucket, existsFinalPath);
+        while (runWithNoRetryOnInterruption(existsRequest, testClient.getRetryUnlessNotFound())) {
             path = pathPrefix + random.nextInt();
+            String existsFinalPathUpdated = path;
+            existsRequest = () -> testClient.exists(bucket, existsFinalPathUpdated);
         }
 
+        final String finalPath = path;
         long writeValue = random.nextLong();
         byte[] data = new byte[Long.BYTES];
         LongPointable.setLong(data, 0, writeValue);
@@ -149,28 +157,29 @@
         ICloudWriter writer = testClient.createWriter(bucket, path, bufferProvider);
         boolean aborted = false;
         try {
-            writer.write(data, 0, data.length);
+            runWithNoRetryOnInterruption(() -> writer.write(data, 0, data.length));
         } catch (HyracksDataException e) {
-            writer.abort();
+            runWithNoRetryOnInterruption(writer::abort);
             aborted = true;
             throw e;
         } finally {
             if (writer != null && !aborted) {
-                writer.finish();
+                runWithNoRetryOnInterruption(writer::finish);
             }
         }
 
         try {
-            long readValue = LongPointable.getLong(testClient.readAllBytes(bucket, path), 0);
+            byte[] bytes = runWithNoRetryOnInterruption(() -> testClient.readAllBytes(bucket, finalPath));
+            long readValue = LongPointable.getLong(bytes, 0);
             if (writeValue != readValue) {
-                // This should never happen unless S3 is messed up. But log for sanity check
+                // This should never happen unless cloud storage is messed up. But log for sanity check
                 LOGGER.warn(
                         "The writer can write but the written values wasn't successfully read back (wrote: {}, read:{})",
                         writeValue, readValue);
             }
         } finally {
             // Delete the written file
-            testClient.deleteObjects(bucket, Collections.singleton(path));
+            runWithNoRetryOnInterruption(() -> testClient.deleteObjects(bucket, Collections.singleton(finalPath)));
         }
     }
 }
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/GlobalVirtualBufferCache.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/GlobalVirtualBufferCache.java
index 3eb1e4c..cb5323f 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/GlobalVirtualBufferCache.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/GlobalVirtualBufferCache.java
@@ -326,12 +326,12 @@
     }
 
     @Override
-    public void unpin(ICachedPage page) throws HyracksDataException {
+    public void unpin(ICachedPage page) {
         unpin(page, DEFAULT);
     }
 
     @Override
-    public void unpin(ICachedPage page, IBufferCacheReadContext context) throws HyracksDataException {
+    public void unpin(ICachedPage page, IBufferCacheReadContext context) {
         vbc.unpin(page, context);
     }
 
diff --git a/asterixdb/asterix-external-data/pom.xml b/asterixdb/asterix-external-data/pom.xml
index d2f47ba..6ede278 100644
--- a/asterixdb/asterix-external-data/pom.xml
+++ b/asterixdb/asterix-external-data/pom.xml
@@ -218,7 +218,6 @@
               <usedDependency>net.razorvine:serpent</usedDependency>
               <usedDependency>io.netty:netty-resolver-dns</usedDependency>
               <usedDependency>io.netty:netty-codec-http2</usedDependency>
-              <usedDependency>io.netty:netty-transport-native-unix-common</usedDependency>
               <usedDependency>io.netty:netty-handler-proxy</usedDependency>
               <usedDependency>io.netty:netty-handler-proxy</usedDependency>
             </usedDependencies>
@@ -557,10 +556,6 @@
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
-      <artifactId>netty-transport-native-unix-common</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>io.netty</groupId>
       <artifactId>netty-handler-proxy</artifactId>
     </dependency>
     <!-- Manually included to avoid CVE-2023-1370 -->
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetRecordLazyVisitor.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetRecordLazyVisitor.java
index 2a03bfd..cffeb2f 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetRecordLazyVisitor.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetRecordLazyVisitor.java
@@ -35,13 +35,16 @@
 import org.apache.hyracks.api.exceptions.ErrorCode;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.api.IValueReference;
+import org.apache.hyracks.util.LogRedactionUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.parquet.io.api.RecordConsumer;
 import org.apache.parquet.schema.GroupType;
 import org.apache.parquet.schema.MessageType;
 import org.apache.parquet.schema.Type;
 
 public class ParquetRecordLazyVisitor implements ILazyVisitablePointableVisitor<Void, Type> {
-
+    private static final Logger LOGGER = LogManager.getLogger();
     private final MessageType schema;
     private final RecordLazyVisitablePointable rec;
     //     The Record Consumer is responsible for traversing the record tree,
@@ -72,6 +75,7 @@
     public Void visit(RecordLazyVisitablePointable pointable, Type type) throws HyracksDataException {
 
         if (type.isPrimitive()) {
+            LOGGER.info("Expected primitive type: {} but got record type", LogRedactionUtil.userData(type.toString()));
             throw new HyracksDataException(ErrorCode.RESULT_DOES_NOT_FOLLOW_SCHEMA, GROUP_TYPE_ERROR_FIELD,
                     PRIMITIVE_TYPE_ERROR_FIELD, type.getName());
         }
@@ -84,6 +88,8 @@
             String columnName = fieldNamesDictionary.getOrCreateFieldNameIndex(pointable.getFieldName());
 
             if (!groupType.containsField(columnName)) {
+                LOGGER.info("Group type: {} does not contain field in record type: {}",
+                        LogRedactionUtil.userData(groupType.getName()), LogRedactionUtil.userData(columnName));
                 throw new HyracksDataException(ErrorCode.EXTRA_FIELD_IN_RESULT_NOT_FOUND_IN_SCHEMA, columnName,
                         groupType.getName());
             }
@@ -99,17 +105,22 @@
     public Void visit(AbstractListLazyVisitablePointable pointable, Type type) throws HyracksDataException {
 
         if (type.isPrimitive()) {
+            LOGGER.info("Expected primitive type: {} but got list type", LogRedactionUtil.userData(type.toString()));
             throw new HyracksDataException(ErrorCode.RESULT_DOES_NOT_FOLLOW_SCHEMA, GROUP_TYPE_ERROR_FIELD,
                     PRIMITIVE_TYPE_ERROR_FIELD, type.getName());
         }
         GroupType groupType = type.asGroupType();
 
         if (!groupType.containsField(LIST_FIELD)) {
+            LOGGER.info("Group type: {} does not contain field in list type: {}",
+                    LogRedactionUtil.userData(groupType.getName()), LIST_FIELD);
             throw new HyracksDataException(ErrorCode.EXTRA_FIELD_IN_RESULT_NOT_FOUND_IN_SCHEMA, LIST_FIELD,
                     groupType.getName());
         }
 
         if (groupType.getType(LIST_FIELD).isPrimitive()) {
+            LOGGER.info("Expected group type: {} but got primitive type",
+                    LogRedactionUtil.userData(groupType.getType(LIST_FIELD).toString()));
             throw new HyracksDataException(ErrorCode.RESULT_DOES_NOT_FOLLOW_SCHEMA, GROUP_TYPE_ERROR_FIELD,
                     PRIMITIVE_TYPE_ERROR_FIELD, LIST_FIELD);
         }
@@ -117,6 +128,8 @@
         GroupType listType = groupType.getType(LIST_FIELD).asGroupType();
 
         if (!listType.containsField(ELEMENT_FIELD)) {
+            LOGGER.info("Group type: {} does not contain field: {}", LogRedactionUtil.userData(listType.toString()),
+                    ELEMENT_FIELD);
             throw new HyracksDataException(ErrorCode.EXTRA_FIELD_IN_RESULT_NOT_FOUND_IN_SCHEMA, ELEMENT_FIELD,
                     listType.getName());
         }
@@ -147,8 +160,9 @@
 
     @Override
     public Void visit(FlatLazyVisitablePointable pointable, Type type) throws HyracksDataException {
-
         if (!type.isPrimitive()) {
+            LOGGER.info("Expected non primitive type: {} but got: {}", LogRedactionUtil.userData(type.toString()),
+                    pointable.getTypeTag());
             throw new HyracksDataException(ErrorCode.RESULT_DOES_NOT_FOLLOW_SCHEMA, PRIMITIVE_TYPE_ERROR_FIELD,
                     GROUP_TYPE_ERROR_FIELD, type.getName());
         }
@@ -168,6 +182,8 @@
             AbstractLazyVisitablePointable child = rec.getChildVisitablePointable();
 
             if (!schema.containsField(columnName)) {
+                LOGGER.info("Schema: {} does not contain field: {}", LogRedactionUtil.userData(schema.toString()),
+                        LogRedactionUtil.userData(columnName));
                 throw new HyracksDataException(ErrorCode.EXTRA_FIELD_IN_RESULT_NOT_FOUND_IN_SCHEMA, columnName,
                         schema.getName());
             }
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaLazyVisitor.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaLazyVisitor.java
index bd869e9..2278372 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaLazyVisitor.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaLazyVisitor.java
@@ -36,11 +36,15 @@
 import org.apache.asterix.om.types.IAType;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.api.IValueReference;
+import org.apache.hyracks.util.LogRedactionUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.parquet.schema.MessageType;
 import org.apache.parquet.schema.Types;
 
 // This class is used to infer the schema of a record into SchemaNode, which is an internal tree representation of the schema.
 public class ParquetSchemaLazyVisitor implements ILazyVisitablePointableVisitor<Void, ParquetSchemaTree.SchemaNode> {
+    private static final Logger LOGGER = LogManager.getLogger();
     private final RecordLazyVisitablePointable rec;
     private final FieldNamesDictionary fieldNamesDictionary;
     private final static String SCHEMA_NAME = "asterix_schema";
@@ -63,6 +67,8 @@
             schemaNode.setType(new ParquetSchemaTree.RecordType());
         }
         if (!(schemaNode.getType() instanceof ParquetSchemaTree.RecordType)) {
+            LOGGER.info("Incompatible type found in record: {} and {}",
+                    LogRedactionUtil.userData(schemaNode.toString()), pointable.getTypeTag());
             throw RuntimeDataException.create(PARQUET_UNSUPPORTED_MIXED_TYPE_ARRAY);
         }
         ParquetSchemaTree.RecordType recordType = (ParquetSchemaTree.RecordType) schemaNode.getType();
@@ -88,11 +94,12 @@
         if (schemaNode.getType() == null) {
             schemaNode.setType(new ParquetSchemaTree.ListType());
         }
-        if (!(schemaNode.getType() instanceof ParquetSchemaTree.ListType)) {
+        if (!(schemaNode.getType() instanceof ParquetSchemaTree.ListType listType)) {
+            LOGGER.info("Incompatible type found in list: {} and {}" ,LogRedactionUtil.userData(schemaNode.toString()) ,pointable.getTypeTag());
             throw RuntimeDataException.create(PARQUET_UNSUPPORTED_MIXED_TYPE_ARRAY);
         }
-        ParquetSchemaTree.ListType listType = (ParquetSchemaTree.ListType) schemaNode.getType();
-        for (int i = 0; i < pointable.getNumberOfChildren(); i++) {
+        int numChildren = pointable.getNumberOfChildren();
+        for (int i = 0; i < numChildren; i++) {
             pointable.nextChild();
             AbstractLazyVisitablePointable child = pointable.getChildVisitablePointable();
             if (listType.isEmpty()) {
@@ -114,11 +121,14 @@
             return null;
         }
         if (!(schemaNode.getType() instanceof ParquetSchemaTree.FlatType)) {
+            LOGGER.info("Incompatible type found: {} and {}", LogRedactionUtil.userData(schemaNode.toString()),
+                    pointable.getTypeTag());
             throw RuntimeDataException.create(PARQUET_UNSUPPORTED_MIXED_TYPE_ARRAY);
         }
         ParquetSchemaTree.FlatType flatType = (ParquetSchemaTree.FlatType) schemaNode.getType();
 
         if (!flatType.isCompatibleWith(pointable.getTypeTag())) {
+            LOGGER.info("Incompatible type found: {} and {}", flatType, pointable.getTypeTag());
             throw RuntimeDataException.create(PARQUET_UNSUPPORTED_MIXED_TYPE_ARRAY);
         }
 
@@ -136,6 +146,7 @@
 
     public static MessageType generateSchema(ParquetSchemaTree.SchemaNode schemaRoot) throws HyracksDataException {
         Types.MessageTypeBuilder builder = Types.buildMessage();
+        LOGGER.info("Building parquet schema: {}", LogRedactionUtil.userData(schemaRoot.toString()));
         if (schemaRoot.getType() == null)
             return builder.named(SCHEMA_NAME);
         for (Map.Entry<String, ParquetSchemaTree.SchemaNode> entry : ((ParquetSchemaTree.RecordType) schemaRoot
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaTree.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaTree.java
index 2ca086f..dae5295 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaTree.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/writer/printer/parquet/ParquetSchemaTree.java
@@ -28,11 +28,15 @@
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.hyracks.api.exceptions.ErrorCode;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.util.LogRedactionUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.parquet.schema.LogicalTypeAnnotation;
 import org.apache.parquet.schema.PrimitiveType;
 import org.apache.parquet.schema.Types;
 
 public class ParquetSchemaTree {
+    private static final Logger LOGGER = LogManager.getLogger();
 
     public static class SchemaNode {
         private AbstractType type;
@@ -48,6 +52,11 @@
         public AbstractType getType() {
             return type;
         }
+
+        @Override
+        public String toString() {
+            return type == null ? "NULL" : type.toString();
+        }
     }
 
     static class RecordType extends AbstractType {
@@ -68,6 +77,17 @@
         Map<String, SchemaNode> getChildren() {
             return children;
         }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("{ ");
+            for (Map.Entry<String, SchemaNode> entry : children.entrySet()) {
+                sb.append(entry.getKey()).append(" : ").append(entry.getValue()).append(", ");
+            }
+            sb.append(" }");
+            return sb.toString();
+        }
     }
 
     abstract static class AbstractType {
@@ -82,6 +102,11 @@
             isHierarchical = AsterixParquetTypeMap.HIERARCHIAL_TYPES.containsKey(typeTag);
         }
 
+        @Override
+        public String toString() {
+            return typeTag.toString();
+        }
+
         public boolean isCompatibleWith(ATypeTag typeTag) {
             if (isHierarchical) {
                 return AsterixParquetTypeMap.HIERARCHIAL_TYPES.containsKey(typeTag);
@@ -113,6 +138,11 @@
             child = null;
         }
 
+        @Override
+        public String toString() {
+            return "[ " + child + " ]";
+        }
+
         void setChild(SchemaNode child) {
             this.child = child;
         }
@@ -129,6 +159,8 @@
     public static void buildParquetSchema(Types.Builder builder, SchemaNode schemaNode, String columnName)
             throws HyracksDataException {
         if (schemaNode.getType() == null) {
+            LOGGER.info(
+                    "Child type not set for record value with column name: " + LogRedactionUtil.userData(columnName));
             throw new HyracksDataException(ErrorCode.EMPTY_TYPE_INFERRED);
         }
         AbstractType typeClass = schemaNode.getType();
@@ -154,6 +186,7 @@
         Types.BaseListBuilder<?, ?> childBuilder = getListChild(builder);
         SchemaNode child = type.child;
         if (child == null) {
+            LOGGER.info("Child type not set for list with column name: " + LogRedactionUtil.userData(columnName));
             throw new HyracksDataException(ErrorCode.EMPTY_TYPE_INFERRED);
         }
         buildParquetSchema(childBuilder, child, columnName);
@@ -161,6 +194,8 @@
 
     private static void buildFlat(Types.Builder builder, FlatType type, String columnName) throws HyracksDataException {
         if (type.getPrimitiveTypeName() == null) {
+            LOGGER.info("Child primitive type not set for flat value with column name: "
+                    + LogRedactionUtil.userData(columnName));
             // Not sure if this is the right thing to do here
             throw new HyracksDataException(ErrorCode.EMPTY_TYPE_INFERRED);
         }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
index 5c89a9f..ef76d14 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
@@ -54,15 +54,16 @@
     private List<Expression> partitionExpressions;
     private List<Expression> orderByList;
     private int varCounter;
-    private RecordTypeDefinition itemType;
-    private TypeExpression typeExpressionItemType;
+    private final RecordTypeDefinition itemType;
+    private final TypeExpression typeExpressionItemType;
+    private final Map<String, String> formatConfigs;
 
     public CopyToStatement(Namespace namespace, String datasetName, Query query, VariableExpr sourceVariable,
             ExternalDetailsDecl externalDetailsDecl, int varCounter, List<Expression> keyExpressions,
             boolean autogenerated) {
         this(namespace, datasetName, query, sourceVariable, externalDetailsDecl, new ArrayList<>(), new ArrayList<>(),
                 new HashMap<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), varCounter, keyExpressions,
-                autogenerated, null, null);
+                autogenerated, null, null, null);
     }
 
     public CopyToStatement(Namespace namespace, String datasetName, Query query, VariableExpr sourceVariable,
@@ -72,7 +73,7 @@
             List<OrderbyClause.NullOrderModifier> orderByNullModifierList, int varCounter) {
         this(namespace, datasetName, query, sourceVariable, externalDetailsDecl, pathExpressions, partitionExpressions,
                 partitionsVariables, orderbyList, orderByModifiers, orderByNullModifierList, varCounter,
-                new ArrayList<>(), false, null, null);
+                new ArrayList<>(), false, null, null, null);
     }
 
     public CopyToStatement(Namespace namespace, String datasetName, Query query, VariableExpr sourceVariable,
@@ -80,10 +81,10 @@
             List<Expression> partitionExpressions, Map<Integer, VariableExpr> partitionsVariables,
             List<Expression> orderbyList, List<OrderbyClause.OrderModifier> orderByModifiers,
             List<OrderbyClause.NullOrderModifier> orderByNullModifierList, int varCounter,
-            TypeExpression typeExpressionItemType, RecordTypeDefinition itemType) {
+            TypeExpression typeExpressionItemType, RecordTypeDefinition itemType, Map<String, String> formatConfigs) {
         this(namespace, datasetName, query, sourceVariable, externalDetailsDecl, pathExpressions, partitionExpressions,
                 partitionsVariables, orderbyList, orderByModifiers, orderByNullModifierList, varCounter,
-                new ArrayList<>(), false, typeExpressionItemType, itemType);
+                new ArrayList<>(), false, typeExpressionItemType, itemType, formatConfigs);
     }
 
     private CopyToStatement(Namespace namespace, String datasetName, Query query, VariableExpr sourceVariable,
@@ -92,7 +93,7 @@
             List<Expression> orderbyList, List<OrderbyClause.OrderModifier> orderByModifiers,
             List<OrderbyClause.NullOrderModifier> orderByNullModifierList, int varCounter,
             List<Expression> keyExpressions, boolean autogenerated, TypeExpression typeExpressionItemType,
-            RecordTypeDefinition itemType) {
+            RecordTypeDefinition itemType, Map<String, String> formatConfigs) {
         this.namespace = namespace;
         this.datasetName = datasetName;
         this.query = query;
@@ -109,6 +110,7 @@
         this.autogenerated = autogenerated;
         this.itemType = itemType;
         this.typeExpressionItemType = typeExpressionItemType;
+        this.formatConfigs = formatConfigs;
 
         if (pathExpressions.isEmpty()) {
             // Ensure path expressions to have at least an empty string
@@ -218,6 +220,10 @@
         return typeExpressionItemType;
     }
 
+    public Map<String, String> getFormatConfigs() {
+        return formatConfigs;
+    }
+
     @Override
     public int getVarCounter() {
         return varCounter;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 8afe035..34f5ba0 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -2986,6 +2986,8 @@
   RecordTypeDefinition recordTypeDefinition = null;
   TypeExpression typeExpr = null;
   Boolean isRecordTypeDefinition = false;
+  Map<String, String> formatConfigs = null;
+  String propertyName = null, propertyValue = null;
 
   List<Expression> partitionExprs = new ArrayList<Expression>();
   Map<Integer, VariableExpr> partitionVarExprs = new HashMap<Integer, VariableExpr>();
@@ -3002,7 +3004,8 @@
       recordTypeDefinition = RecordTypeDef();
       isRecordTypeDefinition = true;
     }
-    <RIGHTPAREN>) ?
+    <RIGHTPAREN>
+  )?
   (<AS>
     {
       if (isRecordTypeDefinition == false) {
@@ -3012,6 +3015,14 @@
       }
     }
   )?
+  (LOOKAHEAD(2) <IDENTIFIER> { propertyName = token.image.toLowerCase(); } propertyValue = StringLiteral()
+    {
+      if (formatConfigs == null) {
+        formatConfigs = new HashMap<String, String>();
+      }
+      formatConfigs.put(propertyName, propertyValue);
+    }
+  )*
   <WITH> withRecord = RecordConstructor()
     {
        ExternalDetailsDecl edd = new ExternalDetailsDecl();
@@ -3026,7 +3037,7 @@
           usedAlias = new VariableExpr(SqlppVariableUtil.toInternalVariableIdentifier(datasetName));
        }
 
-       CopyToStatement stmt = new CopyToStatement(namespace, datasetName, query, usedAlias, edd, pathExprs, partitionExprs, partitionVarExprs, orderbyList, orderbyModifierList, orderbyNullModifierList, getVarCounter(), typeExpr, recordTypeDefinition);
+       CopyToStatement stmt = new CopyToStatement(namespace, datasetName, query, usedAlias, edd, pathExprs, partitionExprs, partitionVarExprs, orderbyList, orderbyModifierList, orderbyNullModifierList, getVarCounter(), typeExpr, recordTypeDefinition, formatConfigs);
        return addSourceLocation(stmt, startToken);
     }
 }
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/IExternalWriteDataSink.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/IExternalWriteDataSink.java
index 1168ba1..157f0f8 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/IExternalWriteDataSink.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/IExternalWriteDataSink.java
@@ -19,6 +19,8 @@
 
 package org.apache.asterix.metadata.declared;
 
+import java.util.Map;
+
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.hyracks.algebricks.core.algebra.metadata.IWriteDataSink;
 import org.apache.hyracks.api.exceptions.SourceLocation;
@@ -28,5 +30,7 @@
 
     ARecordType getParquetSchema();
 
+    Map<String, String> getFormatConfigs();
+
     SourceLocation getSourceLoc();
 }
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/WriteDataSink.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/WriteDataSink.java
index 4a10f7f..4541162 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/WriteDataSink.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/WriteDataSink.java
@@ -29,15 +29,17 @@
     private final String adapterName;
     private final Map<String, String> configuration;
     private final ARecordType itemType;
+    private final Map<String, String> formatConfigs;
     private final ARecordType parquetSchema;
     private final SourceLocation sourceLoc;
 
     public WriteDataSink(String adapterName, Map<String, String> configuration, ARecordType itemType,
-            ARecordType parquetSchema, SourceLocation sourceLoc) {
+            ARecordType parquetSchema, Map<String, String> formatConfigs, SourceLocation sourceLoc) {
         this.adapterName = adapterName;
         this.configuration = configuration;
         this.itemType = itemType;
         this.parquetSchema = parquetSchema;
+        this.formatConfigs = formatConfigs;
         this.sourceLoc = sourceLoc;
     }
 
@@ -46,6 +48,7 @@
         this.configuration = new HashMap<>(writeDataSink.configuration);
         this.itemType = writeDataSink.itemType;
         this.parquetSchema = writeDataSink.parquetSchema;
+        this.formatConfigs = writeDataSink.getFormatConfigs();
         this.sourceLoc = writeDataSink.sourceLoc;
     }
 
@@ -74,6 +77,10 @@
         return configuration;
     }
 
+    public Map<String, String> getFormatConfigs() {
+        return formatConfigs;
+    }
+
     @Override
     public IWriteDataSink createCopy() {
         return new WriteDataSink(this);
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/provider/ExternalWriterProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/provider/ExternalWriterProvider.java
index 4315c97..bdfffa0 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/provider/ExternalWriterProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/provider/ExternalWriterProvider.java
@@ -185,9 +185,10 @@
                 compressStreamFactory = createCompressionStreamFactory(appCtx, compression, configuration);
                 if (sink instanceof IExternalWriteDataSink externalSink) {
                     ARecordType itemType = externalSink.getItemType();
+                    Map<String, String> formatConfigs = externalSink.getFormatConfigs();
                     if (itemType != null) {
                         printerFactory = CSVPrinterFactoryProvider
-                                .createInstance(itemType, externalSink.getConfiguration(), externalSink.getSourceLoc())
+                                .createInstance(itemType, externalSink.getConfiguration(), formatConfigs, externalSink.getSourceLoc())
                                 .getPrinterFactory(sourceType);
                         externalPrinterFactory =
                                 new CsvExternalFilePrinterFactory(printerFactory, compressStreamFactory);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java
index 372b5fd..92fb1bb 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java
@@ -49,7 +49,7 @@
     private static final long CHRONON_OF_DAY = TimeUnit.DAYS.toMillis(1);
 
     public static void printDateString(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
-        long chrononTime = AInt32SerializerDeserializer.getInt(b, s + 1) * CHRONON_OF_DAY;
+        long chrononTime = getDateChronon(b, s + 1);
 
         try {
             gCalInstance.getExtendStringRepUntilField(chrononTime, ps, GregorianCalendarSystem.Fields.YEAR,
@@ -59,8 +59,12 @@
         }
     }
 
+    public static long getDateChronon(byte[] b, int s) {
+        return AInt32SerializerDeserializer.getInt(b, s) * CHRONON_OF_DAY;
+    }
+
     public static void printDateTimeString(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
-        long chrononTime = AInt64SerializerDeserializer.getLong(b, s + 1);
+        long chrononTime = getDateTimeChronon(b, s + 1);
 
         try {
             gCalInstance.getExtendStringRepUntilField(chrononTime, ps, GregorianCalendarSystem.Fields.YEAR,
@@ -70,9 +74,13 @@
         }
     }
 
+    public static long getDateTimeChronon(byte[] b, int s) {
+        return AInt64SerializerDeserializer.getLong(b, s);
+    }
+
     public static void printDayTimeDurationString(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
         boolean positive = true;
-        long milliseconds = AInt64SerializerDeserializer.getLong(b, s + 1);
+        long milliseconds = getDateTimeChronon(b, s + 1);
 
         // set the negative flag. "||" is necessary in case that months field is not there (so it is 0)
         if (milliseconds < 0) {
@@ -218,7 +226,7 @@
     }
 
     public static void printTimeString(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
-        int time = AInt32SerializerDeserializer.getInt(b, s + 1);
+        int time = getTimeChronon(b, s + 1);
 
         try {
             gCalInstance.getExtendStringRepUntilField(time, ps, GregorianCalendarSystem.Fields.HOUR,
@@ -228,6 +236,10 @@
         }
     }
 
+    public static int getTimeChronon(byte[] b, int s) {
+        return AInt32SerializerDeserializer.getInt(b, s);
+    }
+
     public static void printDoubleForJson(byte[] b, int s, PrintStream ps) {
         final double d = ADoubleSerializerDeserializer.getDouble(b, s + 1);
         if (Double.isFinite(d)) {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADatePrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADatePrinterFactory.java
index dd03c97..83146ec 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADatePrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADatePrinterFactory.java
@@ -18,8 +18,6 @@
  */
 package org.apache.asterix.dataflow.data.nontagged.printers.csv;
 
-import java.io.PrintStream;
-
 import org.apache.asterix.dataflow.data.nontagged.printers.PrintTools;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
@@ -30,11 +28,7 @@
     private static final long serialVersionUID = 1L;
     public static final ADatePrinterFactory INSTANCE = new ADatePrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        ps.print("\"");
-        PrintTools.printDateString(b, s, l, ps);
-        ps.print("\"");
-    };
+    public static final IPrinter PRINTER = PrintTools::printDateString;
 
     @Override
     public IPrinter createPrinter(IEvaluatorContext context) {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADateTimePrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADateTimePrinterFactory.java
index b5b6185..f28c012 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADateTimePrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ADateTimePrinterFactory.java
@@ -18,8 +18,6 @@
  */
 package org.apache.asterix.dataflow.data.nontagged.printers.csv;
 
-import java.io.PrintStream;
-
 import org.apache.asterix.dataflow.data.nontagged.printers.PrintTools;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
@@ -30,11 +28,7 @@
     private static final long serialVersionUID = 1L;
     public static final ADateTimePrinterFactory INSTANCE = new ADateTimePrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        ps.print("\"");
-        PrintTools.printDateTimeString(b, s, l, ps);
-        ps.print("\"");
-    };
+    public static final IPrinter PRINTER = PrintTools::printDateTimeString;
 
     @Override
     public IPrinter createPrinter(IEvaluatorContext context) {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AObjectPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AObjectPrinterFactory.java
index 2f4d180..c3ef619 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AObjectPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AObjectPrinterFactory.java
@@ -26,10 +26,15 @@
 import static org.apache.asterix.common.utils.CSVConstants.KEY_QUOTE;
 import static org.apache.asterix.dataflow.data.nontagged.printers.csv.CSVUtils.DEFAULT_VALUES;
 import static org.apache.asterix.dataflow.data.nontagged.printers.csv.CSVUtils.getCharOrDefault;
+import static org.apache.asterix.om.base.temporal.DateTimeFormatUtils.DateTimeParseMode.DATETIME;
+import static org.apache.asterix.om.base.temporal.DateTimeFormatUtils.DateTimeParseMode.DATE_ONLY;
+import static org.apache.asterix.om.base.temporal.DateTimeFormatUtils.DateTimeParseMode.TIME_ONLY;
 
 import java.io.PrintStream;
 import java.util.Map;
 
+import org.apache.asterix.dataflow.data.nontagged.printers.PrintTools;
+import org.apache.asterix.om.base.temporal.DateTimeFormatUtils;
 import org.apache.asterix.om.pointables.ARecordVisitablePointable;
 import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
 import org.apache.asterix.om.pointables.printer.IPrintVisitor;
@@ -42,12 +47,17 @@
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 import org.apache.hyracks.api.context.IEvaluatorContext;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
 
 public class AObjectPrinterFactory implements IPrinterFactory {
     private static final long serialVersionUID = 1L;
+    private static final String DATE_FORMAT_PROPERTY_NAME = "date";
+    private static final String TIME_FORMAT_PROPERTY_NAME = "time";
+    private static final String DATETIME_FORMAT_PROPERTY_NAME = "datetime";
     private static final String DEFAULT_NULL_STRING = "";
     private final ARecordType itemType;
     private final Map<String, String> configuration;
+    private final Map<String, String> formatConfigs;
     private final boolean emptyFieldAsNull;
     private final String nullString;
     private final char quote;
@@ -55,9 +65,28 @@
     private final char escape;
     private final char delimiter;
 
-    private AObjectPrinterFactory(ARecordType itemType, Map<String, String> configuration) {
+    private DateTimeFormatUtils dateTimeFormatUtils;
+    private String timeFormat;
+    private String dateFormat;
+    private String datetimeFormat;
+    private byte[] timeFormatBytes;
+    private byte[] dateFormatBytes;
+    private byte[] datetimeFormatBytes;
+    private int timeFormatOffset;
+    private int dateFormatOffset;
+    private int datetimeFormatOffset;
+    private int timeFormatLength;
+    private int dateFormatLength;
+    private int datetimeFormatLength;
+    private boolean quoteTime;
+    private boolean quoteDate;
+    private boolean quoteDatetime;
+
+    private AObjectPrinterFactory(ARecordType itemType, Map<String, String> formatConfigs,
+            Map<String, String> configuration) {
         this.itemType = itemType;
         this.configuration = configuration;
+        this.formatConfigs = formatConfigs;
         this.emptyFieldAsNull = Boolean.parseBoolean(configuration.get(KEY_EMPTY_STRING_AS_NULL));
         this.nullString =
                 configuration.get(KEY_NULL_STR) != null ? configuration.get(KEY_NULL_STR) : DEFAULT_NULL_STRING;
@@ -65,10 +94,12 @@
         this.quote = getCharOrDefault(configuration.get(KEY_QUOTE), DEFAULT_VALUES.get(KEY_QUOTE));
         this.escape = getCharOrDefault(configuration.get(KEY_ESCAPE), DEFAULT_VALUES.get(KEY_ESCAPE));
         this.delimiter = getCharOrDefault(configuration.get(KEY_DELIMITER), DEFAULT_VALUES.get(KEY_DELIMITER));
+        extractDateTimeFormats(formatConfigs);
     }
 
-    public static AObjectPrinterFactory createInstance(ARecordType itemType, Map<String, String> configuration) {
-        return new AObjectPrinterFactory(itemType, configuration);
+    public static AObjectPrinterFactory createInstance(ARecordType itemType, Map<String, String> formatConfigs,
+            Map<String, String> configuration) {
+        return new AObjectPrinterFactory(itemType, formatConfigs, configuration);
     }
 
     public boolean printFlatValue(ATypeTag typeTag, byte[] b, int s, int l, PrintStream ps)
@@ -100,13 +131,31 @@
                 ADoublePrinterFactory.PRINTER.print(b, s, l, ps);
                 return true;
             case DATE:
-                ADatePrinterFactory.PRINTER.print(b, s, l, ps);
+                if (dateFormat == null) {
+                    ADatePrinterFactory.PRINTER.print(b, s, l, ps);
+                } else {
+                    long chronon = PrintTools.getDateChronon(b, s + 1);
+                    printFormattedDatetime(dateFormatBytes, dateFormatOffset, dateFormatLength, ps, chronon, DATE_ONLY,
+                            quoteDate);
+                }
                 return true;
             case TIME:
-                ATimePrinterFactory.PRINTER.print(b, s, l, ps);
+                if (timeFormat == null) {
+                    ATimePrinterFactory.PRINTER.print(b, s, l, ps);
+                } else {
+                    long chronon = PrintTools.getTimeChronon(b, s + 1);
+                    printFormattedDatetime(timeFormatBytes, timeFormatOffset, timeFormatLength, ps, chronon, TIME_ONLY,
+                            quoteTime);
+                }
                 return true;
             case DATETIME:
-                ADateTimePrinterFactory.PRINTER.print(b, s, l, ps);
+                if (datetimeFormat == null) {
+                    ADateTimePrinterFactory.PRINTER.print(b, s, l, ps);
+                } else {
+                    long chronon = PrintTools.getDateTimeChronon(b, s + 1);
+                    printFormattedDatetime(datetimeFormatBytes, datetimeFormatOffset, datetimeFormatLength, ps, chronon,
+                            DATETIME, quoteDatetime);
+                }
                 return true;
             case DURATION:
                 ADurationPrinterFactory.PRINTER.print(b, s, l, ps);
@@ -161,7 +210,7 @@
         final ARecordVisitablePointable recordVisitablePointable =
                 new ARecordVisitablePointable(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
         final Pair<PrintStream, ATypeTag> streamTag = new Pair<>(null, null);
-        final IPrintVisitor visitor = new APrintVisitor(context, itemType, configuration);
+        final IPrintVisitor visitor = new APrintVisitor(context, itemType, formatConfigs, configuration);
 
         return (byte[] b, int s, int l, PrintStream ps) -> {
             ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[s]);
@@ -185,4 +234,50 @@
     private void printString(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
         CSVUtils.printString(b, s, l, ps, quote, forceQuote, escape, delimiter);
     }
+
+    private void printFormattedDatetime(byte[] formatBytes, int formatOffset, int formatLength, PrintStream ps,
+            long chronon, DateTimeFormatUtils.DateTimeParseMode dateTimeParseMode, boolean shouldQuote)
+            throws HyracksDataException {
+        if (shouldQuote) {
+            ps.print("\"");
+        }
+        dateTimeFormatUtils.printDateTime(chronon, formatBytes, formatOffset, formatLength, ps, dateTimeParseMode);
+        if (shouldQuote) {
+            ps.print("\"");
+        }
+    }
+
+    private void extractDateTimeFormats(Map<String, String> formatConfigs) {
+        if (formatConfigs != null && !formatConfigs.isEmpty()) {
+            timeFormat = formatConfigs.get(TIME_FORMAT_PROPERTY_NAME);
+            dateFormat = formatConfigs.get(DATE_FORMAT_PROPERTY_NAME);
+            datetimeFormat = formatConfigs.get(DATETIME_FORMAT_PROPERTY_NAME);
+            dateTimeFormatUtils = DateTimeFormatUtils.getInstance();
+
+            UTF8StringPointable pointable;
+            if (timeFormat != null) {
+                pointable = UTF8StringPointable.generateUTF8Pointable(timeFormat);
+                timeFormatBytes = pointable.getByteArray();
+                timeFormatOffset = pointable.getStartOffset() + 1;
+                timeFormatLength = pointable.getLength() - 1;
+                quoteTime = timeFormat.indexOf(this.delimiter) != -1;
+            }
+
+            if (dateFormat != null) {
+                pointable = UTF8StringPointable.generateUTF8Pointable(dateFormat);
+                dateFormatBytes = pointable.getByteArray();
+                dateFormatOffset = pointable.getStartOffset() + 1;
+                dateFormatLength = pointable.getLength() - 1;
+                quoteDate = dateFormat.indexOf(this.delimiter) != -1;
+            }
+
+            if (datetimeFormat != null) {
+                pointable = UTF8StringPointable.generateUTF8Pointable(datetimeFormat);
+                datetimeFormatBytes = pointable.getByteArray();
+                datetimeFormatOffset = pointable.getStartOffset() + 1;
+                datetimeFormatLength = pointable.getLength() - 1;
+                quoteDatetime = datetimeFormat.indexOf(this.delimiter) != -1;
+            }
+        }
+    }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ARecordPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ARecordPrinterFactory.java
index d3ec388..cef0e6e 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ARecordPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ARecordPrinterFactory.java
@@ -39,11 +39,14 @@
     private static final long serialVersionUID = 1L;
     private final ARecordType recType;
     private final ARecordType itemType;
+    private final Map<String, String> formatConfigs;
     private final Map<String, String> configuration;
 
-    public ARecordPrinterFactory(ARecordType recType, ARecordType itemType, Map<String, String> configuration) {
+    public ARecordPrinterFactory(ARecordType recType, ARecordType itemType, Map<String, String> formatConfigs,
+            Map<String, String> configuration) {
         this.recType = recType;
         this.itemType = itemType;
+        this.formatConfigs = formatConfigs;
         this.configuration = configuration;
     }
 
@@ -54,7 +57,7 @@
         final IAType inputType =
                 recType == null ? DefaultOpenFieldType.getDefaultOpenFieldType(ATypeTag.OBJECT) : recType;
         final IVisitablePointable recAccessor = allocator.allocateRecordValue(inputType);
-        final APrintVisitor printVisitor = new APrintVisitor(context, itemType, configuration);
+        final APrintVisitor printVisitor = new APrintVisitor(context, itemType, formatConfigs, configuration);
         final Pair<PrintStream, ATypeTag> arg = new Pair<>(null, null);
 
         return new IPrinter() {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ATimePrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ATimePrinterFactory.java
index 2a73c56..e647ec8 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ATimePrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/ATimePrinterFactory.java
@@ -18,8 +18,6 @@
  */
 package org.apache.asterix.dataflow.data.nontagged.printers.csv;
 
-import java.io.PrintStream;
-
 import org.apache.asterix.dataflow.data.nontagged.printers.PrintTools;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
@@ -30,11 +28,7 @@
     private static final long serialVersionUID = 1L;
     public static final ATimePrinterFactory INSTANCE = new ATimePrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        ps.print("\"");
-        PrintTools.printTimeString(b, s, l, ps);
-        ps.print("\"");
-    };
+    public static final IPrinter PRINTER = PrintTools::printTimeString;
 
     @Override
     public IPrinter createPrinter(IEvaluatorContext context) {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/CSVPrinterFactoryProvider.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/CSVPrinterFactoryProvider.java
index 4d28ce4..799df8d 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/CSVPrinterFactoryProvider.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/CSVPrinterFactoryProvider.java
@@ -66,20 +66,22 @@
 public class CSVPrinterFactoryProvider implements IPrinterFactoryProvider {
     private final ARecordType itemType;
     private final Map<String, String> configuration;
+    private final Map<String, String> formatConfigs;
     private final SourceLocation sourceLocation;
 
     public static final CSVPrinterFactoryProvider INSTANCE =
-            new CSVPrinterFactoryProvider(null, Collections.emptyMap(), null);
+            new CSVPrinterFactoryProvider(null, Collections.emptyMap(), null, null);
 
     public static CSVPrinterFactoryProvider createInstance(ARecordType itemType, Map<String, String> configuration,
-            SourceLocation sourceLocation) {
-        return new CSVPrinterFactoryProvider(itemType, configuration, sourceLocation);
+            Map<String, String> formatConfigs, SourceLocation sourceLocation) {
+        return new CSVPrinterFactoryProvider(itemType, configuration, formatConfigs, sourceLocation);
     }
 
     private CSVPrinterFactoryProvider(ARecordType itemType, Map<String, String> configuration,
-            SourceLocation sourceLocation) {
+            Map<String, String> formatConfigs, SourceLocation sourceLocation) {
         this.itemType = itemType;
         this.configuration = configuration;
+        this.formatConfigs = formatConfigs;
         this.sourceLocation = sourceLocation;
     }
 
@@ -137,7 +139,7 @@
                             configuration.get(KEY_FORCE_QUOTE), configuration.get(KEY_ESCAPE),
                             configuration.get(KEY_DELIMITER));
                 case OBJECT:
-                    return new ARecordPrinterFactory((ARecordType) type, itemType, configuration);
+                    return new ARecordPrinterFactory((ARecordType) type, itemType, formatConfigs, configuration);
                 case ARRAY:
                     throw new NotImplementedException("'OrderedList' type unsupported for CSV output");
                 case MULTISET:
@@ -167,7 +169,7 @@
                     break;
             }
         }
-        return AObjectPrinterFactory.createInstance(itemType, configuration);
+        return AObjectPrinterFactory.createInstance(itemType, formatConfigs, configuration);
 
     }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java
index c6cb707..24909d7 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java
@@ -93,6 +93,15 @@
         }
     }
 
+    public static void warnValueOutOfRange(IEvaluatorContext ctx, SourceLocation srcLoc, FunctionIdentifier fid,
+            int inputPosition, int lowerBound, int upperBound, int actual) {
+        IWarningCollector warningCollector = ctx.getWarningCollector();
+        if (warningCollector.shouldWarn()) {
+            warningCollector.warn(Warning.of(srcLoc, ErrorCode.VALUE_OUT_OF_RANGE, fid,
+                    ExceptionUtil.indexToPosition(inputPosition), lowerBound, upperBound, actual));
+        }
+    }
+
     public static void warnTypeMismatch(IEvaluatorContext ctx, SourceLocation srcLoc, FunctionIdentifier fid,
             byte actualType, int argIdx, ATypeTag expectedType) {
         warnTypeMismatch(ctx, srcLoc, fid, actualType, argIdx, expectedType::toString);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
index 2bf5adc..f631b32 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
@@ -398,6 +398,8 @@
     public static final FunctionIdentifier STRING_REPEAT = FunctionConstants.newAsterix("repeat", 2);
     public static final FunctionIdentifier STRING_SPLIT = FunctionConstants.newAsterix("split", 2);
     public static final FunctionIdentifier STRING_PARSE_JSON = FunctionConstants.newAsterix("parse-json", 1);
+    public static final FunctionIdentifier STRING_LPAD = FunctionConstants.newAsterix("lpad", 3);
+    public static final FunctionIdentifier STRING_RPAD = FunctionConstants.newAsterix("rpad", 3);
 
     public static final FunctionIdentifier DATASET =
             FunctionConstants.newAsterix("dataset", FunctionIdentifier.VARARGS); // 1, 2 or 3
@@ -1305,6 +1307,14 @@
 
     public static final FunctionIdentifier ACCESS_NESTED_FIELD = FunctionConstants.newAsterix("access-nested-field", 2);
 
+    public static final FunctionIdentifier IF_ERROR = FunctionConstants.newAsterix("if-error", 2);
+
+    // crypto
+    public static final FunctionIdentifier SHA1_HEX = FunctionConstants.newAsterix("sha1-hex", 1);
+    public static final FunctionIdentifier SHA1_BASE64 = FunctionConstants.newAsterix("sha1-base64", 1);
+
+    public static final FunctionIdentifier FROM_BASE = FunctionConstants.newAsterix("from-base", 2);
+
     static {
         // first, take care of Algebricks builtin functions
         addFunction(IS_MISSING, BooleanOnlyTypeComputer.INSTANCE, true);
@@ -1335,7 +1345,6 @@
         addFunction(NOT, ABooleanTypeComputer.INSTANCE, true);
 
         addFunction(GET_TYPE, AStringTypeComputer.INSTANCE, true);
-
         addPrivateFunction(EQ, BooleanFunctionTypeComputer.INSTANCE, true);
         addPrivateFunction(LE, BooleanFunctionTypeComputer.INSTANCE, true);
         addPrivateFunction(GE, BooleanFunctionTypeComputer.INSTANCE, true);
@@ -1532,6 +1541,8 @@
         addFunction(STRING_REPEAT, AStringTypeComputer.INSTANCE_NULLABLE, true);
         addFunction(STRING_SPLIT, UniformInputTypeComputer.STRING_STRING_LIST_INSTANCE, true);
         addFunction(STRING_PARSE_JSON, AnyTypeComputer.INSTANCE, true);
+        addFunction(STRING_LPAD, AStringTypeComputer.INSTANCE_NULLABLE, true);
+        addFunction(STRING_RPAD, AStringTypeComputer.INSTANCE_NULLABLE, true);
 
         addPrivateFunction(ORDERED_LIST_CONSTRUCTOR, OrderedListConstructorTypeComputer.INSTANCE, true);
         addFunction(POINT_CONSTRUCTOR, APointTypeComputer.INSTANCE, true);
@@ -2161,6 +2172,7 @@
         addPrivateFunction(COLLECTION_TO_SEQUENCE, CollectionToSequenceTypeComputer.INSTANCE, true);
         addFunction(SERIALIZED_SIZE, AInt64TypeComputer.INSTANCE, true);
         // used by CBO's internal sampling queries for determining projection sizes
+        addPrivateFunction(IF_ERROR, AnyTypeComputer.INSTANCE, true);
 
         // external lookup
         addPrivateFunction(EXTERNAL_LOOKUP, AnyTypeComputer.INSTANCE, false);
@@ -2177,6 +2189,11 @@
         addPrivateFunction(ACCESS_FIELD, FieldAccessByNameResultType.INSTANCE, false);
         addPrivateFunction(ACCESS_NESTED_FIELD, FieldAccessNestedResultType.INSTANCE, false);
 
+        // crypto
+        addFunction(SHA1_HEX, AStringTypeComputer.INSTANCE_NULLABLE, true);
+        addFunction(SHA1_BASE64, AStringTypeComputer.INSTANCE_NULLABLE, true);
+
+        addFunction(FROM_BASE, AInt64TypeComputer.INSTANCE_NULLABLE, true);
     }
 
     static {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/csv/APrintVisitor.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/csv/APrintVisitor.java
index 7eadca5..7d5a52d 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/csv/APrintVisitor.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/csv/APrintVisitor.java
@@ -42,13 +42,16 @@
 public class APrintVisitor extends AbstractPrintVisitor {
     private final IEvaluatorContext context;
     private final ARecordType itemType;
+    private final Map<String, String> formatConfigs;
     private final Map<String, String> configuration;
     private AObjectPrinterFactory objectPrinterFactory;
 
-    public APrintVisitor(IEvaluatorContext context, ARecordType itemType, Map<String, String> configuration) {
+    public APrintVisitor(IEvaluatorContext context, ARecordType itemType, Map<String, String> formatConfigs,
+            Map<String, String> configuration) {
         super();
         this.context = context;
         this.itemType = itemType;
+        this.formatConfigs = formatConfigs;
         this.configuration = configuration;
     }
 
@@ -69,7 +72,7 @@
     protected boolean printFlatValue(ATypeTag typeTag, byte[] b, int s, int l, PrintStream ps)
             throws HyracksDataException {
         if (objectPrinterFactory == null) {
-            objectPrinterFactory = AObjectPrinterFactory.createInstance(itemType, configuration);
+            objectPrinterFactory = AObjectPrinterFactory.createInstance(itemType, formatConfigs, configuration);
         }
         return objectPrinterFactory.printFlatValue(typeTag, b, s, l, ps);
     }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/FromBaseDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/FromBaseDescriptor.java
new file mode 100644
index 0000000..fb57fb3
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/FromBaseDescriptor.java
@@ -0,0 +1,127 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.AInt64;
+import org.apache.asterix.om.base.AMutableInt32;
+import org.apache.asterix.om.base.AMutableInt64;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.evaluators.common.ArgumentUtils;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import org.apache.hyracks.util.string.UTF8StringUtil;
+
+@MissingNullInOutFunction
+public class FromBaseDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = FromBaseDescriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
+                return new IScalarEvaluator() {
+
+                    private final ArrayBackedValueStorage storage = new ArrayBackedValueStorage();
+                    private final StringBuilder strBuilder = new StringBuilder();
+                    private final IScalarEvaluator evalString = args[0].createScalarEvaluator(ctx);
+                    private final IScalarEvaluator evalBase = args[1].createScalarEvaluator(ctx);
+                    private final IPointable argString = new VoidPointable();
+                    private final IPointable argNumber = new VoidPointable();
+                    private final AMutableInt32 aInt32 = new AMutableInt32(0);
+                    private final AMutableInt64 aInt64 = new AMutableInt64(0);
+                    @SuppressWarnings("unchecked")
+                    private final ISerializerDeserializer<AInt64> int64Serde =
+                            SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+                        evalString.evaluate(tuple, argString);
+                        evalBase.evaluate(tuple, argNumber);
+
+                        if (PointableHelper.checkAndSetMissingOrNull(result, argString, argNumber)) {
+                            return;
+                        }
+                        byte[] bytes = argNumber.getByteArray();
+                        int offset = argNumber.getStartOffset();
+                        if (!ArgumentUtils.setInteger(ctx, sourceLoc, getIdentifier(), 1, bytes, offset, aInt32)) {
+                            PointableHelper.setNull(result);
+                            return;
+                        }
+                        int base = aInt32.getIntegerValue();
+                        if (base < 2 || base > 36) {
+                            PointableHelper.setNull(result);
+                            ExceptionUtil.warnValueOutOfRange(ctx, sourceLoc, getIdentifier(), 1, 2, 36, base);
+                            return;
+                        }
+
+                        bytes = argString.getByteArray();
+                        offset = argString.getStartOffset();
+                        if (bytes[offset] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+                            PointableHelper.setNull(result);
+                            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, getIdentifier(), bytes[offset], 0,
+                                    ATypeTag.STRING);
+                            return;
+                        }
+                        strBuilder.setLength(0);
+                        UTF8StringUtil.toString(strBuilder, bytes, offset + 1);
+
+                        try {
+                            aInt64.setValue(Long.parseLong(strBuilder, 0, strBuilder.length(), base));
+                        } catch (NumberFormatException e) {
+                            PointableHelper.setNull(result);
+                            ExceptionUtil.warnFunctionEvalFailed(ctx, sourceLoc, getIdentifier(), e.getMessage());
+                            return;
+                        }
+                        storage.reset();
+                        int64Serde.serialize(aInt64, storage.getDataOutput());
+                        result.set(storage);
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.FROM_BASE;
+    }
+
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfErrorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfErrorDescriptor.java
new file mode 100644
index 0000000..d51d8d0
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfErrorDescriptor.java
@@ -0,0 +1,70 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public final class IfErrorDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = IfErrorDescriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException {
+                return new AbstractScalarEval(sourceLoc, getIdentifier()) {
+                    private final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx);
+                    private final IScalarEvaluator eval1 = args[1].createScalarEvaluator(ctx);
+                    private final VoidPointable arg = VoidPointable.FACTORY.createPointable();
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+                        try {
+                            eval0.evaluate(tuple, arg);
+                            result.set(arg);
+                        } catch (Throwable th) {
+                            eval1.evaluate(tuple, arg);
+                            result.set(arg);
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.IF_ERROR;
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1Base64Descriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1Base64Descriptor.java
new file mode 100644
index 0000000..fb9eef6
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1Base64Descriptor.java
@@ -0,0 +1,57 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class Sha1Base64Descriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = Sha1Base64Descriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
+                return new Sha1StringEvaluator(args, ctx, sourceLoc, getIdentifier(),
+                        Sha1StringEvaluator.Encoding.BASE64);
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.SHA1_BASE64;
+    }
+
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1HexDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1HexDescriptor.java
new file mode 100644
index 0000000..bf3449e
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1HexDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class Sha1HexDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = Sha1HexDescriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
+                return new Sha1StringEvaluator(args, ctx, sourceLoc, getIdentifier(), Sha1StringEvaluator.Encoding.HEX);
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.SHA1_HEX;
+    }
+
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1StringEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1StringEvaluator.java
new file mode 100755
index 0000000..3bbf125
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Sha1StringEvaluator.java
@@ -0,0 +1,111 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.asterix.dataflow.data.nontagged.printers.PrintTools;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import org.apache.hyracks.util.bytes.Base64Printer;
+import org.apache.hyracks.util.bytes.HexPrinter;
+import org.apache.hyracks.util.string.UTF8StringWriter;
+
+public class Sha1StringEvaluator extends AbstractScalarEval {
+
+    private final IScalarEvaluator eval;
+    private final ArrayBackedValueStorage storage;
+    private final IPointable argPtr;
+    private final UTF8StringWriter writer;
+    private final StringBuilder strBuilder;
+    private final MessageDigest md;
+    private final IEvaluatorContext ctx;
+    private final Encoding encoding;
+
+    Sha1StringEvaluator(IScalarEvaluatorFactory[] args, IEvaluatorContext ctx, SourceLocation srcLoc,
+            FunctionIdentifier funId, Encoding encoding) throws HyracksDataException {
+        super(srcLoc, funId);
+        this.ctx = ctx;
+        this.encoding = encoding;
+        storage = new ArrayBackedValueStorage(43);
+        eval = args[0].createScalarEvaluator(ctx);
+        strBuilder = new StringBuilder(40);
+        writer = new UTF8StringWriter();
+        argPtr = new VoidPointable();
+        try {
+            md = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e) {
+            throw HyracksDataException.create(e);
+        }
+    }
+
+    @Override
+    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+        eval.evaluate(tuple, argPtr);
+        if (PointableHelper.checkAndSetMissingOrNull(result, argPtr)) {
+            return;
+        }
+        byte[] bytes = argPtr.getByteArray();
+        int offset = argPtr.getStartOffset();
+        if (bytes[offset] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+            PointableHelper.setNull(result);
+            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, bytes[offset], 0, ATypeTag.STRING);
+            return;
+        }
+
+        storage.reset();
+        try {
+            // convert modified UTF-8 bytes to UTF-8 bytes
+            PrintTools.writeUTF8StringRaw(bytes, offset + 1, argPtr.getLength() - 1, storage.getDataOutput());
+            md.update(storage.getByteArray(), storage.getStartOffset(), storage.getLength());
+            byte[] digestBytes = md.digest();
+            strBuilder.setLength(0);
+            // convert UTF-8 bytes to hex or base64 string
+            if (encoding == Encoding.HEX) {
+                HexPrinter.printHexString(digestBytes, 0, digestBytes.length, strBuilder);
+            } else {
+                Base64Printer.printBase64Binary(digestBytes, 0, digestBytes.length, strBuilder);
+            }
+            // serialize the encoded string as modified UTF-8
+            storage.reset();
+            storage.getDataOutput().writeByte(ATypeTag.SERIALIZED_STRING_TYPE_TAG);
+            writer.writeUTF8(strBuilder, storage.getDataOutput());
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
+        result.set(storage);
+    }
+
+    enum Encoding {
+        HEX,
+        BASE64;
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringLpadDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringLpadDescriptor.java
new file mode 100644
index 0000000..a801d9a
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringLpadDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class StringLpadDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = StringLpadDescriptor::new;
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.STRING_LPAD;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException {
+                return new StringPadEvaluator(ctx, args[0], args[1], args[2], StringLpadDescriptor.this.getIdentifier(),
+                        sourceLoc, true) {
+                };
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringPadEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringPadEvaluator.java
new file mode 100644
index 0000000..d4b01e2
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringPadEvaluator.java
@@ -0,0 +1,169 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.asterix.om.base.AMutableInt32;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.runtime.evaluators.common.ArgumentUtils;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.data.std.util.GrowableArray;
+import org.apache.hyracks.data.std.util.UTF8StringBuilder;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import org.apache.hyracks.util.string.UTF8StringUtil;
+
+public abstract class StringPadEvaluator extends AbstractScalarEval {
+
+    private final IEvaluatorContext ctx;
+    private final IScalarEvaluator inStrEval;
+    private final IScalarEvaluator lenEval;
+    private final IScalarEvaluator padStrEval;
+
+    private final UTF8StringPointable inStrUtf8Ptr = new UTF8StringPointable();
+    private final UTF8StringPointable padStrUtf8Ptr = new UTF8StringPointable();
+    private final IPointable inStrArg = new VoidPointable();
+    private final IPointable lenArg = new VoidPointable();
+    private final IPointable padStrArg = new VoidPointable();
+    private final AMutableInt32 mutableInt = new AMutableInt32(0);
+
+    private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+    private final DataOutput out = resultStorage.getDataOutput();
+    private final GrowableArray builderInternalArray = new GrowableArray();
+    private final UTF8StringBuilder builder = new UTF8StringBuilder();
+    private final boolean lpad;
+
+    public StringPadEvaluator(IEvaluatorContext ctx, IScalarEvaluatorFactory inStrEvalFact,
+            IScalarEvaluatorFactory lenEvalFact, IScalarEvaluatorFactory padStrEvalFact, FunctionIdentifier funcID,
+            SourceLocation srcLoc, boolean lpad) throws HyracksDataException {
+        super(srcLoc, funcID);
+        this.lpad = lpad;
+        this.inStrEval = inStrEvalFact.createScalarEvaluator(ctx);
+        this.lenEval = lenEvalFact.createScalarEvaluator(ctx);
+        this.padStrEval = padStrEvalFact.createScalarEvaluator(ctx);
+        this.ctx = ctx;
+    }
+
+    @Override
+    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+        inStrEval.evaluate(tuple, inStrArg);
+        lenEval.evaluate(tuple, lenArg);
+        padStrEval.evaluate(tuple, padStrArg);
+
+        if (PointableHelper.checkAndSetMissingOrNull(result, inStrArg, lenArg, padStrArg)) {
+            return;
+        }
+
+        byte[] inStrBytes = inStrArg.getByteArray();
+        int inStrStart = inStrArg.getStartOffset();
+        if (inStrBytes[inStrStart] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+            PointableHelper.setNull(result);
+            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, inStrBytes[inStrStart], 0, ATypeTag.STRING);
+            return;
+        }
+
+        byte[] lenBytes = lenArg.getByteArray();
+        int lenStart = lenArg.getStartOffset();
+        if (!ArgumentUtils.setInteger(ctx, srcLoc, funID, 1, lenBytes, lenStart, mutableInt)) {
+            PointableHelper.setNull(result);
+            return;
+        }
+        // Desired length of the string in Unicode code points
+        int targetNumCodePoints = mutableInt.getIntegerValue();
+        if (targetNumCodePoints < 0) {
+            PointableHelper.setNull(result);
+            ExceptionUtil.warnNegativeValue(ctx, srcLoc, funID, 1, targetNumCodePoints);
+            return;
+        }
+
+        // TODO: usually this will be a constant. if constant, the code could be optimized
+        byte[] padStrBytes = padStrArg.getByteArray();
+        int padStrStart = padStrArg.getStartOffset();
+        if (padStrBytes[padStrStart] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+            PointableHelper.setNull(result);
+            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, padStrBytes[padStrStart], 2, ATypeTag.STRING);
+            return;
+        }
+
+        int inStrCodePointsNum = UTF8StringUtil.getNumCodePoint(inStrBytes, inStrStart + 1);
+        if (inStrCodePointsNum == targetNumCodePoints) {
+            result.set(inStrArg);
+            return;
+        }
+        try {
+            builderInternalArray.reset();
+            builder.reset(builderInternalArray, targetNumCodePoints);
+            // skip the type tag byte
+            inStrUtf8Ptr.set(inStrBytes, inStrStart + 1, inStrArg.getLength() - 1);
+            padStrUtf8Ptr.set(padStrBytes, padStrStart + 1, padStrArg.getLength() - 1);
+
+            process(targetNumCodePoints, inStrCodePointsNum);
+            builder.finish();
+
+            resultStorage.reset();
+            out.writeByte(ATypeTag.SERIALIZED_STRING_TYPE_TAG);
+            out.write(builderInternalArray.getByteArray(), 0, builderInternalArray.getLength());
+            //result -> type tag, len, actual data
+            result.set(resultStorage);
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
+    }
+
+    public void process(int targetNumCodePoints, int inStrCodePointsNum) throws IOException {
+        if (targetNumCodePoints < inStrCodePointsNum) {
+            truncate(targetNumCodePoints);
+        } else {
+            int numCodePointsToPad = targetNumCodePoints - inStrCodePointsNum;
+            if (lpad) {
+                // For LPAD: first, append the required padding characters.
+                appendPaddingCodepoints(numCodePointsToPad);
+                // Then, append the codepoints of the original string.
+                appendCodePoints();
+            } else {
+                appendCodePoints();
+                appendPaddingCodepoints(numCodePointsToPad);
+            }
+        }
+    }
+
+    private void truncate(int targetNumCodePoints) throws IOException {
+        UTF8StringPointable.append(inStrUtf8Ptr, targetNumCodePoints, builder, builderInternalArray);
+    }
+
+    private void appendCodePoints() throws IOException {
+        builder.appendUtf8StringPointable(inStrUtf8Ptr);
+    }
+
+    private void appendPaddingCodepoints(int numCodePointsToPad) throws IOException {
+        UTF8StringPointable.append(padStrUtf8Ptr, numCodePointsToPad, builder, builderInternalArray);
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRpadDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRpadDescriptor.java
new file mode 100644
index 0000000..2ff28e4
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRpadDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class StringRpadDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = StringRpadDescriptor::new;
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.STRING_RPAD;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException {
+                return new StringPadEvaluator(ctx, args[0], args[1], args[2], StringRpadDescriptor.this.getIdentifier(),
+                        sourceLoc, false) {
+                };
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
index d682d7a..166352c 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
@@ -382,12 +382,14 @@
 import org.apache.asterix.runtime.evaluators.functions.CreateUUIDDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.DecodeDataverseNameDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.DeepEqualityDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.FromBaseDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.FullTextContainsFunctionDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.FullTextContainsWithoutOptionFunctionDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.GetIntersectionDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.GetItemDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.GetJobParameterByNameDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.GetTypeDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.IfErrorDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.IfInfDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.IfMissingDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.IfMissingOrNullDescriptor;
@@ -463,6 +465,8 @@
 import org.apache.asterix.runtime.evaluators.functions.RandomWithSeedDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ReferenceTileDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SerializedSizeDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.Sha1Base64Descriptor;
+import org.apache.asterix.runtime.evaluators.functions.Sha1HexDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SleepDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SpatialAreaDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SpatialCellDescriptor;
@@ -479,6 +483,7 @@
 import org.apache.asterix.runtime.evaluators.functions.StringLengthDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringLikeDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringLowerCaseDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.StringLpadDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringPositionDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringPositionOffset1Descriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringRTrim2Descriptor;
@@ -499,6 +504,7 @@
 import org.apache.asterix.runtime.evaluators.functions.StringReplaceDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringReplaceWithLimitDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringReverseDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.StringRpadDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringSplitDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringStartsWithDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.StringToCodePointDescriptor;
@@ -1055,6 +1061,7 @@
         fc.add(NumericSignDescriptor.FACTORY);
         fc.add(NumericTruncDescriptor.FACTORY);
         fc.add(NumericATan2Descriptor.FACTORY);
+        fc.add(FromBaseDescriptor.FACTORY);
 
         // Comparisons.
         fc.add(EqualsDescriptor.FACTORY);
@@ -1141,6 +1148,8 @@
         fc.add(StringReplaceWithLimitDescriptor.FACTORY);
         fc.add(StringReverseDescriptor.FACTORY);
         fc.add(StringSplitDescriptor.FACTORY);
+        fc.add(StringLpadDescriptor.FACTORY);
+        fc.add(StringRpadDescriptor.FACTORY);
 
         // Constructors
         fc.add(ABooleanConstructorDescriptor.FACTORY);
@@ -1356,11 +1365,16 @@
         // Record function
         fc.add(RecordPairsDescriptor.FACTORY);
 
+        // Crypto functions
+        fc.add(Sha1HexDescriptor.FACTORY);
+        fc.add(Sha1Base64Descriptor.FACTORY);
+
         // Other functions
         fc.add(DecodeDataverseNameDescriptor.FACTORY);
         fc.add(RandomWithSeedDescriptor.FACTORY);
         fc.add(SerializedSizeDescriptor.FACTORY);
         fc.add(PutAutogeneratedKeyDescriptor.FACTORY);
+        fc.add(IfErrorDescriptor.FACTORY);
 
         ServiceLoader.load(IFunctionRegistrant.class).iterator().forEachRemaining(c -> c.register(fc));
         return fc;
diff --git a/asterixdb/pom.xml b/asterixdb/pom.xml
index 35f9219..1216f8a 100644
--- a/asterixdb/pom.xml
+++ b/asterixdb/pom.xml
@@ -662,9 +662,9 @@
               ${coverageArgLine}
               ${extraFailsafeArgLine}
             </argLine>
-            <systemProperties>
+            <systemPropertyVariables>
               <log4j.configurationFile>${testLog4jConfigFile}</log4j.configurationFile>
-            </systemProperties>
+            </systemPropertyVariables>
             <includes>
               <include>${itest.includes}</include>
             </includes>
@@ -1116,6 +1116,10 @@
             <artifactId>jsr311-api</artifactId>
           </exclusion>
           <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-epoll</artifactId>
+          </exclusion>
+          <exclusion>
             <groupId>org.apache.avro</groupId>
             <artifactId>avro</artifactId>
           </exclusion>
@@ -1190,10 +1194,6 @@
             <artifactId>jline</artifactId>
           </exclusion>
           <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-all</artifactId>
-          </exclusion>
-          <exclusion>
             <groupId>org.apache.avro</groupId>
             <artifactId>avro</artifactId>
           </exclusion>
@@ -1569,35 +1569,7 @@
         <exclusions>
           <exclusion>
             <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http2</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-common</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-buffer</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-handler</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport-native-epoll</artifactId>
+            <artifactId>netty-transport-classes-epoll</artifactId>
           </exclusion>
         </exclusions>
       </dependency>
@@ -1693,70 +1665,6 @@
             <groupId>net.minidev</groupId>
             <artifactId>json-smart</artifactId>
           </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-handler</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-handler-proxy</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http2</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-buffer</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-common</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport-native-epoll</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport-native-unix-common</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-tcnative-boringssl-static</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-dns</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport-native-kqueue</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-resolver</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-resolver-dns</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-resolver-dns-native-macos</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec</artifactId>
-          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
@@ -1766,34 +1674,6 @@
         <exclusions>
           <exclusion>
             <groupId>io.netty</groupId>
-            <artifactId>netty-handler</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-handler-proxy</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http2</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-buffer</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-common</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
             <artifactId>netty-transport-native-epoll</artifactId>
           </exclusion>
           <exclusion>
@@ -1802,104 +1682,18 @@
           </exclusion>
           <exclusion>
             <groupId>io.netty</groupId>
-            <artifactId>netty-tcnative-boringssl-static</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-dns</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
             <artifactId>netty-transport-native-kqueue</artifactId>
           </exclusion>
           <exclusion>
             <groupId>io.netty</groupId>
-            <artifactId>netty-resolver</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-resolver-dns</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
             <artifactId>netty-resolver-dns-native-macos</artifactId>
           </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec</artifactId>
-          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
         <groupId>com.azure</groupId>
         <artifactId>azure-storage-common</artifactId>
         <version>${azurecommonjavasdk.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-handler</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-handler-proxy</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-http2</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-buffer</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-common</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport-native-epoll</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport-native-unix-common</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-tcnative-boringssl-static</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec-dns</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport-native-kqueue</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-resolver</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-resolver-dns</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-resolver-dns-native-macos</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-codec</artifactId>
-          </exclusion>
-        </exclusions>
       </dependency>
       <!-- Azure Blob Storage end -->
       <!-- Google Cloud Storage start -->
@@ -2067,12 +1861,17 @@
       <dependency>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-util</artifactId>
-        <version>9.4.56.v20240826</version>
+        <version>9.4.57.v20241219</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-util-ajax</artifactId>
-        <version>9.4.56.v20240826</version>
+        <version>9.4.57.v20241219</version>
+      </dependency>
+      <dependency>
+        <groupId>io.netty</groupId>
+        <artifactId>netty-tcnative-boringssl-static</artifactId>
+        <version>2.0.71.Final</version>
       </dependency>
       <dependency>
         <groupId>io.grpc</groupId>
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/AbstractHashJoinPOperator.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/AbstractHashJoinPOperator.java
index 800c839..920f567 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/AbstractHashJoinPOperator.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/AbstractHashJoinPOperator.java
@@ -143,21 +143,20 @@
                                     Set<LogicalVariable> firstDeliveredVars = unorderedFirstDelivered.getColumnSet();
                                     UnorderedPartitionedProperty unorderedRequired =
                                             (UnorderedPartitionedProperty) requirements;
-                                    Set<LogicalVariable> originalRequiredVars = unorderedRequired.getColumnSet();
                                     Set<LogicalVariable> modifiedRequiredVars = new ListSet<>();
                                     Map<LogicalVariable, EquivalenceClass> eqmap = context.getEquivalenceClassMap(op);
                                     Set<LogicalVariable> coveredVars = new ListSet<>();
-                                    List<LogicalVariable> keysFirst =
-                                            (keysRightBranch.containsAll(originalRequiredVars)) ? keysRightBranch
-                                                    : keysLeftBranch;
+                                    List<LogicalVariable> keysFirst = (keysRightBranch.containsAll(firstDeliveredVars))
+                                            ? keysRightBranch : keysLeftBranch;
                                     List<LogicalVariable> keysSecond =
                                             keysFirst == keysRightBranch ? keysLeftBranch : keysRightBranch;
-                                    for (LogicalVariable r : originalRequiredVars) {
-                                        EquivalenceClass ecSnd = eqmap.get(r);
+                                    for (LogicalVariable r : firstDeliveredVars) {
+                                        EquivalenceClass ecFirst = eqmap.get(r);
                                         boolean found = false;
                                         int j = 0;
                                         for (LogicalVariable rvar : keysFirst) {
-                                            if (rvar == r || ecSnd != null && eqmap.get(rvar) == ecSnd) {
+                                            if (!modifiedRequiredVars.contains(keysSecond.get(j))
+                                                    && (rvar == r || (ecFirst != null && ecFirst == eqmap.get(rvar)))) {
                                                 found = true;
                                                 break;
                                             }
@@ -168,16 +167,8 @@
                                                     + " among " + keysFirst);
                                         }
                                         LogicalVariable v2 = keysSecond.get(j);
-                                        EquivalenceClass ecFst = eqmap.get(v2);
-                                        for (LogicalVariable vset1 : firstDeliveredVars) {
-                                            if (vset1 == v2 || ecFst != null && eqmap.get(vset1) == ecFst) {
-                                                if (!coveredVars.add(vset1)) {
-                                                    continue;
-                                                }
-                                                modifiedRequiredVars.add(r);
-                                                break;
-                                            }
-                                        }
+                                        coveredVars.add(r);
+                                        modifiedRequiredVars.add(v2);
                                         if (coveredVars.equals(firstDeliveredVars)) {
                                             break;
                                         }
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/InvokeUtil.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/InvokeUtil.java
index 9326427..2a77bab 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/InvokeUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/InvokeUtil.java
@@ -56,7 +56,12 @@
     /**
      * Executes the passed interruptible, retrying if the operation is interrupted. Once the interruptible
      * completes, the current thread will be re-interrupted, if the original operation was interrupted.
+     *
+     * @deprecated this method does not throw an exception when the action is interrupted, or when the thread
+     *             was interrupted prior to calling this method. This can lead to confusing behavior, if the caller
+     *             does not check for interrupted thread state after calling this method.
      */
+    @Deprecated
     public static void doUninterruptibly(InterruptibleAction interruptible) {
         boolean interrupted = Thread.interrupted();
         try {
@@ -219,7 +224,6 @@
     public static void tryWithCleanupsAsHyracks(ThrowingAction action, ThrowingAction... cleanups)
             throws HyracksDataException {
         Throwable savedT = null;
-        boolean suppressedInterrupted = false;
         try {
             action.run();
         } catch (Throwable t) {
@@ -229,21 +233,16 @@
                 try {
                     cleanup.run();
                 } catch (Throwable t) {
-                    if (savedT != null) {
-                        savedT.addSuppressed(t);
-                        suppressedInterrupted |= t instanceof InterruptedException;
-                    } else {
-                        savedT = t;
-                    }
+                    savedT = ExceptionUtils.suppress(savedT, t);
                 }
             }
         }
+        if (Thread.interrupted()) {
+            savedT = ExceptionUtils.suppress(savedT, new InterruptedException());
+        }
         if (savedT == null) {
             return;
         }
-        if (suppressedInterrupted) {
-            Thread.currentThread().interrupt();
-        }
         throw HyracksDataException.create(savedT);
     }
 
@@ -251,7 +250,6 @@
     // catching Throwable, instanceofs, false-positive unreachable code
     public static void tryWithCleanups(ThrowingAction action, ThrowingAction... cleanups) throws Exception {
         Throwable savedT = null;
-        boolean suppressedInterrupted = false;
         try {
             action.run();
         } catch (Throwable t) {
@@ -261,21 +259,16 @@
                 try {
                     cleanup.run();
                 } catch (Throwable t) {
-                    if (savedT != null) {
-                        savedT.addSuppressed(t);
-                        suppressedInterrupted = suppressedInterrupted || t instanceof InterruptedException;
-                    } else {
-                        savedT = t;
-                    }
+                    savedT = ExceptionUtils.suppress(savedT, t);
                 }
             }
         }
+        if (Thread.interrupted()) {
+            savedT = ExceptionUtils.suppress(savedT, new InterruptedException());
+        }
         if (savedT == null) {
             return;
         }
-        if (suppressedInterrupted) {
-            Thread.currentThread().interrupt();
-        }
         if (savedT instanceof Error) {
             throw (Error) savedT;
         } else if (savedT instanceof Exception) {
@@ -285,6 +278,20 @@
         }
     }
 
+    /**
+     * Runs the supplied action, and any specified cleanups. Any pending interruption will be cleared prior
+     * to running the action and all cleanups. An error will be logged if the action and/or any of the cleanups
+     * are themselves interrupted. Finally, if any action or cleanup was interrupted, or if the there was an
+     * interrupt cleared as part of running any of these activities, either an InterruptedException will be returned
+     * if the action & cleanups all ran without exception, or an InterruptedException will be suppressed into the
+     * exception if the action or any of the cleanups threw an exception. In the case where InterruptedException is
+     * suppressed, the current thread will be interrupted.
+     *
+     * @param action the action to run
+     * @param cleanups the cleanups to run after the action
+     * @return Exception if the action throws an exception or the action or any of the cleanups are interrupted, or if
+     * the current thread was interrupted before running the action or any of the cleanups.
+     */
     @SuppressWarnings({ "squid:S1181", "squid:S1193", "ConstantConditions", "UnreachableCode" })
     // catching Throwable, instanceofs, false-positive unreachable code
     public static Exception tryUninterruptibleWithCleanups(Exception root, ThrowingAction action,
@@ -297,12 +304,24 @@
         return root;
     }
 
+    /**
+     * Runs the supplied action, and any specified cleanups. Any pending interruption will be cleared prior
+     * to running the action and all cleanups. An error will be logged if the action and/or any of the cleanups
+     * are themselves interrupted. Finally, if any action or cleanup was interrupted, or if the there was an
+     * interrupt cleared as part of running any of these activities, either an InterruptedException will be thrown
+     * if the action & cleanups all ran without exception, or an InterruptedException will be suppressed into the
+     * exception if the action or any of the cleanups threw an exception. In the case where InterruptedException is
+     * suppressed, the current thread will be interrupted.
+     *
+     * @param action the action to run
+     * @param cleanups the cleanups to run after the action
+     * @throws Exception if the action throws an exception or the action or any of the cleanups are interrupted.
+     */
     @SuppressWarnings({ "squid:S1181", "squid:S1193", "ConstantConditions", "UnreachableCode" })
     // catching Throwable, instanceofs, false-positive unreachable code
     public static void tryUninterruptibleWithCleanups(ThrowingAction action, ThrowingAction... cleanups)
             throws Exception {
         Throwable savedT = null;
-        boolean suppressedInterrupted = false;
         try {
             runUninterruptible(action);
         } catch (Throwable t) {
@@ -312,21 +331,16 @@
                 try {
                     runUninterruptible(cleanup);
                 } catch (Throwable t) {
-                    if (savedT != null) {
-                        savedT.addSuppressed(t);
-                        suppressedInterrupted = suppressedInterrupted || t instanceof InterruptedException;
-                    } else {
-                        savedT = t;
-                    }
+                    savedT = ExceptionUtils.suppress(savedT, t);
                 }
             }
         }
+        if (Thread.interrupted()) {
+            savedT = ExceptionUtils.suppress(savedT, new InterruptedException());
+        }
         if (savedT == null) {
             return;
         }
-        if (suppressedInterrupted) {
-            Thread.currentThread().interrupt();
-        }
         if (savedT instanceof Error) {
             throw (Error) savedT;
         } else if (savedT instanceof Exception) {
@@ -494,16 +508,12 @@
         boolean interrupted = Thread.interrupted();
         try {
             action.run();
-            if (Thread.interrupted()) {
+            if (interrupted || Thread.interrupted()) {
                 throw new InterruptedException();
             }
         } catch (InterruptedException e) {
             LOGGER.error("uninterruptible action {} was interrupted!", action, e);
-            interrupted = true;
-        } finally {
-            if (interrupted) {
-                Thread.currentThread().interrupt();
-            }
+            throw e;
         }
     }
 
diff --git a/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/buffercache/context/DefaultCloudReadContext.java b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/buffercache/context/DefaultCloudReadContext.java
index dab23d9..fc66958 100644
--- a/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/buffercache/context/DefaultCloudReadContext.java
+++ b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/buffercache/context/DefaultCloudReadContext.java
@@ -30,6 +30,7 @@
 import org.apache.hyracks.storage.common.buffercache.BufferCache;
 import org.apache.hyracks.storage.common.buffercache.BufferCacheHeaderHelper;
 import org.apache.hyracks.storage.common.buffercache.CachedPage;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
 import org.apache.hyracks.storage.common.buffercache.ICachedPage;
 import org.apache.hyracks.storage.common.buffercache.context.IBufferCacheReadContext;
 import org.apache.hyracks.storage.common.disk.IPhysicalDrive;
@@ -39,7 +40,7 @@
 
 /**
  * Default context for {@link BufferCache#pin(long, IBufferCacheReadContext)}
- * and {@link BufferCache#unpin(ICachedPage, IBufferCacheReadContext)} in a cloud deployment.
+ * and {@link IBufferCache#unpin(ICachedPage, IBufferCacheReadContext)} in a cloud deployment.
  * <p>
  * The default behavior of this context is persisting the pages read from cloud if {@link IPhysicalDrive}
  * reports that the local drive(s) are not pressured.
diff --git a/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/io/request/ICloudBeforeRetryRequest.java b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/io/request/ICloudBeforeRetryRequest.java
index 4dab80d..3ace317 100644
--- a/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/io/request/ICloudBeforeRetryRequest.java
+++ b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/io/request/ICloudBeforeRetryRequest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.hyracks.cloud.io.request;
 
+import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.cloud.util.CloudRetryableRequestUtil;
 
 /**
@@ -30,5 +31,5 @@
     /**
      * Run pre-retry routine before reattempting {@link ICloudRequest} or {@link ICloudReturnableRequest}
      */
-    void beforeRetry();
+    void beforeRetry() throws HyracksDataException;
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/io/request/ICloudRetryPredicate.java b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/io/request/ICloudRetryPredicate.java
new file mode 100644
index 0000000..bcaae11
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/io/request/ICloudRetryPredicate.java
@@ -0,0 +1,29 @@
+/*
+ * 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.hyracks.cloud.io.request;
+
+import java.util.function.Predicate;
+
+/**
+ * An interface for a condition that determines whether a cloud operation should stop or not.
+ * If met, the encountered exception is re-thrown as root cause in HyracksDataException
+ */
+@FunctionalInterface
+public interface ICloudRetryPredicate extends Predicate<Exception> {
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/util/CloudRetryableRequestUtil.java b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/util/CloudRetryableRequestUtil.java
index da9c8fb..e011900 100644
--- a/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/util/CloudRetryableRequestUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-cloud/src/main/java/org/apache/hyracks/cloud/util/CloudRetryableRequestUtil.java
@@ -26,6 +26,7 @@
 import org.apache.hyracks.api.util.ExceptionUtils;
 import org.apache.hyracks.cloud.io.request.ICloudBeforeRetryRequest;
 import org.apache.hyracks.cloud.io.request.ICloudRequest;
+import org.apache.hyracks.cloud.io.request.ICloudRetryPredicate;
 import org.apache.hyracks.cloud.io.request.ICloudReturnableRequest;
 import org.apache.hyracks.util.ExponentialRetryPolicy;
 import org.apache.hyracks.util.IRetryPolicy;
@@ -55,7 +56,8 @@
     private static final int NUMBER_OF_RETRIES = getNumberOfRetries();
     private static final long MAX_DELAY_BETWEEN_RETRIES = getMaxDelayBetweenRetries();
 
-    private static final ICloudBeforeRetryRequest NO_OP_RETRY = () -> {
+    private static final ICloudRetryPredicate RETRY_ALWAYS_PREDICATE = e -> true;
+    private static final ICloudBeforeRetryRequest NO_OP_BEFORE_RETRY = () -> {
     };
 
     private CloudRetryableRequestUtil() {
@@ -67,7 +69,7 @@
      * @param request request to run
      */
     public static void run(ICloudRequest request) throws HyracksDataException {
-        run(request, NO_OP_RETRY);
+        run(request, NO_OP_BEFORE_RETRY);
     }
 
     /**
@@ -89,7 +91,7 @@
      * @return a value of return type
      */
     public static <T> T run(ICloudReturnableRequest<T> request) throws HyracksDataException {
-        return run(request, NO_OP_RETRY);
+        return run(request, NO_OP_BEFORE_RETRY);
     }
 
     /**
@@ -107,7 +109,7 @@
         try {
             while (true) {
                 try {
-                    return doRun(request, retry);
+                    return doRun(request, retry, RETRY_ALWAYS_PREDICATE);
                 } catch (Throwable e) {
                     // First, clear the interrupted flag
                     interrupted |= Thread.interrupted();
@@ -135,7 +137,7 @@
      * @param request request to run
      */
     public static void runWithNoRetryOnInterruption(ICloudRequest request) throws HyracksDataException {
-        doRun(request, NO_OP_RETRY);
+        runWithNoRetryOnInterruption(request, RETRY_ALWAYS_PREDICATE);
     }
 
     /**
@@ -151,14 +153,41 @@
         doRun(request, retry);
     }
 
-    private static <T> T doRun(ICloudReturnableRequest<T> request, ICloudBeforeRetryRequest retry)
+    public static void runWithNoRetryOnInterruption(ICloudRequest request, ICloudRetryPredicate shouldRetry)
             throws HyracksDataException {
+        doRun(request, NO_OP_BEFORE_RETRY, shouldRetry);
+    }
+
+    public static <T> T runWithNoRetryOnInterruption(ICloudReturnableRequest<T> request) throws HyracksDataException {
+        return runWithNoRetryOnInterruption(request, NO_OP_BEFORE_RETRY, RETRY_ALWAYS_PREDICATE);
+    }
+
+    public static <T> T runWithNoRetryOnInterruption(ICloudReturnableRequest<T> request, ICloudBeforeRetryRequest retry)
+            throws HyracksDataException {
+        return runWithNoRetryOnInterruption(request, retry, RETRY_ALWAYS_PREDICATE);
+    }
+
+    public static <T> T runWithNoRetryOnInterruption(ICloudReturnableRequest<T> request,
+            ICloudRetryPredicate shouldRetry) throws HyracksDataException {
+        return runWithNoRetryOnInterruption(request, NO_OP_BEFORE_RETRY, shouldRetry);
+    }
+
+    public static <T> T runWithNoRetryOnInterruption(ICloudReturnableRequest<T> request, ICloudBeforeRetryRequest retry,
+            ICloudRetryPredicate shouldRetry) throws HyracksDataException {
+        return doRun(request, retry, shouldRetry);
+    }
+
+    private static <T> T doRun(ICloudReturnableRequest<T> request, ICloudBeforeRetryRequest retry,
+            ICloudRetryPredicate shouldRetry) throws HyracksDataException {
         int attempt = 1;
         IRetryPolicy retryPolicy = null;
         while (true) {
             try {
                 return request.call();
             } catch (IOException | BaseServiceException | SdkException e) {
+                if (!shouldRetry.test(e)) {
+                    throw HyracksDataException.create(e);
+                }
                 if (retryPolicy == null) {
                     retryPolicy = new ExponentialRetryPolicy(NUMBER_OF_RETRIES, MAX_DELAY_BETWEEN_RETRIES);
                 }
@@ -182,7 +211,12 @@
     }
 
     private static void doRun(ICloudRequest request, ICloudBeforeRetryRequest retry) throws HyracksDataException {
-        doRun(asReturnableRequest(request), retry);
+        doRun(request, retry, RETRY_ALWAYS_PREDICATE);
+    }
+
+    private static void doRun(ICloudRequest request, ICloudBeforeRetryRequest retry, ICloudRetryPredicate shouldRetry)
+            throws HyracksDataException {
+        doRun(asReturnableRequest(request), retry, shouldRetry);
     }
 
     private static int getNumberOfRetries() {
diff --git a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java
index 530dab4..81afdf6 100644
--- a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java
+++ b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java
@@ -474,6 +474,25 @@
         return true;
     }
 
+    /*
+     * Appends {@code numCodePoints} code points from the given source string {@code src} to the {@code builder}.
+     * {@code src} is shorter than {@code numCodePoints}, it repeats from the beginning of {@code src} as needed
+     * until the required number of code points have been appended.
+     */
+    public static void append(UTF8StringPointable src, int numCodePoints, UTF8StringBuilder builder, GrowableArray out)
+            throws IOException {
+        int utfLen = src.getUTF8Length();
+        int byteIdx = 0;
+        while (numCodePoints > 0) {
+            if (byteIdx == utfLen) {
+                byteIdx = 0;
+            }
+            builder.appendCodePoint(src.codePointAt(src.getMetaDataLength() + byteIdx));
+            numCodePoints--;
+            byteIdx += src.codePointSize(src.getMetaDataLength() + byteIdx);
+        }
+    }
+
     public void substrBefore(UTF8StringPointable match, UTF8StringBuilder builder, GrowableArray out)
             throws IOException {
         substrBefore(this, match, builder, out);
diff --git a/hyracks-fullstack/hyracks/hyracks-hdfs/pom.xml b/hyracks-fullstack/hyracks/hyracks-hdfs/pom.xml
index 1291564..0b22744 100644
--- a/hyracks-fullstack/hyracks/hyracks-hdfs/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-hdfs/pom.xml
@@ -160,8 +160,8 @@
       <scope>test</scope>
       <exclusions>
         <exclusion>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-all</artifactId>
+          <groupId>log4j</groupId>
+          <artifactId>log4j</artifactId>
         </exclusion>
         <exclusion>
           <groupId>org.slf4j</groupId>
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeCountingSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeCountingSearchCursor.java
index a010fde..e956622 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeCountingSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeCountingSearchCursor.java
@@ -108,13 +108,14 @@
         stopTupleIndex = getHighKeyIndex();
     }
 
-    private void releasePage() throws HyracksDataException {
+    private void releasePage() {
         if (exclusiveLatchNodes) {
             page.releaseWriteLatch(isPageDirty);
         } else {
             page.releaseReadLatch();
         }
         bufferCache.unpin(page);
+        page = null;
     }
 
     private void fetchNextLeafPage(int nextLeafPage) throws HyracksDataException {
@@ -218,7 +219,6 @@
         }
         tupleBuilder.reset();
         tupleIndex = 0;
-        page = null;
         isPageDirty = false;
         pred = null;
         count = -1;
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeRangeSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeRangeSearchCursor.java
index 034a714..50ecb53 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeRangeSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/BTreeRangeSearchCursor.java
@@ -46,7 +46,6 @@
     protected final IBTreeLeafFrame frame;
     protected final ITreeIndexTupleReference frameTuple;
     protected final boolean exclusiveLatchNodes;
-    protected boolean isPageDirty;
 
     protected IBufferCache bufferCache = null;
     protected int fileId = -1;
@@ -118,7 +117,6 @@
                 releasePage();
             }
             page = nextLeaf;
-            isPageDirty = false;
             frame.setPage(page);
             pageId = nextLeafPage;
             nextLeafPage = frame.getNextLeaf();
@@ -159,8 +157,6 @@
                 reconciliationTuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
 
                 releasePage();
-                page = null;
-                isPageDirty = false;
 
                 // reconcile
                 searchCb.reconcile(reconciliationTuple);
@@ -236,7 +232,6 @@
         originalKeyCmp = initialState.getOriginalKeyComparator();
         pageId = ((BTreeCursorInitialState) initialState).getPageId();
         page = initialState.getPage();
-        isPageDirty = false;
         frame.setPage(page);
 
         pred = (RangePredicate) searchPred;
@@ -267,7 +262,7 @@
         stopTupleIndex = getHighKeyIndex();
     }
 
-    protected void resetBeforeOpen() throws HyracksDataException {
+    protected void resetBeforeOpen() {
         releasePage();
     }
 
@@ -278,8 +273,6 @@
         }
 
         tupleIndex = 0;
-        page = null;
-        isPageDirty = false;
         pred = null;
     }
 
@@ -298,13 +291,17 @@
         return exclusiveLatchNodes;
     }
 
-    protected void releasePage() throws HyracksDataException {
+    /**
+     * Releases the page and unpins it from the buffer cache, clearing the reference to the page.
+     */
+    protected void releasePage() {
         if (exclusiveLatchNodes) {
-            page.releaseWriteLatch(isPageDirty);
+            page.releaseWriteLatch(false);
         } else {
             page.releaseReadLatch();
         }
         bufferCache.unpin(page);
+        page = null;
     }
 
     protected ICachedPage acquirePage(int pageId) throws HyracksDataException {
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTree.java b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTree.java
index 87b0032..fcfaa40 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTree.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTree.java
@@ -220,7 +220,7 @@
         }
 
         @Override
-        protected void releasePage() throws HyracksDataException {
+        protected void releasePage() {
             if (page != null) {
                 bufferCache.unpin(page);
                 page = null;
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreePointSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreePointSearchCursor.java
index 8fd9a96..beadcf1 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreePointSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreePointSearchCursor.java
@@ -76,7 +76,6 @@
         originalKeyCmp = initialState.getOriginalKeyComparator();
         pageId = ((BTreeCursorInitialState) initialState).getPageId();
         page = initialState.getPage();
-        isPageDirty = false;
         frame.setPage(page);
         setCursorToNextKey(searchPred);
     }
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreeRangeSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreeRangeSearchCursor.java
index 3dc4df7..683bbf8 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreeRangeSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/main/java/org/apache/hyracks/storage/am/btree/impls/DiskBTreeRangeSearchCursor.java
@@ -66,8 +66,9 @@
     }
 
     @Override
-    protected void releasePage() throws HyracksDataException {
+    protected void releasePage() {
         bufferCache.unpin(page);
+        page = null;
     }
 
     @Override
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/TreeIndexDiskOrderScanCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/TreeIndexDiskOrderScanCursor.java
index 14decb4..f637ac7 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/TreeIndexDiskOrderScanCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/impls/TreeIndexDiskOrderScanCursor.java
@@ -142,7 +142,10 @@
         return false;
     }
 
-    protected void releasePage() throws HyracksDataException {
+    /**
+     * Releases the current page, if it is not null, clearing the reference to it.
+     */
+    protected void releasePage() {
         if (page != null) {
             page.releaseReadLatch();
             bufferCache.unpin(page);
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/impls/lsm/tuples/ColumnMultiBufferProvider.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/impls/lsm/tuples/ColumnMultiBufferProvider.java
index 2a2926f..22ef4f1 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/impls/lsm/tuples/ColumnMultiBufferProvider.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/impls/lsm/tuples/ColumnMultiBufferProvider.java
@@ -94,8 +94,8 @@
 
     @Override
     public void releaseAll() throws HyracksDataException {
-        while (!pages.isEmpty()) {
-            ICachedPage page = pages.poll();
+        ICachedPage page;
+        while ((page = pages.poll()) != null) {
             multiPageOp.unpin(page);
         }
     }
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/MultitenantVirtualBufferCache.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/MultitenantVirtualBufferCache.java
index f42d0d3..7f4fd38 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/MultitenantVirtualBufferCache.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/MultitenantVirtualBufferCache.java
@@ -79,12 +79,12 @@
     }
 
     @Override
-    public void unpin(ICachedPage page) throws HyracksDataException {
+    public void unpin(ICachedPage page) {
         unpin(page, DEFAULT);
     }
 
     @Override
-    public void unpin(ICachedPage page, IBufferCacheReadContext context) throws HyracksDataException {
+    public void unpin(ICachedPage page, IBufferCacheReadContext context) {
         vbc.unpin(page, context);
     }
 
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
index 564a9b7..66c596d 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
@@ -327,11 +327,11 @@
     }
 
     @Override
-    public void unpin(ICachedPage page) throws HyracksDataException {
+    public void unpin(ICachedPage page) {
     }
 
     @Override
-    public void unpin(ICachedPage page, IBufferCacheReadContext context) throws HyracksDataException {
+    public void unpin(ICachedPage page, IBufferCacheReadContext context) {
     }
 
     @Override
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/AbstractOnDiskInvertedListCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/AbstractOnDiskInvertedListCursor.java
index c5ad6eb..460ac20 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/AbstractOnDiskInvertedListCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/AbstractOnDiskInvertedListCursor.java
@@ -220,6 +220,7 @@
 
             currentBufferIdx++;
             bufferCache.unpin(page);
+            page = null;
             bufferEndPageId = i;
 
             // Buffer full?
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/ondisk/fixedsize/FixedSizeElementInvertedListScanCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/ondisk/fixedsize/FixedSizeElementInvertedListScanCursor.java
index f237865..f570bd8 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/ondisk/fixedsize/FixedSizeElementInvertedListScanCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/ondisk/fixedsize/FixedSizeElementInvertedListScanCursor.java
@@ -127,7 +127,7 @@
     }
 
     @Override
-    public void unloadPages() throws HyracksDataException {
+    public void unloadPages() {
         if (pinned) {
             bufferCache.unpin(page);
             pinned = false;
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
index a4ecb6f..a77ccdf 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
@@ -601,14 +601,14 @@
     }
 
     @Override
-    public void unpin(ICachedPage page) throws HyracksDataException {
+    public void unpin(ICachedPage page) {
         unpin(page, defaultContext);
     }
 
     @Override
-    public void unpin(ICachedPage page, IBufferCacheReadContext context) throws HyracksDataException {
+    public void unpin(ICachedPage page, IBufferCacheReadContext context) {
         if (closed) {
-            throw new HyracksDataException("unpin called on a closed cache");
+            throw new IllegalStateException("unpin called on a closed cache");
         }
 
         context.onUnpin(page);
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/DebugBufferCache.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/DebugBufferCache.java
index 342d003..f1298b7 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/DebugBufferCache.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/DebugBufferCache.java
@@ -93,12 +93,12 @@
     }
 
     @Override
-    public void unpin(ICachedPage page) throws HyracksDataException {
+    public void unpin(ICachedPage page) {
         unpin(page, DEFAULT);
     }
 
     @Override
-    public void unpin(ICachedPage page, IBufferCacheReadContext context) throws HyracksDataException {
+    public void unpin(ICachedPage page, IBufferCacheReadContext context) {
         bufferCache.unpin(page, context);
         unpinCount.addAndGet(1);
     }
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCache.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCache.java
index d69ded1..81d6d56 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCache.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCache.java
@@ -105,7 +105,7 @@
      *
      * @param page the page
      */
-    void unpin(ICachedPage page) throws HyracksDataException;
+    void unpin(ICachedPage page);
 
     /**
      * Unpin a page to indicate can be evicted
@@ -114,7 +114,7 @@
      * @param page    the page
      * @param context read context
      */
-    void unpin(ICachedPage page, IBufferCacheReadContext context) throws HyracksDataException;
+    void unpin(ICachedPage page, IBufferCacheReadContext context);
 
     /**
      * Flush the page if it is dirty
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/StorageFileAccessTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/StorageFileAccessTest.java
index bdcb206..756a29f 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/StorageFileAccessTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/StorageFileAccessTest.java
@@ -143,31 +143,27 @@
 
         private void unpinRandomPage() {
             int index = Math.abs(rnd.nextInt() % pinnedPages.size());
-            try {
-                PinnedLatchedPage plPage = pinnedPages.get(index);
+            PinnedLatchedPage plPage = pinnedPages.get(index);
 
-                if (plPage.latch != null) {
-                    if (plPage.latch == LatchType.LATCH_S) {
-                        if (LOGGER.isInfoEnabled()) {
-                            LOGGER.info(workerId + " S UNLATCHING: " + plPage.pageId);
-                        }
-                        plPage.page.releaseReadLatch();
-                    } else {
-                        if (LOGGER.isInfoEnabled()) {
-                            LOGGER.info(workerId + " X UNLATCHING: " + plPage.pageId);
-                        }
-                        plPage.page.releaseWriteLatch(true);
+            if (plPage.latch != null) {
+                if (plPage.latch == LatchType.LATCH_S) {
+                    if (LOGGER.isInfoEnabled()) {
+                        LOGGER.info(workerId + " S UNLATCHING: " + plPage.pageId);
                     }
+                    plPage.page.releaseReadLatch();
+                } else {
+                    if (LOGGER.isInfoEnabled()) {
+                        LOGGER.info(workerId + " X UNLATCHING: " + plPage.pageId);
+                    }
+                    plPage.page.releaseWriteLatch(true);
                 }
-                if (LOGGER.isInfoEnabled()) {
-                    LOGGER.info(workerId + " UNPINNING PAGE: " + plPage.pageId);
-                }
-
-                bufferCache.unpin(plPage.page);
-                pinnedPages.remove(index);
-            } catch (HyracksDataException e) {
-                e.printStackTrace();
             }
+            if (LOGGER.isInfoEnabled()) {
+                LOGGER.info(workerId + " UNPINNING PAGE: " + plPage.pageId);
+            }
+
+            bufferCache.unpin(plPage.page);
+            pinnedPages.remove(index);
         }
 
         private void openFile() {
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/impl/TestVirtualBufferCache.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/impl/TestVirtualBufferCache.java
index 637e553..d4ea5a0 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/impl/TestVirtualBufferCache.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/impl/TestVirtualBufferCache.java
@@ -111,12 +111,12 @@
     }
 
     @Override
-    public void unpin(ICachedPage page) throws HyracksDataException {
+    public void unpin(ICachedPage page) {
         unpin(page, DEFAULT);
     }
 
     @Override
-    public void unpin(ICachedPage page, IBufferCacheReadContext context) throws HyracksDataException {
+    public void unpin(ICachedPage page, IBufferCacheReadContext context) {
         vbc.unpin(page, context);
     }
 
diff --git a/hyracks-fullstack/pom.xml b/hyracks-fullstack/pom.xml
index 6793d24..aa1f8a2 100644
--- a/hyracks-fullstack/pom.xml
+++ b/hyracks-fullstack/pom.xml
@@ -75,7 +75,7 @@
     <snappy.version>1.1.10.5</snappy.version>
     <jackson.version>2.14.3</jackson.version>
     <jackson-databind.version>${jackson.version}</jackson-databind.version>
-    <netty.version>4.1.118.Final</netty.version>
+    <netty.version>4.1.121.Final</netty.version>
     <asm.version>9.3</asm.version>
     <awsjavasdk.version>2.29.27</awsjavasdk.version>
     <gcsjavasdk.version>2.45.0</gcsjavasdk.version>
@@ -89,6 +89,73 @@
     <dependencies>
       <dependency>
         <groupId>io.netty</groupId>
+        <artifactId>netty-all</artifactId>
+        <version>${netty.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-classes-epoll</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-epoll</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-kqueue</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-classes-kqueue</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-resolver-dns-classes-macos</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-resolver-dns-native-macos</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-rxtx</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-sctp</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-udt</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-memcache</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-mqtt</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-redis</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-smtp</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-socks</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-stomp</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>io.netty</groupId>
         <artifactId>netty-buffer</artifactId>
         <version>${netty.version}</version>
       </dependency>
@@ -126,6 +193,12 @@
         <groupId>io.netty</groupId>
         <artifactId>netty-handler</artifactId>
         <version>${netty.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-unix-common</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>io.netty</groupId>
@@ -149,6 +222,23 @@
       </dependency>
       <dependency>
         <groupId>io.netty</groupId>
+        <artifactId>netty-transport-native-epoll</artifactId>
+        <classifier>linux-x86_64</classifier>
+        <version>${netty.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>io.netty</groupId>
+        <artifactId>netty-transport-native-kqueue</artifactId>
+        <classifier>osx-x86_64</classifier>
+        <version>${netty.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>io.netty</groupId>
+        <artifactId>netty-transport-native-kqueue</artifactId>
+        <version>${netty.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>io.netty</groupId>
         <artifactId>netty-resolver-dns</artifactId>
         <version>${netty.version}</version>
       </dependency>
@@ -158,17 +248,6 @@
         <version>${netty.version}</version>
       </dependency>
       <dependency>
-        <groupId>io.netty</groupId>
-        <artifactId>netty-transport-native-unix-common</artifactId>
-        <version>${netty.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>io.netty</groupId>
-        <artifactId>netty-all</artifactId>
-        <version>${netty.version}</version>
-        <scope>test</scope>
-      </dependency>
-      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.13.2</version>
@@ -224,10 +303,6 @@
         <version>${hadoop.version}</version>
         <exclusions>
           <exclusion>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-all</artifactId>
-          </exclusion>
-          <exclusion>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-reload4j</artifactId>
           </exclusion>