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; }
/* * 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; }
/* * 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; }
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; }
/* * 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; }
/* * _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, ')'); }
/* * 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; }
/* * 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]; }
/* * 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; }
/* * 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); }
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; }