diff options
author | Tom Lane | 2010-11-24 19:20:39 +0000 |
---|---|---|
committer | Tom Lane | 2010-11-24 19:22:17 +0000 |
commit | 725d52d0c27cffe8c99bb78e2b0d2480d5cd702b (patch) | |
tree | 23aae31466c0f7e0e65762946b0012d30e92ab4d /src/backend/commands/opclasscmds.c | |
parent | 4fc09ad00c3cc95003a5523d85999da1dd4f9d75 (diff) |
Create the system catalog infrastructure needed for KNNGIST.
This commit adds columns amoppurpose and amopsortfamily to pg_amop, and
column amcanorderbyop to pg_am. For the moment all the entries in
amcanorderbyop are "false", since the underlying support isn't there yet.
Also, extend the CREATE OPERATOR CLASS/ALTER OPERATOR FAMILY commands with
[ FOR SEARCH | FOR ORDER BY sort_operator_family ] clauses to allow the new
columns of pg_amop to be populated, and create pg_dump support for dumping
that information.
I also added some documentation, although it's perhaps a bit premature
given that the feature doesn't do anything useful yet.
Teodor Sigaev, Robert Haas, Tom Lane
Diffstat (limited to 'src/backend/commands/opclasscmds.c')
-rw-r--r-- | src/backend/commands/opclasscmds.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 8c493363166..132c4ee1e53 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -54,6 +54,7 @@ typedef struct int number; /* strategy or support proc number */ Oid lefttype; /* lefttype */ Oid righttype; /* righttype */ + Oid sortfamily; /* ordering operator's sort opfamily, or 0 */ } OpFamilyMember; @@ -457,6 +458,7 @@ DefineOpClass(CreateOpClassStmt *stmt) CreateOpClassItem *item = lfirst(l); Oid operOid; Oid funcOid; + Oid sortfamilyOid; OpFamilyMember *member; Assert(IsA(item, CreateOpClassItem)); @@ -486,6 +488,13 @@ DefineOpClass(CreateOpClassStmt *stmt) false, -1); } + if (item->order_family) + sortfamilyOid = get_opfamily_oid(BTREE_AM_OID, + item->order_family, + false); + else + sortfamilyOid = InvalidOid; + #ifdef NOT_USED /* XXX this is unnecessary given the superuser check above */ /* Caller must own operator and its underlying function */ @@ -502,6 +511,7 @@ DefineOpClass(CreateOpClassStmt *stmt) member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember)); member->object = operOid; member->number = item->number; + member->sortfamily = sortfamilyOid; assignOperTypes(member, amoid, typeoid); addFamilyMember(&operators, member, false); break; @@ -825,6 +835,7 @@ AlterOpFamilyAdd(List *opfamilyname, Oid amoid, Oid opfamilyoid, CreateOpClassItem *item = lfirst(l); Oid operOid; Oid funcOid; + Oid sortfamilyOid; OpFamilyMember *member; Assert(IsA(item, CreateOpClassItem)); @@ -854,6 +865,13 @@ AlterOpFamilyAdd(List *opfamilyname, Oid amoid, Oid opfamilyoid, operOid = InvalidOid; /* keep compiler quiet */ } + if (item->order_family) + sortfamilyOid = get_opfamily_oid(BTREE_AM_OID, + item->order_family, + false); + else + sortfamilyOid = InvalidOid; + #ifdef NOT_USED /* XXX this is unnecessary given the superuser check above */ /* Caller must own operator and its underlying function */ @@ -870,6 +888,7 @@ AlterOpFamilyAdd(List *opfamilyname, Oid amoid, Oid opfamilyoid, member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember)); member->object = operOid; member->number = item->number; + member->sortfamily = sortfamilyOid; assignOperTypes(member, amoid, InvalidOid); addFamilyMember(&operators, member, false); break; @@ -1043,16 +1062,51 @@ assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid) opform = (Form_pg_operator) GETSTRUCT(optup); /* - * Opfamily operators must be binary ops returning boolean. + * Opfamily operators must be binary. */ if (opform->oprkind != 'b') ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("index operators must be binary"))); - if (opform->oprresult != BOOLOID) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("index operators must return boolean"))); + + if (OidIsValid(member->sortfamily)) + { + /* + * Ordering op, check index supports that. (We could perhaps also + * check that the operator returns a type supported by the sortfamily, + * but that seems more trouble than it's worth here. If it does not, + * the operator will never be matchable to any ORDER BY clause, but + * no worse consequences can ensue. Also, trying to check that would + * create an ordering hazard during dump/reload: it's possible that + * the family has been created but not yet populated with the required + * operators.) + */ + HeapTuple amtup; + Form_pg_am pg_am; + + amtup = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid)); + if (amtup == NULL) + elog(ERROR, "cache lookup failed for access method %u", amoid); + pg_am = (Form_pg_am) GETSTRUCT(amtup); + + if (!pg_am->amcanorderbyop) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("access method \"%s\" does not support ordering operators", + NameStr(pg_am->amname)))); + + ReleaseSysCache(amtup); + } + else + { + /* + * Search operators must return boolean. + */ + if (opform->oprresult != BOOLOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("index search operators must return boolean"))); + } /* * If lefttype/righttype isn't specified, use the operator's input types @@ -1206,6 +1260,7 @@ storeOperators(List *opfamilyname, Oid amoid, foreach(l, operators) { OpFamilyMember *op = (OpFamilyMember *) lfirst(l); + char oppurpose; /* * If adding to an existing family, check for conflict with an @@ -1225,6 +1280,8 @@ storeOperators(List *opfamilyname, Oid amoid, format_type_be(op->righttype), NameListToString(opfamilyname)))); + oppurpose = OidIsValid(op->sortfamily) ? AMOP_ORDER : AMOP_SEARCH; + /* Create the pg_amop entry */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); @@ -1233,8 +1290,10 @@ storeOperators(List *opfamilyname, Oid amoid, values[Anum_pg_amop_amoplefttype - 1] = ObjectIdGetDatum(op->lefttype); values[Anum_pg_amop_amoprighttype - 1] = ObjectIdGetDatum(op->righttype); values[Anum_pg_amop_amopstrategy - 1] = Int16GetDatum(op->number); + values[Anum_pg_amop_amoppurpose - 1] = CharGetDatum(oppurpose); values[Anum_pg_amop_amopopr - 1] = ObjectIdGetDatum(op->object); values[Anum_pg_amop_amopmethod - 1] = ObjectIdGetDatum(amoid); + values[Anum_pg_amop_amopsortfamily - 1] = ObjectIdGetDatum(op->sortfamily); tup = heap_form_tuple(rel->rd_att, values, nulls); @@ -1275,6 +1334,15 @@ storeOperators(List *opfamilyname, Oid amoid, referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); } + + /* A search operator also needs a dep on the referenced opfamily */ + if (OidIsValid(op->sortfamily)) + { + referenced.classId = OperatorFamilyRelationId; + referenced.objectId = op->sortfamily; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } } heap_close(rel, RowExclusiveLock); |