Beispiel #1
0
/*
 * Allocate working buffers needed for WAL record construction.
 */
void
InitXLogInsert(void)
{
	/* Initialize the working areas */
	if (xloginsert_cxt == NULL)
	{
		xloginsert_cxt = AllocSetContextCreate(TopMemoryContext,
											   "WAL record construction",
											   ALLOCSET_DEFAULT_MINSIZE,
											   ALLOCSET_DEFAULT_INITSIZE,
											   ALLOCSET_DEFAULT_MAXSIZE);
	}

	if (registered_buffers == NULL)
	{
		registered_buffers = (registered_buffer *)
			MemoryContextAllocZero(xloginsert_cxt,
				  sizeof(registered_buffer) * (XLR_NORMAL_MAX_BLOCK_ID + 1));
		max_registered_buffers = XLR_NORMAL_MAX_BLOCK_ID + 1;
	}
	if (rdatas == NULL)
	{
		rdatas = MemoryContextAlloc(xloginsert_cxt,
									sizeof(XLogRecData) * XLR_NORMAL_RDATAS);
		max_rdatas = XLR_NORMAL_RDATAS;
	}

	/*
	 * Allocate a buffer to hold the header information for a WAL record.
	 */
	if (hdr_scratch == NULL)
		hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
											 HEADER_SCRATCH_SIZE);
}
Beispiel #2
0
char *lookup_analysis_thing(MemoryContext cxt, char *thing) {
    char       *definition = "";
    StringInfo query;

    SPI_connect();

    query = makeStringInfo();
    appendStringInfo(query, "select (to_json(name) || ':' || definition) from %s;", TextDatumGetCString(DirectFunctionCall1(quote_ident, CStringGetTextDatum(thing))));

    if (SPI_execute(query->data, true, 0) != SPI_OK_SELECT)
        elog(ERROR, "Problem looking up analysis thing with query: %s", query->data);

    if (SPI_processed > 0) {
        StringInfo json = makeStringInfo();
        int        i;

        for (i = 0; i < SPI_processed; i++) {
            if (i > 0) appendStringInfoCharMacro(json, ',');
            appendStringInfo(json, "%s", SPI_getvalue(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1));
        }
        definition = (char *) MemoryContextAllocZero(cxt, (Size) json->len + 1);
        memcpy(definition, json->data, json->len);
    }

    SPI_finish();

    return definition;
}
Beispiel #3
0
/*
 * Construct a PLySavedArgs struct representing the current values of the
 * procedure's arguments in its globals dict.  This can be used to restore
 * those values when exiting a recursive call level or returning control to a
 * set-returning function.
 *
 * This would not be necessary except for an ancient decision to make args
 * available via the proc's globals :-( ... but we're stuck with that now.
 */
static PLySavedArgs *
PLy_function_save_args(PLyProcedure *proc)
{
	PLySavedArgs *result;

	/* saved args are always allocated in procedure's context */
	result = (PLySavedArgs *)
		MemoryContextAllocZero(proc->mcxt,
							   offsetof(PLySavedArgs, namedargs) +
							   proc->nargs * sizeof(PyObject *));
	result->nargs = proc->nargs;

	/* Fetch the "args" list */
	result->args = PyDict_GetItemString(proc->globals, "args");
	Py_XINCREF(result->args);

	/* Fetch all the named arguments */
	if (proc->argnames)
	{
		int			i;

		for (i = 0; i < result->nargs; i++)
		{
			if (proc->argnames[i])
			{
				result->namedargs[i] = PyDict_GetItemString(proc->globals,
														  proc->argnames[i]);
				Py_XINCREF(result->namedargs[i]);
			}
		}
	}

	return result;
}
Beispiel #4
0
char *lookup_field_mapping(MemoryContext cxt, Oid tableRelId, char *fieldname) {
    char       *definition = NULL;
    StringInfo query;

    SPI_connect();

    query = makeStringInfo();
    appendStringInfo(query, "select definition from zdb_mappings where table_name = %d::regclass and field_name = %s;", tableRelId, TextDatumGetCString(DirectFunctionCall1(quote_literal, CStringGetTextDatum(fieldname))));

    if (SPI_execute(query->data, true, 2) != SPI_OK_SELECT)
        elog(ERROR, "Problem looking up analysis thing with query: %s", query->data);

    if (SPI_processed > 1) {
        elog(ERROR, "Too many mappings found");
    } else if (SPI_processed == 1) {
        char *json = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
        Size len   = strlen(json);

        definition = (char *) MemoryContextAllocZero(cxt, (Size) len + 1);
        memcpy(definition, json, len);
    }

    SPI_finish();

    return definition;
}
Beispiel #5
0
/*
 * ResourceOwnerCreate
 *		Create an empty ResourceOwner.
 *
 * All ResourceOwner objects are kept in TopMemoryContext, since they should
 * only be freed explicitly.
 */
ResourceOwner
ResourceOwnerCreate(ResourceOwner parent, const char *name)
{
	ResourceOwner owner;

	owner = (ResourceOwner) MemoryContextAllocZero(TopMemoryContext,
												   sizeof(ResourceOwnerData));
	owner->name = name;

	if (parent)
	{
		owner->parent = parent;
		owner->nextchild = parent->firstchild;
		parent->firstchild = owner;
	}

	ResourceArrayInit(&(owner->bufferarr), BufferGetDatum(InvalidBuffer));
	ResourceArrayInit(&(owner->catrefarr), PointerGetDatum(NULL));
	ResourceArrayInit(&(owner->catlistrefarr), PointerGetDatum(NULL));
	ResourceArrayInit(&(owner->relrefarr), PointerGetDatum(NULL));
	ResourceArrayInit(&(owner->planrefarr), PointerGetDatum(NULL));
	ResourceArrayInit(&(owner->tupdescarr), PointerGetDatum(NULL));
	ResourceArrayInit(&(owner->snapshotarr), PointerGetDatum(NULL));
	ResourceArrayInit(&(owner->filearr), FileGetDatum(-1));
	ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL));
	ResourceArrayInit(&(owner->jitarr), PointerGetDatum(NULL));

	return owner;
}
Beispiel #6
0
static TSVectorStat *
ts_accum(MemoryContext persistentContext, TSVectorStat *stat, Datum data)
{
	TSVector	txt = DatumGetTSVector(data);
	uint32		i,
				nbit = 0,
				offset;

	if (stat == NULL)
	{							/* Init in first */
		stat = MemoryContextAllocZero(persistentContext, sizeof(TSVectorStat));
		stat->maxdepth = 1;
	}

	/* simple check of correctness */
	if (txt == NULL || txt->size == 0)
	{
		if (txt && txt != (TSVector) DatumGetPointer(data))
			pfree(txt);
		return stat;
	}

	i = txt->size - 1;
	for (; i > 0; i >>= 1)
		nbit++;

	nbit = 1 << nbit;
	offset = (nbit - txt->size) / 2;

	insertStatEntry(persistentContext, stat, txt, (nbit >> 1) - offset);
	chooseNextStatEntry(persistentContext, stat, txt, 0, nbit, offset);

	return stat;
}
/*
 * AtStart_Inval
 *		Initialize inval lists at start of a main transaction.
 */
