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

📄 arrayfuncs.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
						if (ndim < nest_level)							ndim = nest_level;					}					break;				case '}':					if (!in_quotes)					{						/*						 * A right brace 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 &&							!(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED))							ereport(ERROR,							   (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),							errmsg("malformed array literal: \"%s\"", str)));						parse_state = ARRAY_LEVEL_COMPLETED;						if (nest_level == 0)							ereport(ERROR,							   (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),							errmsg("malformed array literal: \"%s\"", str)));						nest_level--;						if ((nelems_last[nest_level] != 1) &&							(nelems[nest_level] != nelems_last[nest_level]))							ereport(ERROR,							   (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),								errmsg("multidimensional arrays must have "									   "array expressions with matching "									   "dimensions")));						nelems_last[nest_level] = nelems[nest_level];						nelems[nest_level] = 1;						if (nest_level == 0)							eoArray = itemdone = true;						else						{							/*							 * We don't set itemdone here; see comments in							 * ReadArrayStr							 */							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 by "arrayStr" and converts it to *	 internal format. The external format expected is like C array *	 declaration. Unspecified elements are initialized to zero for fixed length *	 base types and to empty varlena structures for variable length base *	 types.  (This is pretty bogus; NULL would be much safer.) * * result : *	 returns a palloc'd array of Datum representations of the array elements. *	 If element type is pass-by-ref, the Datums point to palloc'd values. *	 *nbytes is set to the amount of data space needed for the array, *	 including alignment padding but not including array header overhead. * *	 CAUTION: the contents of "arrayStr" will be modified! *--------------------------------------------------------------------------- */static Datum *ReadArrayStr(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,			 int *nbytes){	int			i,				nest_level = 0;	Datum	   *values;	char	   *srcptr;	bool		in_quotes = false;	bool		eoArray = false;	int			totbytes;	int			indx[MAXDIM],				prod[MAXDIM];	mda_get_prod(ndim, dim, prod);	values = (Datum *) palloc0(nitems * sizeof(Datum));	MemSet(indx, 0, sizeof(indx));	/*	 * 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;		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;					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;					}					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)));		values[i] = FunctionCall3(inputproc,								  CStringGetDatum(itemstart),								  ObjectIdGetDatum(typioparam),								  Int32GetDatum(typmod));	}	/*	 * Initialize any unset items and compute total data space needed	 */	if (typlen > 0)	{		totbytes = nitems * att_align(typlen, typalign);		if (!typbyval)			for (i = 0; i < nitems; i++)				if (values[i] == (Datum) 0)					values[i] = PointerGetDatum(palloc0(typlen));	}	else	{		Assert(!typbyval);		totbytes = 0;		for (i = 0; i < nitems; i++)		{			if (values[i] != (Datum) 0)			{				/* let's just make sure data is not toasted */				if (typlen == -1)					values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));				totbytes = att_addlength(totbytes, typlen, values[i]);				totbytes = att_align(totbytes, typalign);			}			else if (typlen == -1)			{				/* dummy varlena value (XXX bogus, see notes above) */				values[i] = PointerGetDatum(palloc(sizeof(int32)));				VARATT_SIZEP(DatumGetPointer(values[i])) = sizeof(int32);				totbytes += sizeof(int32);				totbytes = att_align(totbytes, typalign);			}			else			{				/* dummy cstring value */				Assert(typlen == -2);				values[i] = PointerGetDatum(palloc(1));				*((char *) DatumGetPointer(values[i])) = '\0';				totbytes += 1;				totbytes = att_align(totbytes, typalign);			}		}	}	*nbytes = totbytes;	return values;}/*---------- * Copy data into an array object from a temporary array of Datums. * * p: pointer to start of array data area * values: array of Datums to be copied * 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(char *p,			 Datum *values,			 int nitems,			 int typlen,			 bool typbyval,			 char typalign,			 bool freedata){	int			i;	if (typbyval)		freedata = false;	for (i = 0; i < nitems; i++)	{		p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);		if (freedata)			pfree(DatumGetPointer(values[i]));	}}/*------------------------------------------------------------------------- * 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;	int			typlen;	bool		typbyval;	char		typalign;	char		typdelim;	char	   *p,			   *tmp,			   *retval,			  **values,	/*	 * 33 per dim since we assume 15 digits per number + ':' +'[]'	 *	 * +2 allows for assignment operator + trailing null	 */				dims_str[(MAXDIM * 33) + 2];	bool	   *needquotes,				needdims = false;	int			nitems,				overall_length,				i,				j,				k,				indx[MAXDIM];	int			ndim,			   *dims,			   *lb;	ArrayMetaState *my_extra;	element_type = ARR_ELEMTYPE(v);	/*	 * 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 = InvalidOid;	}	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);

⌨️ 快捷键说明

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