Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions presto-docs/src/main/sphinx/functions/array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ The ``||`` operator is used to concatenate an array with an array or an element
Array Functions
---------------

.. function:: all_match(array(T), function(T,boolean)) -> boolean

Returns whether all elements of an array match the given predicate. Returns ``true`` if all the elements
match the predicate (a special case is when the array is empty); ``false`` if one or more elements don't
match; ``NULL`` if the predicate function returns ``NULL`` for one or more elements and ``true`` for all
other elements.

.. function:: any_match(array(T), function(T,boolean)) -> boolean

Returns whether any elements of an array match the given predicate. Returns ``true`` if one or more
elements match the predicate; ``false`` if none of the elements matches (a special case is when the
array is empty); ``NULL`` if the predicate function returns ``NULL`` for one or more elements and ``false``
for all other elements.

.. function:: array_distinct(x) -> array

Remove duplicate values from the array ``x``.
Expand Down Expand Up @@ -153,6 +167,12 @@ Array Functions
SELECT ngrams(ARRAY['foo', 'bar', 'baz', 'foo'], 5); -- [['foo', 'bar', 'baz', 'foo']]
SELECT ngrams(ARRAY[1, 2, 3, 4], 2); -- [[1, 2], [2, 3], [3, 4]]

.. function:: none_match(array(T), function(T,boolean)) -> boolean

Returns whether no elements of an array match the given predicate. Returns ``true`` if none of the elements
matches the predicate (a special case is when the array is empty); ``false`` if one or more elements match;
``NULL`` if the predicate function returns ``NULL`` for one or more elements and ``false`` for all other elements.

.. function:: reduce(array(T), initialState S, inputFunction(S,T,S), outputFunction(S,R)) -> R