void
AtStart_Inval(void)
{
	Assert(transInvalInfo == NULL);
	transInvalInfo = (TransInvalidationInfo *)
		MemoryContextAllocZero(TopTransactionContext,
							   sizeof(TransInvalidationInfo));
	transInvalInfo->my_level = GetCurrentTransactionNestLevel();
}
Beispiel #8
0
static struct brokerstate *
local_amqp_get_a_bs(broker_id) {
  struct brokerstate *bs;
  for(bs = HEAD_BS; bs; bs = bs->next) {
    if(bs->broker_id == broker_id) return bs;
  }
  bs = MemoryContextAllocZero(TopMemoryContext, sizeof(*bs));
  bs->broker_id = broker_id;
  bs->next = HEAD_BS;
  HEAD_BS = bs;
  return bs;
}
Beispiel #9
0
Segment *
CopySegment(Segment *src, MemoryContext cxt)
{
	MemoryContext	valid_cxt = cxt ? cxt : CurrentMemoryContext;
	Segment	*dest = MemoryContextAllocZero(valid_cxt, sizeof(Segment));

	memcpy(dest, src, sizeof(Segment));
	/* memory leak risk! */
	dest->hostname = MemoryContextStrdup(valid_cxt, src->hostname);
	dest->hostip = MemoryContextStrdup(valid_cxt, src->hostip);

	return dest;
}
Beispiel #10
0
/*
 * AtSubStart_Inval
 *		Initialize inval lists at start of a subtransaction.
 */
void
AtSubStart_Inval(void)
{
	TransInvalidationInfo *myInfo;

	Assert(transInvalInfo != NULL);
	myInfo = (TransInvalidationInfo *)
		MemoryContextAllocZero(TopTransactionContext,
							   sizeof(TransInvalidationInfo));
	myInfo->parent = transInvalInfo;
	myInfo->my_level = GetCurrentTransactionNestLevel();
	transInvalInfo = myInfo;
}
Beispiel #11
0
/*
 * CreatePortal
 *		Returns a new portal given a name.
 *
 * allowDup: if true, automatically drop any pre-existing portal of the
 * same name (if false, an error is raised).
 *
 * dupSilent: if true, don't even emit a WARNING.
 */
Portal
CreatePortal(const char *name, bool allowDup, bool dupSilent)
{
	Portal		portal;

	AssertArg(PointerIsValid(name));

	portal = GetPortalByName(name);
	if (PortalIsValid(portal))
	{
		if (!allowDup)
			ereport(ERROR,
					(errcode(ERRCODE_DUPLICATE_CURSOR),
					 errmsg("cursor \"%s\" already exists", name)));
		if (!dupSilent)
			ereport(WARNING,
					(errcode(ERRCODE_DUPLICATE_CURSOR),
					 errmsg("closing existing cursor \"%s\"",
							name)));
		PortalDrop(portal, false);
	}

	/* make new portal structure */
	portal = (Portal) MemoryContextAllocZero(PortalMemory, sizeof *portal);

	/* initialize portal heap context; typically it won't store much */
	portal->heap = AllocSetContextCreate(PortalMemory,
										 "PortalHeapMemory",
										 ALLOCSET_SMALL_MINSIZE,
										 ALLOCSET_SMALL_INITSIZE,
										 ALLOCSET_SMALL_MAXSIZE);

	/* create a resource owner for the portal */
	portal->resowner = ResourceOwnerCreate(CurTransactionResourceOwner,
										   "Portal");

	/* initialize portal fields that don't start off zero */
	portal->cleanup = PortalCleanup;
	portal->createSubid = GetCurrentSubTransactionId();
	portal->strategy = PORTAL_MULTI_QUERY;
	portal->cursorOptions = CURSOR_OPT_NO_SCROLL;
	portal->atStart = true;
	portal->atEnd = true;		/* disallow fetches until query is set */

	/* put portal in table (sets portal->name) */
	PortalHashTableInsert(portal, name);

	return portal;
}
Beispiel #12
0
static struct PgqTriggerInfo *find_trigger_info(struct PgqTableInfo *info, Oid tgoid, bool create)
{
	struct PgqTriggerInfo *tgargs = info->tg_cache;
	for (tgargs = info->tg_cache; tgargs; tgargs = tgargs->next) {
		if (tgargs->tgoid == tgoid)
			return tgargs;
	}
	if (!create)
		return NULL;
	tgargs = MemoryContextAllocZero(tbl_cache_ctx, sizeof(*tgargs));
	tgargs->tgoid = tgoid;
	tgargs->next = info->tg_cache;
	info->tg_cache = tgargs;
	return tgargs;
}
Beispiel #13
0
void
plx_result_insert_cache(FunctionCallInfo fcinfo, PlxFn *plx_fn, PGresult *pg_result)
{
    PlxResultCacheEntry *hentry;
    bool                 found;
    PlxResult           *plx_result;

    plx_result            = MemoryContextAllocZero(plx_result_mctx, sizeof(PlxResult));
    plx_result->plx_fn    = plx_fn;
    plx_result->pg_result = pg_result;

    hentry = hash_search(plx_result_cache, &fcinfo, HASH_ENTER, &found);
    if (found)
        elog(ERROR, "%s (fcinfo = %p) already has plx_result in cache", plx_fn->name, fcinfo);
    hentry->plx_result = plx_result;
}
Beispiel #14
0
/*
 * ResourceOwnerCreate
 *		Create an empty ResourceOwner.
 *
 * All ResourceOwner objects are kept in TopMemoryContext, since they should
 * only be freed explicitly.
 */
ResourceOwner
ResourceOwnerCreate(ResourceOwner parent, const char *name)
{
	ResourceOwner owner;

	owner = (ResourceOwner) MemoryContextAllocZero(TopMemoryContext,
												   sizeof(ResourceOwnerData));
	owner->name = name;

	if (parent)
	{
		owner->parent = parent;
		owner->nextchild = parent->firstchild;
		parent->firstchild = owner;
	}

	return owner;
}
Beispiel #15
0
static int
newLOfd(LargeObjectDesc *lobjCookie)
{
	int			i,
				newsize;

	/* Try to find a free slot */
	for (i = 0; i < cookies_size; i++)
	{
		if (cookies[i] == NULL)
		{
			cookies[i] = lobjCookie;
			return i;
		}
	}

	/* No free slot, so make the array bigger */
	if (cookies_size <= 0)
	{
		/* First time through, arbitrarily make 64-element array */
		i = 0;
		newsize = 64;
		cookies = (LargeObjectDesc **)
			MemoryContextAllocZero(fscxt, newsize * sizeof(LargeObjectDesc *));
		cookies_size = newsize;
	}
	else
	{
		/* Double size of array */
		i = cookies_size;
		newsize = cookies_size * 2;
		cookies = (LargeObjectDesc **)
			repalloc(cookies, newsize * sizeof(LargeObjectDesc *));
		MemSet(cookies + cookies_size, 0,
			   (newsize - cookies_size) * sizeof(LargeObjectDesc *));
		cookies_size = newsize;
	}

	Assert(cookies[i] == NULL);
	cookies[i] = lobjCookie;
	return i;
}
Beispiel #16
0
PlxQuery *
create_plx_query_from_plx_fn(PlxFn *plx_fn)
{
    PlxQuery *plx_q = new_plx_query(plx_fn->mctx);
    int       i;

    appendStringInfo(plx_q->sql, "%s", plx_fn->name);
    appendStringInfo(plx_q->sql, "(");
    for (i = 1; i <= plx_fn->nargs; i++)
        appendStringInfo(plx_q->sql, "$%d%s", i, i < plx_fn->nargs ? "," : "");
    appendStringInfo(plx_q->sql, ")");

    plx_q->plx_fn_arg_indexes = MemoryContextAllocZero(plx_fn->mctx,
                                                       sizeof(int) * plx_fn->nargs);
    for (i = 0; i < plx_fn->nargs; i++)
        plx_q->plx_fn_arg_indexes[i] = i;
    plx_q->nargs = plx_fn->nargs;

    return plx_q;
}
Beispiel #17
0
/*
 * Initialize, or re-initialize, per-column output info for a composite type.
 *
 * This is separate from PLy_output_setup_func() because in cases involving
 * anonymous record types, we need to be passed the tupdesc explicitly.
 * It's caller's responsibility that the tupdesc has adequate lifespan
 * in such cases.  If the tupdesc is for a named composite or registered
 * record type, it does not need to be long-lived.
 */
