diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/TopNKeyOperator.java ql/src/java/org/apache/hadoop/hive/ql/exec/TopNKeyOperator.java index 4734824b73..d2e8d0ba79 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/TopNKeyOperator.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/TopNKeyOperator.java @@ -24,14 +24,19 @@ import org.apache.hadoop.hive.ql.plan.ExprNodeDesc; import org.apache.hadoop.hive.ql.plan.TopNKeyDesc; import org.apache.hadoop.hive.ql.plan.api.OperatorType; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectComparator; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; import java.io.Serializable; +import java.util.ArrayList; import java.util.Comparator; +import java.util.List; import java.util.PriorityQueue; import static org.apache.hadoop.hive.ql.plan.api.OperatorType.TOPNKEY; +import static org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils.NullValueOption.MAXVALUE; +import static org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils.NullValueOption.MINVALUE; /** * TopNKeyOperator passes rows that contains top N keys only. @@ -58,21 +63,23 @@ public TopNKeyOperator(CompilationOpContext ctx) { } public static class KeyWrapperComparator implements Comparator { - private ObjectInspector[] objectInspectors1; - private ObjectInspector[] objectInspectors2; - private boolean[] columnSortOrderIsDesc; - - public KeyWrapperComparator(ObjectInspector[] objectInspectors1, ObjectInspector[] - objectInspectors2, boolean[] columnSortOrderIsDesc) { - this.objectInspectors1 = objectInspectors1; - this.objectInspectors2 = objectInspectors2; - this.columnSortOrderIsDesc = columnSortOrderIsDesc; + private final List> comparators; + + KeyWrapperComparator(List> comparators) { + this.comparators = comparators; } @Override public int compare(KeyWrapper key1, KeyWrapper key2) { - return ObjectInspectorUtils.compare(key1.getKeyArray(), objectInspectors1, - key2.getKeyArray(), objectInspectors2, columnSortOrderIsDesc); + Object[] keyArray1 = key1.getKeyArray(); + Object[] keyArray2 = key2.getKeyArray(); + for (int i = 0; i < comparators.size(); ++i) { + int c = comparators.get(i).compare(keyArray1[i], keyArray2[i]); + if (c != 0) { + return c; + } + } + return 0; } } @@ -82,12 +89,6 @@ protected void initializeOp(Configuration hconf) throws HiveException { this.topN = conf.getTopN(); - String columnSortOrder = conf.getColumnSortOrder(); - boolean[] columnSortOrderIsDesc = new boolean[columnSortOrder.length()]; - for (int i = 0; i < columnSortOrderIsDesc.length; i++) { - columnSortOrderIsDesc[i] = (columnSortOrder.charAt(i) == '-'); - } - ObjectInspector rowInspector = inputObjInspectors[0]; ObjectInspector standardObjInspector = ObjectInspectorUtils.getStandardObjectInspector(rowInspector); outputObjInspector = rowInspector; @@ -107,8 +108,22 @@ protected void initializeOp(Configuration hconf) throws HiveException { standardKeyObjectInspectors[i] = standardKeyFields[i].initialize(standardObjInspector); } - priorityQueue = new PriorityQueue<>(topN + 1, new TopNKeyOperator.KeyWrapperComparator( - standardKeyObjectInspectors, standardKeyObjectInspectors, columnSortOrderIsDesc)); + String columnSortOrder = conf.getColumnSortOrder(); + String nullSortOrder = conf.getNullOrder(); + List> comparators = new ArrayList<>(columnSortOrder.length()); + for (int i = 0; i < numKeys; i++) { + ObjectComparator comparator = new ObjectComparator( + standardKeyObjectInspectors[i], + standardKeyObjectInspectors[i], + nullSortOrder.charAt(i) == 'z' ? MAXVALUE : MINVALUE); + if (columnSortOrder.charAt(i) == '-') { + comparators.add(comparator); + } else { + comparators.add(comparator.reversed()); + } + } + + priorityQueue = new PriorityQueue<>(topN + 1, new KeyWrapperComparator(comparators)); KeyWrapperFactory keyWrapperFactory = new KeyWrapperFactory(keyFields, keyObjectInspectors, standardKeyObjectInspectors); diff --git ql/src/java/org/apache/hadoop/hive/ql/optimizer/TopNKeyProcessor.java ql/src/java/org/apache/hadoop/hive/ql/optimizer/TopNKeyProcessor.java index 721a9b9998..4b4cf99503 100644 --- ql/src/java/org/apache/hadoop/hive/ql/optimizer/TopNKeyProcessor.java +++ ql/src/java/org/apache/hadoop/hive/ql/optimizer/TopNKeyProcessor.java @@ -53,7 +53,7 @@ public TopNKeyProcessor() { @Override public Object process(Node nd, Stack stack, NodeProcessorCtx procCtx, - Object... nodeOutputs) throws SemanticException { + Object... nodeOutputs) throws SemanticException { // Get ReduceSinkOperator ReduceSinkOperator reduceSinkOperator = (ReduceSinkOperator) nd; @@ -95,11 +95,11 @@ public Object process(Node nd, Stack stack, NodeProcessorCtx procCtx, } // Insert a new top n key operator between the group by operator and its parent - TopNKeyDesc topNKeyDesc = new TopNKeyDesc(reduceSinkDesc.getTopN(), reduceSinkDesc.getOrder(), - groupByKeyColumns); + TopNKeyDesc topNKeyDesc = new TopNKeyDesc( + reduceSinkDesc.getTopN(), reduceSinkDesc.getOrder(), reduceSinkDesc.getNullOrder(), groupByKeyColumns); Operator newOperator = OperatorFactory.getAndMakeChild( - groupByOperator.getCompilationOpContext(), (OperatorDesc) topNKeyDesc, - new RowSchema(groupByOperator.getSchema()), groupByOperator.getParentOperators()); + groupByOperator.getCompilationOpContext(), (OperatorDesc) topNKeyDesc, + new RowSchema(groupByOperator.getSchema()), groupByOperator.getParentOperators()); newOperator.getChildOperators().add(groupByOperator); groupByOperator.getParentOperators().add(newOperator); parentOperator.removeChild(groupByOperator); diff --git ql/src/java/org/apache/hadoop/hive/ql/plan/TopNKeyDesc.java ql/src/java/org/apache/hadoop/hive/ql/plan/TopNKeyDesc.java index c62c4a9b66..84e6149a0e 100644 --- ql/src/java/org/apache/hadoop/hive/ql/plan/TopNKeyDesc.java +++ ql/src/java/org/apache/hadoop/hive/ql/plan/TopNKeyDesc.java @@ -33,6 +33,7 @@ private int topN; private String columnSortOrder; + private String nullOrder; private List keyColumns; public TopNKeyDesc() { @@ -41,10 +42,12 @@ public TopNKeyDesc() { public TopNKeyDesc( final int topN, final String columnSortOrder, + final String nullOrder, final List keyColumns) { this.topN = topN; this.columnSortOrder = columnSortOrder; + this.nullOrder = nullOrder; this.keyColumns = keyColumns; } @@ -66,6 +69,15 @@ public void setColumnSortOrder(String columnSortOrder) { this.columnSortOrder = columnSortOrder; } + @Explain(displayName = "null sort order", explainLevels = { Level.EXTENDED }) + public String getNullOrder() { + return nullOrder; + } + + public void setNullOrder(String nullOrder) { + this.nullOrder = nullOrder; + } + @Explain(displayName = "keys") public String getKeyString() { return PlanUtils.getExprListString(keyColumns); @@ -98,6 +110,7 @@ public boolean isSame(OperatorDesc other) { TopNKeyDesc otherDesc = (TopNKeyDesc) other; return getTopN() == otherDesc.getTopN() && Objects.equals(columnSortOrder, otherDesc.columnSortOrder) && + Objects.equals(nullOrder, otherDesc.nullOrder) && ExprNodeDescUtils.isSame(keyColumns, otherDesc.keyColumns); } return false; @@ -108,6 +121,7 @@ public Object clone() { TopNKeyDesc ret = new TopNKeyDesc(); ret.setTopN(topN); ret.setColumnSortOrder(columnSortOrder); + ret.setNullOrder(nullOrder); ret.setKeyColumns(getKeyColumns() == null ? null : new ArrayList<>(getKeyColumns())); return ret; } diff --git ql/src/test/queries/clientpositive/topnkey.q ql/src/test/queries/clientpositive/topnkey.q index e02a41dd57..df67fc2b03 100644 --- ql/src/test/queries/clientpositive/topnkey.q +++ ql/src/test/queries/clientpositive/topnkey.q @@ -14,7 +14,7 @@ set hive.tez.dynamic.partition.pruning=true; set hive.stats.fetch.column.stats=true; set hive.cbo.enable=true; -EXPLAIN +EXPLAIN EXTENDED SELECT key, SUM(CAST(SUBSTR(value,5) AS INT)) FROM src GROUP BY key ORDER BY key LIMIT 5; SELECT key, SUM(CAST(SUBSTR(value,5) AS INT)) FROM src GROUP BY key ORDER BY key LIMIT 5; @@ -29,3 +29,26 @@ SELECT src1.key, src2.value FROM src src1 JOIN src src2 ON (src1.key = src2.key) SELECT src1.key, src2.value FROM src src1 JOIN src src2 ON (src1.key = src2.key) ORDER BY src1.key LIMIT 5; +CREATE TABLE t_test( + a int, + b int, + c int + ); + +INSERT INTO t_test VALUES +(NULL, NULL, NULL), +(5, 2, 3), +(NULL, NULL, NULL), +(NULL, NULL, NULL), +(6, 2, 1), +(7, 8, 4), (7, 8, 4), (7, 8, 4), +(5, 1, 2), (5, 1, 2), (5, 1, 2), +(NULL, NULL, NULL); + +EXPLAIN +SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a LIMIT 2; +SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a LIMIT 2; +SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a DESC LIMIT 2; +SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a DESC NULLS FIRST LIMIT 2; + +DROP TABLE IF EXISTS tstore; diff --git ql/src/test/results/clientpositive/llap/topnkey.q.out ql/src/test/results/clientpositive/llap/topnkey.q.out index e3c0bc102f..4269aa9a7f 100644 --- ql/src/test/results/clientpositive/llap/topnkey.q.out +++ ql/src/test/results/clientpositive/llap/topnkey.q.out @@ -1,13 +1,18 @@ -PREHOOK: query: EXPLAIN +PREHOOK: query: EXPLAIN EXTENDED SELECT key, SUM(CAST(SUBSTR(value,5) AS INT)) FROM src GROUP BY key ORDER BY key LIMIT 5 PREHOOK: type: QUERY PREHOOK: Input: default@src #### A masked pattern was here #### -POSTHOOK: query: EXPLAIN +POSTHOOK: query: EXPLAIN EXTENDED SELECT key, SUM(CAST(SUBSTR(value,5) AS INT)) FROM src GROUP BY key ORDER BY key LIMIT 5 POSTHOOK: type: QUERY POSTHOOK: Input: default@src #### A masked pattern was here #### +OPTIMIZED SQL: SELECT `key` AS `$f0`, SUM(CAST(SUBSTR(`value`, 5) AS INTEGER)) AS `$f1` +FROM `default`.`src` +GROUP BY `key` +ORDER BY `key` +LIMIT 5 STAGE DEPENDENCIES: Stage-1 is a root stage Stage-0 depends on stages: Stage-1 @@ -26,6 +31,7 @@ STAGE PLANS: TableScan alias: src Statistics: Num rows: 500 Data size: 89000 Basic stats: COMPLETE Column stats: COMPLETE + GatherStats: false Select Operator expressions: key (type: string), UDFToInteger(substr(value, 5)) (type: int) outputColumnNames: _col0, _col1 @@ -33,6 +39,7 @@ STAGE PLANS: Top N Key Operator sort order: + keys: _col0 (type: string) + null sort order: z Statistics: Num rows: 500 Data size: 89000 Basic stats: COMPLETE Column stats: COMPLETE top n: 5 Group By Operator @@ -44,15 +51,73 @@ STAGE PLANS: Statistics: Num rows: 250 Data size: 23750 Basic stats: COMPLETE Column stats: COMPLETE Reduce Output Operator key expressions: _col0 (type: string) + null sort order: z sort order: + Map-reduce partition columns: _col0 (type: string) Statistics: Num rows: 250 Data size: 23750 Basic stats: COMPLETE Column stats: COMPLETE + tag: -1 + TopN: 5 TopN Hash Memory Usage: 0.1 value expressions: _col1 (type: bigint) + auto parallelism: true Execution mode: llap LLAP IO: no inputs + Path -> Alias: +#### A masked pattern was here #### + Path -> Partition: +#### A masked pattern was here #### + Partition + base file name: src + input format: org.apache.hadoop.mapred.TextInputFormat + output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat + properties: + COLUMN_STATS_ACCURATE {"BASIC_STATS":"true","COLUMN_STATS":{"key":"true","value":"true"}} + bucket_count -1 + bucketing_version 2 + column.name.delimiter , + columns key,value + columns.comments 'default','default' + columns.types string:string +#### A masked pattern was here #### + name default.src + numFiles 1 + numRows 500 + rawDataSize 5312 + serialization.ddl struct src { string key, string value} + serialization.format 1 + serialization.lib org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + totalSize 5812 +#### A masked pattern was here #### + serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + + input format: org.apache.hadoop.mapred.TextInputFormat + output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat + properties: + COLUMN_STATS_ACCURATE {"BASIC_STATS":"true","COLUMN_STATS":{"key":"true","value":"true"}} + bucket_count -1 + bucketing_version 2 + column.name.delimiter , + columns key,value + columns.comments 'default','default' + columns.types string:string +#### A masked pattern was here #### + name default.src + numFiles 1 + numRows 500 + rawDataSize 5312 + serialization.ddl struct src { string key, string value} + serialization.format 1 + serialization.lib org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + totalSize 5812 +#### A masked pattern was here #### + serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + name: default.src + name: default.src + Truncated Path -> Alias: + /src [src] Reducer 2 Execution mode: llap + Needs Tagging: false Reduce Operator Tree: Group By Operator aggregations: sum(VALUE._col0) @@ -62,12 +127,17 @@ STAGE PLANS: Statistics: Num rows: 250 Data size: 23750 Basic stats: COMPLETE Column stats: COMPLETE Reduce Output Operator key expressions: _col0 (type: string) + null sort order: z sort order: + Statistics: Num rows: 250 Data size: 23750 Basic stats: COMPLETE Column stats: COMPLETE + tag: -1 + TopN: 5 TopN Hash Memory Usage: 0.1 value expressions: _col1 (type: bigint) + auto parallelism: false Reducer 3 Execution mode: llap + Needs Tagging: false Reduce Operator Tree: Select Operator expressions: KEY.reducesinkkey0 (type: string), VALUE._col0 (type: bigint) @@ -78,11 +148,26 @@ STAGE PLANS: Statistics: Num rows: 5 Data size: 475 Basic stats: COMPLETE Column stats: COMPLETE File Output Operator compressed: false + GlobalTableId: 0 +#### A masked pattern was here #### + NumFilesPerFileSink: 1 Statistics: Num rows: 5 Data size: 475 Basic stats: COMPLETE Column stats: COMPLETE +#### A masked pattern was here #### table: input format: org.apache.hadoop.mapred.SequenceFileInputFormat output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat + properties: + columns _col0,_col1 + columns.types string:bigint + escape.delim \ + hive.serialization.extend.additional.nesting.levels true + serialization.escape.crlf true + serialization.format 1 + serialization.lib org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + TotalFiles: 1 + GatherStats: false + MultiFileSpray: false Stage: Stage-0 Fetch Operator @@ -330,3 +415,172 @@ POSTHOOK: Input: default@src 0 val_0 0 val_0 0 val_0 +PREHOOK: query: CREATE TABLE t_test( + a int, + b int, + c int + ) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@t_test +POSTHOOK: query: CREATE TABLE t_test( + a int, + b int, + c int + ) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@t_test +PREHOOK: query: INSERT INTO t_test VALUES +(NULL, NULL, NULL), +(5, 2, 3), +(NULL, NULL, NULL), +(NULL, NULL, NULL), +(6, 2, 1), +(7, 8, 4), (7, 8, 4), (7, 8, 4), +(5, 1, 2), (5, 1, 2), (5, 1, 2), +(NULL, NULL, NULL) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@t_test +POSTHOOK: query: INSERT INTO t_test VALUES +(NULL, NULL, NULL), +(5, 2, 3), +(NULL, NULL, NULL), +(NULL, NULL, NULL), +(6, 2, 1), +(7, 8, 4), (7, 8, 4), (7, 8, 4), +(5, 1, 2), (5, 1, 2), (5, 1, 2), +(NULL, NULL, NULL) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@t_test +POSTHOOK: Lineage: t_test.a SCRIPT [] +POSTHOOK: Lineage: t_test.b SCRIPT [] +POSTHOOK: Lineage: t_test.c SCRIPT [] +PREHOOK: query: EXPLAIN +SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a LIMIT 2 +PREHOOK: type: QUERY +PREHOOK: Input: default@t_test +#### A masked pattern was here #### +POSTHOOK: query: EXPLAIN +SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a LIMIT 2 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@t_test +#### A masked pattern was here #### +STAGE DEPENDENCIES: + Stage-1 is a root stage + Stage-0 depends on stages: Stage-1 + +STAGE PLANS: + Stage: Stage-1 + Tez +#### A masked pattern was here #### + Edges: + Reducer 2 <- Map 1 (SIMPLE_EDGE) + Reducer 3 <- Reducer 2 (SIMPLE_EDGE) +#### A masked pattern was here #### + Vertices: + Map 1 + Map Operator Tree: + TableScan + alias: t_test + Statistics: Num rows: 12 Data size: 72 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: a (type: int), b (type: int) + outputColumnNames: a, b + Statistics: Num rows: 12 Data size: 72 Basic stats: COMPLETE Column stats: COMPLETE + Top N Key Operator + sort order: + + keys: a (type: int) + Statistics: Num rows: 12 Data size: 72 Basic stats: COMPLETE Column stats: COMPLETE + top n: 2 + Group By Operator + aggregations: count(b) + keys: a (type: int) + minReductionHashAggr: 0.6666666 + mode: hash + outputColumnNames: _col0, _col1 + Statistics: Num rows: 4 Data size: 40 Basic stats: COMPLETE Column stats: COMPLETE + Reduce Output Operator + key expressions: _col0 (type: int) + sort order: + + Map-reduce partition columns: _col0 (type: int) + Statistics: Num rows: 4 Data size: 40 Basic stats: COMPLETE Column stats: COMPLETE + TopN Hash Memory Usage: 0.1 + value expressions: _col1 (type: bigint) + Execution mode: llap + LLAP IO: no inputs + Reducer 2 + Execution mode: llap + Reduce Operator Tree: + Group By Operator + aggregations: count(VALUE._col0) + keys: KEY._col0 (type: int) + mode: mergepartial + outputColumnNames: _col0, _col1 + Statistics: Num rows: 4 Data size: 40 Basic stats: COMPLETE Column stats: COMPLETE + Reduce Output Operator + key expressions: _col0 (type: int) + sort order: + + Statistics: Num rows: 4 Data size: 40 Basic stats: COMPLETE Column stats: COMPLETE + TopN Hash Memory Usage: 0.1 + value expressions: _col1 (type: bigint) + Reducer 3 + Execution mode: llap + Reduce Operator Tree: + Select Operator + expressions: KEY.reducesinkkey0 (type: int), VALUE._col0 (type: bigint) + outputColumnNames: _col0, _col1 + Statistics: Num rows: 4 Data size: 40 Basic stats: COMPLETE Column stats: COMPLETE + Limit + Number of rows: 2 + Statistics: Num rows: 2 Data size: 20 Basic stats: COMPLETE Column stats: COMPLETE + File Output Operator + compressed: false + Statistics: Num rows: 2 Data size: 20 Basic stats: COMPLETE Column stats: COMPLETE + table: + input format: org.apache.hadoop.mapred.SequenceFileInputFormat + output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat + serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + + Stage: Stage-0 + Fetch Operator + limit: 2 + Processor Tree: + ListSink + +PREHOOK: query: SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a LIMIT 2 +PREHOOK: type: QUERY +PREHOOK: Input: default@t_test +#### A masked pattern was here #### +POSTHOOK: query: SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a LIMIT 2 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@t_test +#### A masked pattern was here #### +5 4 +6 1 +PREHOOK: query: SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a DESC LIMIT 2 +PREHOOK: type: QUERY +PREHOOK: Input: default@t_test +#### A masked pattern was here #### +POSTHOOK: query: SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a DESC LIMIT 2 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@t_test +#### A masked pattern was here #### +7 3 +6 1 +PREHOOK: query: SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a DESC NULLS FIRST LIMIT 2 +PREHOOK: type: QUERY +PREHOOK: Input: default@t_test +#### A masked pattern was here #### +POSTHOOK: query: SELECT a, count(b) FROM t_test GROUP BY a ORDER BY a DESC NULLS FIRST LIMIT 2 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@t_test +#### A masked pattern was here #### +NULL 0 +7 3 +PREHOOK: query: DROP TABLE IF EXISTS tstore +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS tstore +POSTHOOK: type: DROPTABLE diff --git serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectComparator.java serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectComparator.java new file mode 100644 index 0000000000..9fb7787118 --- /dev/null +++ serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectComparator.java @@ -0,0 +1,45 @@ +/* + * 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.hadoop.hive.serde2.objectinspector; + +import java.util.Comparator; + +import static org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils.NullValueOption; + +/** + * This class wraps the ObjectInspectorUtils.compare method and implements java.util.Comparator. + */ +public class ObjectComparator implements Comparator { + + private final ObjectInspector objectInspector1; + private final ObjectInspector objectInspector2; + private final NullValueOption nullSortOrder; + private final MapEqualComparer mapEqualComparer = new FullMapEqualComparer(); + + public ObjectComparator(ObjectInspector objectInspector1, ObjectInspector objectInspector2, + NullValueOption nullSortOrder) { + this.objectInspector1 = objectInspector1; + this.objectInspector2 = objectInspector2; + this.nullSortOrder = nullSortOrder; + } + + @Override + public int compare(Object o1, Object o2) { + return ObjectInspectorUtils.compare(o1, objectInspector1, o2, objectInspector2, mapEqualComparer, nullSortOrder); + } +}