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

📄 pg_aggregate.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * pg_aggregate.c *	  routines to support manipulation of the pg_aggregate relation * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.20.2.1 1999/08/02 05:56:55 scrappy Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/catname.h"#include "catalog/pg_aggregate.h"#include "catalog/pg_proc.h"#include "catalog/pg_type.h"#include "miscadmin.h"#include "utils/builtins.h"#include "utils/syscache.h"/* ---------------- * AggregateCreate * * aggregates overloading has been added.  Instead of the full * overload support we have for functions, aggregate overloading only * applies to exact basetype matches.  That is, we don't check the * the inheritance hierarchy * * OLD COMMENTS: *		Currently, redefining aggregates using the same name is not *		supported.	In such a case, a warning is printed that the *		aggregate already exists.  If such is not the case, a new tuple *		is created and inserted in the aggregate relation.	The fields *		of this tuple are aggregate name, owner id, 2 transition functions *		(called aggtransfn1 and aggtransfn2), final function (aggfinalfn), *		type of data on which aggtransfn1 operates (aggbasetype), return *		types of the two transition functions (aggtranstype1 and *		aggtranstype2), final return type (aggfinaltype), and initial values *		for the two state transition functions (agginitval1 and agginitval2). *		All types and functions must have been defined *		prior to defining the aggregate. * * --------------- */voidAggregateCreate(char *aggName,				char *aggtransfn1Name,				char *aggtransfn2Name,				char *aggfinalfnName,				char *aggbasetypeName,				char *aggtransfn1typeName,				char *aggtransfn2typeName,				char *agginitval1,				char *agginitval2){	int			i;	Relation	aggdesc;	HeapTuple	tup;	char		nulls[Natts_pg_aggregate];	Datum		values[Natts_pg_aggregate];	Form_pg_proc proc;	Oid			xfn1 = InvalidOid;	Oid			xfn2 = InvalidOid;	Oid			ffn = InvalidOid;	Oid			xbase = InvalidOid;	Oid			xret1 = InvalidOid;	Oid			xret2 = InvalidOid;	Oid			fret = InvalidOid;	Oid			fnArgs[8];	NameData	aname;	TupleDesc	tupDesc;	MemSet(fnArgs, 0, 8 * sizeof(Oid));	/* sanity checks */	if (!aggName)		elog(ERROR, "AggregateCreate: no aggregate name supplied");	if (!aggtransfn1Name && !aggtransfn2Name)		elog(ERROR, "AggregateCreate: aggregate must have at least one transition function");	tup = SearchSysCacheTuple(TYPNAME,							  PointerGetDatum(aggbasetypeName),							  0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "AggregateCreate: Type '%s' undefined", aggbasetypeName);	xbase = tup->t_data->t_oid;	if (aggtransfn1Name)	{		tup = SearchSysCacheTuple(TYPNAME,								  PointerGetDatum(aggtransfn1typeName),								  0, 0, 0);		if (!HeapTupleIsValid(tup))			elog(ERROR, "AggregateCreate: Type '%s' undefined",				 aggtransfn1typeName);		xret1 = tup->t_data->t_oid;		fnArgs[0] = xret1;		fnArgs[1] = xbase;		tup = SearchSysCacheTuple(PRONAME,								  PointerGetDatum(aggtransfn1Name),								  Int32GetDatum(2),								  PointerGetDatum(fnArgs),								  0);		if (!HeapTupleIsValid(tup))			elog(ERROR, "AggregateCreate: '%s('%s', '%s') does not exist",				 aggtransfn1Name, aggtransfn1typeName, aggbasetypeName);		if (((Form_pg_proc) GETSTRUCT(tup))->prorettype != xret1)			elog(ERROR, "AggregateCreate: return type of '%s' is not '%s'",				 aggtransfn1Name,				 aggtransfn1typeName);		xfn1 = tup->t_data->t_oid;		if (!OidIsValid(xfn1) || !OidIsValid(xret1) ||			!OidIsValid(xbase))			elog(ERROR, "AggregateCreate: bogus function '%s'", aggfinalfnName);	}	if (aggtransfn2Name)	{		tup = SearchSysCacheTuple(TYPNAME,								  PointerGetDatum(aggtransfn2typeName),								  0, 0, 0);		if (!HeapTupleIsValid(tup))			elog(ERROR, "AggregateCreate: Type '%s' undefined",				 aggtransfn2typeName);		xret2 = tup->t_data->t_oid;		fnArgs[0] = xret2;		fnArgs[1] = 0;		tup = SearchSysCacheTuple(PRONAME,								  PointerGetDatum(aggtransfn2Name),								  Int32GetDatum(1),								  PointerGetDatum(fnArgs),								  0);		if (!HeapTupleIsValid(tup))			elog(ERROR, "AggregateCreate: '%s'('%s') does not exist",				 aggtransfn2Name, aggtransfn2typeName);		if (((Form_pg_proc) GETSTRUCT(tup))->prorettype != xret2)			elog(ERROR, "AggregateCreate: return type of '%s' is not '%s'",				 aggtransfn2Name, aggtransfn2typeName);		xfn2 = tup->t_data->t_oid;		if (!OidIsValid(xfn2) || !OidIsValid(xret2))			elog(ERROR, "AggregateCreate: bogus function '%s'", aggfinalfnName);	}	tup = SearchSysCacheTuple(AGGNAME,							  PointerGetDatum(aggName),							  ObjectIdGetDatum(xbase),							  0, 0);	if (HeapTupleIsValid(tup))		elog(ERROR,			 "AggregateCreate: aggregate '%s' with base type '%s' already exists",			 aggName, aggbasetypeName);	/* more sanity checks */	if (aggtransfn1Name && aggtransfn2Name && !aggfinalfnName)		elog(ERROR, "AggregateCreate: Aggregate must have final function with both transition functions");	if ((!aggtransfn1Name || !aggtransfn2Name) && aggfinalfnName)		elog(ERROR, "AggregateCreate: Aggregate cannot have final function without both transition functions");	if (aggfinalfnName)	{		fnArgs[0] = xret1;		fnArgs[1] = xret2;		tup = SearchSysCacheTuple(PRONAME,								  PointerGetDatum(aggfinalfnName),								  Int32GetDatum(2),								  PointerGetDatum(fnArgs),								  0);		if (!HeapTupleIsValid(tup))			elog(ERROR, "AggregateCreate: '%s'('%s','%s') does not exist",			   aggfinalfnName, aggtransfn1typeName, aggtransfn2typeName);		ffn = tup->t_data->t_oid;		proc = (Form_pg_proc) GETSTRUCT(tup);		fret = proc->prorettype;		if (!OidIsValid(ffn) || !OidIsValid(fret))			elog(ERROR, "AggregateCreate: bogus function '%s'", aggfinalfnName);	}	/*	 * If transition function 2 is defined, it must have an initial value,	 * whereas transition function 1 does not, which allows man and min	 * aggregates to return NULL if they are evaluated on empty sets.	 */	if (OidIsValid(xfn2) && !agginitval2)		elog(ERROR, "AggregateCreate: transition function 2 MUST have an initial value");	/* initialize nulls and values */	for (i = 0; i < Natts_pg_aggregate; i++)	{		nulls[i] = ' ';		values[i] = (Datum) NULL;	}	namestrcpy(&aname, aggName);	values[Anum_pg_aggregate_aggname - 1] = NameGetDatum(&aname);	values[Anum_pg_aggregate_aggowner - 1] = Int32GetDatum(GetUserId());	values[Anum_pg_aggregate_aggtransfn1 - 1] = ObjectIdGetDatum(xfn1);	values[Anum_pg_aggregate_aggtransfn2 - 1] = ObjectIdGetDatum(xfn2);	values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(ffn);	values[Anum_pg_aggregate_aggbasetype - 1] = ObjectIdGetDatum(xbase);	if (!OidIsValid(xfn1))	{		values[Anum_pg_aggregate_aggtranstype1 - 1] = ObjectIdGetDatum(InvalidOid);		values[Anum_pg_aggregate_aggtranstype2 - 1] = ObjectIdGetDatum(xret2);		values[Anum_pg_aggregate_aggfinaltype - 1] = ObjectIdGetDatum(xret2);	}	else if (!OidIsValid(xfn2))	{		values[Anum_pg_aggregate_aggtranstype1 - 1] = ObjectIdGetDatum(xret1);		values[Anum_pg_aggregate_aggtranstype2 - 1] = ObjectIdGetDatum(InvalidOid);		values[Anum_pg_aggregate_aggfinaltype - 1] = ObjectIdGetDatum(xret1);	}	else	{		values[Anum_pg_aggregate_aggtranstype1 - 1] = ObjectIdGetDatum(xret1);		values[Anum_pg_aggregate_aggtranstype2 - 1] = ObjectIdGetDatum(xret2);		values[Anum_pg_aggregate_aggfinaltype - 1] = ObjectIdGetDatum(fret);	}	if (agginitval1)		values[Anum_pg_aggregate_agginitval1 - 1] = PointerGetDatum(textin(agginitval1));	else		nulls[Anum_pg_aggregate_agginitval1 - 1] = 'n';	if (agginitval2)		values[Anum_pg_aggregate_agginitval2 - 1] = PointerGetDatum(textin(agginitval2));	else		nulls[Anum_pg_aggregate_agginitval2 - 1] = 'n';	if (!RelationIsValid(aggdesc = heap_openr(AggregateRelationName)))		elog(ERROR, "AggregateCreate: could not open '%s'",			 AggregateRelationName);	tupDesc = aggdesc->rd_att;	if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,											   values,											   nulls)))		elog(ERROR, "AggregateCreate: heap_formtuple failed");	if (!OidIsValid(heap_insert(aggdesc, tup)))		elog(ERROR, "AggregateCreate: heap_insert failed");	heap_close(aggdesc);}char *AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull){	HeapTuple	tup;	Relation	aggRel;	int			initValAttno;	Oid			transtype;	text	   *textInitVal;	char	   *strInitVal,			   *initVal;	Assert(PointerIsValid(aggName));	Assert(PointerIsValid(isNull));	Assert(xfuncno == 1 || xfuncno == 2);	tup = SearchSysCacheTuple(AGGNAME,							  PointerGetDatum(aggName),							  ObjectIdGetDatum(basetype),							  0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "AggNameGetInitVal: cache lookup failed for aggregate '%s'",			 aggName);	if (xfuncno == 1)	{		transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype1;		initValAttno = Anum_pg_aggregate_agginitval1;	}	else		/* can only be 1 or 2 */	{		transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2;		initValAttno = Anum_pg_aggregate_agginitval2;	}	aggRel = heap_openr(AggregateRelationName);	if (!RelationIsValid(aggRel))		elog(ERROR, "AggNameGetInitVal: could not open \"%-.*s\"",			 AggregateRelationName);	/*	 * must use fastgetattr in case one or other of the init values is	 * NULL	 */	textInitVal = (text *) fastgetattr(tup, initValAttno,									   RelationGetDescr(aggRel),									   isNull);	if (!PointerIsValid(textInitVal))		*isNull = true;	if (*isNull)	{		heap_close(aggRel);		return (char *) NULL;	}	strInitVal = textout(textInitVal);	heap_close(aggRel);	tup = SearchSysCacheTuple(TYPOID,							  ObjectIdGetDatum(transtype),							  0, 0, 0);	if (!HeapTupleIsValid(tup))	{		pfree(strInitVal);		elog(ERROR, "AggNameGetInitVal: cache lookup failed on aggregate transition function return type");	}	initVal = fmgr(((Form_pg_type) GETSTRUCT(tup))->typinput, strInitVal, -1);	pfree(strInitVal);	return initVal;}

⌨️ 快捷键说明

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