void
PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
{
	int			i;

	/* We should be working on a previously-set-up struct */
	Assert(arg->func == PLyObject_ToComposite);

	/* Save pointer to tupdesc, but only if this is an anonymous record type */
	if (arg->typoid == RECORDOID && arg->typmod < 0)
		arg->u.tuple.recdesc = desc;

	/* (Re)allocate atts array as needed */
	if (arg->u.tuple.natts != desc->natts)
	{
		if (arg->u.tuple.atts)
			pfree(arg->u.tuple.atts);
		arg->u.tuple.natts = desc->natts;
		arg->u.tuple.atts = (PLyObToDatum *)
			MemoryContextAllocZero(arg->mcxt,
								   desc->natts * sizeof(PLyObToDatum));
	}

	/* Fill the atts entries, except for dropped columns */
	for (i = 0; i < desc->natts; i++)
	{
		Form_pg_attribute attr = TupleDescAttr(desc, i);
		PLyObToDatum *att = &arg->u.tuple.atts[i];

		if (attr->attisdropped)
			continue;

		if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
			continue;			/* already set up this entry */

		PLy_output_setup_func(att, arg->mcxt,
							  attr->atttypid, attr->atttypmod,
							  proc);
	}
}
Beispiel #18
0
/*
 * PrepareInvalidationState
 *		Initialize inval lists for the current (sub)transaction.
 */
static void
PrepareInvalidationState(void)
{
	TransInvalidationInfo *myInfo;

	if (transInvalInfo != NULL &&
		transInvalInfo->my_level == GetCurrentTransactionNestLevel())
		return;

	myInfo = (TransInvalidationInfo *)
		MemoryContextAllocZero(TopTransactionContext,
							   sizeof(TransInvalidationInfo));
	myInfo->parent = transInvalInfo;
	myInfo->my_level = GetCurrentTransactionNestLevel();

	/*
	 * If there's any previous entry, this one should be for a deeper nesting
	 * level.
	 */
	Assert(transInvalInfo == NULL ||
		   myInfo->my_level > transInvalInfo->my_level);

	transInvalInfo = myInfo;
}
Beispiel #19
0
/*
 * Recursively initialize the PLyObToDatum structure(s) needed to construct
 * a SQL value of the specified typeOid/typmod from a Python value.
 * (But note that at this point we may have RECORDOID/-1, ie, an indeterminate
 * record type.)
 * proc is used to look up transform functions.
 */
void
PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
					  Oid typeOid, int32 typmod,
					  PLyProcedure *proc)
{
	TypeCacheEntry *typentry;
	char		typtype;
	Oid			trfuncid;
	Oid			typinput;

	/* Since this is recursive, it could theoretically be driven to overflow */
	check_stack_depth();

	arg->typoid = typeOid;
	arg->typmod = typmod;
	arg->mcxt = arg_mcxt;

	/*
	 * Fetch typcache entry for the target type, asking for whatever info
	 * we'll need later.  RECORD is a special case: just treat it as composite
	 * without bothering with the typcache entry.
	 */
	if (typeOid != RECORDOID)
	{
		typentry = lookup_type_cache(typeOid, TYPECACHE_DOMAIN_BASE_INFO);
		typtype = typentry->typtype;
		arg->typbyval = typentry->typbyval;
		arg->typlen = typentry->typlen;
		arg->typalign = typentry->typalign;
	}
	else
	{
		typentry = NULL;
		typtype = TYPTYPE_COMPOSITE;
		/* hard-wired knowledge about type RECORD: */
		arg->typbyval = false;
		arg->typlen = -1;
		arg->typalign = 'd';
	}

	/*
	 * Choose conversion method.  Note that transform functions are checked
	 * for composite and scalar types, but not for arrays or domains.  This is
	 * somewhat historical, but we'd have a problem allowing them on domains,
	 * since we drill down through all levels of a domain nest without looking
	 * at the intermediate levels at all.
	 */
	if (typtype == TYPTYPE_DOMAIN)
	{
		/* Domain */
		arg->func = PLyObject_ToDomain;
		arg->u.domain.domain_info = NULL;
		/* Recursively set up conversion info for the element type */
		arg->u.domain.base = (PLyObToDatum *)
			MemoryContextAllocZero(arg_mcxt, sizeof(PLyObToDatum));
		PLy_output_setup_func(arg->u.domain.base, arg_mcxt,
							  typentry->domainBaseType,
							  typentry->domainBaseTypmod,
							  proc);
	}
	else if (typentry &&
			 OidIsValid(typentry->typelem) && typentry->typlen == -1)
	{
		/* Standard varlena array (cf. get_element_type) */
		arg->func = PLySequence_ToArray;
		/* Get base type OID to insert into constructed array */
		/* (note this might not be the same as the immediate child type) */
		arg->u.array.elmbasetype = getBaseType(typentry->typelem);
		/* Recursively set up conversion info for the element type */
		arg->u.array.elm = (PLyObToDatum *)
			MemoryContextAllocZero(arg_mcxt, sizeof(PLyObToDatum));
		PLy_output_setup_func(arg->u.array.elm, arg_mcxt,
							  typentry->typelem, typmod,
							  proc);
	}
	else if ((trfuncid = get_transform_tosql(typeOid,
											 proc->langid,
											 proc->trftypes)))
	{
		arg->func = PLyObject_ToTransform;
		fmgr_info_cxt(trfuncid, &arg->u.transform.typtransform, arg_mcxt);
	}
	else if (typtype == TYPTYPE_COMPOSITE)
	{
		/* Named composite type, or RECORD */
		arg->func = PLyObject_ToComposite;
		/* We'll set up the per-field data later */
		arg->u.tuple.recdesc = NULL;
		arg->u.tuple.typentry = typentry;
		arg->u.tuple.tupdescseq = typentry ? typentry->tupDescSeqNo - 1 : 0;
		arg->u.tuple.atts = NULL;
		arg->u.tuple.natts = 0;
		/* Mark this invalid till needed, too */
		arg->u.tuple.recinfunc.fn_oid = InvalidOid;
	}
	else
	{
		/* Scalar type, but we have a couple of special cases */
		switch (typeOid)
		{
			case BOOLOID:
				arg->func = PLyObject_ToBool;
				break;
			case BYTEAOID:
				arg->func = PLyObject_ToBytea;
				break;
			default:
				arg->func = PLyObject_ToScalar;
				getTypeInputInfo(typeOid, &typinput, &arg->u.scalar.typioparam);
				fmgr_info_cxt(typinput, &arg->u.scalar.typfunc, arg_mcxt);
				break;
		}
	}
}
Beispiel #20
0
/**
 * @brief This function learns the topics of words in a document and is the
 * main step of a Gibbs sampling iteration. The word topic counts and
 * corpus topic counts are passed to this function in the first call and
 * then transfered to the rest calls through args.mSysInfo->user_fctx for
 * efficiency. 
 * @param args[0]   The unique words in the documents
 * @param args[1]   The counts of each unique words
 * @param args[2]   The topic counts and topic assignments in the document
 * @param args[3]   The model (word topic counts and corpus topic
 *                  counts)
 * @param args[4]   The Dirichlet parameter for per-document topic
 *                  multinomial, i.e. alpha
 * @param args[5]   The Dirichlet parameter for per-topic word
 *                  multinomial, i.e. beta
 * @param args[6]   The size of vocabulary
 * @param args[7]   The number of topics
 * @param args[8]   The number of iterations (=1:training, >1:prediction)
 * @return          The updated topic counts and topic assignments for
 *                  the document
 **/
