⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arrayfuncs.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
							 elmlen, elmbyval, elmalign);		lenbefore = (int) (elt_ptr - ARR_DATA_PTR(array));		olditemlen = att_addlength(0, elmlen, PointerGetDatum(elt_ptr));		olditemlen = att_align(olditemlen, elmalign);		lenafter = (int) (olddatasize - lenbefore - olditemlen);	}	newitemlen = att_addlength(0, elmlen, dataValue);	newitemlen = att_align(newitemlen, elmalign);	newsize = overheadlen + lenbefore + newitemlen + lenafter;	/*	 * OK, do the assignment	 */	newarray = (ArrayType *) palloc(newsize);	newarray->size = newsize;	newarray->ndim = ndim;	newarray->flags = 0;	newarray->elemtype = ARR_ELEMTYPE(array);	memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int));	memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int));	memcpy((char *) newarray + overheadlen,		   (char *) array + overheadlen,		   lenbefore);	memcpy((char *) newarray + overheadlen + lenbefore + newitemlen,		   (char *) array + overheadlen + lenbefore + olditemlen,		   lenafter);	ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign,					(char *) newarray + overheadlen + lenbefore);	return newarray;}/*---------------------------------------------------------------------------- * array_set_slice : *		  This routine sets the value of a range of array locations (specified *		  by upper and lower index values ) to new values passed as *		  another array * result : *		  A new array is returned, just like the old except for the *		  modified range. * * NOTE: we assume it is OK to scribble on the provided index arrays * lowerIndx[] and upperIndx[].  These are generally just temporaries. * * NOTE: For assignments, we throw an error for silly subscripts etc, * rather than returning a NULL as the fetch operations do.  The reasoning * is that returning a NULL would cause the user's whole array to be replaced * with NULL, which will probably not make him happy. *---------------------------------------------------------------------------- */ArrayType *array_set_slice(ArrayType *array,				int nSubscripts,				int *upperIndx,				int *lowerIndx,				ArrayType *srcArray,				int arraylen,				int elmlen,				bool elmbyval,				char elmalign,				bool *isNull){	int			i,				ndim,				dim[MAXDIM],				lb[MAXDIM],				span[MAXDIM];	ArrayType  *newarray;	int			nsrcitems,				olddatasize,				newsize,				olditemsize,				newitemsize,				overheadlen,				lenbefore,				lenafter;	if (array == NULL)		RETURN_NULL(ArrayType *);	if (srcArray == NULL)		return array;	if (arraylen > 0)	{		/*		 * fixed-length arrays -- not got round to doing this...		 */		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),		errmsg("updates on slices of fixed-length arrays not implemented")));	}	/* detoast arrays if necessary */	array = DatumGetArrayTypeP(PointerGetDatum(array));	srcArray = DatumGetArrayTypeP(PointerGetDatum(srcArray));	/* note: we assume srcArray contains no toasted elements */	ndim = ARR_NDIM(array);	/*	 * if number of dims is zero, i.e. an empty array, create an array with	 * nSubscripts dimensions, and set the upper and lower bounds to the	 * supplied subscripts	 */	if (ndim == 0)	{		Datum	   *dvalues;		int			nelems;		Oid			elmtype = ARR_ELEMTYPE(array);		deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign,						  &dvalues, &nelems);		for (i = 0; i < nSubscripts; i++)		{			dim[i] = 1 + upperIndx[i] - lowerIndx[i];			lb[i] = lowerIndx[i];		}		/* complain if too few source items; we ignore extras, however */		if (nelems < ArrayGetNItems(nSubscripts, dim))			ereport(ERROR,					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),					 errmsg("source array too small")));		return construct_md_array(dvalues, nSubscripts, dim, lb, elmtype,								  elmlen, elmbyval, elmalign);	}	if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)		ereport(ERROR,				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),				 errmsg("invalid array subscripts")));	/* copy dim/lb since we may modify them */	memcpy(dim, ARR_DIMS(array), ndim * sizeof(int));	memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int));	/*	 * Check provided subscripts.  A slice exceeding the current array limits	 * throws an error, *except* in the 1-D case where we will extend the	 * array as long as no hole is created. An empty slice is an error, too.	 */	for (i = 0; i < nSubscripts; i++)	{		if (lowerIndx[i] > upperIndx[i])			ereport(ERROR,					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),					 errmsg("invalid array subscripts")));		if (lowerIndx[i] < lb[i])		{			if (ndim == 1 && upperIndx[i] >= lb[i] - 1)			{				dim[i] += lb[i] - lowerIndx[i];				lb[i] = lowerIndx[i];			}			else				ereport(ERROR,						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),						 errmsg("invalid array subscripts")));		}		if (upperIndx[i] >= (dim[i] + lb[i]))		{			if (ndim == 1 && lowerIndx[i] <= (dim[i] + lb[i]))				dim[i] = upperIndx[i] - lb[i] + 1;			else				ereport(ERROR,						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),						 errmsg("invalid array subscripts")));		}	}	/* fill any missing subscript positions with full array range */	for (; i < ndim; i++)	{		lowerIndx[i] = lb[i];		upperIndx[i] = dim[i] + lb[i] - 1;		if (lowerIndx[i] > upperIndx[i])			ereport(ERROR,					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),					 errmsg("invalid array subscripts")));	}	/*	 * Make sure source array has enough entries.  Note we ignore the shape of	 * the source array and just read entries serially.	 */	mda_get_range(ndim, span, lowerIndx, upperIndx);	nsrcitems = ArrayGetNItems(ndim, span);	if (nsrcitems > ArrayGetNItems(ARR_NDIM(srcArray), ARR_DIMS(srcArray)))		ereport(ERROR,				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),				 errmsg("source array too small")));	/*	 * Compute space occupied by new entries, space occupied by replaced	 * entries, and required space for new array.	 */	newitemsize = array_nelems_size(ARR_DATA_PTR(srcArray), nsrcitems,									elmlen, elmbyval, elmalign);	overheadlen = ARR_OVERHEAD(ndim);	olddatasize = ARR_SIZE(array) - overheadlen;	if (ndim > 1)	{		/*		 * here we do not need to cope with extension of the array; it would		 * be a lot more complicated if we had to do so...		 */		olditemsize = array_slice_size(ndim, dim, lb, ARR_DATA_PTR(array),									   lowerIndx, upperIndx,									   elmlen, elmbyval, elmalign);		lenbefore = lenafter = 0;		/* keep compiler quiet */	}	else	{		/*		 * here we must allow for possibility of slice larger than orig array		 */		int			oldlb = ARR_LBOUND(array)[0];		int			oldub = oldlb + ARR_DIMS(array)[0] - 1;		int			slicelb = Max(oldlb, lowerIndx[0]);		int			sliceub = Min(oldub, upperIndx[0]);		char	   *oldarraydata = ARR_DATA_PTR(array);		lenbefore = array_nelems_size(oldarraydata, slicelb - oldlb,									  elmlen, elmbyval, elmalign);		if (slicelb > sliceub)			olditemsize = 0;		else			olditemsize = array_nelems_size(oldarraydata + lenbefore,											sliceub - slicelb + 1,											elmlen, elmbyval, elmalign);		lenafter = olddatasize - lenbefore - olditemsize;	}	newsize = overheadlen + olddatasize - olditemsize + newitemsize;	newarray = (ArrayType *) palloc(newsize);	newarray->size = newsize;	newarray->ndim = ndim;	newarray->flags = 0;	newarray->elemtype = ARR_ELEMTYPE(array);	memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int));	memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int));	if (ndim > 1)	{		/*		 * here we do not need to cope with extension of the array; it would		 * be a lot more complicated if we had to do so...		 */		array_insert_slice(ndim, dim, lb, ARR_DATA_PTR(array), olddatasize,						   ARR_DATA_PTR(newarray),						   lowerIndx, upperIndx, ARR_DATA_PTR(srcArray),						   elmlen, elmbyval, elmalign);	}	else	{		memcpy((char *) newarray + overheadlen,			   (char *) array + overheadlen,			   lenbefore);		memcpy((char *) newarray + overheadlen + lenbefore,			   ARR_DATA_PTR(srcArray),			   newitemsize);		memcpy((char *) newarray + overheadlen + lenbefore + newitemsize,			   (char *) array + overheadlen + lenbefore + olditemsize,			   lenafter);	}	return newarray;}/* * array_map() * * Map an array through an arbitrary function.	Return a new array with * same dimensions and each source element transformed by fn().  Each * source element is passed as the first argument to fn(); additional * arguments to be passed to fn() can be specified by the caller. * The output array can have a different element type than the input. * * Parameters are: * * fcinfo: a function-call data structure pre-constructed by the caller *	 to be ready to call the desired function, with everything except the *	 first argument position filled in.  In particular, flinfo identifies *	 the function fn(), and if nargs > 1 then argument positions after the *	 first must be preset to the additional values to be passed.  The *	 first argument position initially holds the input array value. * * inpType: OID of element type of input array.  This must be the same as, *	 or binary-compatible with, the first argument type of fn(). * * retType: OID of element type of output array.	This must be the same as, *	 or binary-compatible with, the result type of fn(). * * amstate: workspace for array_map.	Must be zeroed by caller before *	 first call, and not touched after that. * * It is legitimate to pass a freshly-zeroed ArrayMapState on each call, * but better performance can be had if the state can be preserved across * a series of calls. * * NB: caller must assure that input array is not NULL.  Currently, * any additional parameters passed to fn() may not be specified as NULL * either. */Datumarray_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,		  ArrayMapState *amstate){	ArrayType  *v;	ArrayType  *result;	Datum	   *values;	Datum		elt;	int		   *dim;	int			ndim;	int			nitems;	int			i;	int			nbytes = 0;	int			inp_typlen;	bool		inp_typbyval;	char		inp_typalign;	int			typlen;	bool		typbyval;	char		typalign;	char	   *s;	ArrayMetaState *inp_extra;	ArrayMetaState *ret_extra;	/* Get input array */	if (fcinfo->nargs < 1)		elog(ERROR, "invalid nargs: %d", fcinfo->nargs);	if (PG_ARGISNULL(0))		elog(ERROR, "null input array");	v = PG_GETARG_ARRAYTYPE_P(0);	Assert(ARR_ELEMTYPE(v) == inpType);	ndim = ARR_NDIM(v);	dim = ARR_DIMS(v);	nitems = ArrayGetNItems(ndim, dim);	/* Check for empty array */	if (nitems <= 0)	{		/* Return empty array */		result = (ArrayType *) palloc0(sizeof(ArrayType));		result->size = sizeof(ArrayType);		result->elemtype = retType;		PG_RETURN_ARRAYTYPE_P(result);	}	/*	 * We arrange to look up info about input and return element types only	 * once per series of calls, assuming the element type doesn't change	 * underneath us.	 */	inp_extra = &amstate->inp_extra;	ret_extra = &amstate->ret_extra;	if (inp_extra->element_type != inpType)	{		get_typlenbyvalalign(inpType,							 &inp_extra->typlen,							 &inp_extra->typbyval,							 &inp_extra->typalign);		inp_extra->element_type = inpType;	}	inp_typlen = inp_extra->typlen;	inp_typbyval = inp_extra->typbyval;	inp_typalign = inp_extra->typalign;	if (ret_extra->element_type != retType)	{		get_typlenbyvalalign(retType,							 &ret_extra->typlen,							 &ret_extra->typbyval,							 &ret_extra->typalign);		ret_extra->element_type = retType;	}	typlen = ret_extra->typlen;	typbyval = ret_extra->typbyval;	typalign = ret_extra->typalign;	/* Allocate temporary array for new values */	values = (Datum *) palloc(nitems * sizeof(Datum));	/* Loop over source data */	s = (char *) ARR_DATA_PTR(v);	for (i = 0; i < nitems; i++)	{		/* Get source element */		elt = fetch_att(s, inp_typbyval, inp_typlen);		s = att_addlength(s, inp_typlen, PointerGetDatum(s));		s = (char *) att_align(s, inp_typalign);		/*		 * Apply the given function to source elt and extra args.		 *		 * We assume the extra args are non-NULL, so need not check whether		 * fn() is strict.	Would need to do more work here to support arrays		 * containing nulls, too.		 */		fcinfo->arg[0] = elt;		fcinfo->argnull[0] = false;		fcinfo->isnull = false;		values[i] = FunctionCallInvoke(fcinfo);		if (fcinfo->isnull)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("null array elements not supported")));		/* Ensure data is not toasted */		if (typlen == -1)			values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));		/* Update total result size */		nbytes = att_addlength(nbytes, typlen, values[i]);		nbytes = att_align(nbytes, typalign);	}	/* Allocate and initialize the result array */	nbytes += ARR_OVERHEAD(ndim);	result = (ArrayType *) palloc0(nbytes);	result->size = nbytes;	result->ndim = ndim;	result->elemtype = retType;	memcpy(ARR_DIMS(result), ARR_DIMS(v), 2 * ndim * sizeof(int));	/*	 * Note: do not risk trying to pfree the results of the called function	 */	CopyArrayEls(ARR_DATA_PTR(result), values, nitems,				 typlen, typbyval, typalign, false);	pfree(values);	PG_RETURN_ARRAYTYPE_P(result);}/*---------- * construct_array	--- simple method for constructing an array object * * elems: array of Datum items to become the array contents * nelems: number of items * elmtype, elmlen, elmbyval, elmalign: info for the datatype of the items * * A palloc'd 1-D array object is constructed and returned.  Note that * elem values will be copied into the object even if pass-by-ref type. * NULL element values are not supported. * * NOTE: it would be cleaner to look up the elmlen/elmbval/elmalign info * from the system catalogs, given the elmtype.  However, the caller is * in a better position to cache this info across multiple uses, or even * to hard-wire values if the element type is hard-wired. *---------- */ArrayType *construct_array(Datum *elems, int nelems,				Oid elmtype,				int elmlen, bool elmbyval, char elmalign){	int			dims[1];	int			lbs[1];	dims[0] = nelems;	lbs[0] = 1;	return construct_md_array(elems, 1, dims, lb

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -