Skip to content

Commit

Permalink
Merge pull request #2606 from VoltDB/ENG-8692-outerjoin-fix-5.4-patch
Browse files Browse the repository at this point in the history
Fix the reverse scan null predicate missing issue for JOIN case
  • Loading branch information
xinjiacs committed Jul 27, 2015
2 parents 232154b + dfcc706 commit 0727225
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 10 deletions.
16 changes: 11 additions & 5 deletions src/frontend/org/voltdb/planner/SelectSubPlanAssembler.java
Expand Up @@ -580,8 +580,11 @@ private AbstractPlanNode getSelectSubPlanForJoin(BranchNode joinNode,
// InnerPlan is an IndexScan. In this case the inner and inner-outer
// non-index join expressions (if any) are in the otherExpr. The former should stay as
// an IndexScanPlan predicate and the latter stay at the NLJ node as a join predicate
List<AbstractExpression> innerExpr = filterSingleTVEExpressions(innerAccessPath.otherExprs);
joinClauses.addAll(innerAccessPath.otherExprs);
ArrayList<AbstractExpression> otherExprs = new ArrayList<AbstractExpression>();
// PLEASE do not update the "innerAccessPath.otherExprs", it may be reused
// for other path evaluation on the other outer side join.
List<AbstractExpression> innerExpr = filterSingleTVEExpressions(innerAccessPath.otherExprs, otherExprs);
joinClauses.addAll(otherExprs);
AbstractExpression indexScanPredicate = ExpressionUtil.combine(innerExpr);
((IndexScanPlanNode)innerPlan).setPredicate(indexScanPredicate);
}
Expand Down Expand Up @@ -644,19 +647,22 @@ else if (canHaveNLIJ) {
/**
* A method to filter out single TVE expressions.
*
* @param expr List of expressions.
* @param expr List of single TVE expressions.
* @param otherExprs List of expressions other than TVE.
* @return List of single TVE expressions from the input collection.
* They are also removed from the input.
*/
private static List<AbstractExpression> filterSingleTVEExpressions(List<AbstractExpression> exprs) {
private static List<AbstractExpression> filterSingleTVEExpressions(List<AbstractExpression> exprs,
List<AbstractExpression> otherExprs) {
List<AbstractExpression> singleTVEExprs = new ArrayList<AbstractExpression>();
for (AbstractExpression expr : exprs) {
List<TupleValueExpression> tves = ExpressionUtil.getTupleValueExpressions(expr);
if (tves.size() == 1) {
singleTVEExprs.add(expr);
} else {
otherExprs.add(expr);
}
}
exprs.removeAll(singleTVEExprs);
return singleTVEExprs;
}

Expand Down
Expand Up @@ -836,23 +836,30 @@ private void subtestOuterJoinMultiTable(Client client)
private void subtestOuterJoinENG8692(Client client)
throws NoConnectionsException, IOException, ProcCallException
{

client.callProcedure("@AdHoc", "INSERT INTO t1 VALUES(1);");
client.callProcedure("@AdHoc", "INSERT INTO t2 VALUES(1);");
client.callProcedure("@AdHoc", "INSERT INTO t3 VALUES(1);");
client.callProcedure("@AdHoc", "INSERT INTO t4 VALUES(1);");
client.callProcedure("@AdHoc", "INSERT INTO t4 VALUES(null);");

String sql;
long MINVAL = Long.MIN_VALUE;

// case 1: missing join expression
sql = "SELECT * FROM t1 INNER JOIN t2 ON t1.i1 = t2.i2 RIGHT OUTER JOIN t3 ON t1.i1 = 1000;";
validateTableOfLongs(client, sql, new long[][]{{MINVAL, MINVAL, 1}});

// case 2: more than 5 table joins
sql = "SELECT * FROM t1 INNER JOIN t2 AS t2_copy1 ON t1.i1 = t2_copy1.i2 "
+ "INNER JOIN t2 AS t2_copy2 ON t1.i1 = t2_copy2.i2 "
+ "INNER JOIN t2 AS t2_copy3 ON t1.i1 = t2_copy3.i2 "
+ "INNER JOIN t2 AS t2_copy4 ON t1.i1 = t2_copy4.i2 "
+ "RIGHT OUTER JOIN t3 ON t1.i1 = t3.i3 AND t3.i3 < -1000;";
validateTableOfLongs(client, sql, new long[][]{{MINVAL, MINVAL, MINVAL, MINVAL, MINVAL, 1}});

// case 3: reverse scan with null data
sql = "SELECT * FROM t1 INNER JOIN t2 ON t1.i1= t2.i2 INNER JOIN t4 ON t4.i4 < 45;";
validateTableOfLongs(client, sql, new long[][]{{1, 1, 1}});
}


Expand Down
4 changes: 3 additions & 1 deletion tests/frontend/org/voltdb/regressionsuites/testjoins-ddl.sql
Expand Up @@ -40,4 +40,6 @@ PARTITION TABLE P3 ON COLUMN A;
-- ENG-8692
CREATE TABLE t1(i1 INTEGER);
CREATE TABLE t2(i2 INTEGER);
CREATE TABLE t3(i3 INTEGER);
CREATE TABLE t3(i3 INTEGER);
CREATE TABLE t4(i4 INTEGER);
CREATE INDEX t4_idx ON T4 (i4);
6 changes: 3 additions & 3 deletions tests/scripts/examples/sql_coverage/join-template.sql
Expand Up @@ -46,6 +46,6 @@ SELECT * FROM @fromtables LHS39 @jointype JOIN @fromtables RHS ON LHS39.@idcol
SELECT * FROM @fromtables LHS40 @jointype JOIN @fromtables MHS ON LHS40.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON LHS40.@numcol = RHS.@numcol
SELECT @idcol, @numcol FROM @fromtables LHS41 @jointype JOIN @fromtables MHS ON LHS41.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON LHS41.@numcol = RHS.@numcol

SELECT * FROM @fromtables LHS42 @jointype JOIN @fromtables MHS ON LHS42.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON LHS42.@numcol < 45;
SELECT * FROM @fromtables LHS43 @jointype JOIN @fromtables MHS ON LHS43.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON MHS.@numcol < 45;
SELECT * FROM @fromtables LHS44 @jointype JOIN @fromtables MHS ON LHS44.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON RHS.@numcol < 45;
SELECT * FROM @fromtables LHS42 @jointype JOIN @fromtables MHS ON LHS42.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON LHS42.@numcol _cmp 45;
SELECT * FROM @fromtables LHS43 @jointype JOIN @fromtables MHS ON LHS43.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON MHS.@numcol _cmp 45;
SELECT * FROM @fromtables LHS44 @jointype JOIN @fromtables MHS ON LHS44.@idcol = MHS.@idcol @jointype JOIN @fromtables RHS ON RHS.@numcol _cmp 45;

0 comments on commit 0727225

Please sign in to comment.