AnyType lda_gibbs_sample::run(AnyType & args)
{
    ArrayHandle<int32_t> words = args[0].getAs<ArrayHandle<int32_t> >();
    ArrayHandle<int32_t> counts = args[1].getAs<ArrayHandle<int32_t> >();
    MutableArrayHandle<int32_t> doc_topic = args[2].getAs<MutableArrayHandle<int32_t> >();
    double alpha = args[4].getAs<double>();
    double beta = args[5].getAs<double>();
    int32_t voc_size = args[6].getAs<int32_t>();
    int32_t topic_num = args[7].getAs<int32_t>();
    int32_t iter_num = args[8].getAs<int32_t>();

    if(alpha <= 0)
        throw std::invalid_argument("invalid argument - alpha");
    if(beta <= 0)
        throw std::invalid_argument("invalid argument - beta");
    if(voc_size <= 0)
        throw std::invalid_argument(
            "invalid argument - voc_size");
    if(topic_num <= 0)
        throw std::invalid_argument(
            "invalid argument - topic_num");
    if(iter_num <= 0)
        throw std::invalid_argument(
            "invalid argument - iter_num");

    if(words.size() != counts.size())
        throw std::invalid_argument(
            "dimensions mismatch: words.size() != counts.size()");
    if(__min(words) < 0 || __max(words) >= voc_size)
        throw std::invalid_argument(
            "invalid values in words");
    if(__min(counts) <= 0)
        throw std::invalid_argument(
            "invalid values in counts");

    int32_t word_count = __sum(counts);
    if(doc_topic.size() != (size_t)(word_count + topic_num))
        throw std::invalid_argument(
            "invalid dimension - doc_topic.size() != word_count + topic_num");
    if(__min(doc_topic, 0, topic_num) < 0)
        throw std::invalid_argument("invalid values in topic_count");
    if(
        __min(doc_topic, topic_num, word_count) < 0 ||
        __max(doc_topic, topic_num, word_count) >= topic_num)
        throw std::invalid_argument( "invalid values in topic_assignment");

    if (!args.getUserFuncContext())
    {
        if(args[3].isNull())
            throw std::invalid_argument("invalid argument - the model \
            parameter should not be null for the first call");
        ArrayHandle<int64_t> model = args[3].getAs<ArrayHandle<int64_t> >();
        if(model.size() != (size_t)((voc_size + 1) * topic_num))
            throw std::invalid_argument(
                "invalid dimension - model.size() != (voc_size + 1) * topic_num");
        if(__min(model) < 0)
            throw std::invalid_argument("invalid topic counts in model");

        int64_t * state = 
            static_cast<int64_t *>(
                MemoryContextAllocZero(
                    args.getCacheMemoryContext(), 
                    model.size() * sizeof(int64_t)));
        memcpy(state, model.ptr(), model.size() * sizeof(int64_t));
        args.setUserFuncContext(state);
    }

    int64_t * state = static_cast<int64_t *>(args.getUserFuncContext());
    if(NULL == state){
        throw std::runtime_error("args.mSysInfo->user_fctx is null");
    }

    int32_t unique_word_count = static_cast<int32_t>(words.size());
    for(int32_t it = 0; it < iter_num; it++){
        int32_t word_index = topic_num;
        for(int32_t i = 0; i < unique_word_count; i++) {
            int32_t wordid = words[i];
            for(int32_t j = 0; j < counts[i]; j++){
                int32_t topic = doc_topic[word_index];
                int32_t retopic = __lda_gibbs_sample(
                    topic_num, topic, doc_topic.ptr(), 
                    state + wordid * topic_num, 
                    state + voc_size * topic_num, alpha, beta);
                doc_topic[word_index] = retopic;
                doc_topic[topic]--;
                doc_topic[retopic]++;

                if(iter_num == 1){
                    state[voc_size * topic_num + topic]--;
                    state[voc_size * topic_num + retopic]++;
                    state[wordid * topic_num + topic]--;
                    state[wordid * topic_num + retopic]++;
                }
                word_index++;
            }
        }
    }
    
    return doc_topic;
}
Beispiel #21
0
static TSVectorStat *
ts_stat_sql(MemoryContext persistentContext, text *txt, text *ws)
{
	char	   *query = text_to_cstring(txt);
	int			i;
	TSVectorStat *stat;
	bool		isnull;
	Portal		portal;
	SPIPlanPtr	plan;

	if ((plan = SPI_prepare(query, 0, NULL)) == NULL)
		/* internal error */
		elog(ERROR, "SPI_prepare(\"%s\") failed", query);

	if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL, true)) == NULL)
		/* internal error */
		elog(ERROR, "SPI_cursor_open(\"%s\") failed", query);

	SPI_cursor_fetch(portal, true, 100);

	if (SPI_tuptable == NULL ||
		SPI_tuptable->tupdesc->natts != 1 ||
		!IsBinaryCoercible(SPI_gettypeid(SPI_tuptable->tupdesc, 1),
						  TSVECTOROID))
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("ts_stat query must return one tsvector column")));

	stat = MemoryContextAllocZero(persistentContext, sizeof(TSVectorStat));
	stat->maxdepth = 1;

	if (ws)
	{
		char	   *buf;

		buf = VARDATA(ws);
		while (buf - VARDATA(ws) < VARSIZE(ws) - VARHDRSZ)
		{
			if (pg_mblen(buf) == 1)
			{
				switch (*buf)
				{
					case 'A':
					case 'a':
						stat->weight |= 1 << 3;
						break;
					case 'B':
					case 'b':
						stat->weight |= 1 << 2;
						break;
					case 'C':
					case 'c':
						stat->weight |= 1 << 1;
						break;
					case 'D':
					case 'd':
						stat->weight |= 1;
						break;
					default:
						stat->weight |= 0;
				}
			}
			buf += pg_mblen(buf);
		}
	}

	while (SPI_processed > 0)
	{
		for (i = 0; i < SPI_processed; i++)
		{
			Datum		data = SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull);

			if (!isnull)
				stat = ts_accum(persistentContext, stat, data);
		}

		SPI_freetuptable(SPI_tuptable);
		SPI_cursor_fetch(portal, true, 100);
	}

	SPI_freetuptable(SPI_tuptable);
	SPI_cursor_close(portal);
	SPI_freeplan(plan);
	pfree(query);

	return stat;
}
Beispiel #22
0
/*
 * Recursively initialize the PLyDatumToOb structure(s) needed to construct
 * a Python value from a SQL value of the specified typeOid/typmod.
 * (But note that at this point we may have RECORDOID/-1, ie, an indeterminate
 * record type.)
 * proc is used to look up transform functions.
 */
