Exemple #1
0
/*
 * Generate plan for a UNION or UNION ALL node
 */
static Plan *
generate_union_plan(SetOperationStmt *op, Query *parse,
                    List *refnames_tlist)
{
    List	   *planlist;
    List	   *tlist;
    Plan	   *plan;

    /*
     * If any of my children are identical UNION nodes (same op, all-flag,
     * and colTypes) then they can be merged into this node so that we
     * generate only one Append and Sort for the lot.  Recurse to find
     * such nodes and compute their children's plans.
     */
    planlist = nconc(recurse_union_children(op->larg, parse,
                                            op, refnames_tlist),
                     recurse_union_children(op->rarg, parse,
                                            op, refnames_tlist));

    /*
     * Generate tlist for Append plan node.
     *
     * The tlist for an Append plan isn't important as far as the Append is
     * concerned, but we must make it look real anyway for the benefit of
     * the next plan level up.
     */
    tlist = generate_append_tlist(op->colTypes, false,
                                  planlist, refnames_tlist);

    /*
     * Append the child results together.
     */
    plan = (Plan *) make_append(planlist, false, tlist);

    /*
     * For UNION ALL, we just need the Append plan.  For UNION, need to
     * add Sort and Unique nodes to produce unique output.
     */
    if (!op->all)
    {
        List	   *sortList;

        tlist = copyObject(tlist);
        sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
        plan = (Plan *) make_sort_from_sortclauses(parse, tlist,
                plan, sortList);
        plan = (Plan *) make_unique(tlist, plan, sortList);
    }
    return plan;
}
Exemple #2
0
/*
 * Generate plan for an INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL node
 */
static Plan *
generate_nonunion_plan(SetOperationStmt *op, Query *parse,
                       List *refnames_tlist)
{
    Plan	   *lplan,
               *rplan,
               *plan;
    List	   *tlist,
               *sortList,
               *planlist;
    SetOpCmd	cmd;

    /* Recurse on children, ensuring their outputs are marked */
    lplan = recurse_set_operations(op->larg, parse,
                                   op->colTypes, false, 0,
                                   refnames_tlist);
    rplan = recurse_set_operations(op->rarg, parse,
                                   op->colTypes, false, 1,
                                   refnames_tlist);
    planlist = makeList2(lplan, rplan);

    /*
     * Generate tlist for Append plan node.
     *
     * The tlist for an Append plan isn't important as far as the Append is
     * concerned, but we must make it look real anyway for the benefit of
     * the next plan level up.	In fact, it has to be real enough that the
     * flag column is shown as a variable not a constant, else setrefs.c
     * will get confused.
     */
    tlist = generate_append_tlist(op->colTypes, true,
                                  planlist, refnames_tlist);

    /*
     * Append the child results together.
     */
    plan = (Plan *) make_append(planlist, false, tlist);

    /*
     * Sort the child results, then add a SetOp plan node to generate the
     * correct output.
     */
    tlist = copyObject(tlist);
    sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
    plan = (Plan *) make_sort_from_sortclauses(parse, tlist, plan, sortList);
    switch (op->op)
    {
    case SETOP_INTERSECT:
        cmd = op->all ? SETOPCMD_INTERSECT_ALL : SETOPCMD_INTERSECT;
        break;
    case SETOP_EXCEPT:
        cmd = op->all ? SETOPCMD_EXCEPT_ALL : SETOPCMD_EXCEPT;
        break;
    default:
        elog(ERROR, "unrecognized set op: %d",
             (int) op->op);
        cmd = SETOPCMD_INTERSECT;	/* keep compiler quiet */
        break;
    }
    plan = (Plan *) make_setop(cmd, tlist, plan, sortList,
                               length(op->colTypes) + 1);
    return plan;
}
/*
 * Generate plan for a UNION or UNION ALL node
 */
static Plan *
generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
					double tuple_fraction,
					List *refnames_tlist,
					List **sortClauses)
{
	List	   *planlist;
	List	   *tlist;
	Plan	   *plan;

	/*
	 * If plain UNION, tell children to fetch all tuples.
	 *
	 * Note: in UNION ALL, we pass the top-level tuple_fraction unmodified to
	 * each arm of the UNION ALL.  One could make a case for reducing the
	 * tuple fraction for later arms (discounting by the expected size of the
	 * earlier arms' results) but it seems not worth the trouble. The normal
	 * case where tuple_fraction isn't already zero is a LIMIT at top level,
	 * and passing it down as-is is usually enough to get the desired result
	 * of preferring fast-start plans.
	 */
	if (!op->all)
		tuple_fraction = 0.0;

	/*
	 * If any of my children are identical UNION nodes (same op, all-flag, and
	 * colTypes) then they can be merged into this node so that we generate
	 * only one Append and Sort for the lot.  Recurse to find such nodes and
	 * compute their children's plans.
	 */
	planlist = list_concat(recurse_union_children(op->larg, root,
												  tuple_fraction,
												  op, refnames_tlist),
						   recurse_union_children(op->rarg, root,
												  tuple_fraction,
												  op, refnames_tlist));

	/*
	 * Generate tlist for Append plan node.
	 *
	 * The tlist for an Append plan isn't important as far as the Append is
	 * concerned, but we must make it look real anyway for the benefit of the
	 * next plan level up.
	 */
	tlist = generate_append_tlist(op->colTypes, false,
								  planlist, refnames_tlist);

	/*
	 * Append the child results together.
	 */
	plan = (Plan *) make_append(planlist, false, tlist);

	/*
	 * For UNION ALL, we just need the Append plan.  For UNION, need to add
	 * Sort and Unique nodes to produce unique output.
	 */
	if (!op->all)
	{
		List	   *sortList;

		sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
		if (sortList)
		{
			plan = (Plan *) make_sort_from_sortclauses(root, sortList, plan);
			plan = (Plan *) make_unique(plan, sortList);
		}
		*sortClauses = sortList;
	}
	else
		*sortClauses = NIL;

	return plan;
}