arrayfuncs.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,367 行 · 第 1/5 页

C
2,367
字号
	 * OK, get the element	 */	offset = ArrayGetOffset(nSubscripts, dim, lb, indx);	retptr = array_seek(arraydataptr, offset, elmlen, elmbyval, elmalign);	*isNull = false;	return ArrayCast(retptr, elmbyval, elmlen);}/*----------------------------------------------------------------------------- * array_get_slice : *		   This routine takes an array and a range of indices (upperIndex and *		   lowerIndx), creates a new array structure for the referred elements *		   and returns a pointer to it. * * NOTE: we assume it is OK to scribble on the provided index arrays * lowerIndx[] and upperIndx[].  These are generally just temporaries. *----------------------------------------------------------------------------- */ArrayType *array_get_slice(ArrayType *array,				int nSubscripts,				int *upperIndx,				int *lowerIndx,				int arraylen,				int elmlen,				bool elmbyval,				char elmalign,				bool *isNull){	int			i,				ndim,			   *dim,			   *lb,			   *newlb;	int			fixedDim[1],				fixedLb[1];	char	   *arraydataptr;	ArrayType  *newarray;	int			bytes,				span[MAXDIM];	if (array == (ArrayType *) NULL)		RETURN_NULL(ArrayType *);	if (arraylen > 0)	{		/*		 * fixed-length arrays -- currently, cannot slice these because		 * parser labels output as being of the fixed-length array type!		 * Code below shows how we could support it if the parser were		 * changed to label output as a suitable varlena array type.		 */		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			   errmsg("slices of fixed-length arrays not implemented")));		/*		 * fixed-length arrays -- these are assumed to be 1-d, 0-based XXX		 * where would we get the correct ELEMTYPE from?		 */		ndim = 1;		fixedDim[0] = arraylen / elmlen;		fixedLb[0] = 0;		dim = fixedDim;		lb = fixedLb;		arraydataptr = (char *) array;	}	else	{		/* detoast input array if necessary */		array = DatumGetArrayTypeP(PointerGetDatum(array));		ndim = ARR_NDIM(array);		dim = ARR_DIMS(array);		lb = ARR_LBOUND(array);		arraydataptr = ARR_DATA_PTR(array);	}	/*	 * Check provided subscripts.  A slice exceeding the current array	 * limits is silently truncated to the array limits.  If we end up	 * with an empty slice, return NULL (should it be an empty array	 * instead?)	 */	if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)		RETURN_NULL(ArrayType *);	for (i = 0; i < nSubscripts; i++)	{		if (lowerIndx[i] < lb[i])			lowerIndx[i] = lb[i];		if (upperIndx[i] >= (dim[i] + lb[i]))			upperIndx[i] = dim[i] + lb[i] - 1;		if (lowerIndx[i] > upperIndx[i])			RETURN_NULL(ArrayType *);	}	/* 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])			RETURN_NULL(ArrayType *);	}	mda_get_range(ndim, span, lowerIndx, upperIndx);	bytes = array_slice_size(ndim, dim, lb, arraydataptr,							 lowerIndx, upperIndx,							 elmlen, elmbyval, elmalign);	bytes += ARR_OVERHEAD(ndim);	newarray = (ArrayType *) palloc(bytes);	newarray->size = bytes;	newarray->ndim = ndim;	newarray->flags = 0;	newarray->elemtype = ARR_ELEMTYPE(array);	memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int));	/*	 * Lower bounds of the new array are set to 1.	Formerly (before 7.3)	 * we copied the given lowerIndx values ... but that seems confusing.	 */	newlb = ARR_LBOUND(newarray);	for (i = 0; i < ndim; i++)		newlb[i] = 1;	array_extract_slice(ndim, dim, lb, arraydataptr,						lowerIndx, upperIndx, ARR_DATA_PTR(newarray),						elmlen, elmbyval, elmalign);	return newarray;}/*----------------------------------------------------------------------------- * array_set : *		  This routine sets the value of an array location (specified by *		  an index array) to a new value specified by "dataValue". * result : *		  A new array is returned, just like the old except for the one *		  modified entry. * * For one-dimensional arrays only, we allow the array to be extended * by assigning to the position one above or one below the existing range. * (We could be more flexible if we had a way to represent NULL elements.) * * NOTE: For assignments, we throw an error for invalid 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(ArrayType *array,		  int nSubscripts,		  int *indx,		  Datum dataValue,		  int arraylen,		  int elmlen,		  bool elmbyval,		  char elmalign,		  bool *isNull){	int			i,				ndim,				dim[MAXDIM],				lb[MAXDIM],				offset;	ArrayType  *newarray;	char	   *elt_ptr;	bool		extendbefore = false;	bool		extendafter = false;	int			olddatasize,				newsize,				olditemlen,				newitemlen,				overheadlen,				lenbefore,				lenafter;	if (array == (ArrayType *) NULL)		RETURN_NULL(ArrayType *);	if (arraylen > 0)	{		/*		 * fixed-length arrays -- these are assumed to be 1-d, 0-based. We		 * cannot extend them, either.		 */		if (nSubscripts != 1)			ereport(ERROR,					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),					 errmsg("invalid array subscripts")));		if (indx[0] < 0 || indx[0] * elmlen >= arraylen)			ereport(ERROR,					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),					 errmsg("invalid array subscripts")));		newarray = (ArrayType *) palloc(arraylen);		memcpy(newarray, array, arraylen);		elt_ptr = (char *) newarray + indx[0] * elmlen;		ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);		return newarray;	}	/* make sure item to be inserted is not toasted */	if (elmlen == -1)		dataValue = PointerGetDatum(PG_DETOAST_DATUM(dataValue));	/* detoast input array if necessary */	array = DatumGetArrayTypeP(PointerGetDatum(array));	ndim = ARR_NDIM(array);	/*	 * if number of dims is zero, i.e. an empty array, create an array	 * with nSubscripts dimensions, and set the lower bounds to the	 * supplied subscripts	 */	if (ndim == 0)	{		Oid			elmtype = ARR_ELEMTYPE(array);		for (i = 0; i < nSubscripts; i++)		{			dim[i] = 1;			lb[i] = indx[i];		}		return construct_md_array(&dataValue, 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 subscripts	 */	for (i = 0; i < ndim; i++)	{		if (indx[i] < lb[i])		{			if (ndim == 1 && indx[i] == lb[i] - 1)			{				dim[i]++;				lb[i]--;				extendbefore = true;			}			else				ereport(ERROR,						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),						 errmsg("invalid array subscripts")));		}		if (indx[i] >= (dim[i] + lb[i]))		{			if (ndim == 1 && indx[i] == (dim[i] + lb[i]))			{				dim[i]++;				extendafter = true;			}			else				ereport(ERROR,						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),						 errmsg("invalid array subscripts")));		}	}	/*	 * Compute sizes of items and areas to copy	 */	overheadlen = ARR_OVERHEAD(ndim);	olddatasize = ARR_SIZE(array) - overheadlen;	if (extendbefore)	{		lenbefore = 0;		olditemlen = 0;		lenafter = olddatasize;	}	else if (extendafter)	{		lenbefore = olddatasize;		olditemlen = 0;		lenafter = 0;	}	else	{		offset = ArrayGetOffset(nSubscripts, dim, lb, indx);		elt_ptr = array_seek(ARR_DATA_PTR(array), offset,							 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 == (ArrayType *) NULL)		RETURN_NULL(ArrayType *);	if (srcArray == (ArrayType *) 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")));		}	}

⌨️ 快捷键说明

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