コード例 #1
0
ファイル: xmlnode.c プロジェクト: andreypopp/pg_xnode
Datum
xmlnode_children(PG_FUNCTION_ARGS)
{
	xmlnode		nodeRaw = (xmlnode) PG_GETARG_VARLENA_P(0);
	char	   *data = (char *) VARDATA(nodeRaw);
	XMLNodeOffset rootNdOff = XNODE_ROOT_OFFSET(nodeRaw);
	XMLNodeHdr	node = (XMLNodeHdr) (data + rootNdOff);
	TypeInfo	nodeType;
	ArrayType  *result;

	/*
	 * Unfortunately the type info has to be retrieved every time again. If
	 * the backend used global variable to remember the values, all backends
	 * would have to invalidate the values whenever the extension gets dropped
	 * / created.
	 */

	Assert(fcinfo->flinfo != NULL);
	initXNodeTypeInfo(fcinfo->flinfo->fn_oid, 0, &nodeType);

	if (node->kind == XMLNODE_DOC || node->kind == XMLNODE_ELEMENT || node->kind == XMLNODE_DOC_FRAGMENT)
	{
		XMLCompNodeHdr root = (XMLCompNodeHdr) node;
		unsigned short children = root->children;
		Datum	   *elems;
		char	   *childOffPtr;
		unsigned short i;

		if (children == 0)
		{
			result = construct_empty_array(nodeType.oid);
			PG_RETURN_POINTER(result);
		}

		elems = (Datum *) palloc(children * sizeof(Datum));

		childOffPtr = XNODE_FIRST_REF(root);
		for (i = 0; i < children; i++)
		{
			XMLNodeOffset childOff = readXMLNodeOffset(&childOffPtr, XNODE_GET_REF_BWIDTH(root), true);
			XMLNodeHdr	childNode = (XMLNodeHdr) (data + rootNdOff - childOff);
			char	   *childNodeCopy = copyXMLNode(childNode, NULL, true, NULL);

			elems[i] = PointerGetDatum(childNodeCopy);
		}

		result = construct_array(elems, children, nodeType.oid, nodeType.elmlen, nodeType.elmbyval,
								 nodeType.elmalign);
		PG_RETURN_POINTER(result);
	}
	else
	{
		result = construct_empty_array(nodeType.oid);
		PG_RETURN_POINTER(result);
	}
}
コード例 #2
0
Datum
hstore_akeys(PG_FUNCTION_ARGS)
{
    HStore	   *hs = PG_GETARG_HS(0);
    Datum	   *d;
    ArrayType  *a;
    HEntry	   *entries = ARRPTR(hs);
    char	   *base = STRPTR(hs);
    int			count = HS_COUNT(hs);
    int			i;

    if (count == 0)
    {
        a = construct_empty_array(TEXTOID);
        PG_RETURN_POINTER(a);
    }

    d = (Datum *) palloc(sizeof(Datum) * count);

    for (i = 0; i < count; ++i)
    {
        text	   *item = cstring_to_text_with_len(HS_KEY(entries, base, i),
                           HS_KEYLEN(entries, i));

        d[i] = PointerGetDatum(item);
    }

    a = construct_array(d, count,
                        TEXTOID, -1, false, 'i');

    PG_RETURN_POINTER(a);
}
コード例 #3
0
ファイル: table_group.c プロジェクト: kikht/hvault
static ArrayType *
intArrayInit(int ndims, int const * dims, int const * lbs)
{
    ArrayType * res;
    int size;
    int nbytes;

    if (ndims < 0)              /* we do allow zero-dimension arrays */
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("invalid number of dimensions: %d", ndims)));
    if (ndims > MAXDIM)
        ereport(ERROR,
                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
                        ndims, MAXDIM)));
    

    /* fast track for empty array */
    if (ndims == 0)
        return construct_empty_array(INT4OID);
    
    size = ArrayGetNItems(ndims, dims);
    nbytes = ARR_OVERHEAD_NONULLS(ndims);
    nbytes += size * 4;
    res = palloc0(nbytes);
    SET_VARSIZE(res, nbytes);
    res->ndim = ndims;
    res->elemtype = INT4OID;
    res->dataoffset = 0;
    memcpy(ARR_DIMS(res), dims, ndims * sizeof(int));
    memcpy(ARR_LBOUND(res), lbs, ndims * sizeof(int));

    return res;
}
コード例 #4
0
ファイル: _int_tool.c プロジェクト: Brar/postgres
/* Create a new int array with room for "num" elements */
ArrayType *
new_intArrayType(int num)
{
	ArrayType  *r;
	int			nbytes;

	/* if no elements, return a zero-dimensional array */
	if (num <= 0)
	{
		r = construct_empty_array(INT4OID);
		return r;
	}

	nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num;

	r = (ArrayType *) palloc0(nbytes);

	SET_VARSIZE(r, nbytes);
	ARR_NDIM(r) = 1;
	r->dataoffset = 0;			/* marker for no null bitmap */
	ARR_ELEMTYPE(r) = INT4OID;
	ARR_DIMS(r)[0] = num;
	ARR_LBOUND(r)[0] = 1;

	return r;
}
コード例 #5
0
Datum
hstore_slice_to_array(PG_FUNCTION_ARGS)
{
    HStore	   *hs = PG_GETARG_HS(0);
    HEntry	   *entries = ARRPTR(hs);
    char	   *ptr = STRPTR(hs);
    ArrayType  *key_array = PG_GETARG_ARRAYTYPE_P(1);
    ArrayType  *aout;
    Datum	   *key_datums;
    bool	   *key_nulls;
    Datum	   *out_datums;
    bool	   *out_nulls;
    int			key_count;
    int			i;

    deconstruct_array(key_array,
                      TEXTOID, -1, false, 'i',
                      &key_datums, &key_nulls, &key_count);

    if (key_count == 0)
    {
        aout = construct_empty_array(TEXTOID);
        PG_RETURN_POINTER(aout);
    }

    out_datums = palloc(sizeof(Datum) * key_count);
    out_nulls = palloc(sizeof(bool) * key_count);

    for (i = 0; i < key_count; ++i)
    {
        text	   *key = (text *) DatumGetPointer(key_datums[i]);
        int			idx;

        if (key_nulls[i])
            idx = -1;
        else
            idx = hstoreFindKey(hs, NULL, VARDATA(key), VARSIZE(key) - VARHDRSZ);

        if (idx < 0 || HS_VALISNULL(entries, idx))
        {
            out_nulls[i] = true;
            out_datums[i] = (Datum) 0;
        }
        else
        {
            out_datums[i] = PointerGetDatum(
                                cstring_to_text_with_len(HS_VAL(entries, ptr, idx),
                                        HS_VALLEN(entries, idx)));
            out_nulls[i] = false;
        }
    }

    aout = construct_md_array(out_datums, out_nulls,
                              ARR_NDIM(key_array),
                              ARR_DIMS(key_array),
                              ARR_LBOUND(key_array),
                              TEXTOID, -1, false, 'i');

    PG_RETURN_POINTER(aout);
}
コード例 #6
0
ファイル: array_userfuncs.c プロジェクト: PJMODOS/postgres
/*
 * fetch_array_arg_replace_nulls
 *
 * Fetch an array-valued argument; if it's null, construct an empty array
 * value of the proper data type.  Also cache basic element type information
 * in fn_extra.
 */
