private static FilterExpression PrepareJoins(QueryTableSetPlanner tablePlanner, TableSelectExpression expression, TableExpressionFromSet fromSet, FilterExpression whereClause) { // Look at the join set and resolve the ON Expression to this statement JoiningSet joinSet = expression.From.JoinSet; var result = whereClause; // Perform a quick scan and see if there are any outer joins in the // expression. bool allInnerJoins = true; for (int i = 0; i < joinSet.TableCount - 1; ++i) { JoinType type = joinSet.GetJoinType(i); if (type != JoinType.Inner) { allInnerJoins = false; } } // Prepare the joins for (int i = 0; i < joinSet.TableCount - 1; ++i) { JoinType type = joinSet.GetJoinType(i); Expression onExpression = joinSet.GetOnExpression(i); if (allInnerJoins) { // If the whole join set is inner joins then simply move the on // expression (if there is one) to the WHERE clause. if (onExpression != null) { result = result.Append(onExpression); } } else { // Not all inner joins, if (type == JoinType.Inner && onExpression == null) { // Regular join with no ON expression, so no preparation necessary } else { // Either an inner join with an ON expression, or an outer join with // ON expression if (onExpression == null) { throw new Exception("No ON expression in join."); } // Resolve the on_expression onExpression = onExpression.Prepare(fromSet.ExpressionQualifier); // And set it in the planner tablePlanner.SetJoinInfoBetweenSources(i, type, onExpression); } } } return(result); }
private static QueryTableSetPlanner SetupPlanners(IDatabaseConnection db, TableExpressionFromSet fromSet) { // Set up plans for each table in the from clause of the command. For // sub-queries, we recurse. var tablePlanner = new QueryTableSetPlanner(); for (int i = 0; i < fromSet.SetCount; ++i) { IFromTableSource table = fromSet.GetTable(i); if (table is FromTableSubQuerySource) { // This represents a sub-command in the FROM clause var sqlTable = (FromTableSubQuerySource)table; TableSelectExpression sqlExpr = sqlTable.TableExpression; TableExpressionFromSet sqlFromSet = sqlTable.FromSet; // Form a plan for evaluating the sub-command FROM IQueryPlanNode sqlPlan = FormQueryPlan(db, sqlExpr, sqlFromSet, null); // The top should always be a SubsetNode, if (sqlPlan is SubsetNode) { var subsetNode = (SubsetNode)sqlPlan; subsetNode.SetGivenName(sqlTable.AliasedName); } else { throw new Exception("Top plan is not a SubsetNode!"); } tablePlanner.AddTableSource(sqlPlan, sqlTable); } else if (table is FromTableDirectSource) { // This represents a direct referencable table in the FROM clause var dsTable = (FromTableDirectSource)table; IQueryPlanNode dsPlan = dsTable.CreateFetchQueryPlanNode(); tablePlanner.AddTableSource(dsPlan, dsTable); } else { throw new Exception("Unknown table source instance: " + table.GetType()); } } return(tablePlanner); }