diff --git itests/src/test/resources/testconfiguration.properties itests/src/test/resources/testconfiguration.properties index a2ccfe0..8318c3a 100644 --- itests/src/test/resources/testconfiguration.properties +++ itests/src/test/resources/testconfiguration.properties @@ -69,6 +69,7 @@ disabled.query.files=ql_rewrite_gbtoidx.q,\ smb_mapjoin_8.q minitez.query.files.shared=acid_globallimit.q,\ + empty_join.q,\ alter_merge_2_orc.q,\ alter_merge_orc.q,\ alter_merge_stats_orc.q,\ diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HashMapWrapper.java ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HashMapWrapper.java index 2ca5c00..5474f71 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HashMapWrapper.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HashMapWrapper.java @@ -58,8 +58,8 @@ private static final int THRESHOLD = 1000000; private static final float LOADFACTOR = 0.75f; private final HashMap mHash; // main memory HashMap - private MapJoinKey lastKey = null; - private Output output = new Output(0); // Reusable output for serialization + private final MapJoinKey lastKey = null; + private final Output output = new Output(0); // Reusable output for serialization public HashMapWrapper(Map metaData) { super(metaData); @@ -248,4 +248,10 @@ public void dumpMetrics() { public boolean hasSpill() { return false; } + + @Override + public void setSerde(MapJoinObjectSerDeContext keyCtx, MapJoinObjectSerDeContext valCtx) + throws SerDeException { + // Does nothing in this case. + } } diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HybridHashTableContainer.java ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HybridHashTableContainer.java index f2f3c09..ba95c50 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HybridHashTableContainer.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/HybridHashTableContainer.java @@ -86,21 +86,21 @@ private int numPartitionsSpilled; // number of spilled partitions private boolean lastPartitionInMem; // only one (last one) partition is left in memory private final int memoryCheckFrequency; // how often (# of rows apart) to check if memory is full - private HybridHashTableConf nwayConf; // configuration for n-way join + private final HybridHashTableConf nwayConf; // configuration for n-way join /** The OI used to deserialize values. We never deserialize keys. */ private LazyBinaryStructObjectInspector internalValueOi; private boolean[] sortableSortOrders; private MapJoinBytesTableContainer.KeyValueHelper writeHelper; - private MapJoinBytesTableContainer.DirectKeyValueWriter directWriteHelper; + private final MapJoinBytesTableContainer.DirectKeyValueWriter directWriteHelper; /* * this is not a real bloom filter, but is a cheap version of the 1-memory * access bloom filters - * + * * In several cases, we'll have map-join spills because the value columns are * a few hundred columns of Text each, while there are very few keys in total * (a few thousand). - * + * * This is a cheap exit option to prevent spilling the big-table in such a * scenario. */ @@ -427,24 +427,6 @@ public LazyBinaryStructObjectInspector getInternalValueOi() { public MapJoinKey putRow(MapJoinObjectSerDeContext keyContext, Writable currentKey, MapJoinObjectSerDeContext valueContext, Writable currentValue) throws SerDeException, HiveException, IOException { - SerDe keySerde = keyContext.getSerDe(), valSerde = valueContext.getSerDe(); - - if (writeHelper == null) { - LOG.info("Initializing container with " - + keySerde.getClass().getName() + " and " + valSerde.getClass().getName()); - - // We assume this hashtable is loaded only when tez is enabled - LazyBinaryStructObjectInspector valSoi = - (LazyBinaryStructObjectInspector) valSerde.getObjectInspector(); - writeHelper = new MapJoinBytesTableContainer.LazyBinaryKvWriter(keySerde, valSoi, - valueContext.hasFilterTag()); - if (internalValueOi == null) { - internalValueOi = valSoi; - } - if (sortableSortOrders == null) { - sortableSortOrders = ((BinarySortableSerDe) keySerde).getSortOrders(); - } - } writeHelper.setKeyValue(currentKey, currentValue); return internalPutRow(writeHelper, currentKey, currentValue); } @@ -793,7 +775,7 @@ public int directSpillPartitionId() { private class ReusableRowContainer implements MapJoinRowContainer, AbstractRowContainer.RowIterator> { private byte aliasFilter; - private BytesBytesMultiHashMap.Result hashMapResult; + private final BytesBytesMultiHashMap.Result hashMapResult; /** * Sometimes, when container is empty in multi-table mapjoin, we need to add a dummy row. @@ -1062,4 +1044,27 @@ public int size() { } return totalSize; } + + @Override + public void setSerde(MapJoinObjectSerDeContext keyCtx, MapJoinObjectSerDeContext valCtx) + throws SerDeException { + SerDe keySerde = keyCtx.getSerDe(), valSerde = valCtx.getSerDe(); + + if (writeHelper == null) { + LOG.info("Initializing container with " + keySerde.getClass().getName() + " and " + + valSerde.getClass().getName()); + + // We assume this hashtable is loaded only when tez is enabled + LazyBinaryStructObjectInspector valSoi = + (LazyBinaryStructObjectInspector) valSerde.getObjectInspector(); + writeHelper = new MapJoinBytesTableContainer.LazyBinaryKvWriter(keySerde, valSoi, + valCtx.hasFilterTag()); + if (internalValueOi == null) { + internalValueOi = valSoi; + } + if (sortableSortOrders == null) { + sortableSortOrders = ((BinarySortableSerDe) keySerde).getSortOrders(); + } + } + } } diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinBytesTableContainer.java ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinBytesTableContainer.java index 3dddee7..269fc31 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinBytesTableContainer.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinBytesTableContainer.java @@ -21,6 +21,7 @@ import java.io.ObjectOutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -28,6 +29,7 @@ import org.slf4j.LoggerFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.ql.debug.Utils; import org.apache.hadoop.hive.ql.exec.ExprNodeEvaluator; import org.apache.hadoop.hive.ql.exec.JoinUtil; import org.apache.hadoop.hive.ql.exec.vector.VectorHashKeyWrapper; @@ -345,26 +347,31 @@ public int getHashFromKey() throws SerDeException { } } - @SuppressWarnings("deprecation") @Override - public MapJoinKey putRow(MapJoinObjectSerDeContext keyContext, Writable currentKey, - MapJoinObjectSerDeContext valueContext, Writable currentValue) throws SerDeException { + public void setSerde(MapJoinObjectSerDeContext keyContext, MapJoinObjectSerDeContext valueContext) + throws SerDeException { SerDe keySerde = keyContext.getSerDe(), valSerde = valueContext.getSerDe(); if (writeHelper == null) { - LOG.info("Initializing container with " - + keySerde.getClass().getName() + " and " + valSerde.getClass().getName()); + LOG.info("Initializing container with " + keySerde.getClass().getName() + " and " + + valSerde.getClass().getName()); if (keySerde instanceof BinarySortableSerDe && valSerde instanceof LazyBinarySerDe) { LazyBinaryStructObjectInspector valSoi = - (LazyBinaryStructObjectInspector)valSerde.getObjectInspector(); + (LazyBinaryStructObjectInspector) valSerde.getObjectInspector(); writeHelper = new LazyBinaryKvWriter(keySerde, valSoi, valueContext.hasFilterTag()); internalValueOi = valSoi; - sortableSortOrders = ((BinarySortableSerDe)keySerde).getSortOrders(); + sortableSortOrders = ((BinarySortableSerDe) keySerde).getSortOrders(); } else { writeHelper = new KeyValueWriter(keySerde, valSerde, valueContext.hasFilterTag()); internalValueOi = createInternalOi(valueContext); sortableSortOrders = null; } } + } + + @SuppressWarnings("deprecation") + @Override + public MapJoinKey putRow(MapJoinObjectSerDeContext keyContext, Writable currentKey, + MapJoinObjectSerDeContext valueContext, Writable currentValue) throws SerDeException { writeHelper.setKeyValue(currentKey, currentValue); hashMap.put(writeHelper, -1); return null; // there's no key to return @@ -538,7 +545,7 @@ public int directSpillPartitionId() { private byte aliasFilter; /** Hash table wrapper specific to the container. */ - private BytesBytesMultiHashMap.Result hashMapResult; + private final BytesBytesMultiHashMap.Result hashMapResult; /** * Sometimes, when container is empty in multi-table mapjoin, we need to add a dummy row. diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinKey.java ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinKey.java index 86cc9bd..cfb9abc 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinKey.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinKey.java @@ -21,12 +21,9 @@ import java.io.IOException; import java.io.ObjectOutputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.hadoop.hive.ql.exec.vector.VectorHashKeyWrapper; import org.apache.hadoop.hive.ql.exec.vector.VectorHashKeyWrapperBatch; import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorExpressionWriter; @@ -40,8 +37,6 @@ import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category; import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory; -import org.apache.hadoop.hive.serde2.objectinspector.StructField; -import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo; import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo; import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils; @@ -53,7 +48,6 @@ */ public abstract class MapJoinKey { private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - public abstract void write(MapJoinObjectSerDeContext context, ObjectOutputStream out) throws IOException, SerDeException; diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinTableContainer.java ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinTableContainer.java index 869aefd..0db5c36 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinTableContainer.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/MapJoinTableContainer.java @@ -111,4 +111,7 @@ MapJoinKey putRow(MapJoinObjectSerDeContext keyContext, Writable currentKey, * Return the size of the hash table */ int size(); + + void setSerde(MapJoinObjectSerDeContext keyCtx, MapJoinObjectSerDeContext valCtx) + throws SerDeException; } diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/tez/HashTableLoader.java ql/src/java/org/apache/hadoop/hive/ql/exec/tez/HashTableLoader.java index ff79110..ef9ccf5 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/tez/HashTableLoader.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/tez/HashTableLoader.java @@ -206,6 +206,7 @@ public void load(MapJoinTableContainer[] mapJoinTables, LOG.info("Using tableContainer " + tableContainer.getClass().getSimpleName()); + tableContainer.setSerde(keyCtx, valCtx); while (kvReader.next()) { tableContainer.putRow(keyCtx, (Writable)kvReader.getCurrentKey(), valCtx, (Writable)kvReader.getCurrentValue()); diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/vector/mapjoin/fast/VectorMapJoinFastTableContainer.java ql/src/java/org/apache/hadoop/hive/ql/exec/vector/mapjoin/fast/VectorMapJoinFastTableContainer.java index bd4a595..128d3d8 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/vector/mapjoin/fast/VectorMapJoinFastTableContainer.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/vector/mapjoin/fast/VectorMapJoinFastTableContainer.java @@ -48,17 +48,17 @@ private static final Logger LOG = LoggerFactory.getLogger(HashTableLoader.class.getName()); - private MapJoinDesc desc; - private Configuration hconf; + private final MapJoinDesc desc; + private final Configuration hconf; - private float keyCountAdj; - private int threshold; - private float loadFactor; - private int wbSize; - private long keyCount; + private final float keyCountAdj; + private final int threshold; + private final float loadFactor; + private final int wbSize; + private final long keyCount; - private VectorMapJoinFastHashTable VectorMapJoinFastHashTable; + private final VectorMapJoinFastHashTable VectorMapJoinFastHashTable; public VectorMapJoinFastTableContainer(MapJoinDesc desc, Configuration hconf, long keyCount) throws SerDeException { @@ -88,7 +88,7 @@ public VectorMapJoinFastTableContainer(MapJoinDesc desc, Configuration hconf, @Override public VectorMapJoinHashTable vectorMapJoinHashTable() { - return (VectorMapJoinHashTable) VectorMapJoinFastHashTable; + return VectorMapJoinFastHashTable; } private VectorMapJoinFastHashTable createHashTable(int newThreshold) { @@ -218,6 +218,13 @@ public int size() { return VectorMapJoinFastHashTable.size(); } + @Override + public void setSerde(MapJoinObjectSerDeContext keyCtx, MapJoinObjectSerDeContext valCtx) + throws SerDeException { + // Do nothing in this case. + + } + /* @Override public com.esotericsoftware.kryo.io.Output getHybridBigTableSpillOutput(int partitionId) { diff --git ql/src/test/queries/clientpositive/empty_join.q ql/src/test/queries/clientpositive/empty_join.q new file mode 100644 index 0000000..b1df416 --- /dev/null +++ ql/src/test/queries/clientpositive/empty_join.q @@ -0,0 +1,24 @@ +set hive.auto.convert.join=true; +set hive.mapjoin.hybridgrace.hashtable=false; + +DROP TABLE IF EXISTS test_1; +CREATE TABLE test_1 AS SELECT 1 AS id; + +DROP TABLE IF EXISTS test_2; +CREATE TABLE test_2 (id INT); + +DROP TABLE IF EXISTS test_3; +CREATE TABLE test_3 AS SELECT 1 AS id; + +explain +SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id; + +SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +; + diff --git ql/src/test/results/clientpositive/empty_join.q.out ql/src/test/results/clientpositive/empty_join.q.out new file mode 100644 index 0000000..3f8aedf --- /dev/null +++ ql/src/test/results/clientpositive/empty_join.q.out @@ -0,0 +1,142 @@ +PREHOOK: query: DROP TABLE IF EXISTS test_1 +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS test_1 +POSTHOOK: type: DROPTABLE +PREHOOK: query: CREATE TABLE test_1 AS SELECT 1 AS id +PREHOOK: type: CREATETABLE_AS_SELECT +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: database:default +PREHOOK: Output: default@test_1 +POSTHOOK: query: CREATE TABLE test_1 AS SELECT 1 AS id +POSTHOOK: type: CREATETABLE_AS_SELECT +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: database:default +POSTHOOK: Output: default@test_1 +PREHOOK: query: DROP TABLE IF EXISTS test_2 +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS test_2 +POSTHOOK: type: DROPTABLE +PREHOOK: query: CREATE TABLE test_2 (id INT) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@test_2 +POSTHOOK: query: CREATE TABLE test_2 (id INT) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@test_2 +PREHOOK: query: DROP TABLE IF EXISTS test_3 +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS test_3 +POSTHOOK: type: DROPTABLE +PREHOOK: query: CREATE TABLE test_3 AS SELECT 1 AS id +PREHOOK: type: CREATETABLE_AS_SELECT +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: database:default +PREHOOK: Output: default@test_3 +POSTHOOK: query: CREATE TABLE test_3 AS SELECT 1 AS id +POSTHOOK: type: CREATETABLE_AS_SELECT +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: database:default +POSTHOOK: Output: default@test_3 +PREHOOK: query: explain +SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +PREHOOK: type: QUERY +POSTHOOK: query: explain +SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +POSTHOOK: type: QUERY +STAGE DEPENDENCIES: + Stage-5 is a root stage + Stage-4 depends on stages: Stage-5 + Stage-0 depends on stages: Stage-4 + +STAGE PLANS: + Stage: Stage-5 + Map Reduce Local Work + Alias -> Map Local Tables: + t2 + Fetch Operator + limit: -1 + t3 + Fetch Operator + limit: -1 + Alias -> Map Local Operator Tree: + t2 + TableScan + alias: t2 + Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE + HashTable Sink Operator + keys: + 0 id (type: int) + 1 id (type: int) + 2 id (type: int) + t3 + TableScan + alias: t3 + Statistics: Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: NONE + HashTable Sink Operator + keys: + 0 id (type: int) + 1 id (type: int) + 2 id (type: int) + + Stage: Stage-4 + Map Reduce + Map Operator Tree: + TableScan + alias: t1 + Statistics: Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: NONE + Map Join Operator + condition map: + Left Outer Join0 to 1 + Inner Join 0 to 2 + keys: + 0 id (type: int) + 1 id (type: int) + 2 id (type: int) + outputColumnNames: _col0, _col4, _col8 + Statistics: Num rows: 2 Data size: 2 Basic stats: COMPLETE Column stats: NONE + Select Operator + expressions: _col0 (type: int), _col4 (type: int), _col8 (type: int) + outputColumnNames: _col0, _col1, _col2 + Statistics: Num rows: 2 Data size: 2 Basic stats: COMPLETE Column stats: NONE + File Output Operator + compressed: false + Statistics: Num rows: 2 Data size: 2 Basic stats: COMPLETE Column stats: NONE + table: + input format: org.apache.hadoop.mapred.TextInputFormat + output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat + serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + Local Work: + Map Reduce Local Work + + Stage: Stage-0 + Fetch Operator + limit: -1 + Processor Tree: + ListSink + +PREHOOK: query: SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +PREHOOK: type: QUERY +PREHOOK: Input: default@test_1 +PREHOOK: Input: default@test_2 +PREHOOK: Input: default@test_3 +#### A masked pattern was here #### +POSTHOOK: query: SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@test_1 +POSTHOOK: Input: default@test_2 +POSTHOOK: Input: default@test_3 +#### A masked pattern was here #### +1 NULL 1 diff --git ql/src/test/results/clientpositive/tez/empty_join.q.out ql/src/test/results/clientpositive/tez/empty_join.q.out new file mode 100644 index 0000000..ca351ec --- /dev/null +++ ql/src/test/results/clientpositive/tez/empty_join.q.out @@ -0,0 +1,115 @@ +PREHOOK: query: DROP TABLE IF EXISTS test_1 +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS test_1 +POSTHOOK: type: DROPTABLE +PREHOOK: query: CREATE TABLE test_1 AS SELECT 1 AS id +PREHOOK: type: CREATETABLE_AS_SELECT +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: database:default +PREHOOK: Output: default@test_1 +POSTHOOK: query: CREATE TABLE test_1 AS SELECT 1 AS id +POSTHOOK: type: CREATETABLE_AS_SELECT +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: database:default +POSTHOOK: Output: default@test_1 +PREHOOK: query: DROP TABLE IF EXISTS test_2 +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS test_2 +POSTHOOK: type: DROPTABLE +PREHOOK: query: CREATE TABLE test_2 (id INT) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@test_2 +POSTHOOK: query: CREATE TABLE test_2 (id INT) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@test_2 +PREHOOK: query: DROP TABLE IF EXISTS test_3 +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS test_3 +POSTHOOK: type: DROPTABLE +PREHOOK: query: CREATE TABLE test_3 AS SELECT 1 AS id +PREHOOK: type: CREATETABLE_AS_SELECT +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: database:default +PREHOOK: Output: default@test_3 +POSTHOOK: query: CREATE TABLE test_3 AS SELECT 1 AS id +POSTHOOK: type: CREATETABLE_AS_SELECT +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: database:default +POSTHOOK: Output: default@test_3 +PREHOOK: query: explain +SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +PREHOOK: type: QUERY +POSTHOOK: query: explain +SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +POSTHOOK: type: QUERY +Plan not optimized by CBO. + +Vertex dependency in root stage +Map 1 <- Map 2 (BROADCAST_EDGE), Map 3 (BROADCAST_EDGE) + +Stage-0 + Fetch Operator + limit:-1 + Stage-1 + Map 1 + File Output Operator [FS_8] + compressed:false + Statistics:Num rows: 2 Data size: 2 Basic stats: COMPLETE Column stats: NONE + table:{"input format:":"org.apache.hadoop.mapred.TextInputFormat","output format:":"org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat","serde:":"org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe"} + Select Operator [SEL_7] + outputColumnNames:["_col0","_col1","_col2"] + Statistics:Num rows: 2 Data size: 2 Basic stats: COMPLETE Column stats: NONE + Map Join Operator [MAPJOIN_16] + | condition map:[{"":"Left Outer Join0 to 1"},{"":"Inner Join 0 to 2"}] + | keys:{"Map 1":"id (type: int)","Map 2":"id (type: int)","Map 3":"id (type: int)"} + | outputColumnNames:["_col0","_col4","_col8"] + | Statistics:Num rows: 2 Data size: 2 Basic stats: COMPLETE Column stats: NONE + |<-Map 2 [BROADCAST_EDGE] + | Reduce Output Operator [RS_4] + | key expressions:id (type: int) + | Map-reduce partition columns:id (type: int) + | sort order:+ + | Statistics:Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE + | TableScan [TS_1] + | alias:t2 + | Statistics:Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE + |<-Map 3 [BROADCAST_EDGE] + | Reduce Output Operator [RS_5] + | key expressions:id (type: int) + | Map-reduce partition columns:id (type: int) + | sort order:+ + | Statistics:Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: NONE + | TableScan [TS_2] + | alias:t3 + | Statistics:Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: NONE + |<-TableScan [TS_0] + alias:t1 + Statistics:Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: NONE + +PREHOOK: query: SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +PREHOOK: type: QUERY +PREHOOK: Input: default@test_1 +PREHOOK: Input: default@test_2 +PREHOOK: Input: default@test_3 +#### A masked pattern was here #### +POSTHOOK: query: SELECT t1.id, t2.id, t3.id +FROM test_1 t1 +LEFT JOIN test_2 t2 ON t1.id = t2.id +INNER JOIN test_3 t3 ON t1.id = t3.id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@test_1 +POSTHOOK: Input: default@test_2 +POSTHOOK: Input: default@test_3 +#### A masked pattern was here #### +1 NULL 1