void
PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
					 Oid typeOid, int32 typmod,
					 PLyProcedure *proc)
{
	TypeCacheEntry *typentry;
	char		typtype;
	Oid			trfuncid;
	Oid			typoutput;
	bool		typisvarlena;

	/* Since this is recursive, it could theoretically be driven to overflow */
	check_stack_depth();

	arg->typoid = typeOid;
	arg->typmod = typmod;
	arg->mcxt = arg_mcxt;

	/*
	 * Fetch typcache entry for the target type, asking for whatever info
	 * we'll need later.  RECORD is a special case: just treat it as composite
	 * without bothering with the typcache entry.
	 */
	if (typeOid != RECORDOID)
	{
		typentry = lookup_type_cache(typeOid, TYPECACHE_DOMAIN_BASE_INFO);
		typtype = typentry->typtype;
		arg->typbyval = typentry->typbyval;
		arg->typlen = typentry->typlen;
		arg->typalign = typentry->typalign;
	}
	else
	{
		typentry = NULL;
		typtype = TYPTYPE_COMPOSITE;
		/* hard-wired knowledge about type RECORD: */
		arg->typbyval = false;
		arg->typlen = -1;
		arg->typalign = 'd';
	}

	/*
	 * Choose conversion method.  Note that transform functions are checked
	 * for composite and scalar types, but not for arrays or domains.  This is
	 * somewhat historical, but we'd have a problem allowing them on domains,
	 * since we drill down through all levels of a domain nest without looking
	 * at the intermediate levels at all.
	 */
	if (typtype == TYPTYPE_DOMAIN)
	{
		/* Domain --- we don't care, just recurse down to the base type */
		PLy_input_setup_func(arg, arg_mcxt,
							 typentry->domainBaseType,
							 typentry->domainBaseTypmod,
							 proc);
	}
	else if (typentry &&
			 OidIsValid(typentry->typelem) && typentry->typlen == -1)
	{
		/* Standard varlena array (cf. get_element_type) */
		arg->func = PLyList_FromArray;
		/* Recursively set up conversion info for the element type */
		arg->u.array.elm = (PLyDatumToOb *)
			MemoryContextAllocZero(arg_mcxt, sizeof(PLyDatumToOb));
		PLy_input_setup_func(arg->u.array.elm, arg_mcxt,
							 typentry->typelem, typmod,
							 proc);
	}
	else if ((trfuncid = get_transform_fromsql(typeOid,
											   proc->langid,
											   proc->trftypes)))
	{
		arg->func = PLyObject_FromTransform;
		fmgr_info_cxt(trfuncid, &arg->u.transform.typtransform, arg_mcxt);
	}
	else if (typtype == TYPTYPE_COMPOSITE)
	{
		/* Named composite type, or RECORD */
		arg->func = PLyDict_FromComposite;
		/* We'll set up the per-field data later */
		arg->u.tuple.recdesc = NULL;
		arg->u.tuple.typentry = typentry;
		arg->u.tuple.tupdescseq = typentry ? typentry->tupDescSeqNo - 1 : 0;
		arg->u.tuple.atts = NULL;
		arg->u.tuple.natts = 0;
	}
	else
	{
		/* Scalar type, but we have a couple of special cases */
		switch (typeOid)
		{
			case BOOLOID:
				arg->func = PLyBool_FromBool;
				break;
			case FLOAT4OID:
				arg->func = PLyFloat_FromFloat4;
				break;
			case FLOAT8OID:
				arg->func = PLyFloat_FromFloat8;
				break;
			case NUMERICOID:
				arg->func = PLyDecimal_FromNumeric;
				break;
			case INT2OID:
				arg->func = PLyInt_FromInt16;
				break;
			case INT4OID:
				arg->func = PLyInt_FromInt32;
				break;
			case INT8OID:
				arg->func = PLyLong_FromInt64;
				break;
			case OIDOID:
				arg->func = PLyLong_FromOid;
				break;
			case BYTEAOID:
				arg->func = PLyBytes_FromBytea;
				break;
			default:
				arg->func = PLyString_FromScalar;
				getTypeOutputInfo(typeOid, &typoutput, &typisvarlena);
				fmgr_info_cxt(typoutput, &arg->u.scalar.typfunc, arg_mcxt);
				break;
		}
	}
}
Beispiel #23
0
/*
 * Create a WaitEventSet with space for nevents different events to wait for.
 *
 * These events can then efficiently waited upon together, using
 * WaitEventSetWait().
 */
