Merge commit '95f508bbb1d07650392c21da2958ba1c53f2a03d' from stabilization-f69489

Change-Id: Ib6a428564681938dceb6ad4a2ba91f15256dc8a2
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
index ae13e42..1301c01 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
@@ -125,6 +125,7 @@
         }
         ccApplication.registerConfig(configManager);
         final CCConfig ccConfig = createCCConfig(configManager);
+        configManager.processConfig();
         cc = new ClusterControllerService(ccConfig, ccApplication);
 
         nodeNames = ccConfig.getConfigManager().getNodeNames();
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/coalesce/coalesce.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/coalesce/coalesce.1.query.sqlpp
new file mode 100644
index 0000000..18a73e3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/coalesce/coalesce.1.query.sqlpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+/* coalesce() is equivalent to ifmissingornull() */
+
+{
+   "a": isnull(coalesce()),
+   "b": isnull(coalesce(missing)),
+   "c": isnull(coalesce(null)),
+   "d": isnull(coalesce(null, missing)),
+   "e": coalesce(null, true, 1),
+   "f": coalesce(missing, true, 1),
+   "g": coalesce(null, missing, true, 1),
+   "h": coalesce(null, missing, true, 1),
+   "i": coalesce(
+            missing,
+            null,
+            case when get_year(current_datetime()) > 0 then missing else false end,
+            case when get_year(current_datetime()) > 0 then null else false end,
+            case when get_year(current_datetime()) > 0 then true else missing end
+        )
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/coalesce/coalesce.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/coalesce/coalesce.1.adm
new file mode 100644
index 0000000..633c503
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/coalesce/coalesce.1.adm
@@ -0,0 +1 @@
+{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, "h": true, "i": true }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 04b484e..b5fc053 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -4946,6 +4946,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="null-missing">
+      <compilation-unit name="coalesce">
+        <output-dir compare="Text">coalesce</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="null-missing">
       <compilation-unit name="query-ASTERIXDB-1689">
         <output-dir compare="Text">query-ASTERIXDB-1689</output-dir>
       </compilation-unit>
diff --git a/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md b/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md
index f0e98fd..8c2dce7 100644
--- a/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md
+++ b/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md
@@ -75,7 +75,7 @@
 
  The function has an alias `ifmissing`.
 
-### if_missing_or_null (ifmissingornull) ###
+### if_missing_or_null (ifmissingornull, coalesce) ###
 
  * Syntax:
 
@@ -100,7 +100,7 @@
 
         { "a": null, "b": null, "c": "asterixdb" }
 
- The function has an alias `ifmissingornull`.
+ The function has two aliases: `ifmissingornull` and `coalesce`.
 
 ### if_inf (ifinf) ###
 
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/jackson/ObjectPool.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/jackson/ObjectPool.java
index 5ccd9e9..8945e71 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/jackson/ObjectPool.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/jackson/ObjectPool.java
@@ -59,4 +59,9 @@
             recycledObjects.add(object);
         }
     }
+
+    @Override
+    public String toString() {
+        return recycledObjects.toString();
+    }
 }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
index 372acab..631bb7b 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
@@ -73,6 +73,7 @@
         addFunctionMapping("ifinf", "if-inf"); // ifinf, internal: if-inf
         addFunctionMapping("ifnan", "if-nan"); // ifnan, internal: if-nan
         addFunctionMapping("ifnanorinf", "if-nan-or-inf"); // ifnanorinf, internal: if-nan-or-inf
+        addFunctionMapping("coalesce", "if-missing-or-null"); // coalesce, internal: if-missing-or-null
         addFunctionMapping("missingif", "missing-if"); // missingif, internal: missing-if
         addFunctionMapping("nanif", "nan-if"); // nanif, internal: nan-if
         addFunctionMapping("neginfif", "neginf-if"); // neginfif, internal: neginf-if
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/SerializerDeserializerProvider.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/SerializerDeserializerProvider.java
index 0cba8b6..356b84c 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/SerializerDeserializerProvider.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/SerializerDeserializerProvider.java
@@ -171,7 +171,7 @@
     }
 
     @SuppressWarnings("rawtypes")
-    private ISerializerDeserializer addTag(final ISerializerDeserializer nonTaggedSerde) {
+    public static ISerializerDeserializer addTag(final ISerializerDeserializer nonTaggedSerde) {
         return new ISerializerDeserializer<IAObject>() {
 
             private static final long serialVersionUID = 1L;
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/AbstractVisitablePointable.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/AbstractVisitablePointable.java
index 2ff9357..e9aa99c 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/AbstractVisitablePointable.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/AbstractVisitablePointable.java
@@ -59,4 +59,10 @@
         set(ivf.getByteArray(), ivf.getStartOffset(), ivf.getLength());
     }
 
+    @Override
+    public String toString() {
+        return "{ \"class\" : \"" + getClass().getSimpleName() + "\", \"data\" : "
+                + (data == null ? "null" : ("\"" + System.identityHashCode(data) + ":" + data.length + "\""))
+                + ", \"offset\" : " + start + ", \"length\" : " + len + " }";
+    }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/PointableAllocator.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/PointableAllocator.java
index 91c47fd..411f067 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/PointableAllocator.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/PointableAllocator.java
@@ -58,7 +58,7 @@
                 }
             });
 
