Skip to content

Commit

Permalink
add array_equals function
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronshan committed Sep 8, 2016
1 parent 487f215 commit 024d838
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 2 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ It will generate hive-third-functions-${version}-shaded.jar in target directory.

You can also directly download file from [release page](https://github.com/aaronshan/hive-third-functions/releases).

> current latest version is `2.2.0`
> current latest version is `2.2.1`
## Functions

Expand All @@ -52,6 +52,7 @@ You can also directly download file from [release page](https://github.com/aaron
| function| description |
|:--|:--|
|array_contains(array<E>, E) -> boolean | whether array contains value or not.|
|array_equals(array<E>, array<E>) -> boolean | whether two array equals or not.|
|array_intersect(array, array) -> array | returns the two array's intersection, without duplicates.|
|array_max(array<E>) -> E | returns the maximum value of input array.|
|array_min(array<E>) -> E | returns the minimum value of input array.|
Expand Down Expand Up @@ -146,6 +147,7 @@ Put these statements into `${HOME}/.hiverc` or exec its on hive cli env.
```
add jar ${jar_location_dir}/hive-third-functions-${version}-shaded.jar
create temporary function array_contains as 'cc.shanruifeng.functions.array.UDFArrayContains';
create temporary function array_equals as 'cc.shanruifeng.functions.array.UDFArrayEquals';
create temporary function array_intersect as 'cc.shanruifeng.functions.array.UDFArrayIntersect';
create temporary function array_max as 'cc.shanruifeng.functions.array.UDFArrayMax';
create temporary function array_min as 'cc.shanruifeng.functions.array.UDFArrayMin';
Expand Down Expand Up @@ -236,6 +238,7 @@ select zodiac_en('1989-01-08') => Capricorn

```
select array_contains(array(16,12,18,9), 12) => true
select array_equals(array(16,12,18,9), array(16,12,18,9)) => true
select array_intersect(array(16,12,18,9,null), array(14,9,6,18,null)) => [null,9,18]
select array_max(array(16,13,12,13,18,16,9,18)) => 18
select array_min(array(16,12,18,9)) => 9
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>cc.shanruifeng</groupId>
<artifactId>hive-third-functions</artifactId>
<version>2.2.0</version>
<version>2.2.1</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
99 changes: 99 additions & 0 deletions src/main/java/cc/shanruifeng/functions/array/UDFArrayEquals.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package cc.shanruifeng.functions.array;

import cc.shanruifeng.functions.utils.ArrayUtils;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.io.BooleanWritable;

/**
* @author ruifeng.shan
* @date 2016-09-08
* @time 16:03
*/
@Description(name = "array_equals"
, value = "_FUNC_(array, array) - whether two arrays equals or not."
, extended = "Example:\n > select _FUNC_(array, array) from src;")
public class UDFArrayEquals extends GenericUDF {
private static final int ARG_COUNT = 2; // Number of arguments to this UDF
private transient ListObjectInspector leftArrayOI;
private transient ListObjectInspector rightArrayOI;
private transient ObjectInspector leftArrayElementOI;
private transient ObjectInspector rightArrayElementOI;

private BooleanWritable result;

public UDFArrayEquals() {
}

@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
// Check if two arguments were passed
if (arguments.length != ARG_COUNT) {
throw new UDFArgumentLengthException(
"The function array_equals(array, array) takes exactly " + ARG_COUNT + " arguments.");
}

// Check if two argument is of category LIST
for (int i = 0; i < 2; i++) {
if (!arguments[i].getCategory().equals(ObjectInspector.Category.LIST)) {
throw new UDFArgumentTypeException(i,
"\"" + org.apache.hadoop.hive.serde.serdeConstants.LIST_TYPE_NAME + "\" "
+ "expected at function array_equals, but "
+ "\"" + arguments[i].getTypeName() + "\" "
+ "is found");
}
}

leftArrayOI = (ListObjectInspector) arguments[0];
rightArrayOI = (ListObjectInspector) arguments[1];

leftArrayElementOI = leftArrayOI.getListElementObjectInspector();
rightArrayElementOI = rightArrayOI.getListElementObjectInspector();

// Check if two array are of same type
if (!ObjectInspectorUtils.compareTypes(leftArrayElementOI, rightArrayElementOI)) {
throw new UDFArgumentTypeException(1,
"\"" + leftArrayElementOI.getTypeName() + "\""
+ " expected at function array_equals, but "
+ "\"" + rightArrayElementOI.getTypeName() + "\""
+ " is found");
}

// Check if the comparison is supported for this type
if (!ObjectInspectorUtils.compareSupported(leftArrayElementOI)) {
throw new UDFArgumentException("The function array_equals"
+ " does not support comparison for "
+ "\"" + leftArrayElementOI.getTypeName() + "\""
+ " types");
}

result = new BooleanWritable(false);
return PrimitiveObjectInspectorFactory.writableBooleanObjectInspector;
}

@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
Object leftArray = arguments[0].get();
Object rightArray = arguments[1].get();

boolean ret = ArrayUtils.arrayEquals(leftArray, rightArray, leftArrayOI);
result.set(ret);

return result;
}

@Override
public String getDisplayString(String[] strings) {
assert (strings.length == ARG_COUNT);
return "array_equals(" + strings[0] + ", "
+ strings[1] + ")";
}
}
28 changes: 28 additions & 0 deletions src/main/java/cc/shanruifeng/functions/utils/ArrayUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,32 @@ public int compare(int left, int right) {
}
};
}

public static boolean arrayEquals(Object left, Object right, ListObjectInspector arrayOI) {
if (left == null || right == null) {
if (left == null && right == null) {
return true;
}
return false;
}

int leftArrayLength = arrayOI.getListLength(left);
int rightArrayLength = arrayOI.getListLength(right);

if (leftArrayLength != rightArrayLength) {
return false;
}

ObjectInspector arrayElementOI = arrayOI.getListElementObjectInspector();
for (int i = 0; i < leftArrayLength; i++) {
Object leftArrayElement = arrayOI.getListElement(left, i);
Object rightArrayElement = arrayOI.getListElement(right, i);
int compareValue = ObjectInspectorUtils.compare(leftArrayElement, arrayElementOI, rightArrayElement, arrayElementOI);
if (compareValue != 0) {
return false;
}
}

return true;
}
}

0 comments on commit 024d838

Please sign in to comment.