static ArrayType *
fetch_array_arg_replace_nulls(FunctionCallInfo fcinfo, int argno)
{
	ArrayType  *v;
	Oid			element_type;
	ArrayMetaState *my_extra;

	/* First collect the array value */
	if (!PG_ARGISNULL(argno))
	{
		v = PG_GETARG_ARRAYTYPE_P(argno);
		element_type = ARR_ELEMTYPE(v);
	}
	else
	{
		/* We have to look up the array type and element type */
		Oid			arr_typeid = get_fn_expr_argtype(fcinfo->flinfo, argno);

		if (!OidIsValid(arr_typeid))
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("could not determine input data type")));
		element_type = get_element_type(arr_typeid);
		if (!OidIsValid(element_type))
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("input data type is not an array")));

		v = construct_empty_array(element_type);
	}

	/* Now cache required info, which might change from call to call */
	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
	if (my_extra == NULL)
	{
		my_extra = (ArrayMetaState *)
			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
							   sizeof(ArrayMetaState));
		my_extra->element_type = InvalidOid;
		fcinfo->flinfo->fn_extra = my_extra;
	}

	if (my_extra->element_type != element_type)
	{
		get_typlenbyvalalign(element_type,
							 &my_extra->typlen,
							 &my_extra->typbyval,
							 &my_extra->typalign);
		my_extra->element_type = element_type;
	}

	return v;
}
コード例 #7
0
ファイル: repack.c プロジェクト: reorg/pg_repack
/**
 * @fn      Datum get_table_and_inheritors(PG_FUNCTION_ARGS)
 * @brief   Return array containing Oids of parent table and its children.
 *          Note that this function does not release relation locks.
 *
 * get_table_and_inheritors(table)
 *
 * @param	table	parent table.
 * @retval	regclass[]
 */
