Repository: asterixdb
Updated Branches:
  refs/heads/master 4819ea447 -> 1a288e9f9


Adds a function: object_pairs.

Change-Id: If57d83c88a813f19c3e64f9eec973b691c84d39b
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1288
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <ti...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/1a288e9f
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/1a288e9f
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/1a288e9f

Branch: refs/heads/master
Commit: 1a288e9f9992b23dde3178a7470c1c31a0d6f7be
Parents: 4819ea4
Author: Yingyi Bu <yin...@couchbase.com>
Authored: Fri Oct 14 18:46:25 2016 -0700
Committer: Yingyi Bu <buyin...@gmail.com>
Committed: Fri Oct 14 20:49:53 2016 -0700

----------------------------------------------------------------------
 .../translator/util/FunctionCollection.java     |   4 +
 .../queries_sqlpp/records/RecordsQueries.xml    |  10 ++
 .../object_pairs-2/object_pairs.1.ddl.sqlpp     |  30 ++++
 .../object_pairs-2/object_pairs.2.update.sqlpp  |  23 +++
 .../object_pairs-2/object_pairs.3.query.sqlpp   |  25 ++++
 .../object_pairs/object_pairs.1.query.sqlpp     |  21 +++
 .../records/object_pairs-2/object_pairs-2.1.adm |   3 +
 .../records/object_pairs/object_pairs.1.adm     |   3 +
 .../lang/common/util/CommonFunctionMapUtil.java |   3 +
 .../om/functions/AsterixBuiltinFunctions.java   |   4 +
 .../impl/RecordPairsTypeComputer.java           |  50 +++++++
 .../asterix/om/types/AOrderedListType.java      |   3 +-
 .../records/RecordPairsDescriptor.java          | 147 +++++++++++++++++++
 .../runtime/formats/NonTaggedDataFormat.java    |  35 ++++-
 14 files changed, 356 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
index dd45c86..fc49503 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
@@ -259,6 +259,7 @@ import 
org.apache.asterix.runtime.evaluators.functions.records.GetRecordFieldVal
 import 