WaitEventSet *
CreateWaitEventSet(MemoryContext context, int nevents)
{
	WaitEventSet *set;
	char	   *data;
	Size		sz = 0;

	sz += sizeof(WaitEventSet);
	sz += sizeof(WaitEvent) * nevents;

#if defined(WAIT_USE_EPOLL)
	sz += sizeof(struct epoll_event) * nevents;
#elif defined(WAIT_USE_POLL)
	sz += sizeof(struct pollfd) * nevents;
#elif defined(WAIT_USE_WIN32)
	/* need space for the pgwin32_signal_event */
	sz += sizeof(HANDLE) * (nevents + 1);
#endif

	data = (char *) MemoryContextAllocZero(context, sz);

	set = (WaitEventSet *) data;
	data += sizeof(WaitEventSet);

	set->events = (WaitEvent *) data;
	data += sizeof(WaitEvent) * nevents;

#if defined(WAIT_USE_EPOLL)
	set->epoll_ret_events = (struct epoll_event *) data;
	data += sizeof(struct epoll_event) * nevents;
#elif defined(WAIT_USE_POLL)
	set->pollfds = (struct pollfd *) data;
	data += sizeof(struct pollfd) * nevents;
#elif defined(WAIT_USE_WIN32)
	set->handles = (HANDLE) data;
	data += sizeof(HANDLE) * nevents;
#endif

	set->latch = NULL;
	set->nevents_space = nevents;

#if defined(WAIT_USE_EPOLL)
	set->epoll_fd = epoll_create(nevents);
	if (set->epoll_fd < 0)
		elog(ERROR, "epoll_create failed: %m");
#elif defined(WAIT_USE_WIN32)

	/*
	 * To handle signals while waiting, we need to add a win32 specific event.
	 * We accounted for the additional event at the top of this routine. See
	 * port/win32/signal.c for more details.
	 *
	 * Note: pgwin32_signal_event should be first to ensure that it will be
	 * reported when multiple events are set.  We want to guarantee that
	 * pending signals are serviced.
	 */
	set->handles[0] = pgwin32_signal_event;
	StaticAssertStmt(WSA_INVALID_EVENT == NULL, "");
#endif

	return set;
}
Beispiel #24
0
/* function subhandler */
Datum
PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
{
	Datum		rv;
	PyObject   *volatile plargs = NULL;
	PyObject   *volatile plrv = NULL;
	FuncCallContext *volatile funcctx = NULL;
	PLySRFState *volatile srfstate = NULL;
	ErrorContextCallback plerrcontext;

	/*
	 * If the function is called recursively, we must push outer-level
	 * arguments into the stack.  This must be immediately before the PG_TRY
	 * to ensure that the corresponding pop happens.
	 */
	PLy_global_args_push(proc);

	PG_TRY();
	{
		if (proc->is_setof)
		{
			/* First Call setup */
			if (SRF_IS_FIRSTCALL())
			{
				funcctx = SRF_FIRSTCALL_INIT();
				srfstate = (PLySRFState *)
					MemoryContextAllocZero(funcctx->multi_call_memory_ctx,
										   sizeof(PLySRFState));
				/* Immediately register cleanup callback */
				srfstate->callback.func = plpython_srf_cleanup_callback;
				srfstate->callback.arg = (void *) srfstate;
				MemoryContextRegisterResetCallback(funcctx->multi_call_memory_ctx,
												   &srfstate->callback);
				funcctx->user_fctx = (void *) srfstate;
			}
			/* Every call setup */
			funcctx = SRF_PERCALL_SETUP();
			Assert(funcctx != NULL);
			srfstate = (PLySRFState *) funcctx->user_fctx;
		}

		if (srfstate == NULL || srfstate->iter == NULL)
		{
			/*
			 * Non-SETOF function or first time for SETOF function: build
			 * args, then actually execute the function.
			 */
			plargs = PLy_function_build_args(fcinfo, proc);
			plrv = PLy_procedure_call(proc, "args", plargs);
			Assert(plrv != NULL);
		}
		else
		{
			/*
			 * Second or later call for a SETOF function: restore arguments in
			 * globals dict to what they were when we left off.  We must do
			 * this in case multiple evaluations of the same SETOF function
			 * are interleaved.  It's a bit annoying, since the iterator may
			 * not look at the arguments at all, but we have no way to know
			 * that.  Fortunately this isn't terribly expensive.
			 */
			if (srfstate->savedargs)
				PLy_function_restore_args(proc, srfstate->savedargs);
			srfstate->savedargs = NULL; /* deleted by restore_args */
		}

		/*
		 * If it returns a set, call the iterator to get the next return item.
		 * We stay in the SPI context while doing this, because PyIter_Next()
		 * calls back into Python code which might contain SPI calls.
		 */
		if (proc->is_setof)
		{
			if (srfstate->iter == NULL)
			{
				/* first time -- do checks and setup */
				ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;

				if (!rsi || !IsA(rsi, ReturnSetInfo) ||
					(rsi->allowedModes & SFRM_ValuePerCall) == 0)
				{
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
							 errmsg("unsupported set function return mode"),
							 errdetail("PL/Python set-returning functions only support returning one value per call.")));
				}
				rsi->returnMode = SFRM_ValuePerCall;

				/* Make iterator out of returned object */
				srfstate->iter = PyObject_GetIter(plrv);

				Py_DECREF(plrv);
				plrv = NULL;

				if (srfstate->iter == NULL)
					ereport(ERROR,
							(errcode(ERRCODE_DATATYPE_MISMATCH),
							 errmsg("returned object cannot be iterated"),
							 errdetail("PL/Python set-returning functions must return an iterable object.")));
			}

			/* Fetch next from iterator */
			plrv = PyIter_Next(srfstate->iter);
			if (plrv == NULL)
			{
				/* Iterator is exhausted or error happened */
				bool		has_error = (PyErr_Occurred() != NULL);

				Py_DECREF(srfstate->iter);
				srfstate->iter = NULL;

				if (has_error)
					PLy_elog(ERROR, "error fetching next item from iterator");

				/* Pass a null through the data-returning steps below */
				Py_INCREF(Py_None);
				plrv = Py_None;
			}
			else
			{
				/*
				 * This won't be last call, so save argument values.  We do
				 * this again each time in case the iterator is changing those
				 * values.
				 */
				srfstate->savedargs = PLy_function_save_args(proc);
			}
		}

		/*
		 * Disconnect from SPI manager and then create the return values datum
		 * (if the input function does a palloc for it this must not be
		 * allocated in the SPI memory context because SPI_finish would free
		 * it).
		 */
		if (SPI_finish() != SPI_OK_FINISH)
			elog(ERROR, "SPI_finish failed");

		plerrcontext.callback = plpython_return_error_callback;
		plerrcontext.previous = error_context_stack;
		error_context_stack = &plerrcontext;

		/*
		 * If the function is declared to return void, the Python return value
		 * must be None. For void-returning functions, we also treat a None
		 * return value as a special "void datum" rather than NULL (as is the
		 * case for non-void-returning functions).
		 */
		if (proc->result.out.d.typoid == VOIDOID)
		{
			if (plrv != Py_None)
				ereport(ERROR,
						(errcode(ERRCODE_DATATYPE_MISMATCH),
						 errmsg("PL/Python function with return type \"void\" did not return None")));

			fcinfo->isnull = false;
			rv = (Datum) 0;
		}
		else if (plrv == Py_None)
		{
			fcinfo->isnull = true;

			/*
			 * In a SETOF function, the iteration-ending null isn't a real
			 * value; don't pass it through the input function, which might
			 * complain.
			 */
			if (srfstate && srfstate->iter == NULL)
				rv = (Datum) 0;
			else if (proc->result.is_rowtype < 1)
				rv = InputFunctionCall(&proc->result.out.d.typfunc,
									   NULL,
									   proc->result.out.d.typioparam,
									   -1);
			else
				/* Tuple as None */
				rv = (Datum) NULL;
		}
		else if (proc->result.is_rowtype >= 1)
		{
			TupleDesc	desc;

			/* make sure it's not an unnamed record */
			Assert((proc->result.out.d.typoid == RECORDOID &&
					proc->result.out.d.typmod != -1) ||
				   (proc->result.out.d.typoid != RECORDOID &&
					proc->result.out.d.typmod == -1));

			desc = lookup_rowtype_tupdesc(proc->result.out.d.typoid,
										  proc->result.out.d.typmod);

			rv = PLyObject_ToCompositeDatum(&proc->result, desc, plrv);
			fcinfo->isnull = (rv == (Datum) NULL);

			ReleaseTupleDesc(desc);
		}
		else
		{
			fcinfo->isnull = false;
			rv = (proc->result.out.d.func) (&proc->result.out.d, -1, plrv);
		}
	}
	PG_CATCH();
	{
		/* Pop old arguments from the stack if they were pushed above */
		PLy_global_args_pop(proc);

		Py_XDECREF(plargs);
		Py_XDECREF(plrv);

		/*
		 * If there was an error within a SRF, the iterator might not have
		 * been exhausted yet.  Clear it so the next invocation of the
		 * function will start the iteration again.  (This code is probably
		 * unnecessary now; plpython_srf_cleanup_callback should take care of
		 * cleanup.  But it doesn't hurt anything to do it here.)
		 */
		if (srfstate)
		{
			Py_XDECREF(srfstate->iter);
			srfstate->iter = NULL;
			/* And drop any saved args; we won't need them */
			if (srfstate->savedargs)
				PLy_function_drop_args(srfstate->savedargs);
			srfstate->savedargs = NULL;
		}

		PG_RE_THROW();
	}
	PG_END_TRY();

	error_context_stack = plerrcontext.previous;

	/* Pop old arguments from the stack if they were pushed above */
	PLy_global_args_pop(proc);

	Py_XDECREF(plargs);
	Py_DECREF(plrv);

	if (srfstate)
	{
		/* We're in a SRF, exit appropriately */
		if (srfstate->iter == NULL)
		{
			/* Iterator exhausted, so we're done */
			SRF_RETURN_DONE(funcctx);
		}
		else if (fcinfo->isnull)
			SRF_RETURN_NEXT_NULL(funcctx);
		else
			SRF_RETURN_NEXT(funcctx, rv);
	}

	/* Plain function, just return the Datum value (possibly null) */
	return rv;
}
Beispiel #25
0
/**
 * @brief This function learns the topics of words in a document and is the
 * main step of a Gibbs sampling iteration. The word topic counts and
 * corpus topic counts are passed to this function in the first call and
 * then transfered to the rest calls through args.mSysInfo->user_fctx for
 * efficiency.
 * @param args[0]   The unique words in the documents
 * @param args[1]   The counts of each unique words
 * @param args[2]   The topic counts and topic assignments in the document
 * @param args[3]   The model (word topic counts and corpus topic
 *                  counts)
 * @param args[4]   The Dirichlet parameter for per-document topic
 *                  multinomial, i.e. alpha
 * @param args[5]   The Dirichlet parameter for per-topic word
 *                  multinomial, i.e. beta
 * @param args[6]   The size of vocabulary
 * @param args[7]   The number of topics
 * @param args[8]   The number of iterations (=1:training, >1:prediction)
 * @return          The updated topic counts and topic assignments for
 *                  the document
 **/