Datum
repack_get_table_and_inheritors(PG_FUNCTION_ARGS)
{
	Oid			parent = PG_GETARG_OID(0);
	List	   *relations;
	Datum	   *relations_array;
	int			relations_array_size;
	ArrayType  *result;
	ListCell   *lc;
	int			i;

	LockRelationOid(parent, AccessShareLock);

	/* Check that parent table exists */
	if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(parent)))
		PG_RETURN_ARRAYTYPE_P(construct_empty_array(OIDOID));

	/* Also check that children exist */
	relations = find_all_inheritors(parent, AccessShareLock, NULL);

	relations_array_size = list_length(relations);
	if (relations_array_size == 0)
		PG_RETURN_ARRAYTYPE_P(construct_empty_array(OIDOID));

	relations_array = palloc(relations_array_size * sizeof(Datum));

	i = 0;
	foreach (lc, relations)
		relations_array[i++] = ObjectIdGetDatum(lfirst_oid(lc));

	result = construct_array(relations_array,
							 relations_array_size,
							 OIDOID, sizeof(Oid),
							 true, 'i');

	pfree(relations_array);

	PG_RETURN_ARRAYTYPE_P(result);
}
コード例 #8
0
Datum
array_agg_distinct_type_by_element(PG_FUNCTION_ARGS)
{
    /* get element type for the dummy second parameter (anynonarray item) */
    Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 1);

    CHECK_AGG_CONTEXT("count_distinct", fcinfo);

    /* return empty array if the state was not initialized */
    if (PG_ARGISNULL(0))
        PG_RETURN_DATUM(PointerGetDatum(construct_empty_array(element_type)));

    return build_array((element_set_t *)PG_GETARG_POINTER(0), element_type);
}
コード例 #9
0
ファイル: guc_test.c プロジェクト: hxford/gpdb
/*
 * Test GUCArrayReset
 *
 * superuser: return NULL
 */
void
test__GUCArrayReset__superuser(void **state)
{
	ArrayType	*in;
	ArrayType	*out;

	will_return(superuser, true);
	in = construct_empty_array(TEXTOID);
	assert_not_null(in);

	out = GUCArrayReset(in);
	assert_null(out);

	pfree(in);
}
コード例 #10
0
static ArrayType *
hstore_to_array_internal(HStore *hs, int ndims)
{
    HEntry	   *entries = ARRPTR(hs);
    char	   *base = STRPTR(hs);
    int			count = HS_COUNT(hs);
    int			out_size[2] = {0, 2};
    int			lb[2] = {1, 1};
    Datum	   *out_datums;
    bool	   *out_nulls;
    int			i;

    Assert(ndims < 3);

    if (count == 0 || ndims == 0)
        return construct_empty_array(TEXTOID);

    out_size[0] = count * 2 / ndims;
    out_datums = palloc(sizeof(Datum) * count * 2);
    out_nulls = palloc(sizeof(bool) * count * 2);

    for (i = 0; i < count; ++i)
    {
        text	   *key = cstring_to_text_with_len(HS_KEY(entries, base, i),
                          HS_KEYLEN(entries, i));

        out_datums[i * 2] = PointerGetDatum(key);
        out_nulls[i * 2] = false;

        if (HS_VALISNULL(entries, i))
        {
            out_datums[i * 2 + 1] = (Datum) 0;
            out_nulls[i * 2 + 1] = true;
        }
        else
        {
            text	   *item = cstring_to_text_with_len(HS_VAL(entries, base, i),
                               HS_VALLEN(entries, i));

            out_datums[i * 2 + 1] = PointerGetDatum(item);
            out_nulls[i * 2 + 1] = false;
        }
    }

    return construct_md_array(out_datums, out_nulls,
                              ndims, out_size, lb,
                              TEXTOID, -1, false, 'i');
}
コード例 #11
0
Datum
hstore_avals(PG_FUNCTION_ARGS)
{
    HStore	   *hs = PG_GETARG_HS(0);
    Datum	   *d;
    bool	   *nulls;
    ArrayType  *a;
    HEntry	   *entries = ARRPTR(hs);
    char	   *base = STRPTR(hs);
    int			count = HS_COUNT(hs);
    int			lb = 1;
    int			i;

    if (count == 0)
    {
        a = construct_empty_array(TEXTOID);
        PG_RETURN_POINTER(a);
    }

    d = (Datum *) palloc(sizeof(Datum) * count);
    nulls = (bool *) palloc(sizeof(bool) * count);

    for (i = 0; i < count; ++i)
    {
        if (HS_VALISNULL(entries, i))
        {
            d[i] = (Datum) 0;
            nulls[i] = true;
        }
        else
        {
            text	   *item = cstring_to_text_with_len(HS_VAL(entries, base, i),
                               HS_VALLEN(entries, i));

            d[i] = PointerGetDatum(item);
            nulls[i] = false;
        }
    }

    a = construct_md_array(d, nulls, 1, &count, &lb,
                           TEXTOID, -1, false, 'i');

    PG_RETURN_POINTER(a);
}
コード例 #12
0
ファイル: array_userfuncs.c プロジェクト: HBPSP8Repo/NoDB
/*-----------------------------------------------------------------------------
 * array_push :
 *		push an element onto either end of a one-dimensional array
 *----------------------------------------------------------------------------
 */
