Ali Alsuliman has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/2756

Change subject: [NO ISSUE][FUN] Implement array functions p2
......................................................................

[NO ISSUE][FUN] Implement array functions p2

- user model changes: no
- storage format changes: no
- interface changes: no

details:
This is part of implementing array functions. This patch
includes array_distinct(), array_sort(). It includes
reorganization of array_reverse()

Change-Id: I5e9c4ff6400b7fe93ca2aab0234750dc78f50659
---
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.1.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.2.update.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.3.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.4.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.5.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.6.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.1.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.2.update.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.3.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.4.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.5.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.6.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_distinct/array_distinct.3.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_sort/array_sort.3.adm
M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
M 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
M 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
A 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessEval.java
A 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayDistinctDescriptor.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReverseDescriptor.java
A 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySortDescriptor.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
23 files changed, 723 insertions(+), 47 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/56/2756/1

diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.1.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.1.ddl.sqlpp
new file mode 100755
index 0000000..257c4dd
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.1.ddl.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.
+ */
+
+drop  dataverse TinySocial if exists;
+create  dataverse TinySocial;
+
+use TinySocial;
+
+
+create type TinySocial.TwitterUserType as
+{
+  `screen-name` : string,
+  lang : string,
+  friends_count : bigint,
+  statuses_count : bigint,
+  name : string,
+  followers_count : bigint
+};
+
+create type TinySocial.TweetMessageType as
+ closed {
+  tweetid : string,
+  user : TwitterUserType,
+  `sender-location` : point?,
+  `send-time` : datetime,
+  `referred-topics` : {{string}},
+  `message-text` : string
+};
+
+create  dataset TweetMessages(TweetMessageType) primary key tweetid hints 
(`CARDINALITY`=`100`);
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.2.update.sqlpp
new file mode 100755
index 0000000..4a0e7ed
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.2.update.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use TinySocial;
+
+load  dataset TweetMessages using localfs 
((`path`=`asterix_nc1://data/tinysocial/twm.adm`),(`format`=`adm`));
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.3.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.3.query.sqlpp
new file mode 100755
index 0000000..ee5070a
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.3.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.
+ */
+
+use TinySocial;
+
+{
+  "t1": (select array_distinct(array_append(t.`referred-topics`, "verizon", 
"platform")) from TweetMessages t order by t.tweetid),
+  "t2": (array_distinct([19, 5, 7, 7, 5, 2])),
+  "t3": (array_distinct([19, 5, 7, 7, 5.1, 5.0, 2, 7])),
+  "t4": (array_distinct([19, 5, "a", 7.5, "A", "a", "John", "a"])),
+  "t5": (array_distinct([19, missing, 7, null, 5, null])),
+  "t6": (array_distinct([3])),
+  "t7": (array_distinct("non_array")),
+  "t8": (array_distinct([])),
+  "t9": (array_distinct(missing)),
+  "t10": (array_distinct(null))
+};
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.4.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.4.ddl.sqlpp
new file mode 100755
index 0000000..a4c7fb0
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.4.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.
+ */
+
+use TinySocial;
+
+select array_distinct([19, 3, [5]]);
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.5.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.5.ddl.sqlpp
new file mode 100755
index 0000000..d3b918c
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.5.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.
+ */
+
+use TinySocial;
+
+select array_distinct([19, 3, {"id": 5}]);
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.6.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.6.ddl.sqlpp
new file mode 100755
index 0000000..3f8c8ec
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_distinct/array_distinct.6.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 TinySocial;
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.1.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.1.ddl.sqlpp
new file mode 100755
index 0000000..257c4dd
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.1.ddl.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.
+ */
+
+drop  dataverse TinySocial if exists;
+create  dataverse TinySocial;
+
+use TinySocial;
+
+
+create type TinySocial.TwitterUserType as
+{
+  `screen-name` : string,
+  lang : string,
+  friends_count : bigint,
+  statuses_count : bigint,
+  name : string,
+  followers_count : bigint
+};
+
+create type TinySocial.TweetMessageType as
+ closed {
+  tweetid : string,
+  user : TwitterUserType,
+  `sender-location` : point?,
+  `send-time` : datetime,
+  `referred-topics` : {{string}},
+  `message-text` : string
+};
+
+create  dataset TweetMessages(TweetMessageType) primary key tweetid hints 
(`CARDINALITY`=`100`);
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.2.update.sqlpp
new file mode 100755
index 0000000..4a0e7ed
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.2.update.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use TinySocial;
+
+load  dataset TweetMessages using localfs 
((`path`=`asterix_nc1://data/tinysocial/twm.adm`),(`format`=`adm`));
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.3.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.3.query.sqlpp
new file mode 100755
index 0000000..3047c11
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.3.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.
+ */
+
+use TinySocial;
+
+{
+  "t1": (select array_sort(t.`referred-topics`) from TweetMessages t order by 
t.tweetid),
+  "t2": (array_sort([19, 5, 7, 7, 5, 2])),
+  "t3": (array_sort([19, 5, 7, 7, 5.1, 5.0, 2])),
+  "t4": (array_sort([19, 5, "a", 7.5, "A", "John", "a"])),
+  "t5": (array_sort([19, missing, 7, null, 5, null])),
+  "t6": (array_sort([3])),
+  "t7": (array_sort("non_array")),
+  "t8": (array_sort([])),
+  "t9": (array_sort(missing)),
+  "t10": (array_sort(null))
+};
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.4.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.4.ddl.sqlpp
new file mode 100755
index 0000000..ecee1bc
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.4.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.
+ */
+
+use TinySocial;
+
+select array_sort([19, 3, [5]]);
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.5.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.5.ddl.sqlpp
new file mode 100755
index 0000000..a1eaae3
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.5.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.
+ */
+
+use TinySocial;
+
+select array_sort([19, 3, {"id": 5}]);
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.6.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.6.ddl.sqlpp
new file mode 100755
index 0000000..3f8c8ec
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_sort/array_sort.6.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 TinySocial;
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_distinct/array_distinct.3.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_distinct/array_distinct.3.adm
new file mode 100644
index 0000000..0482ae3
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_distinct/array_distinct.3.adm
@@ -0,0 +1 @@
+{ "t1": [ { "$1": {{ "t-mobile", "customization", "verizon", "platform" }} }, 
{ "$1": {{ "verizon", "voice-clarity", "platform" }} }, { "$1": {{ "iphone", 
"platform", "verizon" }} }, { "$1": {{ "samsung", "voice-command", "verizon", 
"platform" }} }, { "$1": {{ "verizon", "shortcut-menu", "platform" }} }, { 
"$1": {{ "motorola", "speed", "verizon", "platform" }} }, { "$1": {{ "sprint", 
"voice-command", "verizon", "platform" }} }, { "$1": {{ "motorola", "speed", 
"verizon", "platform" }} }, { "$1": {{ "iphone", "voice-clarity", "verizon", 
"platform" }} }, { "$1": {{ "samsung", "platform", "verizon" }} }, { "$1": {{ 
"t-mobile", "shortcut-menu", "verizon", "platform" }} }, { "$1": {{ "verizon", 
"voicemail-service", "platform" }} } ], "t2": [ 19, 5, 7, 2 ], "t3": [ 19, 5, 
7, 5.1, 2 ], "t4": [ 19, 5, "a", 7.5, "A", "John" ], "t5": [ 19, null, 7, 5 ], 
"t6": [ 3 ], "t7": null, "t8": [  ], "t10": null }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_sort/array_sort.3.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_sort/array_sort.3.adm
new file mode 100644
index 0000000..cc5be40
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_sort/array_sort.3.adm
@@ -0,0 +1 @@
+{ "t1": [ { "$1": {{ "customization", "t-mobile" }} }, { "$1": {{ "verizon", 
"voice-clarity" }} }, { "$1": {{ "iphone", "platform" }} }, { "$1": {{ 
"samsung", "voice-command" }} }, { "$1": {{ "shortcut-menu", "verizon" }} }, { 
"$1": {{ "motorola", "speed" }} }, { "$1": {{ "sprint", "voice-command" }} }, { 
"$1": {{ "motorola", "speed" }} }, { "$1": {{ "iphone", "voice-clarity" }} }, { 
"$1": {{ "platform", "samsung" }} }, { "$1": {{ "shortcut-menu", "t-mobile" }} 
}, { "$1": {{ "verizon", "voicemail-service" }} } ], "t2": [ 2, 5, 5, 7, 7, 19 
], "t3": [ 2, 5.0, 5, 5.1, 7, 7, 19 ], "t4": [ 5, 7.5, 19, "A", "John", "a", 
"a" ], "t5": [ null, null, null, 5, 7, 19 ], "t6": [ 3 ], "t7": null, "t8": [  
], "t10": null }
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 87bf893..53f623e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -1012,6 +1012,20 @@
         <expected-error>HYR0115: Cannot compare non-primitive values (in line 
22, at column 8)</expected-error>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="array_fun">
+      <compilation-unit name="array_distinct">
+        <output-dir compare="Text">array_distinct</output-dir>
+        <expected-error>HYR0115: Cannot compare non-primitive values (in line 
22, at column 8)</expected-error>
+        <expected-error>HYR0115: Cannot compare non-primitive values (in line 
22, at column 8)</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="array_fun">
+      <compilation-unit name="array_sort">
+        <output-dir compare="Text">array_sort</output-dir>
+        <expected-error>HYR0115: Cannot compare non-primitive values (in line 
22, at column 8)</expected-error>
+        <expected-error>HYR0115: Cannot compare non-primitive values (in line 
22, at column 8)</expected-error>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="boolean">
     <test-case FilePath="boolean">
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 da45e29..8e65e3e 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
@@ -194,6 +194,10 @@
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, 
"array-reverse", 1);
     public static final FunctionIdentifier ARRAY_CONTAINS =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, 
