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

📄 pg_operator.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
	{		rightTypeId = TypeGet(rightTypeName, &rightDefined);		if (!OidIsValid(rightTypeId) || !rightDefined)			elog(ERROR, "OperatorDef: right type '%s' nonexistent",				 rightTypeName);	}	if (!((OidIsValid(leftTypeId) && leftDefined) ||		  (OidIsValid(rightTypeId) && rightDefined)))		elog(ERROR, "OperatorDef: must have at least one argument type");	for (i = 0; i < Natts_pg_operator; ++i)	{		values[i] = (Datum) NULL;		replaces[i] = 'r';		nulls[i] = ' ';	}	/* ----------------	 * Look up registered procedures -- find the return type	 * of procedureName to place in "result" field.	 * Do this before shells are created so we don't	 * have to worry about deleting them later.	 * ----------------	 */	MemSet(typeId, 0, 8 * sizeof(Oid));	if (!leftTypeName)	{		typeId[0] = rightTypeId;		nargs = 1;	}	else if (!rightTypeName)	{		typeId[0] = leftTypeId;		nargs = 1;	}	else	{		typeId[0] = leftTypeId;		typeId[1] = rightTypeId;		nargs = 2;	}	tup = SearchSysCacheTuple(PRONAME,							  PointerGetDatum(procedureName),							  Int32GetDatum(nargs),							  PointerGetDatum(typeId),							  0);	if (!HeapTupleIsValid(tup))		func_error("OperatorDef", procedureName, nargs, typeId, NULL);	values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(tup->t_data->t_oid);	values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(((Form_pg_proc)											GETSTRUCT(tup))->prorettype);	/* ----------------	 *	find restriction	 * ----------------	 */	if (restrictionName)	{							/* optional */		MemSet(typeId, 0, 8 * sizeof(Oid));		typeId[0] = OIDOID;		/* operator OID */		typeId[1] = OIDOID;		/* relation OID */		typeId[2] = INT2OID;	/* attribute number */		typeId[3] = 0;			/* value - can be any type	*/		typeId[4] = INT4OID;	/* flags - left or right selectivity */		tup = SearchSysCacheTuple(PRONAME,								  PointerGetDatum(restrictionName),								  Int32GetDatum(5),								  PointerGetDatum(typeId),								  0);		if (!HeapTupleIsValid(tup))			func_error("OperatorDef", restrictionName, 5, typeId, NULL);		values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(tup->t_data->t_oid);	}	else		values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);	/* ----------------	 *	find join - only valid for binary operators	 * ----------------	 */	if (joinName)	{							/* optional */		MemSet(typeId, 0, 8 * sizeof(Oid));		typeId[0] = OIDOID;		/* operator OID */		typeId[1] = OIDOID;		/* relation OID 1 */		typeId[2] = INT2OID;	/* attribute number 1 */		typeId[3] = OIDOID;		/* relation OID 2 */		typeId[4] = INT2OID;	/* attribute number 2 */		tup = SearchSysCacheTuple(PRONAME,								  PointerGetDatum(joinName),								  Int32GetDatum(5),								  PointerGetDatum(typeId),								  0);		if (!HeapTupleIsValid(tup))			func_error("OperatorDef", joinName, 5, typeId, NULL);		values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(tup->t_data->t_oid);	}	else		values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);	/* ----------------	 * set up values in the operator tuple	 * ----------------	 */	i = 0;	namestrcpy(&oname, operatorName);	values[i++] = NameGetDatum(&oname);	values[i++] = Int32GetDatum(GetUserId());	values[i++] = UInt16GetDatum(precedence);	values[i++] = leftTypeName ? (rightTypeName ? 'b' : 'r') : 'l';	values[i++] = Int8GetDatum(isLeftAssociative);	values[i++] = Int8GetDatum(canHash);	values[i++] = ObjectIdGetDatum(leftTypeId);	values[i++] = ObjectIdGetDatum(rightTypeId);	++i;						/* Skip "oprresult", it was filled in								 * above */	/*	 * Set up the other operators.	If they do not currently exist, create	 * shells in order to get ObjectId's.	 */	name[0] = commutatorName;	name[1] = negatorName;	name[2] = leftSortName;	name[3] = rightSortName;	for (j = 0; j < 4; ++j)	{		if (name[j])		{			char	   *otherLeftTypeName = NULL;			char	   *otherRightTypeName = NULL;			Oid			otherLeftTypeId = InvalidOid;			Oid			otherRightTypeId = InvalidOid;			Oid			other_oid = InvalidOid;			bool		otherDefined = false;			switch (j)			{				case 0: /* commutator has reversed arg types */					otherLeftTypeName = rightTypeName;					otherRightTypeName = leftTypeName;					otherLeftTypeId = rightTypeId;					otherRightTypeId = leftTypeId;					other_oid = OperatorGet(name[j],											otherLeftTypeName,											otherRightTypeName,											&otherDefined);					commutatorId = other_oid;					break;				case 1: /* negator has same arg types */					otherLeftTypeName = leftTypeName;					otherRightTypeName = rightTypeName;					otherLeftTypeId = leftTypeId;					otherRightTypeId = rightTypeId;					other_oid = OperatorGet(name[j],											otherLeftTypeName,											otherRightTypeName,											&otherDefined);					negatorId = other_oid;					break;				case 2: /* left sort op takes left-side data type */					otherLeftTypeName = leftTypeName;					otherRightTypeName = leftTypeName;					otherLeftTypeId = leftTypeId;					otherRightTypeId = leftTypeId;					other_oid = OperatorGet(name[j],											otherLeftTypeName,											otherRightTypeName,											&otherDefined);					break;				case 3: /* right sort op takes right-side data								 * type */					otherLeftTypeName = rightTypeName;					otherRightTypeName = rightTypeName;					otherLeftTypeId = rightTypeId;					otherRightTypeId = rightTypeId;					other_oid = OperatorGet(name[j],											otherLeftTypeName,											otherRightTypeName,											&otherDefined);					break;			}			if (OidIsValid(other_oid))			{				/* other op already in catalogs */				values[i++] = ObjectIdGetDatum(other_oid);			}			else if (strcmp(operatorName, name[j]) != 0 ||					 otherLeftTypeId != leftTypeId ||					 otherRightTypeId != rightTypeId)			{				/* not in catalogs, different from operator */				other_oid = OperatorShellMake(name[j],											  otherLeftTypeName,											  otherRightTypeName);				if (!OidIsValid(other_oid))					elog(ERROR,						 "OperatorDef: can't create operator shell '%s'",						 name[j]);				values[i++] = ObjectIdGetDatum(other_oid);			}			else			{				/*				 * self-linkage to this operator; will fix below. Note				 * that only self-linkage for commutation makes sense.				 */				if (j != 0)					elog(ERROR,						 "OperatorDef: operator can't be its own negator or sort op");				selfCommutator = true;				values[i++] = ObjectIdGetDatum(InvalidOid);			}		}		else		{			/* other operator is omitted */			values[i++] = ObjectIdGetDatum(InvalidOid);		}	}	/* last three fields were filled in above */	/*	 * If we are adding to an operator shell, get its t_self	 */	pg_operator_desc = heap_openr(OperatorRelationName);	if (operatorObjectId)	{		opKey[0].sk_argument = PointerGetDatum(operatorName);		opKey[1].sk_argument = ObjectIdGetDatum(leftTypeId);		opKey[2].sk_argument = ObjectIdGetDatum(rightTypeId);		pg_operator_scan = heap_beginscan(pg_operator_desc,										  0,										  SnapshotSelf, /* no cache? */										  3,										  opKey);		tup = heap_getnext(pg_operator_scan, 0);		if (HeapTupleIsValid(tup))		{			tup = heap_modifytuple(tup,								   pg_operator_desc,								   values,								   nulls,								   replaces);			setheapoverride(true);			heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);			setheapoverride(false);		}		else			elog(ERROR, "OperatorDef: no operator %u", operatorObjectId);		heap_endscan(pg_operator_scan);	}	else	{		tupDesc = pg_operator_desc->rd_att;		tup = heap_formtuple(tupDesc, values, nulls);		heap_insert(pg_operator_desc, tup);		operatorObjectId = tup->t_data->t_oid;	}	heap_close(pg_operator_desc);	/*	 * If a commutator and/or negator link is provided, update the other	 * operator(s) to point at this one, if they don't already have a	 * link. This supports an alternate style of operator definition	 * wherein the user first defines one operator without giving negator	 * or commutator, then defines the other operator of the pair with the	 * proper commutator or negator attribute.	That style doesn't require	 * creation of a shell, and it's the only style that worked right	 * before Postgres version 6.5. This code also takes care of the	 * situation where the new operator is its own commutator.	 */	if (selfCommutator)		commutatorId = operatorObjectId;	if (OidIsValid(commutatorId) || OidIsValid(negatorId))		OperatorUpd(operatorObjectId, commutatorId, negatorId);}/* ---------------------------------------------------------------- * OperatorUpd * *	For a given operator, look up its negator and commutator operators. *	If they are defined, but their negator and commutator fields *	(respectively) are empty, then use the new operator for neg or comm. *	This solves a problem for users who need to insert two new operators *	which are the negator or commutator of each other. * ---------------------------------------------------------------- */static voidOperatorUpd(Oid baseId, Oid commId, Oid negId){	int			i;	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];	static ScanKeyData opKey[1] = {		{0, ObjectIdAttributeNumber, F_OIDEQ},	};	fmgr_info(F_OIDEQ, &opKey[0].sk_func);	opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;	for (i = 0; i < Natts_pg_operator; ++i)	{		values[i] = (Datum) NULL;		replaces[i] = ' ';		nulls[i] = ' ';	}	pg_operator_desc = heap_openr(OperatorRelationName);	/* check and update the commutator, if necessary */	opKey[0].sk_argument = ObjectIdGetDatum(commId);	pg_operator_scan = heap_beginscan(pg_operator_desc,									  0,									  SnapshotSelf,		/* no cache? */									  1,									  opKey);	tup = heap_getnext(pg_operator_scan, 0);	/*	 * if the commutator and negator are the same operator, do one update.	 * XXX this is probably useless code --- I doubt it ever makes sense	 * for commutator and negator to be the same thing...	 */	if (commId == negId)	{		if (HeapTupleIsValid(tup))		{			Form_pg_operator t;			t = (Form_pg_operator) GETSTRUCT(tup);			if (!OidIsValid(t->oprcom)				|| !OidIsValid(t->oprnegate))			{				if (!OidIsValid(t->oprnegate))				{					values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(baseId);					replaces[Anum_pg_operator_oprnegate - 1] = 'r';				}				if (!OidIsValid(t->oprcom))				{					values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(baseId);					replaces[Anum_pg_operator_oprcom - 1] = 'r';				}				tup = heap_modifytuple(tup,									   pg_operator_desc,									   values,									   nulls,									   replaces);				setheapoverride(true);				heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);				setheapoverride(false);			}		}		heap_endscan(pg_operator_scan);		heap_close(pg_operator_desc);		return;	}	/* if commutator and negator are different, do two updates */	if (HeapTupleIsValid(tup) &&		!(OidIsValid(((Form_pg_operator) GETSTRUCT(tup))->oprcom)))	{		values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(baseId);		replaces[Anum_pg_operator_oprcom - 1] = 'r';		tup = heap_modifytuple(tup,							   pg_operator_desc,							   values,							   nulls,							   replaces);		setheapoverride(true);		heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);		setheapoverride(false);		values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;		replaces[Anum_pg_operator_oprcom - 1] = ' ';	}	heap_endscan(pg_operator_scan);	/* check and update the negator, if necessary */	opKey[0].sk_argument = ObjectIdGetDatum(negId);	pg_operator_scan = heap_beginscan(pg_operator_desc,									  0,									  SnapshotSelf,		/* no cache? */									  1,									  opKey);	tup = heap_getnext(pg_operator_scan, 0);	if (HeapTupleIsValid(tup) &&		!(OidIsValid(((Form_pg_operator) GETSTRUCT(tup))->oprnegate)))	{		values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(baseId);		replaces[Anum_pg_operator_oprnegate - 1] = 'r';		tup = heap_modifytuple(tup,							   pg_operator_desc,							   values,							   nulls,							   replaces);		setheapoverride(true);		heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);		setheapoverride(false);	}	heap_endscan(pg_operator_scan);	heap_close(pg_operator_desc);}/* ---------------------------------------------------------------- * OperatorCreate * * This is now just an interface procedure for OperatorDef ... * * "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 for operator *		precedence;				-- operator precedence *		isLeftAssociative;		-- operator is left associative *		commutatorName;			-- X commutator operator name *		negatorName;			-- X negator operator name *		restrictionName;		-- X restriction sel. procedure *		joinName;				-- X join sel. procedure *		canHash;				-- hash join can be used with this operator *		leftSortName;			-- X left sort operator (for merge join) *		rightSortName;			-- X right sort operator (for merge join) */voidOperatorCreate(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){	if (!leftTypeName && !rightTypeName)		elog(ERROR, "OperatorCreate: at least one of leftarg or rightarg must be defined");	if (!(leftTypeName && rightTypeName))	{		/* If it's not a binary op, these things mustn't be set: */		if (commutatorName)			elog(ERROR, "OperatorCreate: only binary operators can have commutators");		if (negatorName)			elog(ERROR, "OperatorCreate: only binary operators can have negators");		if (restrictionName || joinName)			elog(ERROR, "OperatorCreate: only binary operators can have selectivity");		if (canHash)			elog(ERROR, "OperatorCreate: only binary operators can hash");		if (leftSortName || rightSortName)			elog(ERROR, "OperatorCreate: only binary operators can have sort links");	}	/* ----------------	 *	Use OperatorDef() to define the specified operator and	 *	also create shells for the operator's associated operators	 *	if they don't already exist.	 * ----------------	 */	OperatorDef(operatorName,				leftTypeName,				rightTypeName,				procedureName,				precedence,				isLeftAssociative,				commutatorName,				negatorName,				restrictionName,				joinName,				canHash,				leftSortName,				rightSortName);}

⌨️ 快捷键说明

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