Datum
array_push(PG_FUNCTION_ARGS)
{
	ArrayType  *v;
	Datum		newelem;
	bool		isNull;
	int		   *dimv,
			   *lb;
	ArrayType  *result;
	int			indx;
	Oid			element_type;
	int16		typlen;
	bool		typbyval;
	char		typalign;
	Oid			arg0_typeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
	Oid			arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
	Oid			arg0_elemid;
	Oid			arg1_elemid;
	ArrayMetaState *my_extra;

	if (arg0_typeid == InvalidOid || arg1_typeid == InvalidOid)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("could not determine input data types")));

	arg0_elemid = get_element_type(arg0_typeid);
	arg1_elemid = get_element_type(arg1_typeid);

	if (arg0_elemid != InvalidOid)
	{
		if (PG_ARGISNULL(0))
			v = construct_empty_array(arg0_elemid);
		else
			v = PG_GETARG_ARRAYTYPE_P(0);
		isNull = PG_ARGISNULL(1);
		if (isNull)
			newelem = (Datum) 0;
		else
			newelem = PG_GETARG_DATUM(1);
	}
	else if (arg1_elemid != InvalidOid)
	{
		if (PG_ARGISNULL(1))
			v = construct_empty_array(arg1_elemid);
		else
			v = PG_GETARG_ARRAYTYPE_P(1);
		isNull = PG_ARGISNULL(0);
		if (isNull)
			newelem = (Datum) 0;
		else
			newelem = PG_GETARG_DATUM(0);
	}
	else
	{
		/* Shouldn't get here given proper type checking in parser */
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("neither input type is an array")));
		PG_RETURN_NULL();		/* keep compiler quiet */
	}

	element_type = ARR_ELEMTYPE(v);

	if (ARR_NDIM(v) == 1)
	{
		lb = ARR_LBOUND(v);
		dimv = ARR_DIMS(v);

		if (arg0_elemid != InvalidOid)
		{
			/* append newelem */
			int			ub = dimv[0] + lb[0] - 1;

			indx = ub + 1;
			/* overflow? */
			if (indx < ub)
				ereport(ERROR,
						(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
						 errmsg("integer out of range")));
		}
		else
		{
			/* prepend newelem */
			indx = lb[0] - 1;
			/* overflow? */
			if (indx > lb[0])
				ereport(ERROR,
						(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
						 errmsg("integer out of range")));
		}
	}
	else if (ARR_NDIM(v) == 0)
		indx = 1;
	else
		ereport(ERROR,
				(errcode(ERRCODE_DATA_EXCEPTION),
				 errmsg("argument must be empty or one-dimensional array")));

	/*
	 * We arrange to look up info about element type only once per series of
	 * calls, assuming the element type doesn't change underneath us.
	 */
	my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
	if (my_extra == NULL)
	{
		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
													  sizeof(ArrayMetaState));
		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
		my_extra->element_type = ~element_type;
	}

	if (my_extra->element_type != element_type)
	{
		/* Get info about element type */
		get_typlenbyvalalign(element_type,
							 &my_extra->typlen,
							 &my_extra->typbyval,
							 &my_extra->typalign);
		my_extra->element_type = element_type;
	}
	typlen = my_extra->typlen;
	typbyval = my_extra->typbyval;
	typalign = my_extra->typalign;

	result = array_set(v, 1, &indx, newelem, isNull,
					   -1, typlen, typbyval, typalign);

	/*
	 * Readjust result's LB to match the input's.  This does nothing in the
	 * append case, but it's the simplest way to implement the prepend case.
	 */
	if (ARR_NDIM(v) == 1)
		ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0];

	PG_RETURN_ARRAYTYPE_P(result);
}
コード例 #13
0
ファイル: cms_topn.c プロジェクト: SufianHassan/cms_topn
/*
 * UpdateTopnArray is a helper function for the unions and inserts. It takes
 * given item and its frequency. If the item is not in the top-n array, it tries
 * to insert new item. If there is place in the top-n array, it insert directly.
 * Otherwise, it compares its frequency with the minimum of current items in the
 * array and updates top-n array if new frequency is bigger.
 */