"array-contains", 2);
+    public static final FunctionIdentifier ARRAY_DISTINCT =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, 
"array-distinct", 1);
+    public static final FunctionIdentifier ARRAY_SORT =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-sort", 
1);
 
     // objects
     public static final FunctionIdentifier RECORD_MERGE =
@@ -1473,8 +1477,10 @@
         addFunction(ARRAY_APPEND, ArrayAppendTypeComputer.INSTANCE, true);
         addFunction(ARRAY_POSITION, AInt32TypeComputer.INSTANCE, true);
         addFunction(ARRAY_REPEAT, ArrayRepeatTypeComputer.INSTANCE, true);
-        addFunction(ARRAY_REVERSE, AListTypeComputer.INSTANCE, true);
         addFunction(ARRAY_CONTAINS, ABooleanTypeComputer.INSTANCE, true);
+        addFunction(ARRAY_REVERSE, AListTypeComputer.INSTANCE, true);
+        addFunction(ARRAY_SORT, AListTypeComputer.INSTANCE, true);
+        addFunction(ARRAY_DISTINCT, AListTypeComputer.INSTANCE, true);
 
         // objects
         addFunction(RECORD_MERGE, RecordMergeTypeComputer.INSTANCE, true);
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
index 92730f5..7467bd1 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
@@ -20,6 +20,7 @@
 package org.apache.asterix.om.typecomputer.impl;
 
 import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.AUnionType;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -41,7 +42,7 @@
         switch (argType.getTypeTag()) {
             case ARRAY:
             case MULTISET:
-                return argType;
+                return AUnionType.createNullableType(argType);
             default:
                 return BuiltinType.ANY;
         }
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessEval.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessEval.java
new file mode 100755
index 0000000..d8f0002
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessEval.java
@@ -0,0 +1,89 @@
+/*
+ * 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 org.apache.asterix.builders.IAsterixListBuilder;
+import org.apache.asterix.builders.OrderedListBuilder;
+import org.apache.asterix.builders.UnorderedListBuilder;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AbstractCollectionType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.runtime.evaluators.common.ListAccessor;
+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 abstract class AbstractArrayProcessEval implements IScalarEvaluator {
+    private final ArrayBackedValueStorage storage;
+    private final IScalarEvaluator listArgEval;
+    private final ListAccessor listAccessor;
+    private final IPointable listArg;
+    private final IAType inputListType;
+
+    public AbstractArrayProcessEval(IScalarEvaluatorFactory[] args, 
IHyracksTaskContext ctx, IAType inputListType)
+            throws HyracksDataException {
+        storage = new ArrayBackedValueStorage();
+        listArg = new VoidPointable();
+        listArgEval = args[0].createScalarEvaluator(ctx);
+        listAccessor = new ListAccessor();
+        this.inputListType = inputListType;
+    }
+
+    @Override
+    public void evaluate(IFrameTupleReference tuple, IPointable result) throws 
HyracksDataException {
+        // get the list argument and make sure it's a list
+        listArgEval.evaluate(tuple, listArg);
+        byte listArgType = listArg.getByteArray()[listArg.getStartOffset()];
+        if (listArgType == ATypeTag.SERIALIZED_MISSING_TYPE_TAG) {
+            PointableHelper.setMissing(result);
+            return;
+        }
+        // create the new list with the same type as the input list
+        IAsterixListBuilder listBuilder;
+        if (listArgType == ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG) {
+            listBuilder = new OrderedListBuilder();
+        } else if (listArgType == ATypeTag.SERIALIZED_UNORDEREDLIST_TYPE_TAG) {
+            listBuilder = new UnorderedListBuilder();
+        } else {
+            PointableHelper.setNull(result);
+            return;
+        }
+
+        listBuilder.reset((AbstractCollectionType) inputListType);
+        listAccessor.reset(listArg.getByteArray(), listArg.getStartOffset());
+
+        try {
+            processList(listAccessor, listBuilder);
+            storage.reset();
+            listBuilder.write(storage.getDataOutput(), true);
+            result.set(storage);
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
+    }
+
+    protected abstract void processList(ListAccessor listAccessor, 
IAsterixListBuilder listBuilder) throws IOException;
+}
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayDistinctDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayDistinctDescriptor.java
new file mode 100755
index 0000000..03bdd27
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayDistinctDescriptor.java
@@ -0,0 +1,134 @@
+/*
+ * 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 static 
org.apache.asterix.om.types.EnumDeserializer.ATYPETAGDESERIALIZER;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.builders.IAsterixListBuilder;
+import 
org.apache.asterix.dataflow.data.nontagged.comparators.AObjectAscBinaryComparatorFactory;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptor;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.functions.IFunctionTypeInferer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.evaluators.common.ListAccessor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+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.dataflow.value.IBinaryComparator;
+import org.apache.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+
+public class ArrayDistinctDescriptor extends 
AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+    private IAType inputListType;
+
+    public static final IFunctionDescriptorFactory FACTORY = new 
IFunctionDescriptorFactory() {
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ArrayDistinctDescriptor();
+        }
+
+        @Override
+        public IFunctionTypeInferer createFunctionTypeInferer() {
+            // the type of the input list is needed in order to use the same 
type for the new returned list
+            return FunctionTypeInferers.SET_ARGUMENT_TYPE;
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.ARRAY_DISTINCT;
+    }
+
+    @Override
+    public void setImmutableStates(Object... states) {
+        inputListType = (IAType) states[0];
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
+                return new ArrayDistinctFunction(args, ctx, sourceLoc);
+            }
+        };
+    }
+
+    public class ArrayDistinctFunction extends AbstractArrayProcessEval {
+        private final IBinaryComparator comp;
+        private final SourceLocation sourceLoc;
+
+        public ArrayDistinctFunction(IScalarEvaluatorFactory[] args, 
IHyracksTaskContext ctx, SourceLocation sourceLoc)
+                throws HyracksDataException {
+            super(args, ctx, inputListType);
+            this.sourceLoc = sourceLoc;
+            comp = 
AObjectAscBinaryComparatorFactory.INSTANCE.createBinaryComparator();
+        }
+
+        @Override
+        protected void processList(ListAccessor listAccessor, 
IAsterixListBuilder listBuilder) throws IOException {
+            boolean addItem;
+            ArrayBackedValueStorage item;
+            List<ArrayBackedValueStorage> distinct = new ArrayList<>();
+            for (int i = 0; i < listAccessor.size(); i++) {
+                item = new ArrayBackedValueStorage();
+                listAccessor.writeItem(i, item.getDataOutput());
+                if 
(ATYPETAGDESERIALIZER.deserialize(item.getByteArray()[item.getStartOffset()]).isDerivedType())
 {
+                    throw 
HyracksDataException.create(ErrorCode.CANNOT_COMPARE_COMPLEX, sourceLoc);
+                }
+                addItem = true;
+                for (ArrayBackedValueStorage addedItem : distinct) {
+                    if (comp.compare(item.getByteArray(), 
item.getStartOffset(), item.getLength(),
+                            addedItem.getByteArray(), 
addedItem.getStartOffset(), addedItem.getLength()) == 0
+                            || isNullAndMissing(item, addedItem)) {
+                        addItem = false;
+                        break;
+                    }
+                }
+                if (addItem) {
+                    listBuilder.addItem(item);
+                    distinct.add(item);
+                }
+            }
+        }
+
+        private boolean isNullAndMissing(ArrayBackedValueStorage item1, 
ArrayBackedValueStorage item2) {
+            byte tag1 = item1.getByteArray()[item1.getStartOffset()];
+            byte tag2 = item2.getByteArray()[item2.getStartOffset()];
+            return (tag1 == ATypeTag.SERIALIZED_NULL_TYPE_TAG && tag2 == 
ATypeTag.SERIALIZED_MISSING_TYPE_TAG)
+                    || (tag1 == ATypeTag.SERIALIZED_MISSING_TYPE_TAG && tag2 
== ATypeTag.SERIALIZED_NULL_TYPE_TAG);
+        }
+    }
+}
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReverseDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReverseDescriptor.java
index eed50ca..bec7bbb 100755
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReverseDescriptor.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReverseDescriptor.java
@@ -21,14 +21,10 @@
 import java.io.IOException;
 
 import org.apache.asterix.builders.IAsterixListBuilder;
-import org.apache.asterix.builders.OrderedListBuilder;
-import org.apache.asterix.builders.UnorderedListBuilder;
 import org.apache.asterix.om.functions.BuiltinFunctions;
 import org.apache.asterix.om.functions.IFunctionDescriptor;
 import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
 import org.apache.asterix.om.functions.IFunctionTypeInferer;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.AbstractCollectionType;
 import org.apache.asterix.om.types.IAType;
 import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
 import org.apache.asterix.runtime.evaluators.common.ListAccessor;
@@ -39,10 +35,7 @@
 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;
 
 /**
  * array_reverse(list) returns a new list with the entries of the original 
input list in reverse order. If the input is
@@ -63,7 +56,6 @@
             // the type of the input list is needed in order to use the same 
type for the new returned list
             return FunctionTypeInferers.SET_ARGUMENT_TYPE;
         }
-
     };
 
     @Override
@@ -89,51 +81,22 @@
         };
     }
 
-    public class ArrayReverseFunction implements IScalarEvaluator {
+    public class ArrayReverseFunction extends AbstractArrayProcessEval {
         private final ArrayBackedValueStorage storage;
-        private final IScalarEvaluator listArgEval;
-        private final ListAccessor listAccessor;
-        private final IPointable listArg;
 
         public ArrayReverseFunction(IScalarEvaluatorFactory[] args, 
IHyracksTaskContext ctx)
                 throws HyracksDataException {
+            super(args, ctx, inputListType);
             storage = new ArrayBackedValueStorage();
-            listArg = new VoidPointable();
-            listArgEval = args[0].createScalarEvaluator(ctx);
-            listAccessor = new ListAccessor();
         }
 
         @Override
-        public void evaluate(IFrameTupleReference tuple, IPointable result) 
throws HyracksDataException {
-            // get the list argument and make sure it's a list
-            listArgEval.evaluate(tuple, listArg);
-            byte listArgType = 
listArg.getByteArray()[listArg.getStartOffset()];
-
-            // create the new list with the same type as the input list
-            IAsterixListBuilder listBuilder;
-            if (listArgType == ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG) {
-                listBuilder = new OrderedListBuilder();
-            } else if (listArgType == 
ATypeTag.SERIALIZED_UNORDEREDLIST_TYPE_TAG) {
-                listBuilder = new UnorderedListBuilder();
-            } else {
-                PointableHelper.setNull(result);
-                return;
-            }
-
-            listBuilder.reset((AbstractCollectionType) inputListType);
-            listAccessor.reset(listArg.getByteArray(), 
listArg.getStartOffset());
-            try {
-                // get the list items in reverse and append to the new list
-                for (int i = listAccessor.size() - 1; i >= 0; i--) {
-                    storage.reset();
-                    listAccessor.writeItem(i, storage.getDataOutput());
-                    listBuilder.addItem(storage);
-                }
+        protected void processList(ListAccessor listAccessor, 
IAsterixListBuilder listBuilder) throws IOException {
+            // get the list items in reverse and append to the new list
+            for (int i = listAccessor.size() - 1; i >= 0; i--) {
                 storage.reset();
-                listBuilder.write(storage.getDataOutput(), true);
-                result.set(storage);
-            } catch (IOException e) {
-                throw HyracksDataException.create(e);
+                listAccessor.writeItem(i, storage.getDataOutput());
+                listBuilder.addItem(storage);
             }
         }
     }
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySortDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySortDescriptor.java
new file mode 100755
index 0000000..bd07647
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySortDescriptor.java
@@ -0,0 +1,128 @@
+/*
+ * 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 static 
org.apache.asterix.om.types.EnumDeserializer.ATYPETAGDESERIALIZER;
+
+import java.io.IOException;
+import java.util.Comparator;
+import java.util.PriorityQueue;
+
+import org.apache.asterix.builders.IAsterixListBuilder;
+import 
org.apache.asterix.dataflow.data.nontagged.comparators.AObjectAscBinaryComparatorFactory;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptor;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.functions.IFunctionTypeInferer;
+import org.apache.asterix.om.types.IAType;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.evaluators.common.ListAccessor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+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.dataflow.value.IBinaryComparator;
+import org.apache.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+
+public class ArraySortDescriptor extends 
AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+    private IAType inputListType;
+
+    public static final IFunctionDescriptorFactory FACTORY = new 
IFunctionDescriptorFactory() {
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ArraySortDescriptor();
+        }
+
+        @Override
+        public IFunctionTypeInferer createFunctionTypeInferer() {
+            // the type of the input list is needed in order to use the same 
type for the new returned list
+            return FunctionTypeInferers.SET_ARGUMENT_TYPE;
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.ARRAY_SORT;
+    }
+
+    @Override
+    public void setImmutableStates(Object... states) {
+        inputListType = (IAType) states[0];
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
+                return new ArraySortFunction(args, ctx, sourceLoc);
+            }
+        };
+    }
+
+    public class ArraySortFunction extends AbstractArrayProcessEval {
+        private final SourceLocation sourceLoc;
+        private final PriorityQueue<ArrayBackedValueStorage> sortedList;
+
+        public ArraySortFunction(IScalarEvaluatorFactory[] args, 
IHyracksTaskContext ctx, SourceLocation sourceLoc)
+                throws HyracksDataException {
+            super(args, ctx, inputListType);
+            this.sourceLoc = sourceLoc;
+            sortedList = new PriorityQueue<>(createComparator());
+        }
+
+        @Override
+        protected void processList(ListAccessor listAccessor, 
IAsterixListBuilder listBuilder) throws IOException {
+            ArrayBackedValueStorage item;
+            for (int i = 0; i < listAccessor.size(); i++) {
+                item = new ArrayBackedValueStorage();
+                listAccessor.writeItem(i, item.getDataOutput());
+                if 
(ATYPETAGDESERIALIZER.deserialize(item.getByteArray()[item.getStartOffset()]).isDerivedType())
 {
+                    throw 
HyracksDataException.create(ErrorCode.CANNOT_COMPARE_COMPLEX, sourceLoc);
+                }
+                sortedList.add(item);
+            }
+            while (!sortedList.isEmpty()) {
+                listBuilder.addItem(sortedList.poll());
+            }
+        }
+
+        private Comparator<ArrayBackedValueStorage> createComparator() {
+            IBinaryComparator comp = 
AObjectAscBinaryComparatorFactory.INSTANCE.createBinaryComparator();
+
+            return (val1, val2) -> {
+                try {
+                    return comp.compare(val1.getByteArray(), 
val1.getStartOffset(), val1.getLength(),
+                            val2.getByteArray(), val2.getStartOffset(), 
val2.getLength());
+                } catch (HyracksDataException e) {
+                    throw new RuntimeException(e);
+                }
+            };
+        }
+    }
+}
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
index 004e50a..ef7c2a3 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
@@ -43,6 +43,7 @@
 public class PointableHelper {
 
     private static final byte[] NULL_BYTES = new byte[] { 
ATypeTag.SERIALIZED_NULL_TYPE_TAG };
+    private static final byte[] MISSING_BYTES = new byte[] { 
ATypeTag.SERIALIZED_MISSING_TYPE_TAG };
 
     private final UTF8StringWriter utf8Writer;
 
@@ -135,4 +136,8 @@
     public static void setNull(IPointable pointable) {
         pointable.set(NULL_BYTES, 0, NULL_BYTES.length);
     }
+
+    public static void setMissing(IPointable pointable) {
+        pointable.set(MISSING_BYTES, 0, MISSING_BYTES.length);
+    }
 }
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 199cc40..a51a865 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
@@ -145,9 +145,11 @@
 import 
org.apache.asterix.runtime.evaluators.functions.AnyCollectionMemberDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayAppendDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayContainsDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ArraySortDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayPositionDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayRepeatDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayReverseDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ArrayDistinctDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.CastTypeDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.CastTypeLaxDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.CheckUnknownDescriptor;
@@ -379,8 +381,10 @@
         fc.addGenerated(ArrayAppendDescriptor.FACTORY);
         fc.addGenerated(ArrayPositionDescriptor.FACTORY);
         fc.addGenerated(ArrayRepeatDescriptor.FACTORY);
-        fc.addGenerated(ArrayReverseDescriptor.FACTORY);
         fc.addGenerated(ArrayContainsDescriptor.FACTORY);
+        fc.add(ArrayReverseDescriptor.FACTORY);
+        fc.add(ArraySortDescriptor.FACTORY);
+        fc.add(ArrayDistinctDescriptor.FACTORY);
 
         // unnesting functions
         fc.add(TidRunningAggregateDescriptor.FACTORY);

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/2756
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I5e9c4ff6400b7fe93ca2aab0234750dc78f50659
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Ali Alsuliman <[email protected]>

Reply via email to