Пример #1
0
static ShareInputScan *make_shareinputscan(PlannerInfo *root, Plan *inputplan) 
{
	ShareInputScan *sisc = NULL;
	Path sipath;

	Assert(IsA(inputplan, Material) || IsA(inputplan, Sort));

	sisc = makeNode(ShareInputScan);
	incr_plan_nsharer(inputplan);


	sisc->plan.targetlist = copyObject(inputplan->targetlist);
	sisc->plan.lefttree = inputplan;
	sisc->plan.flow = copyObject(inputplan->flow); 

	set_plan_share_type((Plan *) sisc, get_plan_share_type(inputplan));
	set_plan_share_id((Plan *) sisc, get_plan_share_id(inputplan));
	sisc->driver_slice = -1;

	sisc->plan.qual = NIL;
	sisc->plan.righttree = NULL;

	cost_shareinputscan(&sipath, root, inputplan->total_cost, inputplan->plan_rows, inputplan->plan_width);

	sisc->plan.startup_cost = sipath.startup_cost;
	sisc->plan.total_cost = sipath.total_cost; 
	sisc->plan.plan_rows = inputplan->plan_rows;
	sisc->plan.plan_width = inputplan->plan_width;

	sisc->plan.extParam = bms_copy(inputplan->extParam);
	sisc->plan.allParam = bms_copy(inputplan->allParam);

	return sisc;
}
Пример #2
0
/*
 * bms_add_members - like bms_union, but left input is recycled
 */
Bitmapset *
bms_add_members(Bitmapset *a, const Bitmapset *b)
{
	Bitmapset  *result;
	const Bitmapset *other;
	int			otherlen;
	int			i;

	/* Handle cases where either input is NULL */
	if (a == NULL)
		return bms_copy(b);
	if (b == NULL)
		return a;
	/* Identify shorter and longer input; copy the longer one if needed */
	if (a->nwords < b->nwords)
	{
		result = bms_copy(b);
		other = a;
	}
	else
	{
		result = a;
		other = b;
	}
	/* And union the shorter input into the result */
	otherlen = other->nwords;
	for (i = 0; i < otherlen; i++)
		result->words[i] |= other->words[i];
	if (result != a)
		pfree(a);
	return result;
}
Пример #3
0
/*
 * bms_intersect - set intersection
 */
Bitmapset *
bms_intersect(const Bitmapset *a, const Bitmapset *b)
{
	Bitmapset  *result;
	const Bitmapset *other;
	int			resultlen;
	int			i;

	/* Handle cases where either input is NULL */
	if (a == NULL || b == NULL)
		return NULL;
	/* Identify shorter and longer input; copy the shorter one */
	if (a->nwords <= b->nwords)
	{
		result = bms_copy(a);
		other = b;
	}
	else
	{
		result = bms_copy(b);
		other = a;
	}
	/* And intersect the longer input with the result */
	resultlen = result->nwords;
	for (i = 0; i < resultlen; i++)
		result->words[i] &= other->words[i];
	return result;
}
Пример #4
0
StreamBatch *StreamBatchCreate(Bitmapset *readers, int num_tuples)
{
	char *ptr = ShmemDynAlloc0(sizeof(StreamBatch) + BITMAPSET_SIZE(readers->nwords) + (bms_num_members(readers) * sizeof(int)));
	StreamBatch *batch = (StreamBatch *) ptr;
	int cq_id;
	int i = 0;

	batch->id = rand() ^ (int) MyProcPid;
	batch->num_tups = num_tuples;
	batch->num_wtups = bms_num_members(readers) * num_tuples;
	SpinLockInit(&batch->mutex);

	ptr += sizeof(StreamBatch);
	batch->readers = (Bitmapset *) ptr;
	memcpy(batch->readers, readers, BITMAPSET_SIZE(readers->nwords));


	ptr += BITMAPSET_SIZE(readers->nwords);
	batch->proc_runs = (int *) ptr;

	readers = bms_copy(readers);
	while ((cq_id = bms_first_member(readers)) != -1)
	{
		CQProcEntry *pentry = GetCQProcEntry(cq_id);
		batch->proc_runs[i] = Max(pentry->proc_runs, pentry->pg_size);
		i++;
	}
	pfree(readers);

	return batch;
}
Пример #5
0
/*
 * bms_difference - set difference (ie, A without members of B)
 */
