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

📄 arrayfuncs.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * arrayfuncs.c *	  Special functions for arrays. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.43.2.1 1999/08/02 05:24:49 scrappy Exp $ * *------------------------------------------------------------------------- */#include <ctype.h>#include "postgres.h"#include "catalog/catalog.h"#include "catalog/pg_type.h"#include "fmgr.h"#include "libpq/be-fsstubs.h"#include "libpq/libpq-fs.h"#include "storage/fd.h"#include "utils/array.h"#include "utils/memutils.h"#include "utils/syscache.h"#define ASSGN	 "="/* An array has the following internal structure: *	  <nbytes>		- total number of bytes *	  <ndim>		- number of dimensions of the array *	  <flags>		- bit mask of flags *	  <dim>			- size of each array axis *	  <dim_lower>	- lower boundary of each dimension *	  <actual data> - whatever is the stored data *//*-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-*/static int	_ArrayCount(char *str, int *dim, int typdelim);static char *_ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim,			  FmgrInfo *inputproc, Oid typelem, int32 typmod,			  char typdelim, int typlen, bool typbyval,			  char typalign, int *nbytes);#ifdef LOARRAYstatic char *_ReadLOArray(char *str, int *nbytes, int *fd, bool *chunkFlag,			 int ndim, int *dim, int baseSize);#endifstatic void _CopyArrayEls(char **values, char *p, int nitems, int typlen,			  char typalign, bool typbyval);static void system_cache_lookup(Oid element_type, bool input, int *typlen,				 bool *typbyval, char *typdelim, Oid *typelem, Oid *proc,					char *typalign);static Datum _ArrayCast(char *value, bool byval, int len);#ifdef LOARRAYstatic char *_AdvanceBy1word(char *str, char **word);#endifstatic void _ArrayRange(int *st, int *endp, int bsize, char *destPtr,			ArrayType *array, int from);static int	_ArrayClipCount(int *stI, int *endpI, ArrayType *array);static void _LOArrayRange(int *st, int *endp, int bsize, int srcfd,			  int destfd, ArrayType *array, int isSrcLO, bool *isNull);static void _ReadArray(int *st, int *endp, int bsize, int srcfd, int destfd,		   ArrayType *array, int isDestLO, bool *isNull);static int	ArrayCastAndSet(char *src, bool typbyval, int typlen, char *dest);static int	SanityCheckInput(int ndim, int n, int *dim, int *lb, int *indx);static int	array_read(char *destptr, int eltsize, int nitems, char *srcptr);static char *array_seek(char *ptr, int eltsize, int nitems);/*--------------------------------------------------------------------- * array_in : *		  converts an array from the external format in "string" to *		  it internal format. * return value : *		  the internal representation of the input array *-------------------------------------------------------------------- */char *array_in(char *string,			/* input array in external form */		 Oid element_type,		/* type OID of an array element */		 int32 typmod){	int			typlen;	bool		typbyval,				done;	char		typdelim;	Oid			typinput;	Oid			typelem;	char	   *string_save,			   *p,			   *q,			   *r;	FmgrInfo	inputproc;	int			i,				nitems;	int32		nbytes;	char	   *dataPtr;	ArrayType  *retval = NULL;	int			ndim,				dim[MAXDIM],				lBound[MAXDIM];	char		typalign;	system_cache_lookup(element_type, true, &typlen, &typbyval, &typdelim,						&typelem, &typinput, &typalign);	fmgr_info(typinput, &inputproc);	string_save = (char *) palloc(strlen(string) + 3);	strcpy(string_save, string);	/* --- read array dimensions  ---------- */	p = q = string_save;	done = false;	for (ndim = 0; !done;)	{		while (isspace(*p))			p++;		if (*p == '[')		{			p++;			if ((r = (char *) strchr(p, ':')) == (char *) NULL)				lBound[ndim] = 1;			else			{				*r = '\0';				lBound[ndim] = atoi(p);				p = r + 1;			}			for (q = p; isdigit(*q); q++);			if (*q != ']')				elog(ERROR, "array_in: missing ']' in array declaration");			*q = '\0';			dim[ndim] = atoi(p);			if ((dim[ndim] < 0) || (lBound[ndim] < 0))				elog(ERROR, "array_in: array dimensions need to be positive");			dim[ndim] = dim[ndim] - lBound[ndim] + 1;			if (dim[ndim] < 0)				elog(ERROR, "array_in: upper_bound cannot be < lower_bound");			p = q + 1;			ndim++;		}		else			done = true;	}	if (ndim == 0)	{		if (*p == '{')		{			ndim = _ArrayCount(p, dim, typdelim);			for (i = 0; i < ndim; lBound[i++] = 1);		}		else			elog(ERROR, "array_in: Need to specify dimension");	}	else	{		while (isspace(*p))			p++;		if (strncmp(p, ASSGN, strlen(ASSGN)))			elog(ERROR, "array_in: missing assignment operator");		p += strlen(ASSGN);		while (isspace(*p))			p++;	}#ifdef ARRAYDEBUG	printf("array_in- ndim %d (", ndim);	for (i = 0; i < ndim; i++)	{		printf(" %d", dim[i]);	};	printf(") for %s\n", string);#endif	nitems = getNitems(ndim, dim);	if (nitems == 0)	{		char	   *emptyArray = palloc(sizeof(ArrayType));		MemSet(emptyArray, 0, sizeof(ArrayType));		*(int32 *) emptyArray = sizeof(ArrayType);		return emptyArray;	}	if (*p == '{')	{		/* array not a large object */		dataPtr = (char *) _ReadArrayStr(p, nitems, ndim, dim, &inputproc, typelem,							typmod, typdelim, typlen, typbyval, typalign,										 &nbytes);		nbytes += ARR_OVERHEAD(ndim);		retval = (ArrayType *) palloc(nbytes);		MemSet(retval, 0, nbytes);		memmove(retval, (char *) &nbytes, sizeof(int));		memmove((char *) ARR_NDIM_PTR(retval), (char *) &ndim, sizeof(int));		SET_LO_FLAG(false, retval);		memmove((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int));		memmove((char *) ARR_LBOUND(retval), (char *) lBound,				ndim * sizeof(int));		/*		 * dataPtr is an array of arbitraystuff even though its type is		 * char* cast to char** to pass to _CopyArrayEls for now  - jolly		 */		_CopyArrayEls((char **) dataPtr,					  ARR_DATA_PTR(retval), nitems,					  typlen, typalign, typbyval);	}	else	{#ifdef LOARRAY		int			dummy,					bytes;		bool		chunked = false;		dataPtr = _ReadLOArray(p, &bytes, &dummy, &chunked, ndim,							   dim, typlen);		nbytes = bytes + ARR_OVERHEAD(ndim);		retval = (ArrayType *) palloc(nbytes);		MemSet(retval, 0, nbytes);		memmove(retval, (char *) &nbytes, sizeof(int));		memmove((char *) ARR_NDIM_PTR(retval), (char *) &ndim, sizeof(int));		SET_LO_FLAG(true, retval);		SET_CHUNK_FLAG(chunked, retval);		memmove((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int));		memmove((char *) ARR_LBOUND(retval), (char *) lBound, ndim * sizeof(int));		memmove(ARR_DATA_PTR(retval), dataPtr, bytes);#endif		elog(ERROR, "large object arrays not supported");	}	pfree(string_save);	return (char *) retval;}/*----------------------------------------------------------------------------- * _ArrayCount *	 Counts the number of dimensions and the *dim array for an array string. *		 The syntax for array input is C-like nested curly braces *----------------------------------------------------------------------------- */static int_ArrayCount(char *str, int *dim, int typdelim){	int			nest_level = 0,				i;	int			ndim = 0,				temp[MAXDIM];	bool		scanning_string = false;	bool		eoArray = false;	char	   *q;	for (i = 0; i < MAXDIM; ++i)		temp[i] = dim[i] = 0;	if (strncmp(str, "{}", 2) == 0)		return 0;	q = str;	while (eoArray != true)	{		bool		done = false;		while (!done)		{			switch (*q)			{				case '\\':					/* skip escaped characters (\ and ") inside strings */					if (scanning_string && *(q + 1))						q++;					break;				case '\0':					/*					 * Signal a premature end of the string.  DZ -					 * 2-9-1996					 */					elog(ERROR, "malformed array constant: %s", str);					break;				case '\"':					scanning_string = !scanning_string;					break;				case '{':					if (!scanning_string)					{						temp[nest_level] = 0;						nest_level++;					}					break;				case '}':					if (!scanning_string)					{						if (!ndim)							ndim = nest_level;						nest_level--;						if (nest_level)							temp[nest_level - 1]++;						if (nest_level == 0)							eoArray = done = true;					}					break;				default:					if (!ndim)						ndim = nest_level;					if (*q == typdelim && !scanning_string)						done = true;					break;			}			if (!done)				q++;		}		temp[ndim - 1]++;		q++;		if (!eoArray)			while (isspace(*q))				q++;	}	for (i = 0; i < ndim; ++i)		dim[i] = temp[i];	return ndim;}/*--------------------------------------------------------------------------- * _ReadArrayStr : *	 parses the array string pointed by "arrayStr" and converts it in the *	 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. * result : *	 returns the internal representation of the array elements *	 nbytes is set to the size of the array in its internal representation. *--------------------------------------------------------------------------- */static char *_ReadArrayStr(char *arrayStr,			  int nitems,			  int ndim,			  int *dim,			  FmgrInfo *inputproc,		/* function used for the										 * conversion */			  Oid typelem,			  int32 typmod,			  char typdelim,			  int typlen,			  bool typbyval,			  char typalign,			  int *nbytes){	int			i,				nest_level = 0;	char	   *p,			   *q,			   *r,			  **values;	bool		scanning_string = false;	int			indx[MAXDIM],				prod[MAXDIM];	bool		eoArray = false;	mda_get_prod(ndim, dim, prod);	for (i = 0; i < ndim; indx[i++] = 0);	/* read array enclosed within {} */	values = (char **) palloc(nitems * sizeof(char *));	MemSet(values, 0, nitems * sizeof(char *));	q = p = arrayStr;	while (!eoArray)	{		bool		done = false;		int			i = -1;		while (!done)		{			switch (*q)			{				case '\\':					/* Crunch the string on top of the backslash. */					for (r = q; *r != '\0'; r++)						*r = *(r + 1);					break;				case '\"':					if (!scanning_string)					{						while (p != q)							p++;						p++;	/* get p past first doublequote */					}					else						*q = '\0';					scanning_string = !scanning_string;					break;				case '{':					if (!scanning_string)					{						p++;						nest_level++;						if (nest_level > ndim)							elog(ERROR, "array_in: illformed array constant");						indx[nest_level - 1] = 0;						indx[ndim - 1] = 0;					}					break;				case '}':					if (!scanning_string)					{						if (i == -1)							i = tuple2linear(ndim, indx, prod);						nest_level--;						if (nest_level == 0)							eoArray = done = true;						else						{							*q = '\0';							indx[nest_level - 1]++;						}					}					break;				default:					if (*q == typdelim && !scanning_string)					{						if (i == -1)							i = tuple2linear(ndim, indx, prod);						done = true;						indx[ndim - 1]++;					}					break;			}			if (!done)				q++;		}		*q = '\0';		if (i >= nitems)			elog(ERROR, "array_in: illformed array constant");		values[i] = (*fmgr_faddr(inputproc)) (p, typelem, typmod);		p = ++q;		if (!eoArray)			/*			 * if not at the end of the array skip white space			 */			while (isspace(*q))			{				p++;				q++;			}	}	if (typlen > 0)	{		*nbytes = nitems * typlen;		if (!typbyval)			for (i = 0; i < nitems; i++)				if (!values[i])				{					values[i] = palloc(typlen);					MemSet(values[i], 0, typlen);				}	}	else	{		for (i = 0, *nbytes = 0; i < nitems; i++)		{			if (values[i])			{				if (typalign == 'd')					*nbytes += MAXALIGN(*(int32 *) values[i]);				else					*nbytes += INTALIGN(*(int32 *) values[i]);			}			else			{				*nbytes += sizeof(int32);				values[i] = palloc(sizeof(int32));				*(int32 *) values[i] = sizeof(int32);			}		}	}	return (char *) values;}/*---------------------------------------------------------------------------- * Read data about an array to be stored as a large object *---------------------------------------------------------------------------- */#ifdef LOARRAYstatic char *_ReadLOArray(char *str,			 int *nbytes,			 int *fd,			 bool *chunkFlag,			 int ndim,			 int *dim,			 int baseSize){	char	   *inputfile,			   *accessfile = NULL,			   *chunkfile = NULL;	char	   *retStr,			   *_AdvanceBy1word();	Oid			lobjId;	str = _AdvanceBy1word(str, &inputfile);	while (str != NULL)	{		char	   *word;		str = _AdvanceBy1word(str, &word);		if (!strcmp(word, "-chunk"))		{			if (str == NULL)				elog(ERROR, "array_in: access pattern file required");			str = _AdvanceBy1word(str, &accessfile);		}		else if (!strcmp(word, "-noreorg"))		{			if (str == NULL)				elog(ERROR, "array_in: chunk file required");			str = _AdvanceBy1word(str, &chunkfile);		}		else			elog(ERROR, "usage: <input file> -chunk DEFAULT/<access pattern file> -invert/-native [-noreorg <chunk file>]");	}	if (inputfile == NULL)		elog(ERROR, "array_in: missing file name");	lobjId = lo_creat(0);	*fd = lo_open(lobjId, INV_READ);	if (*fd < 0)		elog(ERROR, "Large object create failed");	retStr = inputfile;	*nbytes = strlen(retStr) + 2;	if (accessfile)	{		FILE	   *afd;#ifndef __CYGWIN32__		if ((afd = AllocateFile(accessfile, "r")) == NULL)#else		if ((afd = AllocateFile(accessfile, "r")) == NULL)#endif			elog(ERROR, "unable to open access pattern file");		*chunkFlag = true;		retStr = _ChunkArray(*fd, afd, ndim, dim, baseSize, nbytes,							 chunkfile);		FreeFile(afd);	}	return retStr;}#endifstatic void_CopyArrayEls(char **values,			  char *p,			  int nitems,			  int typlen,			  char typalign,			  bool typbyval){	int			i;	for (i = 0; i < nitems; i++)	{		int			inc;		inc = ArrayCastAndSet(values[i], typbyval, typlen, p);		p += inc;		if (!typbyval)			pfree(values[i]);	}	pfree(values);}/*------------------------------------------------------------------------- * array_out : *		   takes the internal representation of an array and returns a string *		  containing the array in its external format. *------------------------------------------------------------------------- */char *array_out(ArrayType *v, Oid element_type){	int			typlen;	bool		typbyval;	char		typdelim;	Oid			typoutput,				typelem;	FmgrInfo	outputproc;	char		typalign;	char	   *p,			   *tmp,			   *retval,			  **values,				delim[2];	int			nitems,				overall_length,				i,				j,				k,#ifndef TCL_ARRAYS				l,#endif				indx[MAXDIM];	bool		dummy_bool;	int			ndim,			   *dim;	if (v == (ArrayType *) NULL)		return (char *) NULL;	if (ARR_IS_LO(v) == true)	{		char	   *p,				   *save_p;		int			nbytes;		/* get a wide string to print to */		p = array_dims(v, &dummy_bool);

⌨️ 快捷键说明

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