This is an automated email from the ASF dual-hosted git repository.
kgyrtkirk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 621bfd1 HIVE-25822: Unexpected result rows in case of outer join
contains conditions only affecting one side (#2891) (Zoltan Haindrich reviewed
by Stamatis Zampetakis, Aman Sinha)
621bfd1 is described below
commit 621bfd164f018063fe5e03d9f7a7d990ce22691a
Author: Zoltan Haindrich <[email protected]>
AuthorDate: Tue Dec 21 11:50:45 2021 +0100
HIVE-25822: Unexpected result rows in case of outer join contains
conditions only affecting one side (#2891) (Zoltan Haindrich reviewed by
Stamatis Zampetakis, Aman Sinha)
---
.../java/org/apache/hadoop/hive/conf/HiveConf.java | 2 +
.../hive/ql/exec/CommonMergeJoinOperator.java | 80 ++++++++++++++++--
.../clientpositive/outer_join_unexpected_rows.q | 17 ++++
.../test/results/clientpositive/llap/join46.q.out | 4 +-
.../results/clientpositive/llap/join_1to1.q.out | 64 +--------------
.../clientpositive/llap/join_emit_interval.q.out | 6 +-
.../results/clientpositive/llap/mapjoin2.q.out | 2 +-
.../llap/outer_join_unexpected_rows.q.out | 95 ++++++++++++++++++++++
.../llap/vector_full_outer_join2.q.out | 18 ++--
9 files changed, 208 insertions(+), 80 deletions(-)
diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
index fd95070..b0b9b4f 100644
--- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
+++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
@@ -1836,6 +1836,8 @@ public class HiveConf extends Configuration {
HIVEALIAS("hive.alias", "", ""),
HIVEMAPSIDEAGGREGATE("hive.map.aggr", true, "Whether to use map-side
aggregation in Hive Group By queries"),
HIVEGROUPBYSKEW("hive.groupby.skewindata", false, "Whether there is skew
in data to optimize group by queries"),
+ HIVE_JOIN_SHORTCUT_UNMATCHED_ROWS("hive.join.shortcut.unmatched.rows",
true,
+ "Enables to shortcut processing of known filtered rows in merge joins.
internal use only. may affect correctness"),
HIVEJOINEMITINTERVAL("hive.join.emit.interval", 1000,
"How many rows in the right-most join operand Hive should buffer
before emitting the join result."),
HIVEJOINCACHESIZE("hive.join.cache.size", 25000,
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/exec/CommonMergeJoinOperator.java
b/ql/src/java/org/apache/hadoop/hive/ql/exec/CommonMergeJoinOperator.java
index e574fb9..0044a04 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/CommonMergeJoinOperator.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/CommonMergeJoinOperator.java
@@ -42,12 +42,12 @@ import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.plan.CommonMergeJoinDesc;
import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
import org.apache.hadoop.hive.ql.plan.JoinCondDesc;
+import org.apache.hadoop.hive.ql.plan.JoinDesc;
import org.apache.hadoop.hive.ql.plan.OperatorDesc;
import org.apache.hadoop.hive.ql.plan.api.OperatorType;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;
import
org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils.ObjectInspectorCopyOption;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
-import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
/*
@@ -74,6 +74,7 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
transient List<Object>[] nextKeyWritables;
transient RowContainer<List<Object>>[] nextGroupStorage;
transient RowContainer<List<Object>>[] candidateStorage;
+ transient RowContainer<List<Object>>[] unmatchedStorage;
transient String[] tagToAlias;
private transient boolean[] fetchDone;
@@ -94,6 +95,7 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
transient InterruptibleProcessing interruptChecker;
transient NullOrdering nullOrdering;
+ transient private boolean shortcutUnmatchedRows;
/** Kryo ctor. */
protected CommonMergeJoinOperator() {
@@ -121,6 +123,7 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
nextGroupStorage = new RowContainer[maxAlias];
candidateStorage = new RowContainer[maxAlias];
+ unmatchedStorage = new RowContainer[maxAlias];
keyWritables = new ArrayList[maxAlias];
nextKeyWritables = new ArrayList[maxAlias];
fetchDone = new boolean[maxAlias];
@@ -134,6 +137,8 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
int bucketSize;
int oldVar = HiveConf.getIntVar(hconf,
HiveConf.ConfVars.HIVEMAPJOINBUCKETCACHESIZE);
+ shortcutUnmatchedRows = HiveConf.getBoolVar(hconf,
HiveConf.ConfVars.HIVE_JOIN_SHORTCUT_UNMATCHED_ROWS);
+
if (oldVar != 100) {
bucketSize = oldVar;
} else {
@@ -149,6 +154,9 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
JoinUtil.getRowContainer(hconf,
rowContainerStandardObjectInspectors[pos], pos,
bucketSize, spillTableDesc, conf, !hasFilter(pos), reporter);
candidateStorage[pos] = candidateRC;
+ RowContainer<List<Object>> unmatchedRC = JoinUtil.getRowContainer(hconf,
+ rowContainerStandardObjectInspectors[pos], pos, bucketSize,
spillTableDesc, conf, !hasFilter(pos), reporter);
+ unmatchedStorage[pos] = unmatchedRC;
}
for (byte pos = 0; pos < order.length; pos++) {
@@ -240,6 +248,18 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
byte alias = (byte) tag;
List<Object> value = getFilteredValue(alias, row);
+
+ if (isOuterJoinUnmatchedRow(tag, value)) {
+ int type = condn[0].getType();
+ if (tag == 0 && (type == JoinDesc.LEFT_OUTER_JOIN || type ==
JoinDesc.FULL_OUTER_JOIN)) {
+ unmatchedStorage[tag].addRow(value);
+ }
+ if (tag == 1 && (type == JoinDesc.RIGHT_OUTER_JOIN || type ==
JoinDesc.FULL_OUTER_JOIN)) {
+ unmatchedStorage[tag].addRow(value);
+ }
+ emitUnmatchedRows(tag, false);
+ return;
+ }
// compute keys and values as StandardObjects
List<Object> key = mergeJoinComputeKeys(row, alias);
// Fetch the first group for all small table aliases.
@@ -302,7 +322,50 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
assert !nextKeyGroup;
candidateStorage[tag].addRow(value);
+ }
+
+ private void emitUnmatchedRows(int tag, boolean force) throws HiveException {
+ if (unmatchedStorage[tag].rowCount() == 0 || (!force &&
unmatchedStorage[tag].rowCount() < joinEmitInterval)) {
+ return;
+ }
+ for (byte i = 0; i < order.length; i++) {
+ if (i == tag) {
+ storage[i] = unmatchedStorage[i];
+ } else {
+ putDummyOrEmpty(i);
+ }
+ }
+ checkAndGenObject();
+ unmatchedStorage[tag].clearRows();
+ }
+ /**
+ * Decides if the actual row must be an unmatched row.
+ *
+ * Unmatched rows are those which are not part of the inner-join.
+ * The current implementation has issues processing filtered rows in FOJ
conditions.
+ * Putting them in a separate group also reduces processing done for them.
+ */
+ private boolean isOuterJoinUnmatchedRow(int tag, List<Object> value) {
+ if (!shortcutUnmatchedRows || condn.length != 1) {
+ return false;
+ }
+ switch (condn[0].getType()) {
+ case JoinDesc.INNER_JOIN:
+ case JoinDesc.LEFT_OUTER_JOIN:
+ case JoinDesc.RIGHT_OUTER_JOIN:
+ case JoinDesc.FULL_OUTER_JOIN:
+ break;
+ default:
+ return false;
+ }
+ if (hasFilter(tag)) {
+ short filterTag = getFilterTag(value);
+ if (JoinUtil.isFiltered(filterTag, 1 - tag)) {
+ return true;
+ }
+ }
+ return false;
}
private List<Byte> joinOneGroup() throws HiveException {
@@ -310,6 +373,9 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
}
private List<Byte> joinOneGroup(boolean clear) throws HiveException {
+ for (int pos = 0; pos < order.length; pos++) {
+ emitUnmatchedRows(pos, true);
+ }
int[] smallestPos = findSmallestKey();
List<Byte> listOfNeedFetchNext = null;
if (smallestPos != null) {
@@ -430,7 +496,7 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
this.nextKeyWritables[t] = null;
}
}
-
+
@Override
public void close(boolean abort) throws HiveException {
joinFinalLeftData(); // Do this WITHOUT checking for parents
@@ -530,7 +596,9 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
}
private void doFirstFetchIfNeeded() throws HiveException {
- if (firstFetchHappened) return;
+ if (firstFetchHappened) {
+ return;
+ }
firstFetchHappened = true;
for (byte pos = 0; pos < order.length; pos++) {
if (pos != posBigTable) {
@@ -541,7 +609,9 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
private boolean allFetchDone() {
for (byte pos = 0; pos < order.length; pos++) {
- if (pos != posBigTable && !fetchDone[pos]) return false;
+ if (pos != posBigTable && !fetchDone[pos]) {
+ return false;
+ }
}
return true;
}
@@ -638,7 +708,7 @@ public class CommonMergeJoinOperator extends
AbstractMapJoinOperator<CommonMerge
ObjectInspectorUtils.partialCopyToStandardObject(key, row,
Utilities.ReduceField.KEY.position, 1, (StructObjectInspector)
inputObjInspectors[alias],
ObjectInspectorCopyOption.WRITABLE);
- return (List<Object>) key.get(0); // this is always 0, even if
KEY.position is not
+ return (List<Object>) key.get(0); // this is always 0, even if
KEY.position is not
}
}
diff --git a/ql/src/test/queries/clientpositive/outer_join_unexpected_rows.q
b/ql/src/test/queries/clientpositive/outer_join_unexpected_rows.q
new file mode 100644
index 0000000..57c4409
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/outer_join_unexpected_rows.q
@@ -0,0 +1,17 @@
+
+with
+t_y as (select col1 as id,col2 as s from (VALUES(0,'a'),(1,'y')) as c),
+t_xy as (select col1 as id,col2 as s from (VALUES(1,'x'),(1,'y')) as c)
+select * from t_xy l full outer join t_y r on (l.id=r.id and l.s='y');
+
+create table t_y (id integer,s string);
+create table t_xy (id integer,s string);
+
+insert into t_y values(0,'a'),(1,'y'),(1,'x');
+insert into t_xy values(1,'x'),(1,'y');
+
+select * from t_xy l full outer join t_y r on (l.id=r.id and l.s='y');
+set hive.auto.convert.join=true;
+select * from t_xy l full outer join t_y r on (l.id=r.id and l.s='y');
+set hive.cbo.enable=false;
+select * from t_xy l full outer join t_y r on (l.id=r.id and l.s='y');
diff --git a/ql/src/test/results/clientpositive/llap/join46.q.out
b/ql/src/test/results/clientpositive/llap/join46.q.out
index e4f393e..a938989 100644
--- a/ql/src/test/results/clientpositive/llap/join46.q.out
+++ b/ql/src/test/results/clientpositive/llap/join46.q.out
@@ -278,11 +278,11 @@ POSTHOOK: Input: default@test1_n2
POSTHOOK: Input: default@test2_n0
#### A masked pattern was here ####
99 0 Alice NULL NULL NULL
-100 1 Bob NULL NULL NULL
99 2 Mat NULL NULL NULL
-101 2 Car 102 2 Del
+100 1 Bob NULL NULL NULL
NULL NULL None NULL NULL NULL
98 NULL None NULL NULL NULL
+101 2 Car 102 2 Del
Warning: Shuffle Join MERGEJOIN[11][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
PREHOOK: query: EXPLAIN
SELECT *
diff --git a/ql/src/test/results/clientpositive/llap/join_1to1.q.out
b/ql/src/test/results/clientpositive/llap/join_1to1.q.out
index 8495894..1ccb613 100644
--- a/ql/src/test/results/clientpositive/llap/join_1to1.q.out
+++ b/ql/src/test/results/clientpositive/llap/join_1to1.q.out
@@ -373,9 +373,6 @@ NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
@@ -466,9 +463,6 @@ NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
@@ -589,6 +583,7 @@ POSTHOOK: Input: default@join_1to1_2
60 10040 66 60 10040 66
60 10040 66 60 10040 66
70 10040 66 NULL NULL NULL
+70 10040 66 NULL NULL NULL
80 10040 88 NULL NULL NULL
80 10040 88 NULL NULL NULL
NULL 10050 66 NULL NULL NULL
@@ -597,22 +592,10 @@ NULL NULL NULL 10 10010 66
NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
-NULL NULL NULL 40 10040 66
NULL NULL NULL 40 10040 88
-NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
-NULL NULL NULL 50 10050 88
-NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
-NULL NULL NULL 70 10040 88
-NULL NULL NULL 80 10040 66
-NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL NULL 10050 66
@@ -690,6 +673,7 @@ POSTHOOK: Input: default@join_1to1_2
60 10040 66 60 10040 66
60 10040 66 60 10040 66
70 10040 66 NULL NULL NULL
+70 10040 66 NULL NULL NULL
80 10040 88 NULL NULL NULL
80 10040 88 NULL NULL NULL
NULL 10050 66 NULL NULL NULL
@@ -698,22 +682,10 @@ NULL NULL NULL 10 10010 66
NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
-NULL NULL NULL 40 10040 66
-NULL NULL NULL 40 10040 88
NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
-NULL NULL NULL 70 10040 88
-NULL NULL NULL 70 10040 88
-NULL NULL NULL 80 10040 66
-NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL NULL 10050 66
@@ -1061,9 +1033,6 @@ NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
@@ -1154,9 +1123,6 @@ NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
@@ -1277,6 +1243,7 @@ POSTHOOK: Input: default@join_1to1_2
60 10040 66 60 10040 66
60 10040 66 60 10040 66
70 10040 66 NULL NULL NULL
+70 10040 66 NULL NULL NULL
80 10040 88 NULL NULL NULL
80 10040 88 NULL NULL NULL
NULL 10050 66 NULL NULL NULL
@@ -1285,22 +1252,10 @@ NULL NULL NULL 10 10010 66
NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
-NULL NULL NULL 40 10040 66
NULL NULL NULL 40 10040 88
-NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
-NULL NULL NULL 50 10050 88
-NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
-NULL NULL NULL 70 10040 88
-NULL NULL NULL 80 10040 66
-NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL NULL 10050 66
@@ -1378,6 +1333,7 @@ POSTHOOK: Input: default@join_1to1_2
60 10040 66 60 10040 66
60 10040 66 60 10040 66
70 10040 66 NULL NULL NULL
+70 10040 66 NULL NULL NULL
80 10040 88 NULL NULL NULL
80 10040 88 NULL NULL NULL
NULL 10050 66 NULL NULL NULL
@@ -1386,22 +1342,10 @@ NULL NULL NULL 10 10010 66
NULL NULL NULL 25 10025 66
NULL NULL NULL 30 10030 88
NULL NULL NULL 35 10035 88
-NULL NULL NULL 40 10040 66
-NULL NULL NULL 40 10040 88
NULL NULL NULL 40 10040 88
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 66
-NULL NULL NULL 50 10050 88
-NULL NULL NULL 50 10050 88
NULL NULL NULL 50 10050 88
NULL NULL NULL 70 10040 88
NULL NULL NULL 70 10040 88
-NULL NULL NULL 70 10040 88
-NULL NULL NULL 70 10040 88
-NULL NULL NULL 80 10040 66
-NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL 80 10040 66
NULL NULL NULL NULL 10050 66
diff --git a/ql/src/test/results/clientpositive/llap/join_emit_interval.q.out
b/ql/src/test/results/clientpositive/llap/join_emit_interval.q.out
index b4b320b..996a740 100644
--- a/ql/src/test/results/clientpositive/llap/join_emit_interval.q.out
+++ b/ql/src/test/results/clientpositive/llap/join_emit_interval.q.out
@@ -155,12 +155,12 @@ POSTHOOK: Input: default@test1_n7
POSTHOOK: Input: default@test2_n4
#### A masked pattern was here ####
99 0 Alice NULL NULL NULL
-100 1 Bob NULL NULL NULL
99 2 Mat NULL NULL NULL
-101 2 Car 102 2 Del
-101 2 Car 103 2 Ema
+100 1 Bob NULL NULL NULL
NULL NULL None NULL NULL NULL
98 NULL None NULL NULL NULL
+101 2 Car 102 2 Del
+101 2 Car 103 2 Ema
Warning: Shuffle Join MERGEJOIN[9][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
PREHOOK: query: EXPLAIN
SELECT *
diff --git a/ql/src/test/results/clientpositive/llap/mapjoin2.q.out
b/ql/src/test/results/clientpositive/llap/mapjoin2.q.out
index 4285ac1..814344f 100644
--- a/ql/src/test/results/clientpositive/llap/mapjoin2.q.out
+++ b/ql/src/test/results/clientpositive/llap/mapjoin2.q.out
@@ -337,8 +337,8 @@ POSTHOOK: query: select isnull(a.n), isnull(a.t),
isnull(b.n), isnull(b.t) from
POSTHOOK: type: QUERY
POSTHOOK: Input: default@tbl_n1
#### A masked pattern was here ####
-false false true true
true true false false
+false false true true
Warning: Map Join MAPJOIN[9][bigTable=?] in task 'Map 1' is a cross product
PREHOOK: query: explain
select a.key, a.a_one, b.b_one, a.a_zero, b.b_zero from ( SELECT 11 key, 0
confuse_you, 1 a_one, 0 a_zero ) a join ( SELECT 11 key, 0 confuse_you, 1
b_one, 0 b_zero ) b on a.key = b.key
diff --git
a/ql/src/test/results/clientpositive/llap/outer_join_unexpected_rows.q.out
b/ql/src/test/results/clientpositive/llap/outer_join_unexpected_rows.q.out
new file mode 100644
index 0000000..4b1dbd7
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/outer_join_unexpected_rows.q.out
@@ -0,0 +1,95 @@
+PREHOOK: query: with
+t_y as (select col1 as id,col2 as s from (VALUES(0,'a'),(1,'y')) as c),
+t_xy as (select col1 as id,col2 as s from (VALUES(1,'x'),(1,'y')) as c)
+select * from t_xy l full outer join t_y r on (l.id=r.id and l.s='y')
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: with
+t_y as (select col1 as id,col2 as s from (VALUES(0,'a'),(1,'y')) as c),
+t_xy as (select col1 as id,col2 as s from (VALUES(1,'x'),(1,'y')) as c)
+select * from t_xy l full outer join t_y r on (l.id=r.id and l.s='y')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+1 x NULL NULL
+NULL NULL 0 a
+1 y 1 y
+PREHOOK: query: create table t_y (id integer,s string)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t_y
+POSTHOOK: query: create table t_y (id integer,s string)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t_y
+PREHOOK: query: create table t_xy (id integer,s string)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t_xy
+POSTHOOK: query: create table t_xy (id integer,s string)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t_xy
+PREHOOK: query: insert into t_y values(0,'a'),(1,'y'),(1,'x')
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t_y
+POSTHOOK: query: insert into t_y values(0,'a'),(1,'y'),(1,'x')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t_y
+POSTHOOK: Lineage: t_y.id SCRIPT []
+POSTHOOK: Lineage: t_y.s SCRIPT []
+PREHOOK: query: insert into t_xy values(1,'x'),(1,'y')
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t_xy
+POSTHOOK: query: insert into t_xy values(1,'x'),(1,'y')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t_xy
+POSTHOOK: Lineage: t_xy.id SCRIPT []
+POSTHOOK: Lineage: t_xy.s SCRIPT []
+PREHOOK: query: select * from t_xy l full outer join t_y r on (l.id=r.id and
l.s='y')
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t_xy
+PREHOOK: Input: default@t_y
+#### A masked pattern was here ####
+POSTHOOK: query: select * from t_xy l full outer join t_y r on (l.id=r.id and
l.s='y')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t_xy
+POSTHOOK: Input: default@t_y
+#### A masked pattern was here ####
+1 x NULL NULL
+NULL NULL 0 a
+1 y 1 y
+1 y 1 x
+PREHOOK: query: select * from t_xy l full outer join t_y r on (l.id=r.id and
l.s='y')
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t_xy
+PREHOOK: Input: default@t_y
+#### A masked pattern was here ####
+POSTHOOK: query: select * from t_xy l full outer join t_y r on (l.id=r.id and
l.s='y')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t_xy
+POSTHOOK: Input: default@t_y
+#### A masked pattern was here ####
+1 x NULL NULL
+NULL NULL 0 a
+1 y 1 y
+1 y 1 x
+PREHOOK: query: select * from t_xy l full outer join t_y r on (l.id=r.id and
l.s='y')
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t_xy
+PREHOOK: Input: default@t_y
+#### A masked pattern was here ####
+POSTHOOK: query: select * from t_xy l full outer join t_y r on (l.id=r.id and
l.s='y')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t_xy
+POSTHOOK: Input: default@t_y
+#### A masked pattern was here ####
+1 x NULL NULL
+NULL NULL 0 a
+1 y 1 y
+1 y 1 x
diff --git
a/ql/src/test/results/clientpositive/llap/vector_full_outer_join2.q.out
b/ql/src/test/results/clientpositive/llap/vector_full_outer_join2.q.out
index b764fe5..ea54dd6 100644
--- a/ql/src/test/results/clientpositive/llap/vector_full_outer_join2.q.out
+++ b/ql/src/test/results/clientpositive/llap/vector_full_outer_join2.q.out
@@ -75,17 +75,17 @@ POSTHOOK: Input: default@t_letters
POSTHOOK: Input: default@t_roman
#### A masked pattern was here ####
one 1 50 NULL NULL NULL
-NULL NULL NULL I 1 50
two 2 30 NULL NULL NULL
-NULL NULL NULL II 2 30
three 3 30 NULL NULL NULL
+NULL NULL NULL I 1 50
+NULL NULL NULL II 2 30
+NULL NULL NULL IV 4 60
+NULL NULL NULL V 5 70
+NULL NULL NULL VI 6 80
NULL NULL NULL III 3 30
four 4 60 NULL NULL NULL
-NULL NULL NULL IV 4 60
five 5 70 NULL NULL NULL
-NULL NULL NULL V 5 70
six 6 80 NULL NULL NULL
-NULL NULL NULL VI 6 80
PREHOOK: query: select x1.`z`, x1.`x`, x1.`y`,
x2.`z`, x2.`x`, x2.`y`
from t_letters x1 full outer join t_roman x2 on (x1.`x` > 2) and (x2.`x` < 4)
and (x1.`x` = x2.`x`)
@@ -101,13 +101,13 @@ POSTHOOK: Input: default@t_letters
POSTHOOK: Input: default@t_roman
#### A masked pattern was here ####
one 1 50 NULL NULL NULL
-NULL NULL NULL I 1 50
two 2 30 NULL NULL NULL
+NULL NULL NULL I 1 50
NULL NULL NULL II 2 30
+NULL NULL NULL IV 4 60
+NULL NULL NULL V 5 70
+NULL NULL NULL VI 6 80
three 3 30 III 3 30
four 4 60 NULL NULL NULL
-NULL NULL NULL IV 4 60
five 5 70 NULL NULL NULL
-NULL NULL NULL V 5 70
six 6 80 NULL NULL NULL
-NULL NULL NULL VI 6 80