Bitmapset *
bms_difference(const Bitmapset *a, const Bitmapset *b)
{
	Bitmapset  *result;
	int			shortlen;
	int			i;

	/* Handle cases where either input is NULL */
	if (a == NULL)
		return NULL;
	if (b == NULL)
		return bms_copy(a);
	/* Copy the left input */
	result = bms_copy(a);
	/* And remove b's bits from result */
	shortlen = Min(a->nwords, b->nwords);
	for (i = 0; i < shortlen; i++)
		result->words[i] &= ~b->words[i];
	return result;
}
Пример #6
0
/*
 * _outBitmapset -
 *	   converts a bitmap set of integers
 *
 * Note: the output format is "(b int int ...)", similar to an integer List.
 */
void
_outBitmapset(StringInfo str, const Bitmapset *bms)
{
	Bitmapset  *tmpset;
	int			x;

	appendStringInfoChar(str, '(');
	appendStringInfoChar(str, 'b');
	tmpset = bms_copy(bms);
	while ((x = bms_first_member(tmpset)) >= 0)
		appendStringInfo(str, " %d", x);
	bms_free(tmpset);
	appendStringInfoChar(str, ')');
}
Пример #7
0
/*
 * fixup_inherited_columns
 *
 * When user is querying on a table with children, it implicitly accesses
 * child tables also. So, we also need to check security label of child
 * tables and columns, but here is no guarantee attribute numbers are
 * same between the parent ans children.
 * It returns a bitmapset which contains attribute number of the child
 * table based on the given bitmapset of the parent.
 */
static Bitmapset *
fixup_inherited_columns(Oid parentId, Oid childId, Bitmapset *columns)
{
	AttrNumber	attno;
	Bitmapset  *tmpset;
	Bitmapset  *result = NULL;
	char	   *attname;
	int			index;

	/*
	 * obviously, no need to do anything here
	 */
	if (parentId == childId)
		return columns;

	tmpset = bms_copy(columns);
	while ((index = bms_first_member(tmpset)) > 0)
	{
		attno = index + FirstLowInvalidHeapAttributeNumber;

		/*
		 * whole-row-reference shall be fixed-up later
		 */
		if (attno == InvalidAttrNumber)
		{
			result = bms_add_member(result, index);
			continue;
		}

		attname = get_attname(parentId, attno);
		if (!attname)
			elog(ERROR, "cache lookup failed for attribute %d of relation %u",
				 attno, parentId);
		attno = get_attnum(childId, attname);
		if (attno == InvalidAttrNumber)
			elog(ERROR, "cache lookup failed for attribute %s of relation %u",
				 attname, childId);

		index = attno - FirstLowInvalidHeapAttributeNumber;
		result = bms_add_member(result, index);

		pfree(attname);
	}
	bms_free(tmpset);

	return result;
}
Пример #8
0
/*
 * GetAnyDataNode
 * Pick any data node from given set, but try a preferred node
 */
int
GetAnyDataNode(Bitmapset *nodes)
{
	Bitmapset  *preferred = NULL;
	int			i, nodeid;
	int			nmembers = 0;
	int			members[NumDataNodes];

	for (i = 0; i < num_preferred_data_nodes; i++)
	{
		char ntype = PGXC_NODE_DATANODE;
		nodeid = PGXCNodeGetNodeId(preferred_data_node[i], &ntype);

		/* OK, found one */
		if (bms_is_member(nodeid, nodes))
			preferred = bms_add_member(preferred, nodeid);
	}

	/*
	 * If no preferred data nodes or they are not in the desired set, pick up
	 * from the original set.
	 */
	if (bms_is_empty(preferred))
		preferred = bms_copy(nodes);

	/*
	 * Load balance.
	 * We can not get item from the set, convert it to array
	 */
	while ((nodeid = bms_first_member(preferred)) >= 0)
		members[nmembers++] = nodeid;
	bms_free(preferred);

	/* If there is a single member nothing to balance */
	if (nmembers == 1)
		return members[0];

	/*
	 * In general, the set may contain any number of nodes, and if we save
	 * previous returned index for load balancing the distribution won't be
	 * flat, because small set will probably reset saved value, and lower
	 * indexes will be picked up more often.
	 * So we just get a random value from 0..nmembers-1.
	 */
	return members[((unsigned int) random()) % nmembers];
}
Пример #9
0
/*
 * fixup_whole_row_references
 *
 * When user reference a whole of row, it is equivalent to reference to
 * all the user columns (not system columns). So, we need to fix up the
 * given bitmapset, if it contains a whole of the row reference.
 */
