static Oid OperatorGet(constchar *operatorName,
Oid operatorNamespace,
Oid leftObjectId,
Oid rightObjectId, bool *defined);
static Oid OperatorShellMake(constchar *operatorName,
Oid operatorNamespace,
Oid leftTypeId,
Oid rightTypeId);
static Oid get_other_operator(List *otherOp,
Oid otherLeftTypeId, Oid otherRightTypeId, constchar *operatorName, Oid operatorNamespace,
Oid leftTypeId, Oid rightTypeId);
/* Can't be empty or too long */ if (len == 0 || len >= NAMEDATALEN) returnfalse;
/* Can't contain any invalid characters */ /* Test string here should match op_chars in scan.l */ if (strspn(name, "~!@#^&|`?+-*/%<>=") != len) returnfalse;
/* Can't contain slash-star or dash-dash (comment starts) */ if (strstr(name, "/*") || strstr(name, "--")) returnfalse;
for (ic = len - 2; ic >= 0; ic--)
{ if (strchr("~!@#^&|`?%", name[ic])) break;
} if (ic < 0) returnfalse; /* nope, not valid */
}
/* != isn't valid either, because parser will convert it to <> */ if (strcmp(name, "!=") == 0) returnfalse;
returntrue;
}
/* *OperatorGet * *findsanoperatorgivenanexactspecification(name,namespace, *leftandrighttypeIDs). * **definedissettrueifdefined(notashell)
*/ static Oid
OperatorGet(constchar *operatorName,
Oid operatorNamespace,
Oid leftObjectId,
Oid rightObjectId, bool *defined)
{
HeapTuple tup;
Oid operatorObjectId;
/* *OperatorShellMake *Makea"shell"entryforanot-yet-existingoperator.
*/ static Oid
OperatorShellMake(constchar *operatorName,
Oid operatorNamespace,
Oid leftTypeId,
Oid rightTypeId)
{
Relation pg_operator_desc;
Oid operatorObjectId; int i;
HeapTuple tup;
Datum values[Natts_pg_operator]; bool nulls[Natts_pg_operator];
NameData oname;
TupleDesc tupDesc;
/* *validateoperatorname
*/ if (!validOperatorName(operatorName))
ereport(ERROR,
(errcode(ERRCODE_INVALID_NAME),
errmsg("\"%s\" is not a valid operator name",
operatorName)));
/* *OperatorCreate * *"X"indicatesanoptionalargument(i.e.onethatcanbeNULLor0) *operatorNamenamefornewoperator *operatorNamespacenamespacefornewoperator *leftTypeIdXlefttypeID *rightTypeIdXrighttypeID *procedureIdprocedureIDforoperator *commutatorNameXcommutatoroperator *negatorNameXnegatoroperator *restrictionIdXrestrictionselectivityprocedureID *joinIdXjoinselectivityprocedureID *canMergemergejoincanbeusedwiththisoperator *canHashhashjoincanbeusedwiththisoperator * *Thecallershouldhavevalidatedpropertiesandpermissionsforthe *objectspassedasOIDreferences.Wemusthandlethecommutatorand *negatoroperatorreferencesspecially,however,sincethoseneednot *existbeforehand. * *Thisroutinegetscomplicatedbecauseitallowstheuserto *specifyoperatorsthatdonotexist.Forexample,ifoperator *"op"isbeingdefined,thenegatoroperator"negop"andthe *commutator"commop"canalsobedefinedwithoutspecifying *anyinformationotherthantheirnames.Sinceinorderto *add"op"tothePG_OPERATORcatalog,alltheOid'sforthese *operatorsmustbeplacedinthefieldsof"op",aforward *declarationisdoneonthecommutatorandnegatoroperators. *Thisiscalledcreatingashell,anditsmaineffectisto *createatupleinthePG_OPERATORcatalogwithminimal *informationabouttheoperator(justitsnameandtypes). *Forwarddeclarationisusedonlyforthispurpose,itis *notavailabletotheuserasitisfortypedefinition.
*/
ObjectAddress
OperatorCreate(constchar *operatorName,
Oid operatorNamespace,
Oid leftTypeId,
Oid rightTypeId,
Oid procedureId,
List *commutatorName,
List *negatorName,
Oid restrictionId,
Oid joinId, bool canMerge, bool canHash)
{
Relation pg_operator_desc;
HeapTuple tup; bool isUpdate; bool nulls[Natts_pg_operator]; bool replaces[Natts_pg_operator];
Datum values[Natts_pg_operator];
Oid operatorObjectId; bool operatorAlreadyDefined;
Oid operResultType;
Oid commutatorId,
negatorId; bool selfCommutator = false;
NameData oname; int i;
ObjectAddress address;
/* *Sanitychecks
*/ if (!validOperatorName(operatorName))
ereport(ERROR,
(errcode(ERRCODE_INVALID_NAME),
errmsg("\"%s\" is not a valid operator name",
operatorName)));
if (commutatorName)
{ /* commutator has reversed arg types */
commutatorId = get_other_operator(commutatorName,
rightTypeId, leftTypeId,
operatorName, operatorNamespace,
leftTypeId, rightTypeId);
/* Permission check: must own other operator */ if (OidIsValid(commutatorId) &&
!object_ownercheck(OperatorRelationId, commutatorId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
NameListToString(commutatorName));
if (negatorName)
{ /* negator has same arg types */
negatorId = get_other_operator(negatorName,
leftTypeId, rightTypeId,
operatorName, operatorNamespace,
leftTypeId, rightTypeId);
/* Permission check: must own other operator */ if (OidIsValid(negatorId) &&
!object_ownercheck(OperatorRelationId, negatorId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
NameListToString(negatorName));
/* *Preventselfnegation,asitdoesn'tmakesense.It'sself *negationifresultisInvalidOid(negatorwouldbethesame *operatorbutitdoesn'texistyet)oroperatorObjectId(weare *replacingashellthatwouldneedtobeitsownnegator).
*/ if (!OidIsValid(negatorId) || negatorId == operatorObjectId)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("operator cannot be its own negator")));
} else
negatorId = InvalidOid;
/* *setupvaluesintheoperatortuple
*/
for (i = 0; i < Natts_pg_operator; ++i)
{
values[i] = (Datum) NULL;
replaces[i] = true;
nulls[i] = false;
}
if (OidIsValid(commutatorId) || OidIsValid(negatorId))
OperatorUpd(operatorObjectId, commutatorId, negatorId, false);
/* Post creation hook for new operator */
InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
table_close(pg_operator_desc, RowExclusiveLock);
return address;
}
/* *OperatorValidateParams * *CheckthatanoperatorwithargumenttypesleftTypeIdandrightTypeId, *returningoperResultType,canhavetheattributesthataresettotrue. *Raiseanerrorforanydisallowedattribute. * *Note:inALTEROPERATOR,weonlybothertopass"true"forattributes *thecommandistryingtoset,notthosethatmayalreadybeset. *ThisisOKaslongastheattributechecksareindependent.
*/ void
OperatorValidateParams(Oid leftTypeId,
Oid rightTypeId,
Oid operResultType, bool hasCommutator, bool hasNegator, bool hasRestrictionSelectivity, bool hasJoinSelectivity, bool canMerge, bool canHash)
{ if (!(OidIsValid(leftTypeId) && OidIsValid(rightTypeId)))
{ /* If it's not a binary op, these things mustn't be set: */ if (hasCommutator)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only binary operators can have commutators"))); if (hasJoinSelectivity)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only binary operators can have join selectivity"))); if (canMerge)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only binary operators can merge join"))); if (canHash)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only binary operators can hash")));
}
if (operResultType != BOOLOID)
{ /* If it's not a boolean op, these things mustn't be set: */ if (hasNegator)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only boolean operators can have negators"))); if (hasRestrictionSelectivity)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only boolean operators can have restriction selectivity"))); if (hasJoinSelectivity)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only boolean operators can have join selectivity"))); if (canMerge)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only boolean operators can merge join"))); if (canHash)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("only boolean operators can hash")));
}
}
/* *Trytolookupanotheroperator(commutator,etc);returnitsOID * *Ifnotfound,checktoseeifitwouldbethesameoperatorwearetrying *todefine;ifso,returnInvalidOid.(Callermustdecidewhether *thatissensible.)Ifitisnotthesameoperator,createashell *operator.
*/ static Oid
get_other_operator(List *otherOp, Oid otherLeftTypeId, Oid otherRightTypeId, constchar *operatorName, Oid operatorNamespace,
Oid leftTypeId, Oid rightTypeId)
{
Oid other_oid; bool otherDefined; char *otherName;
Oid otherNamespace;
AclResult aclresult;
/* *Ifwe'remakinganoperatorintoitsowncommutator,thenweneeda *command-counterincrementhere,sincewe'vejustinsertedthetuple *we'reabouttoupdate.Butwhenwe'redroppinganoperator,wecan *skipthisbecausewe'reatthebeginningofthecommand.
*/ if (!isDelete)
CommandCounterIncrement();
/* Open the relation. */
pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
/* Get a writable copy of the commutator's tuple. */ if (OidIsValid(commId))
tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(commId)); else
tup = NULL;
/* Update the commutator's tuple if need be. */ if (HeapTupleIsValid(tup))
{
Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup); bool update_commutator = false;
if (thirdop != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("commutator operator %s is already the commutator of operator %s",
NameStr(t->oprname), thirdop))); else
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("commutator operator %s is already the commutator of operator %u",
NameStr(t->oprname), t->oprcom)));
}
t->oprcom = baseId;
update_commutator = true;
}
/* If any columns were found to need modification, update tuple. */ if (update_commutator)
{
CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
if (thirdop != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("negator operator %s is already the negator of operator %s",
NameStr(t->oprname), thirdop))); else
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("negator operator %s is already the negator of operator %u",
NameStr(t->oprname), t->oprnegate)));
}
t->oprnegate = baseId;
update_negator = true;
}
/* If any columns were found to need modification, update tuple. */ if (update_negator)
{
CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
/* Dependency on namespace */ if (OidIsValid(oper->oprnamespace))
{
ObjectAddressSet(referenced, NamespaceRelationId, oper->oprnamespace);
add_exact_object_address(&referenced, addrs);
}
/* Dependency on left type */ if (OidIsValid(oper->oprleft))
{
ObjectAddressSet(referenced, TypeRelationId, oper->oprleft);
add_exact_object_address(&referenced, addrs);
}
/* Dependency on right type */ if (OidIsValid(oper->oprright))
{
ObjectAddressSet(referenced, TypeRelationId, oper->oprright);
add_exact_object_address(&referenced, addrs);
}
/* Dependency on result type */ if (OidIsValid(oper->oprresult))
{
ObjectAddressSet(referenced, TypeRelationId, oper->oprresult);
add_exact_object_address(&referenced, addrs);
}
/* Dependency on implementation function */ if (OidIsValid(oper->oprcode))
{
ObjectAddressSet(referenced, ProcedureRelationId, oper->oprcode);
add_exact_object_address(&referenced, addrs);
}
/* Dependency on restriction selectivity function */ if (OidIsValid(oper->oprrest))
{
ObjectAddressSet(referenced, ProcedureRelationId, oper->oprrest);
add_exact_object_address(&referenced, addrs);
}
/* Dependency on join selectivity function */ if (OidIsValid(oper->oprjoin))
{
ObjectAddressSet(referenced, ProcedureRelationId, oper->oprjoin);
add_exact_object_address(&referenced, addrs);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.