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

📄 pg_operator.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * pg_operator.c *	  routines to support manipulation of the pg_operator relation * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.37.2.1 1999/08/02 05:56:55 scrappy Exp $ * * NOTES *	  these routines moved here from commands/define.c and somewhat cleaned up. * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/catname.h"#include "catalog/pg_operator.h"#include "catalog/pg_proc.h"#include "catalog/pg_type.h"#include "miscadmin.h"#include "parser/parse_func.h"#include "utils/builtins.h"#include "utils/syscache.h"static Oid OperatorGetWithOpenRelation(Relation pg_operator_desc,							const char *operatorName,							Oid leftObjectId,							Oid rightObjectId,							bool *defined);static Oid OperatorGet(char *operatorName,			char *leftTypeName,			char *rightTypeName,			bool *defined);static Oid OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,								  char *operatorName,								  Oid leftObjectId,								  Oid rightObjectId);static Oid OperatorShellMake(char *operatorName,				  char *leftTypeName,				  char *rightTypeName);static void OperatorDef(char *operatorName,			char *leftTypeName,			char *rightTypeName,			char *procedureName,			uint16 precedence,			bool isLeftAssociative,			char *commutatorName,			char *negatorName,			char *restrictionName,			char *oinName,			bool canHash,			char *leftSortName,			char *rightSortName);static void OperatorUpd(Oid baseId, Oid commId, Oid negId);/* ---------------------------------------------------------------- *		OperatorGetWithOpenRelation * *		preforms a scan on pg_operator for an operator tuple *		with given name and left/right type oids. * ---------------------------------------------------------------- *	  pg_operator_desc	-- reldesc for pg_operator *	  operatorName		-- name of operator to fetch *	  leftObjectId		-- left data type oid of operator to fetch *	  rightObjectId		-- right data type oid of operator to fetch *	  defined			-- set TRUE if defined (not a shell) */static OidOperatorGetWithOpenRelation(Relation pg_operator_desc,							const char *operatorName,							Oid leftObjectId,							Oid rightObjectId,							bool *defined){	HeapScanDesc pg_operator_scan;	Oid			operatorObjectId;	HeapTuple	tup;	static ScanKeyData opKey[3] = {		{0, Anum_pg_operator_oprname, F_NAMEEQ},		{0, Anum_pg_operator_oprleft, F_OIDEQ},		{0, Anum_pg_operator_oprright, F_OIDEQ},	};	fmgr_info(F_NAMEEQ, &opKey[0].sk_func);	fmgr_info(F_OIDEQ, &opKey[1].sk_func);	fmgr_info(F_OIDEQ, &opKey[2].sk_func);	opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;	opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;	opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;	/* ----------------	 *	form scan key	 * ----------------	 */	opKey[0].sk_argument = PointerGetDatum(operatorName);	opKey[1].sk_argument = ObjectIdGetDatum(leftObjectId);	opKey[2].sk_argument = ObjectIdGetDatum(rightObjectId);	/* ----------------	 *	begin the scan	 * ----------------	 */	pg_operator_scan = heap_beginscan(pg_operator_desc,									  0,									  SnapshotSelf,		/* no cache? */									  3,									  opKey);	/* ----------------	 *	fetch the operator tuple, if it exists, and determine	 *	the proper return oid value.	 * ----------------	 */	tup = heap_getnext(pg_operator_scan, 0);	if (HeapTupleIsValid(tup))	{		regproc		oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;		operatorObjectId = tup->t_data->t_oid;		*defined = RegProcedureIsValid(oprcode);	}	else	{		operatorObjectId = InvalidOid;		*defined = false;	}	/* ----------------	 *	close the scan and return the oid.	 * ----------------	 */	heap_endscan(pg_operator_scan);	return operatorObjectId;}/* ---------------------------------------------------------------- *		OperatorGet * *		finds the operator associated with the specified name *		and left and right type names. * ---------------------------------------------------------------- */static OidOperatorGet(char *operatorName,			char *leftTypeName,			char *rightTypeName,			bool *defined){	Relation	pg_operator_desc;	Oid			operatorObjectId;	Oid			leftObjectId = InvalidOid;	Oid			rightObjectId = InvalidOid;	bool		leftDefined = false;	bool		rightDefined = false;	/* ----------------	 *	look up the operator data types.	 *	 *	Note: types must be defined before operators	 * ----------------	 */	if (leftTypeName)	{		leftObjectId = TypeGet(leftTypeName, &leftDefined);		if (!OidIsValid(leftObjectId) || !leftDefined)			elog(ERROR, "OperatorGet: left type '%s' nonexistent",				 leftTypeName);	}	if (rightTypeName)	{		rightObjectId = TypeGet(rightTypeName, &rightDefined);		if (!OidIsValid(rightObjectId) || !rightDefined)			elog(ERROR, "OperatorGet: right type '%s' nonexistent",				 rightTypeName);	}	if (!((OidIsValid(leftObjectId) && leftDefined) ||		  (OidIsValid(rightObjectId) && rightDefined)))		elog(ERROR, "OperatorGet: must have at least one argument type");	/* ----------------	 *	open the pg_operator relation	 * ----------------	 */	pg_operator_desc = heap_openr(OperatorRelationName);	/* ----------------	 *	get the oid for the operator with the appropriate name	 *	and left/right types.	 * ----------------	 */	operatorObjectId = OperatorGetWithOpenRelation(pg_operator_desc,												   operatorName,												   leftObjectId,												   rightObjectId,												   defined);	/* ----------------	 *	close the relation and return the operator oid.	 * ----------------	 */	heap_close(pg_operator_desc);	return operatorObjectId;}/* ---------------------------------------------------------------- *		OperatorShellMakeWithOpenRelation * * ---------------------------------------------------------------- */static OidOperatorShellMakeWithOpenRelation(Relation pg_operator_desc,								  char *operatorName,								  Oid leftObjectId,								  Oid rightObjectId){	int			i;	HeapTuple	tup;	Datum		values[Natts_pg_operator];	char		nulls[Natts_pg_operator];	Oid			operatorObjectId;	NameData	oname;	TupleDesc	tupDesc;	/* ----------------	 *	initialize our *nulls and *values arrays	 * ----------------	 */	for (i = 0; i < Natts_pg_operator; ++i)	{		nulls[i] = ' ';		values[i] = (Datum) NULL;		/* redundant, but safe */	}	/* ----------------	 *	initialize *values with the operator name and input data types.	 *	Note that oprcode is set to InvalidOid, indicating it's a shell.	 * ----------------	 */	i = 0;	namestrcpy(&oname, operatorName);	values[i++] = NameGetDatum(&oname);	values[i++] = Int32GetDatum(GetUserId());	values[i++] = (Datum) (uint16) 0;	values[i++] = (Datum) 'b';	/* assume it's binary */	values[i++] = (Datum) (bool) 0;	values[i++] = (Datum) (bool) 0;	values[i++] = ObjectIdGetDatum(leftObjectId);		/* <-- left oid */	values[i++] = ObjectIdGetDatum(rightObjectId);		/* <-- right oid */	values[i++] = ObjectIdGetDatum(InvalidOid);	values[i++] = ObjectIdGetDatum(InvalidOid);	values[i++] = ObjectIdGetDatum(InvalidOid);	values[i++] = ObjectIdGetDatum(InvalidOid);	values[i++] = ObjectIdGetDatum(InvalidOid);	values[i++] = ObjectIdGetDatum(InvalidOid);	values[i++] = ObjectIdGetDatum(InvalidOid);	values[i++] = ObjectIdGetDatum(InvalidOid);	/* ----------------	 *	create a new operator tuple	 * ----------------	 */	tupDesc = pg_operator_desc->rd_att;	tup = heap_formtuple(tupDesc,						 values,						 nulls);	/* ----------------	 *	insert our "shell" operator tuple and	 *	close the relation	 * ----------------	 */	heap_insert(pg_operator_desc, tup);	operatorObjectId = tup->t_data->t_oid;	/* ----------------	 *	free the tuple and return the operator oid	 * ----------------	 */	pfree(tup);	return operatorObjectId;}/* ---------------------------------------------------------------- *		OperatorShellMake * *		Specify operator name and left and right type names, *		fill an operator struct with this info and NULL's, *		call heap_insert and return the Oid *		to the caller. * ---------------------------------------------------------------- */static OidOperatorShellMake(char *operatorName,				  char *leftTypeName,				  char *rightTypeName){	Relation	pg_operator_desc;	Oid			operatorObjectId;	Oid			leftObjectId = InvalidOid;	Oid			rightObjectId = InvalidOid;	bool		leftDefined = false;	bool		rightDefined = false;	/* ----------------	 *	get the left and right type oid's for this operator	 * ----------------	 */	if (leftTypeName)		leftObjectId = TypeGet(leftTypeName, &leftDefined);	if (rightTypeName)		rightObjectId = TypeGet(rightTypeName, &rightDefined);	if (!((OidIsValid(leftObjectId) && leftDefined) ||		  (OidIsValid(rightObjectId) && rightDefined)))		elog(ERROR, "OperatorShellMake: no valid argument types??");	/* ----------------	 *	open pg_operator	 * ----------------	 */	pg_operator_desc = heap_openr(OperatorRelationName);	/* ----------------	 *	add a "shell" operator tuple to the operator relation	 *	and recover the shell tuple's oid.	 * ----------------	 */	operatorObjectId = OperatorShellMakeWithOpenRelation(pg_operator_desc,														 operatorName,														 leftObjectId,														 rightObjectId);	/* ----------------	 *	close the operator relation and return the oid.	 * ----------------	 */	heap_close(pg_operator_desc);	return operatorObjectId;}/* -------------------------------- * OperatorDef * * This routine gets complicated because it allows the user to * specify operators that do not exist.  For example, if operator * "op" is being defined, the negator operator "negop" and the * commutator "commop" can also be defined without specifying * any information other than their names.	Since in order to * add "op" to the PG_OPERATOR catalog, all the Oid's for these * operators must be placed in the fields of "op", a forward * declaration is done on the commutator and negator operators. * This is called creating a shell, and its main effect is to * create a tuple in the PG_OPERATOR catalog with minimal * information about the operator (just its name and types). * Forward declaration is used only for this purpose, it is * not available to the user as it is for type definition. * * Algorithm: * * check if operator already defined *	  if so, but oprcode is null, save the Oid -- we are filling in a shell *	  otherwise error * get the attribute types from relation descriptor for pg_operator * assign values to the fields of the operator: *	 operatorName *	 owner id (simply the user id of the caller) *	 precedence *	 operator "kind" either "b" for binary or "l" for left unary *	 isLeftAssociative boolean *	 canHash boolean *	 leftTypeObjectId -- type must already be defined *	 rightTypeObjectId -- this is optional, enter ObjectId=0 if none specified *	 resultType -- defer this, since it must be determined from *				   the pg_procedure catalog *	 commutatorObjectId -- if this is NULL, enter ObjectId=0 *					  else if this already exists, enter it's ObjectId *					  else if this does not yet exist, and is not *						the same as the main operatorName, then create *						a shell and enter the new ObjectId *					  else if this does not exist but IS the same *						name & types as the main operator, set the ObjectId=0. *						(We are creating a self-commutating operator.) *						The link will be fixed later by OperatorUpd. *	 negatorObjectId   -- same as for commutatorObjectId *	 leftSortObjectId  -- same as for commutatorObjectId *	 rightSortObjectId -- same as for commutatorObjectId *	 operatorProcedure -- must access the pg_procedure catalog to get the *				   ObjectId of the procedure that actually does the operator *				   actions this is required.  Do an amgetattr to find out the *				   return type of the procedure *	 restrictionProcedure -- must access the pg_procedure catalog to get *				   the ObjectId but this is optional *	 joinProcedure -- same as restrictionProcedure * now either insert or replace the operator into the pg_operator catalog * if the operator shell is being filled in *	 access the catalog in order to get a valid buffer *	 create a tuple using ModifyHeapTuple *	 get the t_self from the modified tuple and call RelationReplaceHeapTuple * else if a new operator is being created *	 create a tuple using heap_formtuple *	 call heap_insert * -------------------------------- *		"X" indicates an optional argument (i.e. one that can be NULL) *		operatorName;			-- operator name *		leftTypeName;			-- X left type name *		rightTypeName;			-- X right type name *		procedureName;			-- procedure name for operator code *		precedence;				-- operator precedence *		isLeftAssociative;		-- operator is left associative? *		commutatorName;			-- X commutator operator name *		negatorName;			-- X negator operator name *		restrictionName;		-- X restriction sel. procedure name *		joinName;				-- X join sel. procedure name *		canHash;				-- can hash join be used with operator? *		leftSortName;			-- X left sort operator (for merge join) *		rightSortName;			-- X right sort operator (for merge join) */static voidOperatorDef(char *operatorName,			char *leftTypeName,			char *rightTypeName,			char *procedureName,			uint16 precedence,			bool isLeftAssociative,			char *commutatorName,			char *negatorName,			char *restrictionName,			char *joinName,			bool canHash,			char *leftSortName,			char *rightSortName){	int			i,				j;	Relation	pg_operator_desc;	HeapScanDesc pg_operator_scan;	HeapTuple	tup;	char		nulls[Natts_pg_operator];	char		replaces[Natts_pg_operator];	Datum		values[Natts_pg_operator];	Oid			operatorObjectId;	bool		operatorAlreadyDefined;	Oid			leftTypeId = InvalidOid;	Oid			rightTypeId = InvalidOid;	Oid			commutatorId = InvalidOid;	Oid			negatorId = InvalidOid;	bool		leftDefined = false;	bool		rightDefined = false;	bool		selfCommutator = false;	char	   *name[4];	Oid			typeId[8];	int			nargs;	NameData	oname;	TupleDesc	tupDesc;	static ScanKeyData opKey[3] = {		{0, Anum_pg_operator_oprname, F_NAMEEQ},		{0, Anum_pg_operator_oprleft, F_OIDEQ},		{0, Anum_pg_operator_oprright, F_OIDEQ},	};	fmgr_info(F_NAMEEQ, &opKey[0].sk_func);	fmgr_info(F_OIDEQ, &opKey[1].sk_func);	fmgr_info(F_OIDEQ, &opKey[2].sk_func);	opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;	opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;	opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;	operatorObjectId = OperatorGet(operatorName,								   leftTypeName,								   rightTypeName,								   &operatorAlreadyDefined);	if (operatorAlreadyDefined)		elog(ERROR, "OperatorDef: operator \"%s\" already defined",			 operatorName);	/*	 * At this point, if operatorObjectId is not InvalidOid then we are	 * filling in a previously-created shell.	 */	/* ----------------	 *	look up the operator data types.	 *	 *	Note: types must be defined before operators	 * ----------------	 */	if (leftTypeName)	{		leftTypeId = TypeGet(leftTypeName, &leftDefined);		if (!OidIsValid(leftTypeId) || !leftDefined)			elog(ERROR, "OperatorDef: left type '%s' nonexistent",				 leftTypeName);	}	if (rightTypeName)

⌨️ 快捷键说明

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