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

📄 pg_operator.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
		restOid = LookupFuncName(restrictionName, 4, typeId, false);	}	else		restOid = InvalidOid;	/*	 * find join estimator	 */	if (joinName)	{		typeId[0] = INTERNALOID;	/* Query */		typeId[1] = OIDOID;		/* operator OID */		typeId[2] = INTERNALOID;	/* args list */		typeId[3] = INT2OID;	/* jointype */		joinOid = LookupFuncName(joinName, 4, typeId, false);	}	else		joinOid = InvalidOid;	/*	 * set up values in the operator tuple	 */	for (i = 0; i < Natts_pg_operator; ++i)	{		values[i] = (Datum) NULL;		replaces[i] = 'r';		nulls[i] = ' ';	}	i = 0;	namestrcpy(&oname, operatorName);	values[i++] = NameGetDatum(&oname); /* oprname */	values[i++] = ObjectIdGetDatum(operatorNamespace);	/* oprnamespace */	values[i++] = ObjectIdGetDatum(GetUserId());		/* oprowner */	values[i++] = CharGetDatum(leftTypeId ? (rightTypeId ? 'b' : 'r') : 'l');	/* oprkind */	values[i++] = BoolGetDatum(canHash);		/* oprcanhash */	values[i++] = ObjectIdGetDatum(leftTypeId); /* oprleft */	values[i++] = ObjectIdGetDatum(rightTypeId);		/* oprright */	values[i++] = ObjectIdGetDatum(operResultType);		/* oprresult */	/*	 * Set up the other operators.	If they do not currently exist, create	 * shells in order to get ObjectId's.	 */	if (commutatorName)	{		/* commutator has reversed arg types */		commutatorId = get_other_operator(commutatorName,										  rightTypeId, leftTypeId,										  operatorName, operatorNamespace,										  leftTypeId, rightTypeId,										  true);		/*		 * self-linkage to this operator; will fix below. Note that only		 * self-linkage for commutation makes sense.		 */		if (!OidIsValid(commutatorId))			selfCommutator = true;	}	else		commutatorId = InvalidOid;	values[i++] = ObjectIdGetDatum(commutatorId);		/* oprcom */	if (negatorName)	{		/* negator has same arg types */		negatorId = get_other_operator(negatorName,									   leftTypeId, rightTypeId,									   operatorName, operatorNamespace,									   leftTypeId, rightTypeId,									   false);	}	else		negatorId = InvalidOid;	values[i++] = ObjectIdGetDatum(negatorId);	/* oprnegate */	if (leftSortName)	{		/* left sort op takes left-side data type */		leftSortId = get_other_operator(leftSortName,										leftTypeId, leftTypeId,										operatorName, operatorNamespace,										leftTypeId, rightTypeId,										false);	}	else		leftSortId = InvalidOid;	values[i++] = ObjectIdGetDatum(leftSortId); /* oprlsortop */	if (rightSortName)	{		/* right sort op takes right-side data type */		rightSortId = get_other_operator(rightSortName,										 rightTypeId, rightTypeId,										 operatorName, operatorNamespace,										 leftTypeId, rightTypeId,										 false);	}	else		rightSortId = InvalidOid;	values[i++] = ObjectIdGetDatum(rightSortId);		/* oprrsortop */	if (ltCompareName)	{		/* comparator has same arg types */		ltCompareId = get_other_operator(ltCompareName,										 leftTypeId, rightTypeId,										 operatorName, operatorNamespace,										 leftTypeId, rightTypeId,										 false);	}	else		ltCompareId = InvalidOid;	values[i++] = ObjectIdGetDatum(ltCompareId);		/* oprltcmpop */	if (gtCompareName)	{		/* comparator has same arg types */		gtCompareId = get_other_operator(gtCompareName,										 leftTypeId, rightTypeId,										 operatorName, operatorNamespace,										 leftTypeId, rightTypeId,										 false);	}	else		gtCompareId = InvalidOid;	values[i++] = ObjectIdGetDatum(gtCompareId);		/* oprgtcmpop */	values[i++] = ObjectIdGetDatum(procOid);	/* oprcode */	values[i++] = ObjectIdGetDatum(restOid);	/* oprrest */	values[i++] = ObjectIdGetDatum(joinOid);	/* oprjoin */	pg_operator_desc = heap_open(OperatorRelationId, RowExclusiveLock);	/*	 * If we are adding to an operator shell, update; else insert	 */	if (operatorObjectId)	{		tup = SearchSysCacheCopy(OPEROID,								 ObjectIdGetDatum(operatorObjectId),								 0, 0, 0);		if (!HeapTupleIsValid(tup))			elog(ERROR, "cache lookup failed for operator %u",				 operatorObjectId);		tup = heap_modifytuple(tup,							   RelationGetDescr(pg_operator_desc),							   values,							   nulls,							   replaces);		simple_heap_update(pg_operator_desc, &tup->t_self, tup);	}	else	{		tupDesc = pg_operator_desc->rd_att;		tup = heap_formtuple(tupDesc, values, nulls);		operatorObjectId = simple_heap_insert(pg_operator_desc, tup);	}	/* Must update the indexes in either case */	CatalogUpdateIndexes(pg_operator_desc, tup);	/* Add dependencies for the entry */	makeOperatorDependencies(tup);	heap_close(pg_operator_desc, RowExclusiveLock);	/*	 * 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);}/* * Try to lookup another operator (commutator, etc) * * If not found, check to see if it is exactly the operator we are trying * to define; if so, return InvalidOid.  (Note that this case is only * sensible for a commutator, so we error out otherwise.)  If it is not * the same operator, create a shell operator. */static Oidget_other_operator(List *otherOp, Oid otherLeftTypeId, Oid otherRightTypeId,				   const char *operatorName, Oid operatorNamespace,				   Oid leftTypeId, Oid rightTypeId, bool isCommutator){	Oid			other_oid;	bool		otherDefined;	char	   *otherName;	Oid			otherNamespace;	AclResult	aclresult;	other_oid = OperatorLookup(otherOp,							   otherLeftTypeId,							   otherRightTypeId,							   &otherDefined);	if (OidIsValid(other_oid))	{		/* other op already in catalogs */		return other_oid;	}	otherNamespace = QualifiedNameGetCreationNamespace(otherOp,													   &otherName);	if (strcmp(otherName, operatorName) == 0 &&		otherNamespace == operatorNamespace &&		otherLeftTypeId == leftTypeId &&		otherRightTypeId == rightTypeId)	{		/*		 * self-linkage to this operator; caller will fix later. Note that		 * only self-linkage for commutation makes sense.		 */		if (!isCommutator)			ereport(ERROR,					(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),			 errmsg("operator cannot be its own negator or sort operator")));		return InvalidOid;	}	/* not in catalogs, different from operator, so make shell */	aclresult = pg_namespace_aclcheck(otherNamespace, GetUserId(),									  ACL_CREATE);	if (aclresult != ACLCHECK_OK)		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,					   get_namespace_name(otherNamespace));	other_oid = OperatorShellMake(otherName,								  otherNamespace,								  otherLeftTypeId,								  otherRightTypeId);	return other_oid;}/* * 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;	HeapTuple	tup;	char		nulls[Natts_pg_operator];	char		replaces[Natts_pg_operator];	Datum		values[Natts_pg_operator];	for (i = 0; i < Natts_pg_operator; ++i)	{		values[i] = (Datum) 0;		replaces[i] = ' ';		nulls[i] = ' ';	}	/*	 * check and update the commutator & negator, if necessary	 *	 * First make sure we can see them...	 */	CommandCounterIncrement();	pg_operator_desc = heap_open(OperatorRelationId, RowExclusiveLock);	tup = SearchSysCacheCopy(OPEROID,							 ObjectIdGetDatum(commId),							 0, 0, 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 = (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,									   RelationGetDescr(pg_operator_desc),									   values,									   nulls,									   replaces);				simple_heap_update(pg_operator_desc, &tup->t_self, tup);				CatalogUpdateIndexes(pg_operator_desc, tup);			}		}		heap_close(pg_operator_desc, RowExclusiveLock);		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,							   RelationGetDescr(pg_operator_desc),							   values,							   nulls,							   replaces);		simple_heap_update(pg_operator_desc, &tup->t_self, tup);		CatalogUpdateIndexes(pg_operator_desc, tup);		values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;		replaces[Anum_pg_operator_oprcom - 1] = ' ';	}	/* check and update the negator, if necessary */	tup = SearchSysCacheCopy(OPEROID,							 ObjectIdGetDatum(negId),							 0, 0, 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,							   RelationGetDescr(pg_operator_desc),							   values,							   nulls,							   replaces);		simple_heap_update(pg_operator_desc, &tup->t_self, tup);		CatalogUpdateIndexes(pg_operator_desc, tup);	}	heap_close(pg_operator_desc, RowExclusiveLock);}/* * Create dependencies for a new operator (either a freshly inserted * complete operator, a new shell operator, or a just-updated shell). * * NB: the OidIsValid tests in this routine are necessary, in case * the given operator is a shell. */static voidmakeOperatorDependencies(HeapTuple tuple){	Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);	ObjectAddress myself,				referenced;	myself.classId = OperatorRelationId;	myself.objectId = HeapTupleGetOid(tuple);	myself.objectSubId = 0;	/* In case we are updating a shell, delete any existing entries */	deleteDependencyRecordsFor(myself.classId, myself.objectId);	deleteSharedDependencyRecordsFor(myself.classId, myself.objectId);	/* Dependency on namespace */	if (OidIsValid(oper->oprnamespace))	{		referenced.classId = NamespaceRelationId;		referenced.objectId = oper->oprnamespace;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	/* Dependency on left type */	if (OidIsValid(oper->oprleft))	{		referenced.classId = TypeRelationId;		referenced.objectId = oper->oprleft;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	/* Dependency on right type */	if (OidIsValid(oper->oprright))	{		referenced.classId = TypeRelationId;		referenced.objectId = oper->oprright;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	/* Dependency on result type */	if (OidIsValid(oper->oprresult))	{		referenced.classId = TypeRelationId;		referenced.objectId = oper->oprresult;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	/*	 * NOTE: we do not consider the operator to depend on the associated	 * operators oprcom, oprnegate, oprlsortop, oprrsortop, oprltcmpop,	 * oprgtcmpop.	We would not want to delete this operator if those go	 * away, but only reset the link fields; which is not a function that the	 * dependency code can presently handle.  (Something could perhaps be done	 * with objectSubId though.)  For now, it's okay to let those links dangle	 * if a referenced operator is removed.	 */	/* Dependency on implementation function */	if (OidIsValid(oper->oprcode))	{		referenced.classId = ProcedureRelationId;		referenced.objectId = oper->oprcode;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	/* Dependency on restriction selectivity function */	if (OidIsValid(oper->oprrest))	{		referenced.classId = ProcedureRelationId;		referenced.objectId = oper->oprrest;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	/* Dependency on join selectivity function */	if (OidIsValid(oper->oprjoin))	{		referenced.classId = ProcedureRelationId;		referenced.objectId = oper->oprjoin;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	/* Dependency on owner */	recordDependencyOnOwner(OperatorRelationId, HeapTupleGetOid(tuple),							oper->oprowner);}

⌨️ 快捷键说明

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