-    public IVisitablePointable allocateEmpty() {
+    public AFlatValuePointable allocateEmpty() {
         return flatValueAllocator.allocate(null);
     }
 
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
index 806235c..f1f1be3 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
@@ -168,7 +168,7 @@
         }
         IAType resultType = type;
         if ((category & NULLABLE) != 0 || (category & NULL) != 0) {
-            resultType = AUnionType.createUnknownableType(resultType);
+            resultType = AUnionType.createNullableType(resultType);
         }
         if ((category & MISSABLE) != 0 || (category & MISSING) != 0) {
             resultType = AUnionType.createMissableType(resultType);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/AdmNodeUtils.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/AdmNodeUtils.java
index 6f4ee17..f8ce905 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/AdmNodeUtils.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/AdmNodeUtils.java
@@ -36,6 +36,7 @@
 import org.apache.asterix.om.types.AOrderedListType;
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.om.types.ATypeTag;
+import org.apache.hyracks.data.std.api.IPointable;
 import org.apache.hyracks.data.std.primitive.BooleanPointable;
 import org.apache.hyracks.data.std.primitive.DoublePointable;
 import org.apache.hyracks.data.std.primitive.LongPointable;
@@ -56,6 +57,45 @@
         return map;
     }
 
+    public static IAdmNode getAsAdmNode(IPointable pointable) throws IOException {
+        byte[] bytes = pointable.getByteArray();
+        int offset = pointable.getStartOffset();
+        int len = pointable.getLength();
+        if (len == 0) {
+            throw new IllegalArgumentException();
+        }
+        byte tagByte = bytes[offset];
+        ATypeTag tag = ATypeTag.VALUE_TYPE_MAPPING[tagByte];
+        switch (tag) {
+            case ARRAY:
+                AListPointable listPointable = AListPointable.FACTORY.createPointable();
+                listPointable.set(bytes, offset, len);
+                return getAsAdmNode(listPointable);
+            case BIGINT:
+                return new AdmBigIntNode(LongPointable.getLong(bytes, offset + 1));
+            case BOOLEAN:
+                return AdmBooleanNode.get(BooleanPointable.getBoolean(bytes, offset + 1));
+            case DOUBLE:
+                return new AdmDoubleNode(DoublePointable.getDouble(bytes, offset + 1));
+            case NULL:
+                return AdmNullNode.INSTANCE;
+            case OBJECT:
+                ARecordPointable recPointable = ARecordPointable.FACTORY.createPointable();
+                recPointable.set(bytes, offset, len);
+                try {
+                    return new AdmObjectNode(getOpenFields(recPointable, RecordUtil.FULLY_OPEN_RECORD_TYPE));
+                } catch (IOException e) {
+                    throw new IllegalArgumentException(e);
+                }
+            case STRING:
+                UTF8StringPointable str = UTF8StringPointable.FACTORY.createPointable();
+                str.set(bytes, offset + 1, len - 1);
+                return new AdmStringNode(str.toString());
+            default:
+                throw new UnsupportedOperationException("Unsupported item type: " + tag);
+        }
+    }
+
     private static IAdmNode getOpenField(ARecordPointable recPointable, ARecordType type, int i) throws IOException {
         byte tagByte = recPointable.getOpenFieldTag(type, i);
         ATypeTag tag = ATypeTag.VALUE_TYPE_MAPPING[tagByte];
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/CCDriver.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/CCDriver.java
index c4ad139..8b58046 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/CCDriver.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/CCDriver.java
@@ -53,6 +53,7 @@
             CCLogConfigurationFactory logCfgFactory = new CCLogConfigurationFactory(ccConfig);
             ConfigurationFactory.setConfigurationFactory(logCfgFactory);
             cfg.removeLogger("Console");
+            configManager.processConfig();
             ctx.start(logCfgFactory.getConfiguration(ctx, ConfigurationSource.NULL_SOURCE));
             ClusterControllerService ccService = new ClusterControllerService(ccConfig, application);
             ccService.start();
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
index b5dacfb..b2e4a5e 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
@@ -161,7 +161,6 @@
             throw new IllegalArgumentException("ICCApplication cannot be null");
         }
         this.application = application;
-        configManager.processConfig();
         File jobLogFolder = new File(ccConfig.getRootDir(), "logs/jobs");
         jobLog = new LogFile(jobLogFolder);
 
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java
index fdd271c..b460735 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java
@@ -52,6 +52,7 @@
             Configuration cfg = ctx.getConfiguration();
             NCLogConfigurationFactory logCfgFactory = new NCLogConfigurationFactory(ncConfig);
             ConfigurationFactory.setConfigurationFactory(logCfgFactory);
+            configManager.processConfig();
             cfg.removeLogger("Console");
             ctx.start(logCfgFactory.getConfiguration(ctx, ConfigurationSource.NULL_SOURCE));
             final NodeControllerService ncService = new NodeControllerService(ncConfig, application);
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
index 653d6e01..d7da5a4 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
@@ -193,7 +193,6 @@
         if (application == null) {
             throw new IllegalArgumentException("INCApplication cannot be null");
         }
-        configManager.processConfig();
         this.application = application;
         id = ncConfig.getNodeId();
         if (id == null) {