1/*-------------------------------------------------------------------------
5 * Routines for opclass (and opfamily) manipulation commands
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/backend/commands/opclasscmds.c
14 *-------------------------------------------------------------------------
46#include "utils/fmgroids.h"
52 Oid amoid,
Oid opfamilyoid,
53 int maxOpNumber,
int maxProcNumber,
56 Oid amoid,
Oid opfamilyoid,
57 int maxOpNumber,
int maxProcNumber,
62 int opclassOptsProcNum);
65 List *operators,
bool isAdd);
67 List *procedures,
bool isAdd);
76 * Look up an existing opfamily by name.
78 * Returns a syscache tuple reference, or NULL if not found.
87 /* deconstruct the name list */
92 /* Look in specific schema only */
106 /* Unqualified opfamily name, so search the search path */
121 elog(
ERROR,
"cache lookup failed for access method %u", amID);
123 (
errcode(ERRCODE_UNDEFINED_OBJECT),
124 errmsg(
"operator family \"%s\" does not exist for access method \"%s\"",
134 * find an opfamily OID by possibly qualified name
136 * If not found, returns InvalidOid if missing_ok, else throws error.
149 opfID = opfamform->oid;
157 * Look up an existing opclass by name.
159 * Returns a syscache tuple reference, or NULL if not found.
168 /* deconstruct the name list */
173 /* Look in specific schema only */
187 /* Unqualified opclass name, so search the search path */
202 elog(
ERROR,
"cache lookup failed for access method %u", amID);
204 (
errcode(ERRCODE_UNDEFINED_OBJECT),
205 errmsg(
"operator class \"%s\" does not exist for access method \"%s\"",
215 * find an opclass OID by possibly qualified name
217 * If not found, returns InvalidOid if missing_ok, else throws error.
230 opcID = opcform->oid;
238 * Internal routine to make the catalog entry for a new operator family.
240 * Caller must have done permissions checks etc. already.
244 Oid namespaceoid,
Oid amoid)
250 bool nulls[Natts_pg_opfamily];
258 * Make sure there is no existing opfamily of this name (this is just to
259 * give a more friendly error message than "duplicate key").
267 errmsg(
"operator family \"%s\" for access method \"%s\" already exists",
268 opfname,
stmt->amname)));
271 * Okay, let's create the pg_opfamily entry.
274 memset(nulls,
false,
sizeof(nulls));
277 Anum_pg_opfamily_oid);
292 * Create dependencies for the opfamily proper.
294 myself.
classId = OperatorFamilyRelationId;
298 /* dependency on access method */
299 referenced.
classId = AccessMethodRelationId;
304 /* dependency on namespace */
305 referenced.
classId = NamespaceRelationId;
310 /* dependency on owner */
313 /* dependency on extension */
316 /* Report the new operator family to possibly interested event triggers */
320 /* Post creation hook for new operator family */
330 * Define a new index operator class.
335 char *opcname;
/* name of opclass we're creating */
336 Oid amoid,
/* our AM's oid */
337 typeoid,
/* indexable datatype oid */
338 storageoid,
/* storage datatype oid, if any */
339 namespaceoid,
/* namespace to create opclass in */
340 opfamilyoid,
/* oid of containing opfamily */
341 opclassoid;
/* oid of opclass we create */
342 int maxOpNumber,
/* amstrategies value */
343 optsProcNumber,
/* amoptsprocnum value */
344 maxProcNumber;
/* amsupport value */
345 bool amstorage;
/* amstorage flag */
346 List *operators;
/* OpFamilyMember list for operators */
347 List *procedures;
/* OpFamilyMember list for support procs */
354 bool nulls[Natts_pg_opclass];
360 /* Convert list of names to a name and namespace */
364 /* Check we have creation rights in target namespace */
370 /* Get necessary info about access method */
374 (
errcode(ERRCODE_UNDEFINED_OBJECT),
375 errmsg(
"access method \"%s\" does not exist",
384 /* if amstrategies is zero, just enforce that op numbers fit in int16 */
385 if (maxOpNumber <= 0)
386 maxOpNumber = SHRT_MAX;
391 /* XXX Should we make any privilege check against the AM? */
394 * The question of appropriate permissions for CREATE OPERATOR CLASS is
395 * interesting. Creating an opclass is tantamount to granting public
396 * execute access on the functions involved, since the index machinery
397 * generally does not check access permission before using the functions.
398 * A minimum expectation therefore is that the caller have execute
399 * privilege with grant option. Since we don't have a way to make the
400 * opclass go away if the grant option is revoked, we choose instead to
401 * require ownership of the functions. It's also not entirely clear what
402 * permissions should be required on the datatype, but ownership seems
403 * like a safe choice.
405 * Currently, we require superuser privileges to create an opclass. This
406 * seems necessary because we have no way to validate that the offered set
407 * of operators and functions are consistent with the AM's expectations.
408 * It would be nice to provide such a check someday, if it can be done
409 * without solving the halting problem :-(
411 * XXX re-enable NOT_USED code sections below if you remove this test.
415 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
416 errmsg(
"must be superuser to create an operator class")));
418 /* Look up the datatype */
422 /* XXX this is unnecessary given the superuser check above */
423 /* Check we have ownership of the datatype */
429 * Look up the containing operator family, or create one if FAMILY option
430 * was omitted and there's not a match already.
432 if (
stmt->opfamilyname)
438 /* Lookup existing family of same name and namespace */
448 * XXX given the superuser check above, there's no need for an
449 * ownership check here
463 * Create it ... again no need for more permissions ...
473 /* Storage datatype is optional */
477 * Scan the "items" list to obtain additional info.
479 foreach(l,
stmt->items)
492 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
493 errmsg(
"invalid operator number %d,"
494 " must be between 1 and %d",
495 item->
number, maxOpNumber)));
500 /* Default to binary op on input datatype */
514 /* XXX this is unnecessary given the superuser check above */
515 /* Caller must own operator and its underlying function */
537 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
538 errmsg(
"invalid function number %d,"
539 " must be between 1 and %d",
540 item->
number, maxProcNumber)));
543 /* XXX this is unnecessary given the superuser check above */
544 /* Caller must own function */
555 /* allow overriding of the function's actual arg types */
566 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
567 errmsg(
"storage type specified more than once")));
571 /* XXX this is unnecessary given the superuser check above */
572 /* Check we have ownership of the datatype */
584 * If storagetype is specified, make sure it's legal.
588 /* Just drop the spec if same as column datatype */
589 if (storageoid == typeoid)
593 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
594 errmsg(
"storage type cannot be different from data type for access method \"%s\"",
601 * Make sure there is no existing opclass of this name (this is just to
602 * give a more friendly error message than "duplicate key").
610 errmsg(
"operator class \"%s\" for access method \"%s\" already exists",
611 opcname,
stmt->amname)));
614 * If we are creating a default opclass, check there isn't one already.
615 * (Note we do not restrict this test to visible opclasses; this ensures
616 * that typcache.c can find unique solutions to its questions.)
624 Anum_pg_opclass_opcmethod,
635 if (opclass->opcintype == typeoid && opclass->opcdefault)
638 errmsg(
"could not make operator class \"%s\" be default for type %s",
641 errdetail(
"Operator class \"%s\" already is the default.",
649 * Okay, let's create the pg_opclass entry.
652 memset(nulls,
false,
sizeof(nulls));
655 Anum_pg_opclass_oid);
674 * Now that we have the opclass OID, set up default dependency info for
675 * the pg_amop and pg_amproc entries. Historically, CREATE OPERATOR CLASS
676 * has created hard dependencies on the opclass, so that's what we use.
678 foreach(l, operators)
686 foreach(l, procedures)
696 * Let the index AM editorialize on the dependency choices. It could also
697 * do further validation on the operators and functions, if it likes.
706 * Now add tuples to pg_amop and pg_amproc tying in the operators and
707 * functions. Dependencies on them are inserted, too.
714 /* let event triggers know what happened */
718 * Create dependencies for the opclass proper. Note: we do not need a
719 * dependency link to the AM, because that exists through the opfamily.
721 myself.
classId = OperatorClassRelationId;
725 /* dependency on namespace */
726 referenced.
classId = NamespaceRelationId;
731 /* dependency on opfamily */
732 referenced.
classId = OperatorFamilyRelationId;
737 /* dependency on indexed datatype */
738 referenced.
classId = TypeRelationId;
743 /* dependency on storage datatype */
746 referenced.
classId = TypeRelationId;
752 /* dependency on owner */
755 /* dependency on extension */
758 /* Post creation hook for new operator class */
769 * Define a new index operator family.
774 char *opfname;
/* name of opfamily we're creating */
775 Oid amoid,
/* our AM's oid */
776 namespaceoid;
/* namespace to create opfamily in */
779 /* Convert list of names to a name and namespace */
783 /* Check we have creation rights in target namespace */
789 /* Get access method OID, throwing an error if it doesn't exist. */
792 /* XXX Should we make any privilege check against the AM? */
795 * Currently, we require superuser privileges to create an opfamily. See
796 * comments in DefineOpClass.
800 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
801 errmsg(
"must be superuser to create an operator family")));
803 /* Insert pg_opfamily catalog entry */
810 * Add or remove operators/procedures within an existing operator family.
812 * Note: this implements only ALTER OPERATOR FAMILY ... ADD/DROP. Some
813 * other commands called ALTER OPERATOR FAMILY exist, but go through
814 * different code paths.
819 Oid amoid,
/* our AM's oid */
820 opfamilyoid;
/* oid of opfamily */
821 int maxOpNumber,
/* amstrategies value */
822 optsProcNumber,
/* amoptsprocnum value */
823 maxProcNumber;
/* amsupport value */
828 /* Get necessary info about access method */
832 (
errcode(ERRCODE_UNDEFINED_OBJECT),
833 errmsg(
"access method \"%s\" does not exist",
842 /* if amstrategies is zero, just enforce that op numbers fit in int16 */
843 if (maxOpNumber <= 0)
844 maxOpNumber = SHRT_MAX;
848 /* XXX Should we make any privilege check against the AM? */
850 /* Look up the opfamily */
854 * Currently, we require superuser privileges to alter an opfamily.
856 * XXX re-enable NOT_USED code sections below if you remove this test.
860 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
861 errmsg(
"must be superuser to alter an operator family")));
864 * ADD and DROP cases need separate code from here on down.
868 maxOpNumber, maxProcNumber,
stmt->items);
871 maxOpNumber, maxProcNumber, optsProcNumber,
878 * ADD part of ALTER OP FAMILY
882 int maxOpNumber,
int maxProcNumber,
int optsProcNumber,
886 List *operators;
/* OpFamilyMember list for operators */
887 List *procedures;
/* OpFamilyMember list for support procs */
894 * Scan the "items" list to obtain additional info.
909 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
910 errmsg(
"invalid operator number %d,"
911 " must be between 1 and %d",
912 item->
number, maxOpNumber)));
918 (
errcode(ERRCODE_SYNTAX_ERROR),
919 errmsg(
"operator argument types must be specified in ALTER OPERATOR FAMILY")));
920 operOid =
InvalidOid;
/* keep compiler quiet */
931 /* XXX this is unnecessary given the superuser check above */
932 /* Caller must own operator and its underlying function */
948 /* We can set up dependency fields immediately */
949 /* Historically, ALTER ADD has created soft dependencies */
959 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
960 errmsg(
"invalid function number %d,"
961 " must be between 1 and %d",
962 item->
number, maxProcNumber)));
965 /* XXX this is unnecessary given the superuser check above */
966 /* Caller must own function */
977 /* We can set up dependency fields immediately */
978 /* Historically, ALTER ADD has created soft dependencies */
983 /* allow overriding of the function's actual arg types */
993 (
errcode(ERRCODE_SYNTAX_ERROR),
994 errmsg(
"STORAGE cannot be specified in ALTER OPERATOR FAMILY")));
1003 * Let the index AM editorialize on the dependency choices. It could also
1004 * do further validation on the operators and functions, if it likes.
1013 * Add tuples to pg_amop and pg_amproc tying in the operators and
1014 * functions. Dependencies on them are inserted, too.
1021 /* make information available to event triggers */
1023 operators, procedures);
1027 * DROP part of ALTER OP FAMILY
1031 int maxOpNumber,
int maxProcNumber,
List *
items)
1033 List *operators;
/* OpFamilyMember list for operators */
1034 List *procedures;
/* OpFamilyMember list for support procs */
1041 * Scan the "items" list to obtain additional info.
1055 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1056 errmsg(
"invalid operator number %d,"
1057 " must be between 1 and %d",
1058 item->
number, maxOpNumber)));
1071 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1072 errmsg(
"invalid function number %d,"
1073 " must be between 1 and %d",
1074 item->
number, maxProcNumber)));
1085 /* grammar prevents this from appearing */
1093 * Remove tuples from pg_amop and pg_amproc.
1098 /* make information available to event triggers */
1100 operators, procedures);
1105 * Deal with explicit arg types used in ALTER ADD/DROP
1123 *righttype = *lefttype;
1127 (
errcode(ERRCODE_SYNTAX_ERROR),
1128 errmsg(
"one or two argument types must be specified")));
1133 * Determine the lefttype/righttype to assign to an operator,
1134 * and do any validity checking we can manage.
1142 /* Fetch the operator definition */
1149 * Opfamily operators must be binary.
1151 if (opform->oprkind !=
'b')
1153 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1154 errmsg(
"index operators must be binary")));
1159 * Ordering op, check index supports that. (We could perhaps also
1160 * check that the operator returns a type supported by the sortfamily,
1161 * but that seems more trouble than it's worth here. If it does not,
1162 * the operator will never be matchable to any ORDER BY clause, but no
1163 * worse consequences can ensue. Also, trying to check that would
1164 * create an ordering hazard during dump/reload: it's possible that
1165 * the family has been created but not yet populated with the required
1172 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1173 errmsg(
"access method \"%s\" does not support ordering operators",
1179 * Search operators must return boolean.
1181 if (opform->oprresult != BOOLOID)
1183 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1184 errmsg(
"index search operators must return boolean")));
1188 * If lefttype/righttype isn't specified, use the operator's input types
1191 member->
lefttype = opform->oprleft;
1199 * Determine the lefttype/righttype to assign to a support procedure,
1200 * and do any validity checking we can manage.
1204 int opclassOptsProcNum)
1209 /* Fetch the procedure definition */
1215 /* Check the signature of the opclass options parsing function */
1216 if (member->
number == opclassOptsProcNum)
1223 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1224 errmsg(
"associated data types for operator class options parsing functions must match opclass input type")));
1230 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1231 errmsg(
"left and right associated data types for operator class options parsing functions must match")));
1234 if (procform->prorettype != VOIDOID ||
1235 procform->pronargs != 1 ||
1236 procform->proargtypes.values[0] != INTERNALOID)
1238 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1239 errmsg(
"invalid operator class options parsing function"),
1240 errhint(
"Valid signature of operator class options parsing function is %s.",
1241 "(internal) RETURNS void")));
1245 * Ordering comparison procs must be 2-arg procs returning int4. Ordering
1246 * sortsupport procs must take internal and return void. Ordering
1247 * in_range procs must be 5-arg procs returning bool. Ordering equalimage
1248 * procs must take 1 arg and return bool. Hashing support proc 1 must be
1249 * a 1-arg proc returning int4, while proc 2 must be a 2-arg proc
1250 * returning int8. Otherwise we don't know.
1256 if (procform->pronargs != 2)
1258 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1259 errmsg(
"ordering comparison functions must have two arguments")));
1260 if (procform->prorettype != INT4OID)
1262 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1263 errmsg(
"ordering comparison functions must return integer")));
1266 * If lefttype/righttype isn't specified, use the proc's input
1270 member->
lefttype = procform->proargtypes.values[0];
1272 member->
righttype = procform->proargtypes.values[1];
1276 if (procform->pronargs != 1 ||
1277 procform->proargtypes.values[0] != INTERNALOID)
1279 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1280 errmsg(
"ordering sort support functions must accept type \"internal\"")));
1281 if (procform->prorettype != VOIDOID)
1283 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1284 errmsg(
"ordering sort support functions must return void")));
1287 * Can't infer lefttype/righttype from proc, so use default rule
1292 if (procform->pronargs != 5)
1294 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1295 errmsg(
"ordering in_range functions must have five arguments")));
1296 if (procform->prorettype != BOOLOID)
1298 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1299 errmsg(
"ordering in_range functions must return boolean")));
1302 * If lefttype/righttype isn't specified, use the proc's input
1303 * types (we look at the test-value and offset arguments)
1306 member->
lefttype = procform->proargtypes.values[0];
1308 member->
righttype = procform->proargtypes.values[2];
1312 if (procform->pronargs != 1)
1314 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1315 errmsg(
"ordering equal image functions must have one argument")));
1316 if (procform->prorettype != BOOLOID)
1318 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1319 errmsg(
"ordering equal image functions must return boolean")));
1322 * pg_amproc functions are indexed by (lefttype, righttype), but
1323 * an equalimage function can only be called at CREATE INDEX time.
1324 * The same opclass opcintype OID is always used for lefttype and
1325 * righttype. Providing a cross-type routine isn't sensible.
1326 * Reject cross-type ALTER OPERATOR FAMILY ... ADD FUNCTION 4
1331 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1332 errmsg(
"ordering equal image functions must not be cross-type")));
1336 if (procform->pronargs != 1 ||
1337 procform->proargtypes.values[0] != INTERNALOID)
1339 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1340 errmsg(
"btree skip support functions must accept type \"internal\"")));
1341 if (procform->prorettype != VOIDOID)
1343 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1344 errmsg(
"btree skip support functions must return void")));
1347 * pg_amproc functions are indexed by (lefttype, righttype), but a
1348 * skip support function doesn't make sense in cross-type
1349 * scenarios. The same opclass opcintype OID is always used for
1350 * lefttype and righttype. Providing a cross-type routine isn't
1351 * sensible. Reject cross-type ALTER OPERATOR FAMILY ... ADD
1352 * FUNCTION 6 statements here.
1356 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1357 errmsg(
"btree skip support functions must not be cross-type")));
1364 if (procform->pronargs != 1)
1366 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1367 errmsg(
"hash function 1 must have one argument")));
1368 if (procform->prorettype != INT4OID)
1370 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1371 errmsg(
"hash function 1 must return integer")));
1375 if (procform->pronargs != 2)
1377 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1378 errmsg(
"hash function 2 must have two arguments")));
1379 if (procform->prorettype != INT8OID)
1381 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1382 errmsg(
"hash function 2 must return bigint")));
1386 * If lefttype/righttype isn't specified, use the proc's input type
1389 member->
lefttype = procform->proargtypes.values[0];
1391 member->
righttype = procform->proargtypes.values[0];
1395 * The default in CREATE OPERATOR CLASS is to use the class' opcintype as
1396 * lefttype and righttype. In CREATE or ALTER OPERATOR FAMILY, opcintype
1397 * isn't available, so make the user specify the types.
1406 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1407 errmsg(
"associated data types must be specified for index support function")));
1413 * Add a new family member to the appropriate list, after checking for
1414 * duplicated strategy or proc number.
1431 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1432 errmsg(
"function number %d for (%s,%s) appears more than once",
1438 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1439 errmsg(
"operator number %d for (%s,%s) appears more than once",
1449 * Dump the operators to pg_amop
1451 * We also make dependency entries in pg_depend for the pg_amop entries.
1455 List *operators,
bool isAdd)
1459 bool nulls[Natts_pg_amop];
1468 foreach(l, operators)
1474 * If adding to an existing family, check for conflict with an
1475 * existing pg_amop entry (just to give a nicer error message)
1485 errmsg(
"operator %d(%s,%s) already exists in operator family \"%s\"",
1493 /* Create the pg_amop entry */
1495 memset(nulls,
false,
sizeof(nulls));
1515 /* Make its dependencies */
1516 myself.
classId = AccessMethodOperatorRelationId;
1520 referenced.
classId = OperatorRelationId;
1524 /* see comments in amapi.h about dependency strength */
1529 OperatorClassRelationId;
1538 referenced.
classId = TypeRelationId;
1542 /* see comments in amapi.h about dependency strength */
1550 referenced.
classId = TypeRelationId;
1554 /* see comments in amapi.h about dependency strength */
1559 /* A search operator also needs a dep on the referenced opfamily */
1562 referenced.
classId = OperatorFamilyRelationId;
1570 /* Post create hook of this access method operator */
1579 * Dump the procedures (support routines) to pg_amproc
1581 * We also make dependency entries in pg_depend for the pg_amproc entries.
1585 List *procedures,
bool isAdd)
1589 bool nulls[Natts_pg_amproc];
1598 foreach(l, procedures)
1603 * If adding to an existing family, check for conflict with an
1604 * existing pg_amproc entry (just to give a nicer error message)
1614 errmsg(
"function %d(%s,%s) already exists in operator family \"%s\"",
1620 /* Create the pg_amproc entry */
1622 memset(nulls,
false,
sizeof(nulls));
1625 Anum_pg_amproc_oid);
1639 /* Make its dependencies */
1640 myself.
classId = AccessMethodProcedureRelationId;
1644 referenced.
classId = ProcedureRelationId;
1648 /* see comments in amapi.h about dependency strength */
1653 OperatorClassRelationId;
1662 referenced.
classId = TypeRelationId;
1666 /* see comments in amapi.h about dependency strength */
1674 referenced.
classId = TypeRelationId;
1678 /* see comments in amapi.h about dependency strength */
1683 /* Post create hook of access method procedure */
1692 * Detect whether a pg_amop or pg_amproc entry needs an explicit dependency
1693 * on its lefttype or righttype.
1695 * We make such a dependency unless the entry has an indirect dependency
1696 * via its referenced operator or function. That's nearly always true
1697 * for operators, but might well not be true for support functions.
1705 * If the type is pinned, we don't need a dependency. This is a bit of a
1706 * layering violation perhaps (recordDependencyOn would ignore the request
1707 * anyway), but it's a cheap test and will frequently save a syscache
1713 /* Nope, so check the input types of the function or operator. */
1720 for (
int i = 0;
i < nargs;
i++)
1722 if (typid == argtypes[
i])
1724 result =
false;
/* match, no dependency needed */
1736 if (typid == lefttype || typid == righttype)
1737 result =
false;
/* match, no dependency needed */
1744 * Remove operator entries from an opfamily.
1746 * Note: this is only allowed for "loose" members of an opfamily, hence
1747 * behavior is always RESTRICT.
1755 foreach(l, operators)
1768 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1769 errmsg(
"operator %d(%s,%s) does not exist in operator family \"%s\"",
1775 object.classId = AccessMethodOperatorRelationId;
1776 object.objectId = amopid;
1777 object.objectSubId = 0;
1784 * Remove procedure entries from an opfamily.
1786 * Note: this is only allowed for "loose" members of an opfamily, hence
1787 * behavior is always RESTRICT.
1795 foreach(l, procedures)
1808 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1809 errmsg(
"function %d(%s,%s) does not exist in operator family \"%s\"",
1815 object.classId = AccessMethodProcedureRelationId;
1816 object.objectId = amprocid;
1817 object.objectSubId = 0;
1824 * Subroutine for ALTER OPERATOR CLASS SET SCHEMA/RENAME
1826 * Is there an operator class with the given name and signature already
1827 * in the given namespace? If so, raise an appropriate error message.
1833 /* make sure the new name doesn't exist */
1840 errmsg(
"operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"",
1847 * Subroutine for ALTER OPERATOR FAMILY SET SCHEMA/RENAME
1849 * Is there an operator family with the given name and signature already
1850 * in the given namespace? If so, raise an appropriate error message.
1856 /* make sure the new name doesn't exist */
1863 errmsg(
"operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"",
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Oid get_index_am_oid(const char *amname, bool missing_ok)
char * get_am_name(Oid amOid)
static Datum values[MAXATTR]
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
bool IsPinnedObject(Oid classId, Oid objectId)
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures)
void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid, List *operators, List *procedures)
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
#define HASHSTANDARD_PROC
#define HASHEXTENDED_PROC
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
List * lappend(List *list, void *datum)
char * get_opname(Oid opno)
Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
RegProcedure get_opcode(Oid opno)
char * get_func_name(Oid funcid)
char * get_namespace_name(Oid nspid)
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
void pfree(void *pointer)
void * palloc0(Size size)
void namestrcpy(Name name, const char *str)
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
char * NameListToString(const List *names)
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
void DeconstructQualifiedName(const List *names, char **nspname_p, char **objname_p)
Oid OpfamilynameGetOpfid(Oid amid, const char *opfname)
#define BTEQUALIMAGE_PROC
#define BTSKIPSUPPORT_PROC
#define BTSORTSUPPORT_PROC
#define InvokeObjectPostCreateHook(classId, objectId, subId)
const ObjectAddress InvalidObjectAddress
static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
static HeapTuple OpFamilyCacheLookup(Oid amID, List *opfamilyname, bool missing_ok)
ObjectAddress DefineOpClass(CreateOpClassStmt *stmt)
static ObjectAddress CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname, Oid namespaceoid, Oid amoid)
static void storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures, bool isAdd)
static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators, bool isAdd)
static bool typeDepNeeded(Oid typid, OpFamilyMember *member)
static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators)
static void assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, int opclassOptsProcNum)
Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok)
static void addFamilyMember(List **list, OpFamilyMember *member)
void IsThereOpFamilyInNamespace(const char *opfname, Oid opfmethod, Oid opfnamespace)
static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures)
ObjectAddress DefineOpFamily(CreateOpFamilyStmt *stmt)
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
static HeapTuple OpClassCacheLookup(Oid amID, List *opclassname, bool missing_ok)
static void AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, List *items)
Oid AlterOpFamily(AlterOpFamilyStmt *stmt)
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
static void AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, int optsProcNumber, List *items)
void IsThereOpClassInNamespace(const char *opcname, Oid opcmethod, Oid opcnamespace)
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
char * TypeNameToString(const TypeName *typeName)
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
#define OPCLASS_ITEM_STORAGETYPE
#define OPCLASS_ITEM_OPERATOR
#define OPCLASS_ITEM_FUNCTION
FormData_pg_am * Form_pg_am
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
#define lfirst_node(type, lc)
static int list_length(const List *l)
FormData_pg_opclass * Form_pg_opclass
FormData_pg_operator * Form_pg_operator
FormData_pg_opfamily * Form_pg_opfamily
FormData_pg_proc * Form_pg_proc
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
static Datum PointerGetDatum(const void *X)
static Datum Int16GetDatum(int16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum NameGetDatum(const NameData *X)
static Datum CStringGetDatum(const char *X)
static Datum CharGetDatum(char X)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
#define BTEqualStrategyNumber
#define ERRCODE_DUPLICATE_OBJECT
amadjustmembers_function amadjustmembers
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
#define GetSysCacheOid4(cacheId, oidcol, key1, key2, key3, key4)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)