Index: ql/src/test/results/clientpositive/join12.q.out =================================================================== --- ql/src/test/results/clientpositive/join12.q.out (revision 738963) +++ ql/src/test/results/clientpositive/join12.q.out (working copy) @@ -84,7 +84,7 @@ Join Operator condition map: Inner Join 0 to 1 - Inner Join 0 to 1 + Inner Join 0 to 2 condition expressions: 0 {VALUE.0} {VALUE.1} 1 {VALUE.0} {VALUE.1} Index: ql/src/test/results/clientpositive/join19.q.out =================================================================== --- ql/src/test/results/clientpositive/join19.q.out (revision 738963) +++ ql/src/test/results/clientpositive/join19.q.out (working copy) @@ -110,7 +110,7 @@ Join Operator condition map: Inner Join 0 to 1 - Inner Join 0 to 1 + Inner Join 0 to 2 condition expressions: 0 {VALUE.0} 1 {VALUE.0} {VALUE.1} @@ -212,7 +212,7 @@ Join Operator condition map: Inner Join 0 to 1 - Inner Join 1 to 1 + Inner Join 1 to 2 condition expressions: 0 {VALUE.0} {VALUE.1} {VALUE.2} {VALUE.3} {VALUE.4} 1 {VALUE.0} Index: ql/src/test/results/clientpositive/join20.q.out =================================================================== --- ql/src/test/results/clientpositive/join20.q.out (revision 0) +++ ql/src/test/results/clientpositive/join20.q.out (revision 0) @@ -0,0 +1,138 @@ +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +NULL NULL NULL NULL 10 val_10 +NULL NULL NULL NULL 11 val_11 +NULL NULL NULL NULL 12 val_12 +NULL NULL NULL NULL 12 val_12 +NULL NULL NULL NULL 15 val_15 +NULL NULL NULL NULL 15 val_15 +NULL NULL NULL NULL 17 val_17 +NULL NULL NULL NULL 18 val_18 +NULL NULL NULL NULL 18 val_18 +NULL NULL NULL NULL 19 val_19 +2 val_2 2 val_2 2 val_2 +4 val_4 4 val_4 4 val_4 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +8 val_8 8 val_8 8 val_8 +9 val_9 9 val_9 9 val_9 +68 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +0 val_0 0 val_0 0 val_0 +NULL NULL NULL NULL 10 val_10 +NULL NULL NULL NULL 11 val_11 +NULL NULL NULL NULL 12 val_12 +NULL NULL NULL NULL 12 val_12 +NULL NULL NULL NULL 15 val_15 +NULL NULL NULL NULL 15 val_15 +NULL NULL NULL NULL 17 val_17 +NULL NULL NULL NULL 18 val_18 +NULL NULL NULL NULL 18 val_18 +NULL NULL NULL NULL 19 val_19 +2 val_2 2 val_2 2 val_2 +4 val_4 4 val_4 4 val_4 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +5 val_5 5 val_5 5 val_5 +8 val_8 8 val_8 8 val_8 +9 val_9 9 val_9 9 val_9 +68 Index: ql/src/test/results/clientpositive/join3.q.out =================================================================== --- ql/src/test/results/clientpositive/join3.q.out (revision 738963) +++ ql/src/test/results/clientpositive/join3.q.out (working copy) @@ -62,7 +62,7 @@ Join Operator condition map: Inner Join 0 to 1 - Inner Join 0 to 1 + Inner Join 0 to 2 condition expressions: 0 {VALUE.0} 1 {VALUE.0} Index: ql/src/test/results/clientpositive/join7.q.out =================================================================== --- ql/src/test/results/clientpositive/join7.q.out (revision 738963) +++ ql/src/test/results/clientpositive/join7.q.out (working copy) @@ -88,7 +88,7 @@ Join Operator condition map: Outer Join 0 to 1 - Left Outer Join0 to 1 + Left Outer Join0 to 2 condition expressions: 0 {VALUE.0} {VALUE.1} 1 {VALUE.0} {VALUE.1} Index: ql/src/test/queries/clientpositive/join20.q =================================================================== --- ql/src/test/queries/clientpositive/join20.q (revision 0) +++ ql/src/test/queries/clientpositive/join20.q (revision 0) @@ -0,0 +1,8 @@ +SELECT * FROM src src1 JOIN src src2 ON (src1.key = src2.key AND src1.key < 10) RIGHT OUTER JOIN src src3 ON (src1.key = src3.key AND src3.key < 20); + +SELECT count(1) FROM src src1 JOIN src src2 ON (src1.key = src2.key AND src1.key < 10) RIGHT OUTER JOIN src src3 ON (src1.key = src3.key AND src3.key < 20); + + +SELECT * FROM src src1 JOIN src src2 ON (src1.key = src2.key AND src1.key < 10 AND src2.key < 15) RIGHT OUTER JOIN src src3 ON (src1.key = src3.key AND src3.key < 20); + +SELECT count(1) FROM src src1 JOIN src src2 ON (src1.key = src2.key AND src1.key < 10 AND src2.key < 15) RIGHT OUTER JOIN src src3 ON (src1.key = src3.key AND src3.key < 20); Index: ql/src/java/org/apache/hadoop/hive/ql/exec/JoinOperator.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/JoinOperator.java (revision 738963) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/JoinOperator.java (working copy) @@ -305,11 +305,21 @@ private Vector joinObjectsRightOuterJoin( Vector resNulls, Vector inputNulls, ArrayList newObj, IntermediateObject intObj, int left, - boolean newObjNull) { + boolean newObjNull, boolean firstRow) { if (newObjNull) return resNulls; - boolean allOldObjsNull = true; + if (inputNulls.isEmpty() && firstRow) { + boolean[] newNulls = new boolean[intObj.getCurSize()]; + for (int i = 0; i < intObj.getCurSize() - 1; i++) + newNulls[i] = true; + newNulls[intObj.getCurSize()-1] = newObjNull; + resNulls.add(newNulls); + return resNulls; + } + + boolean allOldObjsNull = firstRow; + Iterator nullsIter = inputNulls.iterator(); while (nullsIter.hasNext()) { boolean[] oldNulls = nullsIter.next(); @@ -334,6 +344,7 @@ for (int i = 0; i < intObj.getCurSize() - 1; i++) newNulls[i] = true; newNulls[oldNulls.length] = newObjNull; + resNulls.add(newNulls); return resNulls; } } @@ -343,7 +354,7 @@ private Vector joinObjectsFullOuterJoin( Vector resNulls, Vector inputNulls, ArrayList newObj, IntermediateObject intObj, int left, - boolean newObjNull) { + boolean newObjNull, boolean firstRow) { if (newObjNull) { Iterator nullsIter = inputNulls.iterator(); while (nullsIter.hasNext()) { @@ -356,8 +367,17 @@ return resNulls; } - boolean allOldObjsNull = true; + if (inputNulls.isEmpty() && firstRow) { + boolean[] newNulls = new boolean[intObj.getCurSize()]; + for (int i = 0; i < intObj.getCurSize() - 1; i++) + newNulls[i] = true; + newNulls[intObj.getCurSize()-1] = newObjNull; + resNulls.add(newNulls); + return resNulls; + } + boolean allOldObjsNull = firstRow; + Iterator nullsIter = inputNulls.iterator(); while (nullsIter.hasNext()) { boolean[] oldNulls = nullsIter.next(); @@ -405,7 +425,8 @@ * inner join. The outer joins are processed appropriately. */ private Vector joinObjects(Vector inputNulls, - ArrayList newObj, IntermediateObject intObj, int joinPos) { + ArrayList newObj, IntermediateObject intObj, + int joinPos, boolean firstRow) { Vector resNulls = new Vector(); boolean newObjNull = newObj == dummyObj[joinPos] ? true : false; if (joinPos == 0) { @@ -422,7 +443,7 @@ // process all nulls for RIGHT and FULL OUTER JOINS if (((type == joinDesc.RIGHT_OUTER_JOIN) || (type == joinDesc.FULL_OUTER_JOIN)) - && !newObjNull && (inputNulls == null)) { + && !newObjNull && (inputNulls == null) && firstRow) { boolean[] newNulls = new boolean[intObj.getCurSize()]; for (int i = 0; i < newNulls.length - 1; i++) newNulls[i] = true; @@ -442,10 +463,10 @@ left, newObjNull); else if (type == joinDesc.RIGHT_OUTER_JOIN) return joinObjectsRightOuterJoin(resNulls, inputNulls, newObj, intObj, - left, newObjNull); + left, newObjNull, firstRow); assert (type == joinDesc.FULL_OUTER_JOIN); return joinObjectsFullOuterJoin(resNulls, inputNulls, newObj, intObj, left, - newObjNull); + newObjNull, firstRow); } /* @@ -456,7 +477,8 @@ * are accounted for, the output is forwared appropriately. */ private void genObject(Vector inputNulls, int aliasNum, - IntermediateObject intObj) throws HiveException { + IntermediateObject intObj, boolean firstRow) throws HiveException { + boolean childFirstRow = firstRow; if (aliasNum < numValues) { Iterator> aliasRes = storage.get(order[aliasNum]) .iterator(); @@ -465,9 +487,10 @@ ArrayList newObj = aliasRes.next(); intObj.pushObj(newObj); Vector newNulls = joinObjects(inputNulls, newObj, intObj, - aliasNum); - genObject(newNulls, aliasNum + 1, intObj); + aliasNum, childFirstRow); + genObject(newNulls, aliasNum + 1, intObj, firstRow); intObj.popObj(); + firstRow = false; } iterators.pop(); } else { @@ -506,7 +529,7 @@ } LOG.trace("calling genObject"); - genObject(null, 0, new IntermediateObject(new ArrayList[numValues], 0)); + genObject(null, 0, new IntermediateObject(new ArrayList[numValues], 0), true); LOG.trace("called genObject"); } Index: ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java (revision 738963) +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java (working copy) @@ -2618,8 +2618,8 @@ if (nodeCondn.getLeft() == 0) nodeCondn.setLeft(pos); else - nodeCondn.setLeft(nodeCondn.getLeft() + targetCondnsSize - 1); - nodeCondn.setRight(nodeCondn.getRight() + targetCondnsSize - 1); + nodeCondn.setLeft(nodeCondn.getLeft() + targetCondnsSize); + nodeCondn.setRight(nodeCondn.getRight() + targetCondnsSize); newCondns[targetCondnsSize + i] = nodeCondn; }