static Bitmapset *
fixup_whole_row_references(Oid relOid, Bitmapset *columns)
{
	Bitmapset  *result;
	HeapTuple	tuple;
	AttrNumber	natts;
	AttrNumber	attno;
	int			index;

	/* if no whole of row references, do not anything */
	index = InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber;
	if (!bms_is_member(index, columns))
		return columns;

	/* obtain number of attributes */
	tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
	if (!HeapTupleIsValid(tuple))
		elog(ERROR, "cache lookup failed for relation %u", relOid);
	natts = ((Form_pg_class) GETSTRUCT(tuple))->relnatts;
	ReleaseSysCache(tuple);

	/* fix up the given columns */
	result = bms_copy(columns);
	result = bms_del_member(result, index);

	for (attno = 1; attno <= natts; attno++)
	{
		tuple = SearchSysCache2(ATTNUM,
								ObjectIdGetDatum(relOid),
								Int16GetDatum(attno));
		if (!HeapTupleIsValid(tuple))
			continue;

		if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
			continue;

		index = attno - FirstLowInvalidHeapAttributeNumber;

		result = bms_add_member(result, index);

		ReleaseSysCache(tuple);
	}
	return result;
}
Пример #10
0
/*
 * Add new entry or update existing entry in the relation map cache.
 *
 * Called when new relation mapping is sent by the publisher to update
 * our expected view of incoming data from said publisher.
 */
void
logicalrep_relmap_update(LogicalRepRelation *remoterel)
{
	MemoryContext			oldctx;
	LogicalRepRelMapEntry  *entry;
	bool					found;
	int						i;

	if (LogicalRepRelMap == NULL)
		logicalrep_relmap_init();

	/*
	 * HASH_ENTER returns the existing entry if present or creates a new one.
	 */
	entry = hash_search(LogicalRepRelMap, (void *) &remoterel->remoteid,
						HASH_ENTER, &found);

	if (found)
		logicalrep_relmap_free_entry(entry);

	/* Make cached copy of the data */
	oldctx = MemoryContextSwitchTo(LogicalRepRelMapContext);
	entry->remoterel.remoteid = remoterel->remoteid;
	entry->remoterel.nspname = pstrdup(remoterel->nspname);
	entry->remoterel.relname = pstrdup(remoterel->relname);
	entry->remoterel.natts = remoterel->natts;
	entry->remoterel.attnames = palloc(remoterel->natts * sizeof(char *));
	entry->remoterel.atttyps = palloc(remoterel->natts * sizeof(Oid));
	for (i = 0; i < remoterel->natts; i++)
	{
		entry->remoterel.attnames[i] = pstrdup(remoterel->attnames[i]);
		entry->remoterel.atttyps[i] = remoterel->atttyps[i];
	}
	entry->remoterel.replident = remoterel->replident;
	entry->remoterel.attkeys = bms_copy(remoterel->attkeys);
	entry->attrmap = NULL;
	entry->localreloid = InvalidOid;
	MemoryContextSwitchTo(oldctx);
}
Пример #11
0
static int num_cq_crashes(StreamBatch *batch)
{
	int cq_id;
	int num_crashes = 0;
	Bitmapset *readers = bms_copy(batch->readers);
	int i = 0;

	while ((cq_id = bms_first_member(readers)) != -1)
	{
		CQProcEntry *pentry = GetCQProcEntry(cq_id);

		if (!pentry)
			num_crashes++;
		else if (batch->proc_runs[i] < pentry->proc_runs)
			num_crashes++;
		i++;
	}

	pfree(readers);

	return num_crashes;
}