arrayfuncs.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,484 行 · 第 1/5 页

C
2,484
字号
							temp[nest_level - 1]++;						}					}					break;				default:					if (!in_quotes)					{						if (*ptr == typdelim)						{							/*							 * Delimiters can occur after an element start, an							 * element completion, a quoted element							 * completion, or a level completion.							 */							if (parse_state != ARRAY_ELEM_STARTED &&								parse_state != ARRAY_ELEM_COMPLETED &&								parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&								parse_state != ARRAY_LEVEL_COMPLETED)								ereport(ERROR,								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),								 errmsg("malformed array literal: \"%s\"", str)));							if (parse_state == ARRAY_LEVEL_COMPLETED)								parse_state = ARRAY_LEVEL_DELIMITED;							else								parse_state = ARRAY_ELEM_DELIMITED;							itemdone = true;							nelems[nest_level - 1]++;						}						else if (!isspace((unsigned char) *ptr))						{							/*							 * Other non-space characters must be after a							 * level start, after an element start, or after							 * an element delimiter. In any case we now must							 * be past an element start.							 */							if (parse_state != ARRAY_LEVEL_STARTED &&								parse_state != ARRAY_ELEM_STARTED &&								parse_state != ARRAY_ELEM_DELIMITED)								ereport(ERROR,								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),								 errmsg("malformed array literal: \"%s\"", str)));							parse_state = ARRAY_ELEM_STARTED;						}					}					break;			}			if (!itemdone)				ptr++;		}		temp[ndim - 1]++;		ptr++;	}	/* only whitespace is allowed after the closing brace */	while (*ptr)	{		if (!isspace((unsigned char) *ptr++))			ereport(ERROR,					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),					 errmsg("malformed array literal: \"%s\"", str)));	}	/* special case for an empty array */	if (empty_array)		return 0;	for (i = 0; i < ndim; ++i)		dim[i] = temp[i];	return ndim;}/* * ReadArrayStr : *	 parses the array string pointed to by "arrayStr" and converts the values *	 to internal format.  Unspecified elements are initialized to nulls. *	 The array dimensions must already have been determined. * * Inputs: *	arrayStr: the string to parse. *			  CAUTION: the contents of "arrayStr" will be modified! *	origStr: the unmodified input string, used only in error messages. *	nitems: total number of array elements, as already determined. *	ndim: number of array dimensions *	dim[]: array axis lengths *	inputproc: type-specific input procedure for element datatype. *	typioparam, typmod: auxiliary values to pass to inputproc. *	typdelim: the value delimiter (type-specific). *	typlen, typbyval, typalign: storage parameters of element datatype. * * Outputs: *	values[]: filled with converted data values. *	nulls[]: filled with is-null markers. *	*hasnulls: set TRUE iff there are any null elements. *	*nbytes: set to total size of data area needed (including alignment *		padding but not including array header overhead). * * Note that values[] and nulls[] are allocated by the caller, and must have * nitems elements. */static voidReadArrayStr(char *arrayStr,			 const char *origStr,			 int nitems,			 int ndim,			 int *dim,			 FmgrInfo *inputproc,			 Oid typioparam,			 int32 typmod,			 char typdelim,			 int typlen,			 bool typbyval,			 char typalign,			 Datum *values,			 bool *nulls,			 bool *hasnulls,			 int32 *nbytes){	int			i,				nest_level = 0;	char	   *srcptr;	bool		in_quotes = false;	bool		eoArray = false;	bool		hasnull;	int32		totbytes;	int			indx[MAXDIM],				prod[MAXDIM];	mda_get_prod(ndim, dim, prod);	MemSet(indx, 0, sizeof(indx));	/* Initialize is-null markers to true */	memset(nulls, true, nitems * sizeof(bool));	/*	 * We have to remove " and \ characters to create a clean item value to	 * pass to the datatype input routine.	We overwrite each item value	 * in-place within arrayStr to do this.  srcptr is the current scan point,	 * and dstptr is where we are copying to.	 *	 * We also want to suppress leading and trailing unquoted whitespace. We	 * use the leadingspace flag to suppress leading space.  Trailing space is	 * tracked by using dstendptr to point to the last significant output	 * character.	 *	 * The error checking in this routine is mostly pro-forma, since we expect	 * that ArrayCount() already validated the string.	 */	srcptr = arrayStr;	while (!eoArray)	{		bool		itemdone = false;		bool		leadingspace = true;		bool		hasquoting = false;		char	   *itemstart;		char	   *dstptr;		char	   *dstendptr;		i = -1;		itemstart = dstptr = dstendptr = srcptr;		while (!itemdone)		{			switch (*srcptr)			{				case '\0':					/* Signal a premature end of the string */					ereport(ERROR,							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),							 errmsg("malformed array literal: \"%s\"",									origStr)));					break;				case '\\':					/* Skip backslash, copy next character as-is. */					srcptr++;					if (*srcptr == '\0')						ereport(ERROR,								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),								 errmsg("malformed array literal: \"%s\"",										origStr)));					*dstptr++ = *srcptr++;					/* Treat the escaped character as non-whitespace */					leadingspace = false;					dstendptr = dstptr;					hasquoting = true;	/* can't be a NULL marker */					break;				case '\"':					in_quotes = !in_quotes;					if (in_quotes)						leadingspace = false;					else					{						/*						 * Advance dstendptr when we exit in_quotes; this						 * saves having to do it in all the other in_quotes						 * cases.						 */						dstendptr = dstptr;					}					hasquoting = true;	/* can't be a NULL marker */					srcptr++;					break;				case '{':					if (!in_quotes)					{						if (nest_level >= ndim)							ereport(ERROR,							   (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),								errmsg("malformed array literal: \"%s\"",									   origStr)));						nest_level++;						indx[nest_level - 1] = 0;						srcptr++;					}					else						*dstptr++ = *srcptr++;					break;				case '}':					if (!in_quotes)					{						if (nest_level == 0)							ereport(ERROR,							   (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),								errmsg("malformed array literal: \"%s\"",									   origStr)));						if (i == -1)							i = ArrayGetOffset0(ndim, indx, prod);						indx[nest_level - 1] = 0;						nest_level--;						if (nest_level == 0)							eoArray = itemdone = true;						else							indx[nest_level - 1]++;						srcptr++;					}					else						*dstptr++ = *srcptr++;					break;				default:					if (in_quotes)						*dstptr++ = *srcptr++;					else if (*srcptr == typdelim)					{						if (i == -1)							i = ArrayGetOffset0(ndim, indx, prod);						itemdone = true;						indx[ndim - 1]++;						srcptr++;					}					else if (isspace((unsigned char) *srcptr))					{						/*						 * If leading space, drop it immediately.  Else, copy						 * but don't advance dstendptr.						 */						if (leadingspace)							srcptr++;						else							*dstptr++ = *srcptr++;					}					else					{						*dstptr++ = *srcptr++;						leadingspace = false;						dstendptr = dstptr;					}					break;			}		}		Assert(dstptr < srcptr);		*dstendptr = '\0';		if (i < 0 || i >= nitems)			ereport(ERROR,					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),					 errmsg("malformed array literal: \"%s\"",							origStr)));		if (Array_nulls && !hasquoting &&			pg_strcasecmp(itemstart, "NULL") == 0)		{			/* it's a NULL item */			values[i] = InputFunctionCall(inputproc, NULL,										  typioparam, typmod);			nulls[i] = true;		}		else		{			values[i] = InputFunctionCall(inputproc, itemstart,										  typioparam, typmod);			nulls[i] = false;		}	}	/*	 * Check for nulls, compute total data space needed	 */	hasnull = false;	totbytes = 0;	for (i = 0; i < nitems; i++)	{		if (nulls[i])			hasnull = true;		else		{			/* let's just make sure data is not toasted */			if (typlen == -1)				values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));			totbytes = att_addlength_datum(totbytes, typlen, values[i]);			totbytes = att_align_nominal(totbytes, typalign);			/* check for overflow of total request */			if (!AllocSizeIsValid(totbytes))				ereport(ERROR,						(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),						 errmsg("array size exceeds the maximum allowed (%d)",								(int) MaxAllocSize)));		}	}	*hasnulls = hasnull;	*nbytes = totbytes;}/* * Copy data into an array object from a temporary array of Datums. * * array: array object (with header fields already filled in) * values: array of Datums to be copied * nulls: array of is-null flags (can be NULL if no nulls) * nitems: number of Datums to be copied * typbyval, typlen, typalign: info about element datatype * freedata: if TRUE and element type is pass-by-ref, pfree data values * referenced by Datums after copying them. * * If the input data is of varlena type, the caller must have ensured that * the values are not toasted.	(Doing it here doesn't work since the * caller has already allocated space for the array...) */static voidCopyArrayEls(ArrayType *array,			 Datum *values,			 bool *nulls,			 int nitems,			 int typlen,			 bool typbyval,			 char typalign,			 bool freedata){	char	   *p = ARR_DATA_PTR(array);	bits8	   *bitmap = ARR_NULLBITMAP(array);	int			bitval = 0;	int			bitmask = 1;	int			i;	if (typbyval)		freedata = false;	for (i = 0; i < nitems; i++)	{		if (nulls && nulls[i])		{			if (!bitmap)		/* shouldn't happen */				elog(ERROR, "null array element where not supported");			/* bitmap bit stays 0 */		}		else		{			bitval |= bitmask;			p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);			if (freedata)				pfree(DatumGetPointer(values[i]));		}		if (bitmap)		{			bitmask <<= 1;			if (bitmask == 0x100)			{				*bitmap++ = bitval;				bitval = 0;				bitmask = 1;			}		}	}	if (bitmap && bitmask != 1)		*bitmap = bitval;}/* * array_out : *		   takes the internal representation of an array and returns a string *		  containing the array in its external format. */Datumarray_out(PG_FUNCTION_ARGS){	ArrayType  *v = PG_GETARG_ARRAYTYPE_P(0);	Oid			element_type = ARR_ELEMTYPE(v);	int			typlen;	bool		typbyval;	char		typalign;	char		typdelim;	char	   *p,			   *tmp,			   *retval,			  **values,				dims_str[(MAXDIM * 33) + 2];	/*	 * 33 per dim since we assume 15 digits per number + ':' +'[]'	 *	 * +2 allows for assignment operator + trailing null	 */	bits8	   *bitmap;	int			bitmask;	bool	   *needquotes,				needdims = false;	int			nitems,				overall_length,				i,				j,				k,				indx[MAXDIM];	int			ndim,			   *dims,			   *lb;	ArrayMetaState *my_extra;	/*	 * We arrange to look up info about element type, including its output	 * conversion proc, 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, including its output conversion proc		 */		get_type_io_data(element_type, IOFunc_output,						 &my_extra->typlen, &my_extra->typbyval,						 &my_extra->typalign, &my_extra->typdelim,						 &my_extra->typioparam, &my_extra->typiofunc);		fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,					  fcinfo->flinfo->fn_mcxt);		my_extra->element_type = element_type;	}	typlen = my_extra->typlen;	typbyval = my_extra->typbyval;	typalign = my_extra->typalign;	typdelim = my_extra->typdelim;	ndim = ARR_NDIM(v);	dims = ARR_DIMS(v);	lb = ARR_LBOUND(v);	nitems = ArrayGetNItems(ndim, dims);	if (nitems == 0)	{		retval = pstrdup("{}");		PG_RETURN_CSTRING(retval);	}	/*	 * we will need to add explicit dimensions if any dimension has a lower	 * bound other than one	 */	for (i = 0; i < ndim; i++)	{		if (lb[i] != 1)		{			needdims = true;			break;		}	}	/*	 * Convert all values to string form, count total space needed (including	 * any overhead such as escaping backslashes), and detect whether each	 * item needs double quotes.	 */	values = (char **) palloc(nitems * sizeof(char *));	needquotes = (bool *) palloc(nitems * sizeof(bool));	overall_length = 1;			/* don't forget to count \0 at end. */	p = ARR_DATA_PTR(v);	bitmap = ARR_NULLBITMAP(v);

⌨️ 快捷键说明

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