From 5cb8d630067c0a35f11a172665d311657b49b289 Mon Sep 17 00:00:00 2001 From: Gopal V Date: Thu, 28 Mar 2019 23:12:00 -0700 Subject: [PATCH] HIVE-21531: Vectorization: all NULL hashcodes are not computed using Murmur3 --- .../org/apache/hive/common/util/HashCodeUtil.java | 2 + .../test/resources/testconfiguration.properties | 1 + .../keyseries/VectorKeySeriesSerializedImpl.java | 5 +- .../VectorReduceSinkUniformHashOperator.java | 4 +- .../queries/clientpositive/vector_union_null.q | 29 +++ .../clientpositive/llap/vector_union_null.q.out | 254 +++++++++++++++++++++ .../results/clientpositive/vector_union_null.q.out | 173 ++++++++++++++ 7 files changed, 463 insertions(+), 5 deletions(-) create mode 100644 ql/src/test/queries/clientpositive/vector_union_null.q create mode 100644 ql/src/test/results/clientpositive/llap/vector_union_null.q.out create mode 100644 ql/src/test/results/clientpositive/vector_union_null.q.out diff --git common/src/java/org/apache/hive/common/util/HashCodeUtil.java common/src/java/org/apache/hive/common/util/HashCodeUtil.java index 1330cbe..d763b13 100644 --- common/src/java/org/apache/hive/common/util/HashCodeUtil.java +++ common/src/java/org/apache/hive/common/util/HashCodeUtil.java @@ -47,7 +47,9 @@ public static void calculateLongArrayHashCodes(long[] longs, int[] hashCodes, fi } } + @Deprecated public static int calculateBytesHashCode(byte[] keyBytes, int keyStart, int keyLength) { + // Don't use this for ReduceSinkOperators return murmurHash(keyBytes, keyStart, keyLength); } diff --git itests/src/test/resources/testconfiguration.properties itests/src/test/resources/testconfiguration.properties index 8c4d9b7..996eddc 100644 --- itests/src/test/resources/testconfiguration.properties +++ itests/src/test/resources/testconfiguration.properties @@ -329,6 +329,7 @@ minillaplocal.shared.query.files=alter_merge_2_orc.q,\ vector_varchar_mapjoin1.q,\ vector_varchar_simple.q,\ vector_when_case_null.q,\ + vector_union_null.q,\ vectorization_0.q,\ vectorization_1.q,\ vectorization_10.q,\ diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/vector/keyseries/VectorKeySeriesSerializedImpl.java ql/src/java/org/apache/hadoop/hive/ql/exec/vector/keyseries/VectorKeySeriesSerializedImpl.java index 77c9ecc..f81c636 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/vector/keyseries/VectorKeySeriesSerializedImpl.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/vector/keyseries/VectorKeySeriesSerializedImpl.java @@ -93,9 +93,8 @@ public int getSerializedLength() { * Batch compute the hash codes for all the serialized keys. * * NOTE: MAJOR MAJOR ASSUMPTION: - * We assume that HashCodeUtil.murmurHash produces the same result - * as MurmurHash.hash with seed = 0 (the method used by ReduceSinkOperator for - * UNIFORM distribution). + * We use Murmur3.hash32(seed=0) across the board for the ReduceSink UNIFORM distribution. + * Previous use of HashCodeUtil is deprecated. */ protected void computeSerializedHashCodes() { int offset = 0; diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/vector/reducesink/VectorReduceSinkUniformHashOperator.java ql/src/java/org/apache/hadoop/hive/ql/exec/vector/reducesink/VectorReduceSinkUniformHashOperator.java index 324aa97..1201a1d 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/vector/reducesink/VectorReduceSinkUniformHashOperator.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/vector/reducesink/VectorReduceSinkUniformHashOperator.java @@ -28,7 +28,7 @@ import org.apache.hadoop.hive.ql.plan.OperatorDesc; import org.apache.hadoop.hive.ql.plan.VectorDesc; import org.apache.hadoop.hive.serde2.ByteStream.Output; -import org.apache.hive.common.util.HashCodeUtil; +import org.apache.hive.common.util.Murmur3; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -86,7 +86,7 @@ protected void initializeOp(Configuration hconf) throws HiveException { int nullBytesLength = nullKeyOutput.getLength(); nullBytes = new byte[nullBytesLength]; System.arraycopy(nullKeyOutput.getData(), 0, nullBytes, 0, nullBytesLength); - nullKeyHashCode = HashCodeUtil.calculateBytesHashCode(nullBytes, 0, nullBytesLength); + nullKeyHashCode = Murmur3.hash32(nullBytes, 0, nullBytesLength, 0); } catch (Exception e) { throw new HiveException(e); } diff --git ql/src/test/queries/clientpositive/vector_union_null.q ql/src/test/queries/clientpositive/vector_union_null.q new file mode 100644 index 0000000..3429cf6 --- /dev/null +++ ql/src/test/queries/clientpositive/vector_union_null.q @@ -0,0 +1,29 @@ +-- HIVE-21531 + +create temporary table null_tab(x int) stored as orc; +create temporary table dummy_tab(x int) stored as textfile; + +-- this disables vectorization for the text file +set hive.vectorized.use.vector.serde.deserialize=false; +set hive.vectorized.use.row.serde.deserialize=false; + +insert into null_tab values(1); +insert into dummy_tab values(1); + +set hive.explain.user=false; + +explain vectorization detail +SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3; + +SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3; + diff --git ql/src/test/results/clientpositive/llap/vector_union_null.q.out ql/src/test/results/clientpositive/llap/vector_union_null.q.out new file mode 100644 index 0000000..184155a --- /dev/null +++ ql/src/test/results/clientpositive/llap/vector_union_null.q.out @@ -0,0 +1,254 @@ +PREHOOK: query: create temporary table null_tab(x int) stored as orc +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@null_tab +POSTHOOK: query: create temporary table null_tab(x int) stored as orc +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@null_tab +PREHOOK: query: create temporary table dummy_tab(x int) stored as textfile +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@dummy_tab +POSTHOOK: query: create temporary table dummy_tab(x int) stored as textfile +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@dummy_tab +PREHOOK: query: insert into null_tab values(1) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@null_tab +POSTHOOK: query: insert into null_tab values(1) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@null_tab +POSTHOOK: Lineage: null_tab.x SCRIPT [] +PREHOOK: query: insert into dummy_tab values(1) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@dummy_tab +POSTHOOK: query: insert into dummy_tab values(1) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@dummy_tab +POSTHOOK: Lineage: dummy_tab.x SCRIPT [] +PREHOOK: query: explain vectorization detail +SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +PREHOOK: type: QUERY +PREHOOK: Input: default@dummy_tab +PREHOOK: Input: default@null_tab +#### A masked pattern was here #### +POSTHOOK: query: explain vectorization detail +SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@dummy_tab +POSTHOOK: Input: default@null_tab +#### A masked pattern was here #### +PLAN VECTORIZATION: + enabled: true + enabledConditionsMet: [hive.vectorized.execution.enabled IS true] + +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: + Map 1 <- Union 2 (CONTAINS) + Map 4 <- Union 2 (CONTAINS) + Reducer 3 <- Union 2 (SIMPLE_EDGE) +#### A masked pattern was here #### + Vertices: + Map 1 + Map Operator Tree: + TableScan + alias: null_tab + Statistics: Num rows: 1 Data size: 4 Basic stats: COMPLETE Column stats: COMPLETE + TableScan Vectorization: + native: true + vectorizationSchemaColumns: [0:x:int, 1:ROW__ID:struct] + Select Operator + expressions: 'a' (type: string) + outputColumnNames: _col0 + Select Vectorization: + className: VectorSelectOperator + native: true + projectedOutputColumnNums: [2] + selectExpressions: ConstantVectorExpression(val a) -> 2:string + Statistics: Num rows: 1 Data size: 85 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: _col0 (type: string) + outputColumnNames: _col1 + Select Vectorization: + className: VectorSelectOperator + native: true + projectedOutputColumnNums: [2] + Statistics: Num rows: 2 Data size: 170 Basic stats: COMPLETE Column stats: COMPLETE + Group By Operator + aggregations: min(_col1) + Group By Vectorization: + aggregators: VectorUDAFMinString(col 2:string) -> string + className: VectorGroupByOperator + groupByMode: HASH + keyExpressions: ConstantVectorExpression(val 1) -> 3:boolean + native: false + vectorProcessingMode: HASH + projectedOutputColumnNums: [0] + keys: true (type: boolean) + minReductionHashAggr: 0.0 + mode: hash + outputColumnNames: _col0, _col1 + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + Reduce Output Operator + key expressions: _col0 (type: boolean) + sort order: + + Map-reduce partition columns: _col0 (type: boolean) + Reduce Sink Vectorization: + className: VectorReduceSinkLongOperator + keyColumns: 0:boolean + native: true + nativeConditionsMet: hive.vectorized.execution.reducesink.new.enabled IS true, hive.execution.engine tez IN [tez, spark] IS true, No PTF TopN IS true, No DISTINCT columns IS true, BinarySortableSerDe for keys IS true, LazyBinarySerDe for values IS true + valueColumns: 1:string + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + value expressions: _col1 (type: string) + Execution mode: vectorized, llap + LLAP IO: all inputs + Map Vectorization: + enabled: true + enabledConditionsMet: hive.vectorized.use.vectorized.input.format IS true + inputFormatFeatureSupport: [DECIMAL_64] + featureSupportInUse: [DECIMAL_64] + inputFileFormats: org.apache.hadoop.hive.ql.io.orc.OrcInputFormat + allNative: false + usesVectorUDFAdaptor: false + vectorized: true + rowBatchContext: + dataColumnCount: 1 + includeColumns: [] + dataColumns: x:int + partitionColumnCount: 0 + scratchColumnTypeNames: [string, bigint] + Map 4 + Map Operator Tree: + TableScan + alias: dummy_tab + Statistics: Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: 'b' (type: string) + outputColumnNames: _col0 + Statistics: Num rows: 1 Data size: 85 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: _col0 (type: string) + outputColumnNames: _col1 + Statistics: Num rows: 2 Data size: 170 Basic stats: COMPLETE Column stats: COMPLETE + Group By Operator + aggregations: min(_col1) + keys: true (type: boolean) + minReductionHashAggr: 0.0 + mode: hash + outputColumnNames: _col0, _col1 + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + Reduce Output Operator + key expressions: _col0 (type: boolean) + sort order: + + Map-reduce partition columns: _col0 (type: boolean) + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + value expressions: _col1 (type: string) + Execution mode: llap + LLAP IO: no inputs + Map Vectorization: + enabled: false + enabledConditionsNotMet: hive.vectorized.use.vector.serde.deserialize IS false + inputFileFormats: org.apache.hadoop.mapred.TextInputFormat + Reducer 3 + Execution mode: vectorized, llap + Reduce Vectorization: + enabled: true + enableConditionsMet: hive.vectorized.execution.reduce.enabled IS true, hive.execution.engine tez IN [tez, spark] IS true + reduceColumnNullOrder: a + reduceColumnSortOrder: + + allNative: false + usesVectorUDFAdaptor: false + vectorized: true + rowBatchContext: + dataColumnCount: 2 + dataColumns: KEY._col0:boolean, VALUE._col0:string + partitionColumnCount: 0 + scratchColumnTypeNames: [] + Reduce Operator Tree: + Group By Operator + aggregations: min(VALUE._col0) + Group By Vectorization: + aggregators: VectorUDAFMinString(col 1:string) -> string + className: VectorGroupByOperator + groupByMode: MERGEPARTIAL + keyExpressions: col 0:boolean + native: false + vectorProcessingMode: MERGE_PARTIAL + projectedOutputColumnNums: [0] + keys: KEY._col0 (type: boolean) + mode: mergepartial + outputColumnNames: _col0, _col1 + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: _col1 (type: string), null (type: void), null (type: void), null (type: void) + outputColumnNames: _col0, _col1, _col2, _col3 + Select Vectorization: + className: VectorSelectOperator + native: true + projectedOutputColumnNums: [1, 2, 3, 4] + selectExpressions: ConstantVectorExpression(val null) -> 2:void, ConstantVectorExpression(val null) -> 3:void, ConstantVectorExpression(val null) -> 4:void + Statistics: Num rows: 1 Data size: 196 Basic stats: COMPLETE Column stats: COMPLETE + File Output Operator + compressed: false + File Sink Vectorization: + className: VectorFileSinkOperator + native: false + Statistics: Num rows: 1 Data size: 196 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 + Union 2 + Vertex: Union 2 + + Stage: Stage-0 + Fetch Operator + limit: -1 + Processor Tree: + ListSink + +PREHOOK: query: SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +PREHOOK: type: QUERY +PREHOOK: Input: default@dummy_tab +PREHOOK: Input: default@null_tab +#### A masked pattern was here #### +POSTHOOK: query: SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@dummy_tab +POSTHOOK: Input: default@null_tab +#### A masked pattern was here #### +a NULL NULL NULL diff --git ql/src/test/results/clientpositive/vector_union_null.q.out ql/src/test/results/clientpositive/vector_union_null.q.out new file mode 100644 index 0000000..37c7ac9 --- /dev/null +++ ql/src/test/results/clientpositive/vector_union_null.q.out @@ -0,0 +1,173 @@ +PREHOOK: query: create temporary table null_tab(x int) stored as orc +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@null_tab +POSTHOOK: query: create temporary table null_tab(x int) stored as orc +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@null_tab +PREHOOK: query: create temporary table dummy_tab(x int) stored as textfile +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@dummy_tab +POSTHOOK: query: create temporary table dummy_tab(x int) stored as textfile +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@dummy_tab +PREHOOK: query: insert into null_tab values(1) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@null_tab +POSTHOOK: query: insert into null_tab values(1) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@null_tab +POSTHOOK: Lineage: null_tab.x SCRIPT [] +PREHOOK: query: insert into dummy_tab values(1) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@dummy_tab +POSTHOOK: query: insert into dummy_tab values(1) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@dummy_tab +POSTHOOK: Lineage: dummy_tab.x SCRIPT [] +PREHOOK: query: explain vectorization detail +SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +PREHOOK: type: QUERY +PREHOOK: Input: default@dummy_tab +PREHOOK: Input: default@null_tab +#### A masked pattern was here #### +POSTHOOK: query: explain vectorization detail +SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@dummy_tab +POSTHOOK: Input: default@null_tab +#### A masked pattern was here #### +PLAN VECTORIZATION: + enabled: true + enabledConditionsMet: [hive.vectorized.execution.enabled IS true] + +STAGE DEPENDENCIES: + Stage-1 is a root stage + Stage-0 depends on stages: Stage-1 + +STAGE PLANS: + Stage: Stage-1 + Map Reduce + Map Operator Tree: + TableScan + alias: null_tab + Statistics: Num rows: 1 Data size: 4 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: 'a' (type: string) + outputColumnNames: _col0 + Statistics: Num rows: 1 Data size: 85 Basic stats: COMPLETE Column stats: COMPLETE + Union + Statistics: Num rows: 2 Data size: 170 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: _col0 (type: string) + outputColumnNames: _col1 + Statistics: Num rows: 2 Data size: 170 Basic stats: COMPLETE Column stats: COMPLETE + Group By Operator + aggregations: min(_col1) + keys: true (type: boolean) + minReductionHashAggr: 0.99 + mode: hash + outputColumnNames: _col0, _col1 + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + Reduce Output Operator + key expressions: _col0 (type: boolean) + sort order: + + Map-reduce partition columns: _col0 (type: boolean) + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + value expressions: _col1 (type: string) + TableScan + alias: dummy_tab + Statistics: Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: 'b' (type: string) + outputColumnNames: _col0 + Statistics: Num rows: 1 Data size: 85 Basic stats: COMPLETE Column stats: COMPLETE + Union + Statistics: Num rows: 2 Data size: 170 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: _col0 (type: string) + outputColumnNames: _col1 + Statistics: Num rows: 2 Data size: 170 Basic stats: COMPLETE Column stats: COMPLETE + Group By Operator + aggregations: min(_col1) + keys: true (type: boolean) + minReductionHashAggr: 0.99 + mode: hash + outputColumnNames: _col0, _col1 + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + Reduce Output Operator + key expressions: _col0 (type: boolean) + sort order: + + Map-reduce partition columns: _col0 (type: boolean) + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + value expressions: _col1 (type: string) + Map Vectorization: + enabled: false + enabledConditionsNotMet: Vectorized map work only works with 1 TableScanOperator IS false + Reduce Vectorization: + enabled: false + enableConditionsMet: hive.vectorized.execution.reduce.enabled IS true + enableConditionsNotMet: hive.execution.engine mr IN [tez, spark] IS false + Reduce Operator Tree: + Group By Operator + aggregations: min(VALUE._col0) + keys: KEY._col0 (type: boolean) + mode: mergepartial + outputColumnNames: _col0, _col1 + Statistics: Num rows: 1 Data size: 188 Basic stats: COMPLETE Column stats: COMPLETE + Select Operator + expressions: _col1 (type: string), null (type: void), null (type: void), null (type: void) + outputColumnNames: _col0, _col1, _col2, _col3 + Statistics: Num rows: 1 Data size: 196 Basic stats: COMPLETE Column stats: COMPLETE + File Output Operator + compressed: false + Statistics: Num rows: 1 Data size: 196 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: -1 + Processor Tree: + ListSink + +PREHOOK: query: SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +PREHOOK: type: QUERY +PREHOOK: Input: default@dummy_tab +PREHOOK: Input: default@null_tab +#### A masked pattern was here #### +POSTHOOK: query: SELECT MIN(table_name) as table_name, c1,c2,c3 from( +select 'a' as table_name, null as c1, null as c2, null as c3 from null_tab +union all +select 'b' as table_name, null as c1, null as c2, null as c3 from dummy_tab +) t_union +group by c1,c2,c3 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@dummy_tab +POSTHOOK: Input: default@null_tab +#### A masked pattern was here #### +a NULL NULL NULL -- 2.4.0