AnyType lda_gibbs_sample::run(AnyType & args)
{
    ArrayHandle<int32_t> words = args[0].getAs<ArrayHandle<int32_t> >();
    ArrayHandle<int32_t> counts = args[1].getAs<ArrayHandle<int32_t> >();
    MutableArrayHandle<int32_t> doc_topic = args[2].getAs<MutableArrayHandle<int32_t> >();
    double alpha = args[4].getAs<double>();
    double beta = args[5].getAs<double>();
    int32_t voc_size = args[6].getAs<int32_t>();
    int32_t topic_num = args[7].getAs<int32_t>();
    int32_t iter_num = args[8].getAs<int32_t>();
    size_t model64_size = static_cast<size_t>(voc_size * (topic_num + 1) + 1) * sizeof(int32_t) / sizeof(int64_t);

    if(alpha <= 0)
        throw std::invalid_argument("invalid argument - alpha");
    if(beta <= 0)
        throw std::invalid_argument("invalid argument - beta");
    if(voc_size <= 0)
        throw std::invalid_argument(
            "invalid argument - voc_size");
    if(topic_num <= 0)
        throw std::invalid_argument(
            "invalid argument - topic_num");
    if(iter_num <= 0)
        throw std::invalid_argument(
            "invalid argument - iter_num");

    if(words.size() != counts.size())
        throw std::invalid_argument(
            "dimensions mismatch: words.size() != counts.size()");
    if(__min(words) < 0 || __max(words) >= voc_size)
        throw std::invalid_argument(
            "invalid values in words");
    if(__min(counts) <= 0)
        throw std::invalid_argument(
            "invalid values in counts");

    int32_t word_count = __sum(counts);
    if(doc_topic.size() != (size_t)(word_count + topic_num))
        throw std::invalid_argument(
            "invalid dimension - doc_topic.size() != word_count + topic_num");
    if(__min(doc_topic, 0, topic_num) < 0)
        throw std::invalid_argument("invalid values in topic_count");
    if(
        __min(doc_topic, topic_num, word_count) < 0 ||
        __max(doc_topic, topic_num, word_count) >= topic_num)
        throw std::invalid_argument( "invalid values in topic_assignment");

    if (!args.getUserFuncContext()) {
        ArrayHandle<int64_t> model64 = args[3].getAs<ArrayHandle<int64_t> >();
        if (model64.size() != model64_size) {
            std::stringstream ss;
            ss << "invalid dimension: model64.size() = " << model64.size();
            throw std::invalid_argument(ss.str());
        }
        if (__min(model64) < 0) {
            throw std::invalid_argument("invalid topic counts in model");
        }

        int32_t *context =
            static_cast<int32_t *>(
                MemoryContextAllocZero(
                    args.getCacheMemoryContext(),
                    model64.size() * sizeof(int64_t)
                        + topic_num * sizeof(int64_t)));
        memcpy(context, model64.ptr(), model64.size() * sizeof(int64_t));
        int32_t *model = context;

        int64_t *running_topic_counts = reinterpret_cast<int64_t *>(
                context + model64_size * sizeof(int64_t) / sizeof(int32_t));
        for (int i = 0; i < voc_size; i ++) {
            for (int j = 0; j < topic_num; j ++) {
                running_topic_counts[j] += model[i * (topic_num + 1) + j];
            }
        }

        args.setUserFuncContext(context);
    }

    int32_t *context = static_cast<int32_t *>(args.getUserFuncContext());
    if (context == NULL) {
        throw std::runtime_error("args.mSysInfo->user_fctx is null");
    }
    int32_t *model = context;
    int64_t *running_topic_counts = reinterpret_cast<int64_t *>(
            context + model64_size * sizeof(int64_t) / sizeof(int32_t));

    int32_t unique_word_count = static_cast<int32_t>(words.size());
    for(int32_t it = 0; it < iter_num; it++){
        int32_t word_index = topic_num;
        for(int32_t i = 0; i < unique_word_count; i++) {
            int32_t wordid = words[i];
            for(int32_t j = 0; j < counts[i]; j++){
                int32_t topic = doc_topic[word_index];
                int32_t retopic = __lda_gibbs_sample(
                    topic_num, topic, doc_topic.ptr(),
                    model + wordid * (topic_num + 1),
                    running_topic_counts, alpha, beta);
                doc_topic[word_index] = retopic;
                doc_topic[topic]--;
                doc_topic[retopic]++;

                if(iter_num == 1) {
                    if (model[wordid * (topic_num + 1) + retopic] <= 2e9) {
                        running_topic_counts[topic] --;
                        running_topic_counts[retopic] ++;
                        model[wordid * (topic_num + 1) + topic]--;
                        model[wordid * (topic_num + 1) + retopic]++;
                    } else {
                        model[wordid * (topic_num + 1) + topic_num] = 1;
                    }
                }
                word_index++;
            }
        }
    }

    return doc_topic;
}
Beispiel #26
0
/*
 * Fetch local cache of AM-specific info about the index, initializing it
 * if necessary
 */
SpGistCache *
spgGetCache(Relation index)
{
	SpGistCache *cache;

	if (index->rd_amcache == NULL)
	{
		Oid			atttype;
		spgConfigIn in;
		FmgrInfo   *procinfo;
		Buffer		metabuffer;
		SpGistMetaPageData *metadata;

		cache = MemoryContextAllocZero(index->rd_indexcxt,
									   sizeof(SpGistCache));

		/* SPGiST doesn't support multi-column indexes */
		Assert(index->rd_att->natts == 1);

		/*
		 * Get the actual data type of the indexed column from the index
		 * tupdesc.  We pass this to the opclass config function so that
		 * polymorphic opclasses are possible.
		 */
		atttype = index->rd_att->attrs[0]->atttypid;

		/* Call the config function to get config info for the opclass */
		in.attType = atttype;

		procinfo = index_getprocinfo(index, 1, SPGIST_CONFIG_PROC);
		FunctionCall2Coll(procinfo,
						  index->rd_indcollation[0],
						  PointerGetDatum(&in),
						  PointerGetDatum(&cache->config));

		/* Get the information we need about each relevant datatype */
		fillTypeDesc(&cache->attType, atttype);
		fillTypeDesc(&cache->attPrefixType, cache->config.prefixType);
		fillTypeDesc(&cache->attLabelType, cache->config.labelType);

		/* Last, get the lastUsedPages data from the metapage */
		metabuffer = ReadBuffer(index, SPGIST_METAPAGE_BLKNO);
		LockBuffer(metabuffer, BUFFER_LOCK_SHARE);

		metadata = SpGistPageGetMeta(BufferGetPage(metabuffer));

		if (metadata->magicNumber != SPGIST_MAGIC_NUMBER)
			elog(ERROR, "index \"%s\" is not an SP-GiST index",
				 RelationGetRelationName(index));

		cache->lastUsedPages = metadata->lastUsedPages;

		UnlockReleaseBuffer(metabuffer);

		index->rd_amcache = (void *) cache;
	}
	else
	{
		/* assume it's up to date */
		cache = (SpGistCache *) index->rd_amcache;
	}

	return cache;
}
Beispiel #27
0
/*
 * This is a mocked version of palloc0 to be used in ExecWorkFile_Create.
 *   It asserts that it is executed in the TopMemoryContext.
 */