org.apache.asterix.runtime.evaluators.functions.records.GetRecordFieldsDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.records.RecordAddFieldsDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.records.RecordMergeDescriptor;
+import 
org.apache.asterix.runtime.evaluators.functions.records.RecordPairsDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.records.RecordRemoveFieldsDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.temporal.AdjustDateTimeForTimeZoneDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.temporal.AdjustTimeForTimeZoneDescriptor;
@@ -681,6 +682,9 @@ public class FunctionCollection {
         // Cast function
         functionsToInjectUnkownHandling.add(CastTypeDescriptor.FACTORY);
 
+        // Record function
+        functionsToInjectUnkownHandling.add(RecordPairsDescriptor.FACTORY);
+
         List<IFunctionDescriptorFactory> generatedFactories = new 
ArrayList<>();
         for (IFunctionDescriptorFactory factory : 
functionsToInjectUnkownHandling) {
             generatedFactories

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/RecordsQueries.xml
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/RecordsQueries.xml
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/RecordsQueries.xml
index 7c2b0a4..10a8702 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/RecordsQueries.xml
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/RecordsQueries.xml
@@ -103,6 +103,16 @@
     </compilation-unit>
   </test-case>
   <test-case FilePath="records">
+    <compilation-unit name="object_pairs">
+      <output-dir compare="Text">object_pairs</output-dir>
+    </compilation-unit>
+  </test-case>
+  <test-case FilePath="records">
+    <compilation-unit name="object_pairs-2">
+      <output-dir compare="Text">object_pairs-2</output-dir>
+    </compilation-unit>
+  </test-case>
+  <test-case FilePath="records">
     <compilation-unit name="open-record-constructor_01">
       <output-dir compare="Text">open-record-constructor_01</output-dir>
     </compilation-unit>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.1.ddl.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.1.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.1.ddl.sqlpp
new file mode 100644
index 0000000..96752bf
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.1.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  dataverse TinySocial if exists;
+create  dataverse TinySocial;
+
+use TinySocial;
+
+create type FacebookUserType as
+ open {
+  id : bigint
+}
+
+create  dataset FacebookUsers(FacebookUserType) primary key id;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.2.update.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.2.update.sqlpp
new file mode 100644
index 0000000..cdb516e
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.2.update.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+use TinySocial;
+
+load  dataset FacebookUsers using localfs 
((`path`=`asterix_nc1://data/tinysocial/fbu.adm`),(`format`=`adm`));

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.3.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.3.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.3.query.sqlpp
new file mode 100644
index 0000000..39edbac
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs-2/object_pairs.3.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 TinySocial;
+
+SELECT kv.name, COUNT(*) values
+FROM FacebookUsers fu, fu.employment emp, OBJECT_PAIRS(emp) kv
+GROUP BY kv.name
+ORDER BY values, kv.name;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs/object_pairs.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs/object_pairs.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs/object_pairs.1.query.sqlpp
new file mode 100644
index 0000000..d7ea115
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/records/object_pairs/object_pairs.1.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 name, `value` FROM
+object_pairs({"a":1, "b": "c", "d":[1, "e"]}) t;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs-2/object_pairs-2.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs-2/object_pairs-2.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs-2/object_pairs-2.1.adm
new file mode 100644
index 0000000..65692e8
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs-2/object_pairs-2.1.adm
@@ -0,0 +1,3 @@
+{ "values": 3, "name": "end-date" }
+{ "values": 10, "name": "organization-name" }
+{ "values": 10, "name": "start-date" }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs/object_pairs.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs/object_pairs.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs/object_pairs.1.adm
new file mode 100644
index 0000000..48c6c50
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/records/object_pairs/object_pairs.1.adm
@@ -0,0 +1,3 @@
+{ "name": "a", "value": 1 }
+{ "name": "b", "value": "c" }
+{ "name": "d", "value": [ 1, "e" ] }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
----------------------------------------------------------------------
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 6e7349e..ea373cb 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
@@ -62,6 +62,9 @@ public class CommonFunctionMapUtil {
         FUNCTION_NAME_MAP.put("isarray", "is-array"); // isarray, internal: 
is-array
         FUNCTION_NAME_MAP.put("isobject", "is-object"); // isobject, internal: 
is-object
         FUNCTION_NAME_MAP.put("isobj", "is-object"); // isobj, internal: 
is-object
+
+        // Record functions.
+        FUNCTION_NAME_MAP.put("object_pairs", "record-pairs"); // 
object_pairs, internal: record-pairs
     }
 
     private CommonFunctionMapUtil() {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
index 873ea9e..29d6e88 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
@@ -88,6 +88,7 @@ import 
org.apache.asterix.om.typecomputer.impl.OrderedListOfAnyTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.PropagateTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.RecordAddFieldsTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.RecordMergeTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.RecordPairsTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.RecordRemoveFieldsTypeComputer;
 import 
org.apache.asterix.om.typecomputer.impl.ScalarVersionOfAggregateResultType;
 import org.apache.asterix.om.typecomputer.impl.StringBooleanTypeComputer;
@@ -188,6 +189,8 @@ public class AsterixBuiltinFunctions {
             "get-record-fields", 1);
     public static final FunctionIdentifier GET_RECORD_FIELD_VALUE = new 
FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "get-record-field-value", 2);
+    public static final FunctionIdentifier RECORD_PAIRS = new 
FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "record-pairs", FunctionIdentifier.VARARGS);
 
     // numeric
     public static final FunctionIdentifier NUMERIC_UNARY_MINUS = new 
FunctionIdentifier(FunctionConstants.ASTERIX_NS,
@@ -1063,6 +1066,7 @@ public class AsterixBuiltinFunctions {
         addPrivateFunction(FIELD_ACCESS_BY_NAME, 
FieldAccessByNameResultType.INSTANCE, true);
         addFunction(GET_RECORD_FIELDS, OrderedListOfAnyTypeComputer.INSTANCE, 
true);
         addFunction(GET_RECORD_FIELD_VALUE, 
FieldAccessNestedResultType.INSTANCE, true);
+        addFunction(RECORD_PAIRS, RecordPairsTypeComputer.INSTANCE, true);
 
         // temporal type accessors
         addFunction(ACCESSOR_TEMPORAL_YEAR, AInt64TypeComputer.INSTANCE, true);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPairsTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPairsTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPairsTypeComputer.java
new file mode 100644
index 0000000..10b115f
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPairsTypeComputer.java
@@ -0,0 +1,50 @@
+/*
+ *  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.om.typecomputer.impl;
+
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+
+public class RecordPairsTypeComputer extends AbstractResultTypeComputer {
+
+    public static final RecordPairsTypeComputer INSTANCE = new 
RecordPairsTypeComputer();
+
+    private RecordPairsTypeComputer() {
+    }
+
+    @Override
+    protected void checkArgType(int argIndex, IAType type) throws 
AlgebricksException {
+        ATypeTag typeTag = type.getTypeTag();
+        if (typeTag != ATypeTag.RECORD) {
+            throw new AlgebricksException("Function " + 
AsterixBuiltinFunctions.RECORD_PAIRS
+                    + " expects a record as the input, " + "but get a " + 
typeTag);
+        }
+    }
+
+    @Override
+    public IAType getResultType(ILogicalExpression expr, IAType... 
strippedInputTypes) throws AlgebricksException {
+        return AOrderedListType.FULL_OPEN_ORDEREDLIST_TYPE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AOrderedListType.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AOrderedListType.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AOrderedListType.java
index a5af127..d523124 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AOrderedListType.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AOrderedListType.java
@@ -18,7 +18,6 @@
  */
 package org.apache.asterix.om.types;
 
-import org.apache.asterix.om.base.AOrderedList;
 import org.apache.asterix.om.base.IAObject;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -27,7 +26,7 @@ public class AOrderedListType extends AbstractCollectionType {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AOrderedListType FULL_OPEN_ORDEREDLIST_TYPE = new 
AOrderedListType(null,"");
+    public static final AOrderedListType FULL_OPEN_ORDEREDLIST_TYPE = new 
AOrderedListType(BuiltinType.ANY, "");
 
     /**
      * @param itemType

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPairsDescriptor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPairsDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPairsDescriptor.java
new file mode 100644
index 0000000..b6aedb4
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPairsDescriptor.java
@@ -0,0 +1,147 @@
+/*
+ * 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.records;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.asterix.builders.OrderedListBuilder;
+import org.apache.asterix.builders.RecordBuilder;
+import 
org.apache.asterix.dataflow.data.nontagged.serde.AObjectSerializerDeserializer;
+import org.apache.asterix.om.base.AString;
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptor;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.pointables.ARecordVisitablePointable;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.EnumDeserializer;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+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.IHyracksTaskContext;
+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;
+
+public class RecordPairsDescriptor extends 
AbstractScalarFunctionDynamicDescriptor {
+
+    public static final IFunctionDescriptorFactory FACTORY = new 
IFunctionDescriptorFactory() {
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new RecordPairsDescriptor();
+        }
+    };
+
+    private static final long serialVersionUID = 1L;
+    private ARecordType recType;
+
+    public void reset(ARecordType recType) {
+        this.recType = recType;
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.RECORD_PAIRS;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext 
ctx) throws AlgebricksException {
+                // For writing each individual output record.
+                final ArrayBackedValueStorage itemStorage = new 
ArrayBackedValueStorage();
+                final DataOutput itemOutput = itemStorage.getDataOutput();
+                final RecordBuilder recBuilder = new RecordBuilder();
+                recBuilder.reset(ARecordType.FULLY_OPEN_RECORD_TYPE);
+
+                // For writing the resulting list of records.
+                final OrderedListBuilder listBuilder = new 
OrderedListBuilder();
+                final ArrayBackedValueStorage resultStorage = new 
ArrayBackedValueStorage();
+                final DataOutput resultOut = resultStorage.getDataOutput();
+
+                // Sets up the constant field names, "name" for the key field, 
"value" for the value field.
+                final ArrayBackedValueStorage nameStorage = new 
ArrayBackedValueStorage();
+                final ArrayBackedValueStorage valueStorage = new 
ArrayBackedValueStorage();
+                AObjectSerializerDeserializer serde = 
AObjectSerializerDeserializer.INSTANCE;
+                try {
+                    serde.serialize(new AString("name"), 
nameStorage.getDataOutput());
+                    serde.serialize(new AString("value"), 
valueStorage.getDataOutput());
+                } catch (IOException e) {
+                    throw new AlgebricksException(e);
+                }
+
+                return new IScalarEvaluator() {
+                    private final IScalarEvaluator argEvaluator = 
args[0].createScalarEvaluator(ctx);
+                    private final IPointable argPtr = new VoidPointable();
+                    private final ARecordVisitablePointable 
recordVisitablePointable = new ARecordVisitablePointable(
+                            recType);
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, 
IPointable result) throws AlgebricksException {
+                        try {
+                            // Resets the result storage.
+                            resultStorage.reset();
+
+                            // Gets the input record.
+                            argEvaluator.evaluate(tuple, argPtr);
+                            byte inputTypeTag = 
argPtr.getByteArray()[argPtr.getStartOffset()];
+                            if (inputTypeTag != 
ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
+                                throw new AlgebricksException("Function " + 
RecordPairsDescriptor.this.getIdentifier()
+                                        + " expects a record as the input, " + 
"but get a "
+                                        + 
EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputTypeTag));
+                            }
+                            recordVisitablePointable.set(argPtr);
+
+                            
listBuilder.reset(AOrderedListType.FULL_OPEN_ORDEREDLIST_TYPE);
+                            List<IVisitablePointable> fieldNames = 
recordVisitablePointable.getFieldNames();
+                            List<IVisitablePointable> fieldValues = 
recordVisitablePointable.getFieldValues();
+                            // Adds each field of the input record as a 
key-value pair into the result.
+                            int numFields = 
recordVisitablePointable.getFieldNames().size();
+                            for (int fieldIndex = 0; fieldIndex < numFields; 
++fieldIndex) {
+                                itemStorage.reset();
+                                recBuilder.init();
+                                recBuilder.addField(nameStorage, 
fieldNames.get(fieldIndex));
+                                recBuilder.addField(valueStorage, 
fieldValues.get(fieldIndex));
+                                recBuilder.write(itemOutput, true);
+                                listBuilder.addItem(itemStorage);
+                            }
+
+                            // Writes the result and sets the result pointable.
+                            listBuilder.write(resultOut, true);
+                            result.set(resultStorage);
+                        } catch (HyracksDataException e) {
+                            throw new AlgebricksException(e);
+                        }
+                    }
+                };
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1a288e9f/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
index 5955e57..c046743 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
@@ -553,6 +553,10 @@ public class NonTaggedDataFormat implements IDataFormat {
                                 listFieldPath);
                         break;
                     }
+                    case ANY:
+                        PA.invokeMethod(fd, 
"reset(org.apache.asterix.om.types.ARecordType, java.util.List)",
+                                ARecordType.FULLY_OPEN_RECORD_TYPE, 
listFieldPath);
+                        break;
                     default: {
                         throw new NotImplementedException("field-access-nested 
for data of type " + t);
                     }
@@ -565,9 +569,13 @@ public class NonTaggedDataFormat implements IDataFormat {
                     throws AlgebricksException {
                 AbstractFunctionCallExpression fce = 
(AbstractFunctionCallExpression) expr;
                 IAType t = (IAType) 
context.getType(fce.getArguments().get(0).getValue());
-                if (t.getTypeTag().equals(ATypeTag.RECORD)) {
+                ATypeTag typeTag = t.getTypeTag();
+                if (typeTag.equals(ATypeTag.RECORD)) {
                     ARecordType recType = (ARecordType) t;
                     PA.invokeMethod(fd, 
"reset(org.apache.asterix.om.types.ARecordType)", recType);
+                } else if (typeTag.equals(ATypeTag.ANY)) {
+                    PA.invokeMethod(fd, 
"reset(org.apache.asterix.om.types.ARecordType)",
+                            ARecordType.FULLY_OPEN_RECORD_TYPE);
                 } else {
                     throw new NotImplementedException("get-record-fields for 
data of type " + t);
                 }
@@ -579,15 +587,36 @@ public class NonTaggedDataFormat implements IDataFormat {
                     throws AlgebricksException {
                 AbstractFunctionCallExpression fce = 
(AbstractFunctionCallExpression) expr;
                 IAType t = (IAType) 
context.getType(fce.getArguments().get(0).getValue());
-                if (t.getTypeTag().equals(ATypeTag.RECORD)) {
+                ATypeTag typeTag = t.getTypeTag();
+                if (typeTag.equals(ATypeTag.RECORD)) {
                     ARecordType recType = (ARecordType) t;
                     PA.invokeMethod(fd, 
"reset(org.apache.asterix.om.types.ARecordType)", recType);
+                } else if (typeTag.equals(ATypeTag.ANY)) {
+                    PA.invokeMethod(fd, 
"reset(org.apache.asterix.om.types.ARecordType)",
+                            ARecordType.FULLY_OPEN_RECORD_TYPE);
                 } else {
                     throw new NotImplementedException("get-record-field-value 
for data of type " + t);
                 }
             }
         });
-
+        functionTypeInferers.put(AsterixBuiltinFunctions.RECORD_PAIRS, new 
FunctionTypeInferer() {
+            @Override
+            public void infer(ILogicalExpression expr, IFunctionDescriptor fd, 
IVariableTypeEnvironment context)
+                    throws AlgebricksException {
+                AbstractFunctionCallExpression fce = 
(AbstractFunctionCallExpression) expr;
+                IAType t = (IAType) 
context.getType(fce.getArguments().get(0).getValue());
+                ATypeTag typeTag = t.getTypeTag();
+                if (typeTag.equals(ATypeTag.RECORD)) {
+                    ARecordType recType = (ARecordType) t;
+                    PA.invokeMethod(fd, 
"reset(org.apache.asterix.om.types.ARecordType)", recType);
+                } else if (typeTag.equals(ATypeTag.ANY)) {
+                    PA.invokeMethod(fd, 
"reset(org.apache.asterix.om.types.ARecordType)",
+                            ARecordType.FULLY_OPEN_RECORD_TYPE);
+                } else {
+                    throw new NotImplementedException("record-fields with data 
of type " + t);
+                }
+            }
+        });
     }
 
     @Override

Reply via email to