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

📄 rowtypes.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * rowtypes.c *	  I/O functions for generic composite types. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.13.2.1 2006/01/17 17:33:21 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include "access/heapam.h"#include "access/htup.h"#include "catalog/pg_type.h"#include "lib/stringinfo.h"#include "libpq/pqformat.h"#include "utils/builtins.h"#include "utils/lsyscache.h"#include "utils/typcache.h"/* * structure to cache metadata needed for record I/O */typedef struct ColumnIOData{	Oid			column_type;	Oid			typiofunc;	Oid			typioparam;	FmgrInfo	proc;} ColumnIOData;typedef struct RecordIOData{	Oid			record_type;	int32		record_typmod;	int			ncolumns;	ColumnIOData columns[1];	/* VARIABLE LENGTH ARRAY */} RecordIOData;/* * record_in		- input routine for any composite type. */Datumrecord_in(PG_FUNCTION_ARGS){	char	   *string = PG_GETARG_CSTRING(0);	Oid			tupType = PG_GETARG_OID(1);#ifdef NOT_USED	int32		typmod = PG_GETARG_INT32(2);#endif	HeapTupleHeader result;	int32		tupTypmod;	TupleDesc	tupdesc;	HeapTuple	tuple;	RecordIOData *my_extra;	bool		needComma = false;	int			ncolumns;	int			i;	char	   *ptr;	Datum	   *values;	char	   *nulls;	StringInfoData buf;	/*	 * Use the passed type unless it's RECORD; we can't support input of	 * anonymous types, mainly because there's no good way to figure out which	 * anonymous type is wanted.  Note that for RECORD, what we'll probably	 * actually get is RECORD's typelem, ie, zero.	 */	if (tupType == InvalidOid || tupType == RECORDOID)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),		   errmsg("input of anonymous composite types is not implemented")));	tupTypmod = -1;				/* for all non-anonymous types */	tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);	tupdesc = CreateTupleDescCopy(tupdesc);	ncolumns = tupdesc->natts;	/*	 * We arrange to look up the needed I/O info just once per series of	 * calls, assuming the record type doesn't change underneath us.	 */	my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;	if (my_extra == NULL ||		my_extra->ncolumns != ncolumns)	{		fcinfo->flinfo->fn_extra =			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,							   sizeof(RecordIOData) - sizeof(ColumnIOData)							   + ncolumns * sizeof(ColumnIOData));		my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;		my_extra->record_type = InvalidOid;		my_extra->record_typmod = 0;	}	if (my_extra->record_type != tupType ||		my_extra->record_typmod != tupTypmod)	{		MemSet(my_extra, 0,			   sizeof(RecordIOData) - sizeof(ColumnIOData)			   + ncolumns * sizeof(ColumnIOData));		my_extra->record_type = tupType;		my_extra->record_typmod = tupTypmod;		my_extra->ncolumns = ncolumns;	}	values = (Datum *) palloc(ncolumns * sizeof(Datum));	nulls = (char *) palloc(ncolumns * sizeof(char));	/*	 * Scan the string.  We use "buf" to accumulate the de-quoted data for	 * each column, which is then fed to the appropriate input converter.	 */	ptr = string;	/* Allow leading whitespace */	while (*ptr && isspace((unsigned char) *ptr))		ptr++;	if (*ptr++ != '(')		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),				 errmsg("malformed record literal: \"%s\"", string),				 errdetail("Missing left parenthesis.")));	initStringInfo(&buf);	for (i = 0; i < ncolumns; i++)	{		ColumnIOData *column_info = &my_extra->columns[i];		Oid			column_type = tupdesc->attrs[i]->atttypid;		/* Ignore dropped columns in datatype, but fill with nulls */		if (tupdesc->attrs[i]->attisdropped)		{			values[i] = (Datum) 0;			nulls[i] = 'n';			continue;		}		if (needComma)		{			/* Skip comma that separates prior field from this one */			if (*ptr == ',')				ptr++;			else				/* *ptr must be ')' */				ereport(ERROR,						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),						 errmsg("malformed record literal: \"%s\"", string),						 errdetail("Too few columns.")));		}		/* Check for null: completely empty input means null */		if (*ptr == ',' || *ptr == ')')		{			values[i] = (Datum) 0;			nulls[i] = 'n';		}		else		{			/* Extract string for this column */			bool		inquote = false;			buf.len = 0;			buf.data[0] = '\0';			while (inquote || !(*ptr == ',' || *ptr == ')'))			{				char		ch = *ptr++;				if (ch == '\0')					ereport(ERROR,							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),							 errmsg("malformed record literal: \"%s\"",									string),							 errdetail("Unexpected end of input.")));				if (ch == '\\')				{					if (*ptr == '\0')						ereport(ERROR,								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),								 errmsg("malformed record literal: \"%s\"",										string),								 errdetail("Unexpected end of input.")));					appendStringInfoChar(&buf, *ptr++);				}				else if (ch == '\"')				{					if (!inquote)						inquote = true;					else if (*ptr == '\"')					{						/* doubled quote within quote sequence */						appendStringInfoChar(&buf, *ptr++);					}					else						inquote = false;				}				else					appendStringInfoChar(&buf, ch);			}			/*			 * Convert the column value			 */			if (column_info->column_type != column_type)			{				getTypeInputInfo(column_type,								 &column_info->typiofunc,								 &column_info->typioparam);				fmgr_info_cxt(column_info->typiofunc, &column_info->proc,							  fcinfo->flinfo->fn_mcxt);				column_info->column_type = column_type;			}			values[i] = FunctionCall3(&column_info->proc,									  CStringGetDatum(buf.data),								   ObjectIdGetDatum(column_info->typioparam),								Int32GetDatum(tupdesc->attrs[i]->atttypmod));			nulls[i] = ' ';		}		/*		 * Prep for next column		 */		needComma = true;	}	if (*ptr++ != ')')		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),				 errmsg("malformed record literal: \"%s\"", string),				 errdetail("Too many columns.")));	/* Allow trailing whitespace */	while (*ptr && isspace((unsigned char) *ptr))		ptr++;	if (*ptr)		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),				 errmsg("malformed record literal: \"%s\"", string),				 errdetail("Junk after right parenthesis.")));	tuple = heap_formtuple(tupdesc, values, nulls);	/*	 * We cannot return tuple->t_data because heap_formtuple allocates it as	 * part of a larger chunk, and our caller may expect to be able to pfree	 * our result.	So must copy the info into a new palloc chunk.	 */	result = (HeapTupleHeader) palloc(tuple->t_len);	memcpy(result, tuple->t_data, tuple->t_len);	heap_freetuple(tuple);	pfree(buf.data);	pfree(values);	pfree(nulls);	FreeTupleDesc(tupdesc);	PG_RETURN_HEAPTUPLEHEADER(result);}/* * record_out		- output routine for any composite type. */Datumrecord_out(PG_FUNCTION_ARGS){	HeapTupleHeader rec = PG_GETARG_HEAPTUPLEHEADER(0);	Oid			tupType;	int32		tupTypmod;	TupleDesc	tupdesc;	HeapTupleData tuple;	RecordIOData *my_extra;	bool		needComma = false;	int			ncolumns;	int			i;	Datum	   *values;	char	   *nulls;	StringInfoData buf;	/* Extract type info from the tuple itself */	tupType = HeapTupleHeaderGetTypeId(rec);	tupTypmod = HeapTupleHeaderGetTypMod(rec);	tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);	tupdesc = CreateTupleDescCopy(tupdesc);	ncolumns = tupdesc->natts;	/* Build a temporary HeapTuple control structure */	tuple.t_len = HeapTupleHeaderGetDatumLength(rec);	ItemPointerSetInvalid(&(tuple.t_self));	tuple.t_tableOid = InvalidOid;	tuple.t_data = rec;	/*	 * We arrange to look up the needed I/O info just once per series of	 * calls, assuming the record type doesn't change underneath us.	 */	my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;	if (my_extra == NULL ||		my_extra->ncolumns != ncolumns)	{		fcinfo->flinfo->fn_extra =			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,							   sizeof(RecordIOData) - sizeof(ColumnIOData)							   + ncolumns * sizeof(ColumnIOData));		my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;		my_extra->record_type = InvalidOid;		my_extra->record_typmod = 0;	}	if (my_extra->record_type != tupType ||		my_extra->record_typmod != tupTypmod)	{		MemSet(my_extra, 0,			   sizeof(RecordIOData) - sizeof(ColumnIOData)			   + ncolumns * sizeof(ColumnIOData));		my_extra->record_type = tupType;		my_extra->record_typmod = tupTypmod;		my_extra->ncolumns = ncolumns;	}	values = (Datum *) palloc(ncolumns * sizeof(Datum));	nulls = (char *) palloc(ncolumns * sizeof(char));	/* Break down the tuple into fields */	heap_deformtuple(&tuple, tupdesc, values, nulls);	/* And build the result string */	initStringInfo(&buf);	appendStringInfoChar(&buf, '(');	for (i = 0; i < ncolumns; i++)	{		ColumnIOData *column_info = &my_extra->columns[i];		Oid			column_type = tupdesc->attrs[i]->atttypid;		char	   *value;		char	   *tmp;		bool		nq;		/* Ignore dropped columns in datatype */		if (tupdesc->attrs[i]->attisdropped)			continue;		if (needComma)			appendStringInfoChar(&buf, ',');		needComma = true;		if (nulls[i] == 'n')		{			/* emit nothing... */			continue;		}		/*		 * Convert the column value to text		 */		if (column_info->column_type != column_type)		{			bool		typIsVarlena;

⌨️ 快捷键说明

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