Returns a single value reduced from ``array``. ``inputFunction`` will
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
import io.prestosql.operator.aggregation.arrayagg.ArrayAggregationFunction;
import io.prestosql.operator.aggregation.histogram.Histogram;
import io.prestosql.operator.aggregation.multimapagg.MultimapAggregationFunction;
import io.prestosql.operator.scalar.ArrayAllMatchFunction;
import io.prestosql.operator.scalar.ArrayAnyMatchFunction;
import io.prestosql.operator.scalar.ArrayCardinalityFunction;
import io.prestosql.operator.scalar.ArrayCombinationsFunction;
import io.prestosql.operator.scalar.ArrayContains;
Expand All @@ -87,6 +89,7 @@
import io.prestosql.operator.scalar.ArrayMaxFunction;
import io.prestosql.operator.scalar.ArrayMinFunction;
import io.prestosql.operator.scalar.ArrayNgramsFunction;
import io.prestosql.operator.scalar.ArrayNoneMatchFunction;
import io.prestosql.operator.scalar.ArrayNotEqualOperator;
import io.prestosql.operator.scalar.ArrayPositionFunction;
import io.prestosql.operator.scalar.ArrayRemoveFunction;
Expand Down Expand Up @@ -563,6 +566,9 @@ public FunctionRegistry(Metadata metadata, FeaturesConfig featuresConfig)
.scalar(ArrayIndeterminateOperator.class)
.scalar(ArrayCombinationsFunction.class)
.scalar(ArrayNgramsFunction.class)
.scalar(ArrayAllMatchFunction.class)
.scalar(ArrayAnyMatchFunction.class)
.scalar(ArrayNoneMatchFunction.class)
.scalar(MapDistinctFromOperator.class)
.scalar(MapEqualOperator.class)
.scalar(MapEntriesFunction.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Licensed 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 io.prestosql.operator.scalar;

import io.airlift.slice.Slice;
import io.prestosql.spi.block.Block;
import io.prestosql.spi.function.Description;
import io.prestosql.spi.function.ScalarFunction;
import io.prestosql.spi.function.SqlNullable;
import io.prestosql.spi.function.SqlType;
import io.prestosql.spi.function.TypeParameter;
import io.prestosql.spi.function.TypeParameterSpecialization;
import io.prestosql.spi.type.StandardTypes;
import io.prestosql.spi.type.Type;

import static java.lang.Boolean.FALSE;

@Description("Returns true if all elements of the array match the given predicate")
@ScalarFunction(value = "all_match")
public final class ArrayAllMatchFunction
{
private ArrayAllMatchFunction() {}

@TypeParameter("T")
@TypeParameterSpecialization(name = "T", nativeContainerType = Block.class)
@SqlType(StandardTypes.BOOLEAN)
@SqlNullable
public static Boolean allMatchBlock(
@TypeParameter("T") Type elementType,
@SqlType("array(T)") Block arrayBlock,
@SqlType("function(T, boolean)") BlockToBooleanFunction function)
{
boolean hasNullResult = false;
for (int i = 0; i < arrayBlock.getPositionCount(); i++) {
Block element = null;
if (!arrayBlock.isNull(i)) {
element = (Block) elementType.getObject(arrayBlock, i);
}
Boolean match = function.apply(element);
if (FALSE.equals(match)) {
return false;
}
if (match == null) {
hasNullResult = true;
}
}
if (hasNullResult) {
return null;
}
return true;
}

@TypeParameter("T")
@TypeParameterSpecialization(name = "T", nativeContainerType = Slice.class)
@SqlType(StandardTypes.BOOLEAN)
@SqlNullable
public static Boolean allMatchSlice(
@TypeParameter("T") Type elementType,
@SqlType("array(T)") Block arrayBlock,
@SqlType("function(T, boolean)") SliceToBooleanFunction function)
{
boolean hasNullResult = false;
int positionCount = arrayBlock.getPositionCount();
for (int i = 0; i < positionCount; i++) {
Slice element = null;
if (!arrayBlock.isNull(i)) {
element = elementType.getSlice(arrayBlock, i);
}
Boolean match = function.apply(element);
if (FALSE.equals(match)) {
return false;
}
if (match == null) {
hasNullResult = true;
}
}
if (hasNullResult) {
return null;
}
return true;
}

@TypeParameter("T")
@TypeParameterSpecialization(name = "T", nativeContainerType = long.class)
@SqlType(StandardTypes.BOOLEAN)
@SqlNullable
public static Boolean allMatchLong(
@TypeParameter("T") Type elementType,
@SqlType("array(T)") Block arrayBlock,
@SqlType("function(T, boolean)") LongToBooleanFunction function)
{
boolean hasNullResult = false;
int positionCount = arrayBlock.getPositionCount();
for (int i = 0; i < positionCount; i++) {
Long element = null;
if (!arrayBlock.isNull(i)) {
element = elementType.getLong(arrayBlock, i);
}
Boolean match = function.apply(element);
if (FALSE.equals(match)) {
return false;
}
if (match == null) {
hasNullResult = true;
}
}
if (hasNullResult) {
return null;
}
return true;
}

@TypeParameter("T")
@TypeParameterSpecialization(name = "T", nativeContainerType = double.class)
@SqlType(StandardTypes.BOOLEAN)
@SqlNullable
public static Boolean allMatchDouble(
@TypeParameter("T") Type elementType,
@SqlType("array(T)") Block arrayBlock,
@SqlType("function(T, boolean)") DoubleToBooleanFunction function)
{
boolean hasNullResult = false;
int positionCount = arrayBlock.getPositionCount();
for (int i = 0; i < positionCount; i++) {
Double element = null;
if (!arrayBlock.isNull(i)) {
element = elementType.getDouble(arrayBlock, i);
}
Boolean match = function.apply(element);
if (FALSE.equals(match)) {
return false;
}
if (match == null) {
hasNullResult = true;
}
}
if (hasNullResult) {
return null;
}
return true;
}

@TypeParameter("T")
@TypeParameterSpecialization(name = "T", nativeContainerType = boolean.class)
@SqlType(StandardTypes.BOOLEAN)
@SqlNullable
public static Boolean allMatchBoolean(
@TypeParameter("T") Type elementType,
@SqlType("array(T)") Block arrayBlock,
@SqlType("function(T, boolean)") BooleanToBooleanFunction function)
{
boolean hasNullResult = false;
int positionCount = arrayBlock.getPositionCount();
for (int i = 0; i < positionCount; i++) {
Boolean element = null;
if (!arrayBlock.isNull(i)) {
element = elementType.getBoolean(arrayBlock, i);
}
Boolean match = function.apply(element);
if (FALSE.equals(match)) {
return false;
}
if (match == null) {
hasNullResult = true;
}
}
if (hasNullResult) {
return null;
}
return true;
}
}
Loading