void *
execWorkfile_palloc0_mock(Size size)
{
	assert_int_equal(CurrentMemoryContext, TopMemoryContext);
	return MemoryContextAllocZero(CurrentMemoryContext, size);
}
Beispiel #28
0
Relation DirectOpen_Open(
	DirectOpen *direct,

	Oid relationId,

	Oid tablespace,

	Oid database,

	Oid relfilenode,

	FormData_pg_class *pgClass,

	FormData_pg_attribute *attrArray,

	FormData_pg_am *pgAm,

	FormData_pg_index *pgIndex,

	int2 *indKeyArray,

	Oid *indClassArray,

	bool relHasOid)
{
	int natts;
	int i;

	Assert(pgClass != NULL);
	natts = pgClass->relnatts;

	if (relationId == -1)
		relationId = pgClass->relfilenode;		// Assume it is ok to use the relfilenode as the relationId in our limited usage.

	if (relfilenode == -1)
		relfilenode = pgClass->relfilenode;

	if (!direct->isInit)
	{
		/*
		 * Lots of Hard-coded construction of the gp_persistent* RelationS and
		 * dependent objects like tuple descriptors, etc.
		 */

		direct->relationData.rd_refcnt = 0;
		direct->relationData.rd_isvalid = true;

		direct->relationData.rd_id = relationId;

		direct->relationData.rd_rel = pgClass;

		if (pgIndex != NULL)
		{
			int pgIndexFixedLen = offsetof(FormData_pg_index, indkey);
			int indKeyVectorLen = Int2VectorSize(natts);
			int2vector *indKeyVector;
			oidvector  *indClassVector;

			uint16		amstrategies;
			uint16		amsupport;

			Oid 	   *operator;
			RegProcedure *support;
			FmgrInfo   *supportinfo;

			Assert(pgAm != NULL);
			Assert(indKeyArray != NULL);
			Assert(indClassArray != NULL);

			/*
			 * Allocate Formdata_pg_index with fields through indkey
			 * where indkey is a variable length int2vector with indKeyArray values.
			 */
			direct->relationData.rd_index = 
						(FormData_pg_index*)palloc(
								pgIndexFixedLen + indKeyVectorLen);
			memcpy(direct->relationData.rd_index, pgIndex, pgIndexFixedLen);

			indKeyVector = buildint2vector(
									indKeyArray,
									natts);
			memcpy(
				&direct->relationData.rd_index->indkey, 
				indKeyVector, 
				indKeyVectorLen);

			pfree(indKeyVector);

			direct->relationData.rd_am = pgAm;

			amstrategies = pgAm->amstrategies;
			amsupport = pgAm->amsupport;

			direct->relationData.rd_indexcxt = TopMemoryContext;

			/*
			 * Allocate arrays to hold data
			 */
			direct->relationData.rd_aminfo = (RelationAmInfo *)
				MemoryContextAllocZero(TopMemoryContext, sizeof(RelationAmInfo));

			direct->relationData.rd_opfamily = (Oid *)
				MemoryContextAllocZero(TopMemoryContext, natts * sizeof(Oid));
			direct->relationData.rd_opcintype = (Oid *)
				MemoryContextAllocZero(TopMemoryContext, natts * sizeof(Oid));

			if (amstrategies > 0)
				operator = (Oid *)
					MemoryContextAllocZero(TopMemoryContext,
										   natts * amstrategies * sizeof(Oid));
			else
				operator = NULL;

			if (amsupport > 0)
			{
				int			nsupport = natts * amsupport;

				support = (RegProcedure *)
					MemoryContextAllocZero(TopMemoryContext, nsupport * sizeof(RegProcedure));
				supportinfo = (FmgrInfo *)
					MemoryContextAllocZero(TopMemoryContext, nsupport * sizeof(FmgrInfo));
			}
			else
			{
				support = NULL;
				supportinfo = NULL;
			}

			direct->relationData.rd_operator = operator;
			direct->relationData.rd_support = support;
			direct->relationData.rd_supportinfo = supportinfo;

			direct->relationData.rd_indoption = (int16 *)
				MemoryContextAllocZero(TopMemoryContext, natts * sizeof(int16));

			/*
			 * Create oidvector in rd_indclass with values from indClassArray.
			 */
			indClassVector = buildoidvector(indClassArray, natts);
 
			/*
			 * Fill the operator and support procedure OID arrays.	(aminfo and
			 * supportinfo are left as zeroes, and are filled on-the-fly when used)
			 */
			IndexSupportInitialize(indClassVector,
								   operator, support,
								   direct->relationData.rd_opfamily,
								   direct->relationData.rd_opcintype,
								   amstrategies, amsupport, natts);

			/*
			 * expressions and predicate cache will be filled later.
			 */
			direct->relationData.rd_indexprs = NIL;
			direct->relationData.rd_indpred = NIL;
			direct->relationData.rd_amcache = NULL;		
		}

		// Not much in terms of contraints.
		direct->constrData.has_not_null = true;

		/*
		 * Setup tuple descriptor for columns.
		 */
		direct->descData.natts = pgClass->relnatts;

		// Make the array of pointers.
		direct->descData.attrs = 
				(Form_pg_attribute*)
						MemoryContextAllocZero(
									TopMemoryContext, 
									sizeof(Form_pg_attribute*) * pgClass->relnatts);

		for (i = 0; i < pgClass->relnatts; i++)
		{
			direct->descData.attrs[i] = 
						(Form_pg_attribute)
								MemoryContextAllocZero(
											TopMemoryContext, 
											sizeof(FormData_pg_attribute));

			memcpy(direct->descData.attrs[i], &(attrArray[i]), sizeof(FormData_pg_attribute));

			// Patch up relation id.
			direct->descData.attrs[i]->attrelid = relationId;
		}

		direct->descData.constr = &direct->constrData;
		direct->descData.tdtypeid = pgClass->reltype;
		direct->descData.tdtypmod = -1;
		direct->descData.tdqdtypmod = -1;
		direct->descData.tdhasoid = relHasOid;
		direct->descData.tdrefcount = 1;

		direct->relationData.rd_att = &direct->descData;

		direct->pgStat.t_id = relationId;
		direct->pgStat.t_shared = 1;

		direct->relationData.pgstat_info = &direct->pgStat;

		direct->isInit = true;
	}
	
	// UNDONE: Should verify for NON-SHARED relations we don't open relations in different databases / or
	// UNDONE: open different relations in same database at same time !!!
	direct->relationData.rd_node.spcNode = tablespace;
	direct->relationData.rd_node.dbNode = database;
	direct->relationData.rd_node.relNode = relfilenode;

	direct->relationData.rd_targblock = InvalidBlockNumber;

	for (i = 0; i < direct->relationData.rd_rel->relnatts; i++)
	{
		Assert(direct->descData.attrs[i] != NULL);
		
		// Patch up relation id.
		direct->descData.attrs[i]->attrelid = direct->relationData.rd_id;
	}

	direct->relationData.rd_refcnt++;

	RelationOpenSmgr(&direct->relationData);

	return &direct->relationData;
}
Beispiel #29
0
/*
 * init_MultiFuncCall
 * Create an empty FuncCallContext data structure
 * and do some other basic Multi-function call setup
 * and error checking
 */
FuncCallContext *
init_MultiFuncCall(PG_FUNCTION_ARGS)
{
	FuncCallContext *retval;

	/*
	 * Bail if we're called in the wrong context
	 */
	if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("set-valued function called in context that cannot accept a set")));

	if (fcinfo->flinfo->fn_extra == NULL)
	{
		/*
		 * First call
		 */
		ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
		MemoryContext multi_call_ctx;

		/*
		 * Create a suitably long-lived context to hold cross-call data
		 */
		multi_call_ctx = AllocSetContextCreate(fcinfo->flinfo->fn_mcxt,
											   "SRF multi-call context",
											   ALLOCSET_SMALL_MINSIZE,
											   ALLOCSET_SMALL_INITSIZE,
											   ALLOCSET_SMALL_MAXSIZE);

		/*
		 * Allocate suitably long-lived space and zero it
		 */
		retval = (FuncCallContext *)
			MemoryContextAllocZero(multi_call_ctx,
								   sizeof(FuncCallContext));

		/*
		 * initialize the elements
		 */
		retval->call_cntr = 0;
		retval->max_calls = 0;
		retval->slot = NULL;
		retval->user_fctx = NULL;
		retval->attinmeta = NULL;
		retval->tuple_desc = NULL;
		retval->multi_call_memory_ctx = multi_call_ctx;

		/*
		 * save the pointer for cross-call use
		 */
		fcinfo->flinfo->fn_extra = retval;

		/*
		 * Ensure we will get shut down cleanly if the exprcontext is not run
		 * to completion.
		 */
		RegisterExprContextCallback(rsi->econtext,
									shutdown_MultiFuncCall,
									PointerGetDatum(fcinfo->flinfo));
	}
	else
	{
		/* second and subsequent calls */
		elog(ERROR, "init_MultiFuncCall cannot be called more than once");

		/* never reached, but keep compiler happy */
		retval = NULL;
	}

	return retval;
}