static ArrayType *
UpdateTopnArray(CmsTopn *cmsTopn, Datum candidateItem, TypeCacheEntry *itemTypeCacheEntry,
                Frequency itemFrequency, bool *topnArrayUpdated)
{
	ArrayType *currentTopnArray = TopnArray(cmsTopn);
	ArrayType *updatedTopnArray = NULL;
	int16 itemTypeLength = itemTypeCacheEntry->typlen;
	bool itemTypeByValue = itemTypeCacheEntry->typbyval;
	char itemTypeAlignment = itemTypeCacheEntry->typalign;
	Frequency minOfNewTopnItems = MAX_FREQUENCY;
	bool candidateAlreadyInArray = false;
	int candidateIndex = -1;

	int currentArrayLength = ARR_DIMS(currentTopnArray)[0];
	if (currentArrayLength == 0)
	{
		Oid itemType = itemTypeCacheEntry->type_id;
		if (itemTypeCacheEntry->typtype == TYPTYPE_COMPOSITE)
		{
			ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
			                errmsg("composite types are not supported")));
		}

		currentTopnArray = construct_empty_array(itemType);
	}

	/*
	 * If item frequency is smaller than min frequency of old top-n items,
	 * it cannot be in the top-n items and we insert it only if there is place.
	 * Otherwise, we need to check new minimum and whether it is in the top-n.
	 */
	if (itemFrequency <= cmsTopn->minFrequencyOfTopnItems)
	{
		if (currentArrayLength < cmsTopn->topnItemCount)
		{
			candidateIndex =  currentArrayLength + 1;
			minOfNewTopnItems = itemFrequency;
		}
	}
	else
	{
		ArrayIterator iterator = array_create_iterator(currentTopnArray, 0);
		Datum topnItem = 0;
		int topnItemIndex = 1;
		int minItemIndex = 1;
		bool hasMoreItem = false;
		bool isNull = false;

		/*
		 * Find the top-n item with minimum frequency to replace it with candidate
		 * item.
		 */
		hasMoreItem = array_iterate(iterator, &topnItem, &isNull);
		while (hasMoreItem)
		{
			Frequency topnItemFrequency = 0;

			/* check if we already have this item in top-n array */
			candidateAlreadyInArray = datumIsEqual(topnItem, candidateItem,
			                                       itemTypeByValue, itemTypeLength);
			if (candidateAlreadyInArray)
			{
				minItemIndex = -1;
				break;
			}

			/* keep track of minumum frequency item in the top-n array */
			topnItemFrequency = CmsTopnEstimateItemFrequency(cmsTopn, topnItem,
			                                                 itemTypeCacheEntry);
			if (topnItemFrequency < minOfNewTopnItems)
			{
				minOfNewTopnItems = topnItemFrequency;
				minItemIndex = topnItemIndex;
			}

			hasMoreItem = array_iterate(iterator, &topnItem, &isNull);
			topnItemIndex++;
		}

		/* if new item is not in the top-n and there is place, insert the item */
		if (!candidateAlreadyInArray && currentArrayLength < cmsTopn->topnItemCount)
		{
			minItemIndex = currentArrayLength + 1;
			minOfNewTopnItems = Min(minOfNewTopnItems, itemFrequency);
		}

		candidateIndex = minItemIndex;
	}

	/*
	 * If it is not in the top-n structure and its frequency bigger than minimum
	 * put into top-n instead of the item which has minimum frequency. If it is
	 * in top-n or not frequent items, do not change anything.
	 */
	if (!candidateAlreadyInArray && minOfNewTopnItems <= itemFrequency)
	{
		updatedTopnArray = array_set(currentTopnArray, 1, &candidateIndex,
		                             candidateItem, false, -1, itemTypeLength,
		                             itemTypeByValue, itemTypeAlignment);
		cmsTopn->minFrequencyOfTopnItems = minOfNewTopnItems;
		*topnArrayUpdated = true;
	}
	else
	{
		updatedTopnArray = currentTopnArray;
		*topnArrayUpdated = false;
	}

	return updatedTopnArray;
}