Exemple #1
0
/*
 * pglogGetForeignPlan
 *		Create a ForeignScan plan node for scanning the foreign table
 */
static ForeignScan *
pglogGetForeignPlan(PlannerInfo *root,
				   RelOptInfo *baserel,
				   Oid foreigntableid,
				   ForeignPath *best_path,
				   List *tlist,
				   List *scan_clauses)
{
	Index		scan_relid = baserel->relid;

	elog(DEBUG1,"Entering function %s",__func__);

	/*
	 * We have no native ability to evaluate restriction clauses, so we just
	 * put all the scan_clauses into the plan node's qual list for the
	 * executor to check.  So all we have to do here is strip RestrictInfo
	 * nodes from the clauses and ignore pseudoconstants (which will be
	 * handled elsewhere).
	 */
	scan_clauses = extract_actual_clauses(scan_clauses, false);

	/* Create the ForeignScan node */
	return make_foreignscan(tlist,
							scan_clauses,
							scan_relid,
							NIL,	/* no expressions to evaluate */
							best_path->fdw_private);
}
static ForeignScan *
cassandraGetForeignPlan(PlannerInfo *root,
						RelOptInfo *baserel,
						Oid foreigntableid,
						ForeignPath *best_path,
						List *tlist,
						List *scan_clauses)
{
	/*
	 * Create a ForeignScan plan node from the selected foreign access path.
	 * This is called at the end of query planning. The parameters are as for
	 * GetForeignRelSize, plus the selected ForeignPath (previously produced
	 * by GetForeignPaths), the target list to be emitted by the plan node,
	 * and the restriction clauses to be enforced by the plan node.
	 *
	 * This function must create and return a ForeignScan plan node; it's
	 * recommended to use make_foreignscan to build the ForeignScan node.
	 *
	 */

	Index		scan_relid = baserel->relid;

	/*
	 * We have no native ability to evaluate restriction clauses, so we just
	 * put all the scan_clauses into the plan node's qual list for the
	 * executor to check. So all we have to do here is strip RestrictInfo
	 * nodes from the clauses and ignore pseudoconstants (which will be
	 * handled elsewhere).
	 */

	elog(DEBUG1,"entering function %s",__func__);

	scan_clauses = extract_actual_clauses(scan_clauses, false);

	/* Create the ForeignScan node */
	return make_foreignscan(tlist,
							scan_clauses,
							scan_relid,
							NIL,	/* no expressions to evaluate */
							NIL);		/* no private state either */

}
Exemple #3
0
/* Take care of joins */
void
pathman_join_pathlist_hook(PlannerInfo *root,
						   RelOptInfo *joinrel,
						   RelOptInfo *outerrel,
						   RelOptInfo *innerrel,
						   JoinType jointype,
						   JoinPathExtraData *extra)
{
	JoinCostWorkspace		workspace;
	JoinType				saved_jointype = jointype;
	RangeTblEntry		   *inner_rte = root->simple_rte_array[innerrel->relid];
	const PartRelationInfo *inner_prel;
	List				   *joinclauses,
						   *otherclauses;
	WalkerContext			context;
	double					paramsel;
	Node				   *part_expr;
	ListCell			   *lc;

	/* Call hooks set by other extensions */
	if (pathman_set_join_pathlist_next)
		pathman_set_join_pathlist_next(root, joinrel, outerrel,
									   innerrel, jointype, extra);

	/* Check that both pg_pathman & RuntimeAppend nodes are enabled */
	if (!IsPathmanReady() || !pg_pathman_enable_runtimeappend)
		return;

	/* We should only consider base relations */
	if (innerrel->reloptkind != RELOPT_BASEREL)
		return;

	/* We shouldn't process tables with active children */
	if (inner_rte->inh)
		return;

	/* We can't handle full or right outer joins */
	if (jointype == JOIN_FULL || jointype == JOIN_RIGHT)
		return;

	/* Check that innerrel is a BASEREL with PartRelationInfo */
	if (innerrel->reloptkind != RELOPT_BASEREL ||
		!(inner_prel = get_pathman_relation_info(inner_rte->relid)))
		return;

	/*
	 * Check if query is:
	 *		1) UPDATE part_table SET = .. FROM part_table.
	 *		2) DELETE FROM part_table USING part_table.
	 *
	 * Either outerrel or innerrel may be a result relation.
	 */
	if ((root->parse->resultRelation == outerrel->relid ||
		 root->parse->resultRelation == innerrel->relid) &&
			(root->parse->commandType == CMD_UPDATE ||
			 root->parse->commandType == CMD_DELETE))
	{
		int		rti = -1,
				count = 0;

		/* Inner relation must be partitioned */
		Assert(inner_prel);

		/* Check each base rel of outer relation */
		while ((rti = bms_next_member(outerrel->relids, rti)) >= 0)
		{
			Oid outer_baserel = root->simple_rte_array[rti]->relid;

			/* Is it partitioned? */
			if (get_pathman_relation_info(outer_baserel))
				count++;
		}

		if (count > 0)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("DELETE and UPDATE queries with a join "
							"of partitioned tables are not supported")));
	}

	/* Skip if inner table is not allowed to act as parent (e.g. FROM ONLY) */
	if (PARENTHOOD_DISALLOWED == get_rel_parenthood_status(inner_rte))
		return;

	/*
	 * These codes are used internally in the planner, but are not supported
	 * by the executor (nor, indeed, by most of the planner).
	 */
	if (jointype == JOIN_UNIQUE_OUTER || jointype == JOIN_UNIQUE_INNER)
		jointype = JOIN_INNER; /* replace with a proper value */

	/* Extract join clauses which will separate partitions */
	if (IS_OUTER_JOIN(extra->sjinfo->jointype))
	{
		extract_actual_join_clauses_compat(extra->restrictlist,
										   joinrel->relids,
										   &joinclauses,
										   &otherclauses);
	}
	else
	{
		/* We can treat all clauses alike for an inner join */
		joinclauses = extract_actual_clauses(extra->restrictlist, false);
		otherclauses = NIL;
	}

	/* Make copy of partitioning expression and fix Var's  varno attributes */
	part_expr = PrelExpressionForRelid(inner_prel, innerrel->relid);

	paramsel = 1.0;
	foreach (lc, joinclauses)
	{
		WrapperNode *wrap;

		InitWalkerContext(&context, part_expr, inner_prel, NULL);
		wrap = walk_expr_tree((Expr *) lfirst(lc), &context);
		paramsel *= wrap->paramsel;
	}
