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

📄 spi.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (rel->rd_rel->relhasoids)			HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));	}	else	{		mtuple = NULL;		SPI_result = SPI_ERROR_NOATTRIBUTE;	}	pfree(v);	pfree(n);	if (oldcxt)		MemoryContextSwitchTo(oldcxt);	return mtuple;}intSPI_fnumber(TupleDesc tupdesc, const char *fname){	int			res;	Form_pg_attribute sysatt;	for (res = 0; res < tupdesc->natts; res++)	{		if (namestrcmp(&tupdesc->attrs[res]->attname, fname) == 0)			return res + 1;	}	sysatt = SystemAttributeByName(fname, true /* "oid" will be accepted */ );	if (sysatt != NULL)		return sysatt->attnum;	/* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */	return SPI_ERROR_NOATTRIBUTE;}char *SPI_fname(TupleDesc tupdesc, int fnumber){	Form_pg_attribute att;	SPI_result = 0;	if (fnumber > tupdesc->natts || fnumber == 0 ||		fnumber <= FirstLowInvalidHeapAttributeNumber)	{		SPI_result = SPI_ERROR_NOATTRIBUTE;		return NULL;	}	if (fnumber > 0)		att = tupdesc->attrs[fnumber - 1];	else		att = SystemAttributeDefinition(fnumber, true);	return pstrdup(NameStr(att->attname));}char *SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber){	Datum		origval,				val,				result;	bool		isnull;	Oid			typoid,				foutoid,				typelem;	int32		typmod;	bool		typisvarlena;	SPI_result = 0;	if (fnumber > tuple->t_data->t_natts || fnumber == 0 ||		fnumber <= FirstLowInvalidHeapAttributeNumber)	{		SPI_result = SPI_ERROR_NOATTRIBUTE;		return NULL;	}	origval = heap_getattr(tuple, fnumber, tupdesc, &isnull);	if (isnull)		return NULL;	if (fnumber > 0)	{		typoid = tupdesc->attrs[fnumber - 1]->atttypid;		typmod = tupdesc->attrs[fnumber - 1]->atttypmod;	}	else	{		typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;		typmod = -1;	}	getTypeOutputInfo(typoid, &foutoid, &typelem, &typisvarlena);	/*	 * If we have a toasted datum, forcibly detoast it here to avoid	 * memory leakage inside the type's output routine.	 */	if (typisvarlena)		val = PointerGetDatum(PG_DETOAST_DATUM(origval));	else		val = origval;	result = OidFunctionCall3(foutoid,							  val,							  ObjectIdGetDatum(typelem),							  Int32GetDatum(typmod));	/* Clean up detoasted copy, if any */	if (val != origval)		pfree(DatumGetPointer(val));	return DatumGetCString(result);}DatumSPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull){	SPI_result = 0;	if (fnumber > tuple->t_data->t_natts || fnumber == 0 ||		fnumber <= FirstLowInvalidHeapAttributeNumber)	{		SPI_result = SPI_ERROR_NOATTRIBUTE;		*isnull = true;		return (Datum) NULL;	}	return heap_getattr(tuple, fnumber, tupdesc, isnull);}char *SPI_gettype(TupleDesc tupdesc, int fnumber){	Oid			typoid;	HeapTuple	typeTuple;	char	   *result;	SPI_result = 0;	if (fnumber > tupdesc->natts || fnumber == 0 ||		fnumber <= FirstLowInvalidHeapAttributeNumber)	{		SPI_result = SPI_ERROR_NOATTRIBUTE;		return NULL;	}	if (fnumber > 0)		typoid = tupdesc->attrs[fnumber - 1]->atttypid;	else		typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;	typeTuple = SearchSysCache(TYPEOID,							   ObjectIdGetDatum(typoid),							   0, 0, 0);	if (!HeapTupleIsValid(typeTuple))	{		SPI_result = SPI_ERROR_TYPUNKNOWN;		return NULL;	}	result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));	ReleaseSysCache(typeTuple);	return result;}OidSPI_gettypeid(TupleDesc tupdesc, int fnumber){	SPI_result = 0;	if (fnumber > tupdesc->natts || fnumber == 0 ||		fnumber <= FirstLowInvalidHeapAttributeNumber)	{		SPI_result = SPI_ERROR_NOATTRIBUTE;		return InvalidOid;	}	if (fnumber > 0)		return tupdesc->attrs[fnumber - 1]->atttypid;	else		return (SystemAttributeDefinition(fnumber, true))->atttypid;}char *SPI_getrelname(Relation rel){	return pstrdup(RelationGetRelationName(rel));}void *SPI_palloc(Size size){	MemoryContext oldcxt = NULL;	void	   *pointer;	if (_SPI_curid + 1 == _SPI_connected)		/* connected */	{		if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))			elog(ERROR, "SPI stack corrupted");		oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);	}	pointer = palloc(size);	if (oldcxt)		MemoryContextSwitchTo(oldcxt);	return pointer;}void *SPI_repalloc(void *pointer, Size size){	/* No longer need to worry which context chunk was in... */	return repalloc(pointer, size);}voidSPI_pfree(void *pointer){	/* No longer need to worry which context chunk was in... */	pfree(pointer);}voidSPI_freetuple(HeapTuple tuple){	/* No longer need to worry which context tuple was in... */	heap_freetuple(tuple);}voidSPI_freetuptable(SPITupleTable *tuptable){	if (tuptable != NULL)		MemoryContextDelete(tuptable->tuptabcxt);}/* * SPI_cursor_open() * *	Open a prepared SPI plan as a portal */PortalSPI_cursor_open(const char *name, void *plan, Datum *Values, const char *Nulls){	_SPI_plan  *spiplan = (_SPI_plan *) plan;	List	   *qtlist = spiplan->qtlist;	List	   *ptlist = spiplan->ptlist;	Query	   *queryTree;	Plan	   *planTree;	ParamListInfo paramLI;	MemoryContext oldcontext;	Portal		portal;	int			k;	/* Ensure that the plan contains only one regular SELECT query */	if (length(ptlist) != 1 || length(qtlist) != 1)		ereport(ERROR,				(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),				 errmsg("cannot open multi-query plan as cursor")));	queryTree = (Query *) lfirst((List *) lfirst(qtlist));	planTree = (Plan *) lfirst(ptlist);	if (queryTree->commandType != CMD_SELECT)		ereport(ERROR,				(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),				 errmsg("cannot open non-SELECT query as cursor")));	if (queryTree->into != NULL)		ereport(ERROR,				(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),				 errmsg("cannot open SELECT INTO query as cursor")));	/* Increment CommandCounter to see changes made by now */	CommandCounterIncrement();	/* Reset SPI result */	SPI_processed = 0;	SPI_tuptable = NULL;	_SPI_current->processed = 0;	_SPI_current->tuptable = NULL;	/* Create the portal */	if (name == NULL || name[0] == '\0')	{		/* Use a random nonconflicting name */		portal = CreateNewPortal();	}	else	{		/* In this path, error if portal of same name already exists */		portal = CreatePortal(name, false, false);	}	/* Switch to portals memory and copy the parsetree and plan to there */	oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));	queryTree = copyObject(queryTree);	planTree = copyObject(planTree);	/* If the plan has parameters, set them up */	if (spiplan->nargs > 0)	{		paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) *										  sizeof(ParamListInfoData));		for (k = 0; k < spiplan->nargs; k++)		{			paramLI[k].kind = PARAM_NUM;			paramLI[k].id = k + 1;			paramLI[k].isnull = (Nulls && Nulls[k] == 'n');			if (paramLI[k].isnull)			{				/* nulls just copy */				paramLI[k].value = Values[k];			}			else			{				/* pass-by-ref values must be copied into portal context */				int16		paramTypLen;				bool		paramTypByVal;				get_typlenbyval(spiplan->argtypes[k],								&paramTypLen, &paramTypByVal);				paramLI[k].value = datumCopy(Values[k],											 paramTypByVal, paramTypLen);			}		}		paramLI[k].kind = PARAM_INVALID;	}	else		paramLI = NULL;	/*	 * Set up the portal.	 */	PortalDefineQuery(portal,					  NULL,		/* unfortunately don't have sourceText */					  "SELECT", /* cursor's query is always a SELECT */					  makeList1(queryTree),					  makeList1(planTree),					  PortalGetHeapMemory(portal));	MemoryContextSwitchTo(oldcontext);	/*	 * Set up options for portal.	 */	portal->cursorOptions &= ~(CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL);	if (ExecSupportsBackwardScan(plan))		portal->cursorOptions |= CURSOR_OPT_SCROLL;	else		portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;	/*	 * Start portal execution.	 */	PortalStart(portal, paramLI);	Assert(portal->strategy == PORTAL_ONE_SELECT);	/* Return the created portal */	return portal;}/* * SPI_cursor_find() * *	Find the portal of an existing open cursor */PortalSPI_cursor_find(const char *name){	return GetPortalByName(name);}/* * SPI_cursor_fetch() * *	Fetch rows in a cursor */voidSPI_cursor_fetch(Portal portal, bool forward, int count){	_SPI_cursor_operation(portal, forward, count,						  CreateDestReceiver(SPI, NULL));	/* we know that the SPI receiver doesn't need a destroy call */}/* * SPI_cursor_move() * *	Move in a cursor */voidSPI_cursor_move(Portal portal, bool forward, int count){	_SPI_cursor_operation(portal, forward, count, None_Receiver);}/* * SPI_cursor_close() * *	Close a cursor */voidSPI_cursor_close(Portal portal){	if (!PortalIsValid(portal))		elog(ERROR, "invalid portal in SPI cursor operation");	PortalDrop(portal, false);}/* =================== private functions =================== *//* * spi_dest_startup *		Initialize to receive tuples from Executor into SPITupleTable *		of current SPI procedure */voidspi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo){	SPITupleTable *tuptable;	MemoryContext oldcxt;	MemoryContext tuptabcxt;	/*	 * When called by Executor _SPI_curid expected to be equal to	 * _SPI_connected	 */	if (_SPI_curid != _SPI_connected || _SPI_connected < 0)		elog(ERROR, "improper call to spi_dest_startup");	if (_SPI_current != &(_SPI_stack[_SPI_curid]))		elog(ERROR, "SPI stack corrupted");	if (_SPI_current->tuptable != NULL)		elog(ERROR, "improper call to spi_dest_startup");	oldcxt = _SPI_procmem();	/* switch to procedure memory context */	tuptabcxt = AllocSetContextCreate(CurrentMemoryContext,									  "SPI TupTable",									  ALLOCSET_DEFAULT_MINSIZE,									  ALLOCSET_DEFAULT_INITSIZE,									  ALLOCSET_DEFAULT_MAXSIZE);	MemoryContextSwitchTo(tuptabcxt);	_SPI_current->tuptable = tuptable = (SPITupleTable *)		palloc(sizeof(SPITupleTable));	tuptable->tuptabcxt = tuptabcxt;	tuptable->alloced = tuptable->free = 128;	tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));	tuptable->tupdesc = CreateTupleDescCopy(typeinfo);	MemoryContextSwitchTo(oldcxt);}/* * spi_printtup *		store tuple retrieved by Executor into SPITupleTable *		of current SPI procedure */voidspi_printtup(HeapTuple tuple, TupleDesc tupdesc, DestReceiver *self){	SPITupleTable *tuptable;	MemoryContext oldcxt;	/*	 * When called by Executor _SPI_curid expected to be equal to	 * _SPI_connected	 */

⌨️ 快捷键说明

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