Exemple #4
0
/* Take care of joins */
void
pathman_join_pathlist_hook(PlannerInfo *root,
						   RelOptInfo *joinrel,
						   RelOptInfo *outerrel,
						   RelOptInfo *innerrel,
						   JoinType jointype,
						   JoinPathExtraData *extra)
{
	JoinCostWorkspace		workspace;
	JoinType				saved_jointype = jointype;
	RangeTblEntry		   *inner_rte = root->simple_rte_array[innerrel->relid];
	const PartRelationInfo *inner_prel;
	List				   *joinclauses,
						   *otherclauses;
	WalkerContext			context;
	double					paramsel;
	Node				   *part_expr;
	ListCell			   *lc;

	/* Call hooks set by other extensions */
	if (set_join_pathlist_next)
		set_join_pathlist_next(root, joinrel, outerrel,
							   innerrel, jointype, extra);

	/* Check that both pg_pathman & RuntimeAppend nodes are enabled */
	if (!IsPathmanReady() || !pg_pathman_enable_runtimeappend)
		return;

	/* We should only consider base relations */
	if (innerrel->reloptkind != RELOPT_BASEREL)
		return;

	/* We shouldn't process tables with active children */
	if (inner_rte->inh)
		return;

	/* We can't handle full or right outer joins */
	if (jointype == JOIN_FULL || jointype == JOIN_RIGHT)
		return;

	/* Check that innerrel is a BASEREL with PartRelationInfo */
	if (innerrel->reloptkind != RELOPT_BASEREL ||
		!(inner_prel = get_pathman_relation_info(inner_rte->relid)))
		return;

	/* Skip if inner table is not allowed to act as parent (e.g. FROM ONLY) */
	if (PARENTHOOD_DISALLOWED == get_rel_parenthood_status(root->parse->queryId,
														   inner_rte))
		return;

	/*
	 * These codes are used internally in the planner, but are not supported
	 * by the executor (nor, indeed, by most of the planner).
	 */
	if (jointype == JOIN_UNIQUE_OUTER || jointype == JOIN_UNIQUE_INNER)
		jointype = JOIN_INNER; /* replace with a proper value */

	/* Extract join clauses which will separate partitions */
	if (IS_OUTER_JOIN(extra->sjinfo->jointype))
	{
		extract_actual_join_clauses(extra->restrictlist,
									&joinclauses, &otherclauses);
	}
	else
	{
		/* We can treat all clauses alike for an inner join */
		joinclauses = extract_actual_clauses(extra->restrictlist, false);
		otherclauses = NIL;
	}

	/* Make copy of partitioning expression and fix Var's  varno attributes */
	part_expr = PrelExpressionForRelid(inner_prel, innerrel->relid);

	paramsel = 1.0;
	foreach (lc, joinclauses)
	{
		WrapperNode *wrap;

		InitWalkerContext(&context, part_expr, inner_prel, NULL);
		wrap = walk_expr_tree((Expr *) lfirst(lc), &context);
		paramsel *= wrap->paramsel;
	}
Exemple #5
0
/*
 * GetStreamScanPlan
 */
ForeignScan *
GetStreamScanPlan(PlannerInfo *root, RelOptInfo *baserel,
                  Oid relid, ForeignPath *best_path, List *tlist, List *scan_clauses, Plan *outer_plan)
{
    StreamFdwInfo *sinfo = (StreamFdwInfo *) baserel->fdw_private;
    List *physical_tlist = build_physical_tlist(root, baserel);
    RangeTblEntry *rte = NULL;
    int i;
    TableSampleClause *sample;
    Value *sample_cutoff = NULL;

    /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    scan_clauses = extract_actual_clauses(scan_clauses, false);

    for (i = 1; i <= root->simple_rel_array_size; i++)
    {
        rte = root->simple_rte_array[i];
        if (rte && rte->relid == relid)
            break;
    }

    if (!rte || rte->relid != relid)
        elog(ERROR, "stream RTE missing");

    sample = rte->tablesample;
    if (sample)
    {
        double dcutoff;
        Datum d;
        ExprContext *econtext;
        bool isnull;
        Node *node;
        Expr *expr;
        ExprState *estate;
        ParseState *ps = make_parsestate(NULL);
        float4 percent;

        if (sample->tsmhandler != BERNOULLI_OID)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("tablesample method %s is not supported by streams", get_func_name(sample->tsmhandler)),
                     errhint("Only bernoulli tablesample method can be used with streams.")));

        if (sample->repeatable)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("streams don't support the REPEATABLE clause for tablesample")));

        econtext = CreateStandaloneExprContext();

        ps = make_parsestate(NULL);
        node = (Node *) linitial(sample->args);
        node = transformExpr(ps, node, EXPR_KIND_OTHER);
        expr = expression_planner((Expr *) node);

        estate = ExecInitExpr(expr, NULL);
        d = ExecEvalExpr(estate, econtext, &isnull, NULL);

        free_parsestate(ps);
        FreeExprContext(econtext, false);

        percent = DatumGetFloat4(d);
        if (percent < 0 || percent > 100 || isnan(percent))
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
                     errmsg("sample percentage must be between 0 and 100")));

        dcutoff = rint(((double) RAND_MAX + 1) * percent / 100);
        sample_cutoff = makeInteger((int) dcutoff);
    }

    return make_foreignscan(tlist, scan_clauses, baserel->relid,
                            NIL, list_make3(sinfo->colnames, physical_tlist, sample_cutoff), NIL, NIL, outer_plan);
}