diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 9a8729b8b31..54a6dcc102c 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -423,7 +423,16 @@
amcanorderbool
- Does the access method support ordered scans?
+ Does the access method support ordered scans sorted by the
+ indexed column's value?
+
+
+
+ amcanorderbyop
+ bool
+
+ Does the access method support ordered scans sorted by the result
+ of an operator on the indexed column?
@@ -598,9 +607,13 @@
The catalog pg_amop stores information about
operators associated with access method operator families. There is one
- row for each operator that is a member of an operator family. An operator
+ row for each operator that is a member of an operator family. A family
+ member can be either a search> operator or an
+ ordering> operator. An operator
can appear in more than one family, but cannot appear in more than one
- position within a family.
+ search position nor more than one ordering position within a family.
+ (It is allowed, though unlikely, for an operator to be used for both
+ search and ordering purposes.)
@@ -645,6 +658,14 @@
Operator strategy number
+
+ amoppurpose
+ char
+
+ Operator purpose, either s> for search or
+ o> for ordering
+
+
amopoproid
@@ -659,10 +680,52 @@
Index access method operator family is for
+
+ amopsortfamily
+ oid
+ pg_opfamily.oid
+ The btree operator family this entry sorts according to, if an
+ ordering operator; zero if a search operator
+
+
+
+ A search> operator entry indicates that an index of this operator
+ family can be searched to find all rows satisfying
+ WHERE>
+ indexed_column>
+ operator>
+ constant>.
+ Obviously, such an operator must return boolean, and its left-hand input
+ type must match the index's column data type.
+
+
+
+ An ordering> operator entry indicates that an index of this
+ operator family can be scanned to return rows in the order represented by
+ ORDER BY>
+ indexed_column>
+ operator>
+ constant>.
+ Such an operator could return any sortable data type, though again
+ its left-hand input type must match the index's column data type.
+ The exact semantics of the ORDER BY> are specified by the
+ amopsortfamily column, which must reference
+ a btree operator family for the operator's result type.
+
+
+
+
+ At present, it's assumed that the sort order for an ordering operator
+ is the default for the referenced opfamily, i.e., ASC NULLS
+ LAST>. This might someday be relaxed by adding additional columns
+ to specify sort options explicitly.
+
+
+
An entry's amopmethod> must match the
opfmethod> of its containing operator family (including
diff --git a/doc/src/sgml/ref/alter_opfamily.sgml b/doc/src/sgml/ref/alter_opfamily.sgml
index 1018af8412d..3c8ca21f61e 100644
--- a/doc/src/sgml/ref/alter_opfamily.sgml
+++ b/doc/src/sgml/ref/alter_opfamily.sgml
@@ -22,7 +22,7 @@ PostgreSQL documentation
ALTER OPERATOR FAMILY name USING index_method ADD
- { OPERATOR strategy_numberoperator_name ( op_type, op_type )
+ { OPERATOR strategy_numberoperator_name ( op_type, op_type ) [ FOR SEARCH | FOR ORDER BY sort_family_name ]
| FUNCTION support_number [ ( op_type [ , op_type ] ) ] function_name ( argument_type [, ...] )
} [, ... ]
ALTER OPERATOR FAMILY name USING index_method DROP
@@ -154,6 +154,22 @@ ALTER OPERATOR FAMILY name USING sort_family_name
+
+
+ The name (optionally schema-qualified) of an existing btree operator
+ family that describes the sort ordering associated with an ordering
+ operator.
+
+
+
+ If neither FOR SEARCH> nor FOR ORDER BY> is
+ specified, FOR SEARCH> is the default.
+
+
+
+
support_number
diff --git a/doc/src/sgml/ref/create_opclass.sgml b/doc/src/sgml/ref/create_opclass.sgml
index f12f13dc08e..eff585405cd 100644
--- a/doc/src/sgml/ref/create_opclass.sgml
+++ b/doc/src/sgml/ref/create_opclass.sgml
@@ -23,7 +23,7 @@ PostgreSQL documentation
CREATE OPERATOR CLASS name [ DEFAULT ] FOR TYPE data_type
USING index_method [ FAMILY family_name ] AS
- { OPERATOR strategy_numberoperator_name [ ( op_type, op_type ) ]
+ { OPERATOR strategy_numberoperator_name [ ( op_type, op_type ) ] [ FOR SEARCH | FOR ORDER BY sort_family_name ]
| FUNCTION support_number [ ( op_type [ , op_type ] ) ] function_name ( argument_type [, ...] )
| STORAGE storage_type
} [, ... ]
@@ -180,6 +180,22 @@ CREATE OPERATOR CLASS name [ DEFAUL
+
+ sort_family_name
+
+
+ The name (optionally schema-qualified) of an existing btree operator
+ family that describes the sort ordering associated with an ordering
+ operator.
+
+
+
+ If neither FOR SEARCH> nor FOR ORDER BY> is
+ specified, FOR SEARCH> is the default.
+
+
+
+
support_number
diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml
index 8f9fd21f386..6d059bda706 100644
--- a/doc/src/sgml/xindex.sgml
+++ b/doc/src/sgml/xindex.sgml
@@ -276,10 +276,13 @@
- Notice that all strategy operators return Boolean values. In
- practice, all operators defined as index method strategies must
+ Notice that all the operators listed above return Boolean values. In
+ practice, all operators defined as index method search operators must
return type boolean, since they must appear at the top
level of a WHERE> clause to be used with an index.
+ (Some index access methods also support ordering operators>,
+ which typically don't return Boolean values; that feature is discussed
+ in .)
@@ -464,7 +467,7 @@
- Unlike strategy operators, support functions return whichever data
+ Unlike search operators, support functions return whichever data
type the particular index method expects; for example in the case
of the comparison function for B-trees, a signed integer. The number
and types of the arguments to each support function are likewise
@@ -921,6 +924,62 @@ ALTER OPERATOR FAMILY integer_ops USING btree ADD
+
+ Ordering Operators
+
+
+ Some index access methods (currently, only GiST) support the concept of
+ ordering operators>. What we have been discussing so far
+ are search operators>. A search operator is one for which
+ the index can be searched to find all rows satisfying
+ WHERE>
+ indexed_column>
+ operator>
+ constant>.
+ Note that nothing is promised about the order in which the matching rows
+ will be returned. In contrast, an ordering operator does not restrict the
+ set of rows that can be returned, but instead determines their order.
+ An ordering operator is one for which the index can be scanned to return
+ rows in the order represented by
+ ORDER BY>
+ indexed_column>
+ operator>
+ constant>.
+ The reason for defining ordering operators that way is that it supports
+ nearest-neighbor searches, if the operator is one that measures distance.
+ For example, a query like
+ point '(101,456)' LIMIT 10;
+]]>
+
+ finds the ten places closest to a given target point. A GiST index
+ on the location column can do this efficiently because
+ <->> is an ordering operator.
+
+
+
+ While search operators have to return Boolean results, ordering operators
+ usually return some other type, such as float or numeric for distances.
+ This type is normally not the same as the data type being indexed.
+ To avoid hard-wiring assumptions about the behavior of different data
+ types, the definition of an ordering operator is required to name
+ a B-tree operator family that specifies the sort ordering of the result
+ data type. As was stated in the previous section, B-tree operator families
+ define PostgreSQL's notion of ordering, so
+ this is a natural representation. Since the point <->>
+ operator returns float8>, it could be specified in an operator
+ class creation command like this:
+ (point, point) FOR ORDER BY float_ops
+]]>
+
+ where float_ops> is the built-in operator family that includes
+ operations on float8>. This declaration states that the index
+ is able to return rows in order of increasing values of the
+ <->> operator.
+
+
+
Special Features of Operator Classes
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);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index bbfbab2e39b..0e0b4dc598a 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2991,6 +2991,7 @@ _copyCreateOpClassItem(CreateOpClassItem *from)
COPY_NODE_FIELD(name);
COPY_NODE_FIELD(args);
COPY_SCALAR_FIELD(number);
+ COPY_NODE_FIELD(order_family);
COPY_NODE_FIELD(class_args);
COPY_NODE_FIELD(storedtype);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index be4b835585c..2d2b8c77634 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1464,6 +1464,7 @@ _equalCreateOpClassItem(CreateOpClassItem *a, CreateOpClassItem *b)
COMPARE_NODE_FIELD(name);
COMPARE_NODE_FIELD(args);
COMPARE_SCALAR_FIELD(number);
+ COMPARE_NODE_FIELD(order_family);
COMPARE_NODE_FIELD(class_args);
COMPARE_NODE_FIELD(storedtype);
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 73132ddf5ca..908b4f7205d 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -212,6 +212,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
info->relam = indexRelation->rd_rel->relam;
info->amcostestimate = indexRelation->rd_am->amcostestimate;
+ info->amcanorderbyop = indexRelation->rd_am->amcanorderbyop;
info->amoptionalkey = indexRelation->rd_am->amoptionalkey;
info->amsearchnulls = indexRelation->rd_am->amsearchnulls;
info->amhasgettuple = OidIsValid(indexRelation->rd_am->amgettuple);
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 5ab4a31e152..d7ccba0a112 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -1661,8 +1661,9 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
* From the same opfamily, find a strategy number for the clause_op,
* if possible
*/
- clause_tuple = SearchSysCache2(AMOPOPID,
+ clause_tuple = SearchSysCache3(AMOPOPID,
ObjectIdGetDatum(clause_op),
+ CharGetDatum(AMOP_SEARCH),
ObjectIdGetDatum(opfamily_id));
if (HeapTupleIsValid(clause_tuple))
{
@@ -1677,8 +1678,9 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
}
else if (OidIsValid(clause_op_negator))
{
- clause_tuple = SearchSysCache2(AMOPOPID,
- ObjectIdGetDatum(clause_op_negator),
+ clause_tuple = SearchSysCache3(AMOPOPID,
+ ObjectIdGetDatum(clause_op_negator),
+ CharGetDatum(AMOP_SEARCH),
ObjectIdGetDatum(opfamily_id));
if (HeapTupleIsValid(clause_tuple))
{
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index f0c2cd06ea6..1c17be89214 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -295,7 +295,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
ctext_expr_list ctext_row def_list indirection opt_indirection
reloption_list group_clause TriggerFuncArgs select_limit
opt_select_limit opclass_item_list opclass_drop_list
- opt_opfamily transaction_mode_list_or_empty
+ opclass_purpose opt_opfamily transaction_mode_list_or_empty
OptTableFuncElementList TableFuncElementList opt_type_modifiers
prep_type_clause
execute_param_clause using_clause returning_clause
@@ -3935,22 +3935,25 @@ opclass_item_list:
;
opclass_item:
- OPERATOR Iconst any_operator opt_recheck
+ OPERATOR Iconst any_operator opclass_purpose opt_recheck
{
CreateOpClassItem *n = makeNode(CreateOpClassItem);
n->itemtype = OPCLASS_ITEM_OPERATOR;
n->name = $3;
n->args = NIL;
n->number = $2;
+ n->order_family = $4;
$$ = (Node *) n;
}
- | OPERATOR Iconst any_operator oper_argtypes opt_recheck
+ | OPERATOR Iconst any_operator oper_argtypes opclass_purpose
+ opt_recheck
{
CreateOpClassItem *n = makeNode(CreateOpClassItem);
n->itemtype = OPCLASS_ITEM_OPERATOR;
n->name = $3;
n->args = $4;
n->number = $2;
+ n->order_family = $5;
$$ = (Node *) n;
}
| FUNCTION Iconst func_name func_args
@@ -3989,6 +3992,11 @@ opt_opfamily: FAMILY any_name { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
+opclass_purpose: FOR SEARCH { $$ = NIL; }
+ | FOR ORDER BY any_name { $$ = $4; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
opt_recheck: RECHECK
{
/*
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index df765e9d5e3..9beae0d9ef1 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -46,12 +46,15 @@ get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
* op_in_opfamily
*
* Return t iff operator 'opno' is in operator family 'opfamily'.
+ *
+ * This function only considers search operators, not ordering operators.
*/
bool
op_in_opfamily(Oid opno, Oid opfamily)
{
- return SearchSysCacheExists2(AMOPOPID,
+ return SearchSysCacheExists3(AMOPOPID,
ObjectIdGetDatum(opno),
+ CharGetDatum(AMOP_SEARCH),
ObjectIdGetDatum(opfamily));
}
@@ -60,6 +63,8 @@ op_in_opfamily(Oid opno, Oid opfamily)
*
* Get the operator's strategy number within the specified opfamily,
* or 0 if it's not a member of the opfamily.
+ *
+ * This function only considers search operators, not ordering operators.
*/
int
get_op_opfamily_strategy(Oid opno, Oid opfamily)
@@ -68,8 +73,9 @@ get_op_opfamily_strategy(Oid opno, Oid opfamily)
Form_pg_amop amop_tup;
int result;
- tp = SearchSysCache2(AMOPOPID,
+ tp = SearchSysCache3(AMOPOPID,
ObjectIdGetDatum(opno),
+ CharGetDatum(AMOP_SEARCH),
ObjectIdGetDatum(opfamily));
if (!HeapTupleIsValid(tp))
return 0;
@@ -85,6 +91,8 @@ get_op_opfamily_strategy(Oid opno, Oid opfamily)
* Get the operator's strategy number and declared input data types
* within the specified opfamily.
*
+ * This function only considers search operators, not ordering operators.
+ *
* Caller should already have verified that opno is a member of opfamily,
* therefore we raise an error if the tuple is not found.
*/
@@ -97,8 +105,9 @@ get_op_opfamily_properties(Oid opno, Oid opfamily,
HeapTuple tp;
Form_pg_amop amop_tup;
- tp = SearchSysCache2(AMOPOPID,
+ tp = SearchSysCache3(AMOPOPID,
ObjectIdGetDatum(opno),
+ CharGetDatum(AMOP_SEARCH),
ObjectIdGetDatum(opfamily));
if (!HeapTupleIsValid(tp))
elog(ERROR, "operator %u is not a member of opfamily %u",
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 94bef7dd018..08a14431b16 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -135,11 +135,11 @@ static const struct cachedesc cacheinfo[] = {
},
{AccessMethodOperatorRelationId, /* AMOPOPID */
AccessMethodOperatorIndexId,
- 2,
+ 3,
{
Anum_pg_amop_amopopr,
+ Anum_pg_amop_amoppurpose,
Anum_pg_amop_amopfamily,
- 0,
0
},
64
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 3bca417cef9..66274b442e6 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -8815,22 +8815,28 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
int i_opckeytype;
int i_opcdefault;
int i_opcfamily;
+ int i_opcfamilyname;
int i_opcfamilynsp;
int i_amname;
int i_amopstrategy;
int i_amopreqcheck;
int i_amopopr;
+ int i_sortfamily;
+ int i_sortfamilynsp;
int i_amprocnum;
int i_amproc;
char *opcintype;
char *opckeytype;
char *opcdefault;
char *opcfamily;
+ char *opcfamilyname;
char *opcfamilynsp;
char *amname;
char *amopstrategy;
char *amopreqcheck;
char *amopopr;
+ char *sortfamily;
+ char *sortfamilynsp;
char *amprocnum;
char *amproc;
bool needComma;
@@ -8860,8 +8866,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
{
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
"opckeytype::pg_catalog.regtype, "
- "opcdefault, "
- "opfname AS opcfamily, "
+ "opcdefault, opcfamily, "
+ "opfname AS opcfamilyname, "
"nspname AS opcfamilynsp, "
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
"FROM pg_catalog.pg_opclass c "
@@ -8874,8 +8880,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
{
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
"opckeytype::pg_catalog.regtype, "
- "opcdefault, "
- "NULL AS opcfamily, "
+ "opcdefault, NULL AS opcfamily, "
+ "NULL AS opcfamilyname, "
"NULL AS opcfamilynsp, "
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
"FROM pg_catalog.pg_opclass "
@@ -8901,13 +8907,16 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
i_opckeytype = PQfnumber(res, "opckeytype");
i_opcdefault = PQfnumber(res, "opcdefault");
i_opcfamily = PQfnumber(res, "opcfamily");
+ i_opcfamilyname = PQfnumber(res, "opcfamilyname");
i_opcfamilynsp = PQfnumber(res, "opcfamilynsp");
i_amname = PQfnumber(res, "amname");
opcintype = PQgetvalue(res, 0, i_opcintype);
opckeytype = PQgetvalue(res, 0, i_opckeytype);
opcdefault = PQgetvalue(res, 0, i_opcdefault);
- opcfamily = PQgetvalue(res, 0, i_opcfamily);
+ /* opcfamily will still be needed after we PQclear res */
+ opcfamily = strdup(PQgetvalue(res, 0, i_opcfamily));
+ opcfamilyname = PQgetvalue(res, 0, i_opcfamilyname);
opcfamilynsp = PQgetvalue(res, 0, i_opcfamilynsp);
/* amname will still be needed after we PQclear res */
amname = strdup(PQgetvalue(res, 0, i_amname));
@@ -8930,14 +8939,14 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
appendPQExpBuffer(q, "FOR TYPE %s USING %s",
opcintype,
fmtId(amname));
- if (strlen(opcfamily) > 0 &&
- (strcmp(opcfamily, opcinfo->dobj.name) != 0 ||
+ if (strlen(opcfamilyname) > 0 &&
+ (strcmp(opcfamilyname, opcinfo->dobj.name) != 0 ||
strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
{
appendPQExpBuffer(q, " FAMILY ");
if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
- appendPQExpBuffer(q, "%s", fmtId(opcfamily));
+ appendPQExpBuffer(q, "%s", fmtId(opcfamilyname));
}
appendPQExpBuffer(q, " AS\n ");
@@ -8954,23 +8963,41 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
/*
* Now fetch and print the OPERATOR entries (pg_amop rows).
+ *
+ * Print only those opfamily members that are tied to the opclass by
+ * pg_depend entries.
+ *
+ * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
+ * an older server's opclass in which it is used. This is to avoid
+ * hard-to-detect breakage if a newer pg_dump is used to dump from an
+ * older server and then reload into that old version. This can go
+ * away once 8.3 is so old as to not be of interest to anyone.
*/
resetPQExpBuffer(query);
- if (g_fout->remoteVersion >= 80400)
+ if (g_fout->remoteVersion >= 90100)
{
- /*
- * Print only those opfamily members that are tied to the opclass by
- * pg_depend entries.
- *
- * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
- * an older server's opclass in which it is used. This is to avoid
- * hard-to-detect breakage if a newer pg_dump is used to dump from an
- * older server and then reload into that old version. This can go
- * away once 8.3 is so old as to not be of interest to anyone.
- */
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
- "amopopr::pg_catalog.regoperator "
+ "amopopr::pg_catalog.regoperator, "
+ "opfname AS sortfamily, "
+ "nspname AS sortfamilynsp "
+ "FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON "
+ "(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) "
+ "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily "
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
+ "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+ "AND refobjid = '%u'::pg_catalog.oid "
+ "AND amopfamily = '%s'::pg_catalog.oid "
+ "ORDER BY amopstrategy",
+ opcinfo->dobj.catId.oid,
+ opcfamily);
+ }
+ else if (g_fout->remoteVersion >= 80400)
+ {
+ appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
+ "amopopr::pg_catalog.regoperator, "
+ "NULL AS sortfamily, "
+ "NULL AS sortfamilynsp "
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
"WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
@@ -8981,12 +9008,10 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
}
else if (g_fout->remoteVersion >= 80300)
{
- /*
- * Print only those opfamily members that are tied to the opclass by
- * pg_depend entries.
- */
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
- "amopopr::pg_catalog.regoperator "
+ "amopopr::pg_catalog.regoperator, "
+ "NULL AS sortfamily, "
+ "NULL AS sortfamilynsp "
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
"WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
@@ -8997,8 +9022,14 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
}
else
{
+ /*
+ * Here, we print all entries since there are no opfamilies and
+ * hence no loose operators to worry about.
+ */
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
- "amopopr::pg_catalog.regoperator "
+ "amopopr::pg_catalog.regoperator, "
+ "NULL AS sortfamily, "
+ "NULL AS sortfamilynsp "
"FROM pg_catalog.pg_amop "
"WHERE amopclaid = '%u'::pg_catalog.oid "
"ORDER BY amopstrategy",
@@ -9013,18 +9044,31 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
i_amopstrategy = PQfnumber(res, "amopstrategy");
i_amopreqcheck = PQfnumber(res, "amopreqcheck");
i_amopopr = PQfnumber(res, "amopopr");
+ i_sortfamily = PQfnumber(res, "sortfamily");
+ i_sortfamilynsp = PQfnumber(res, "sortfamilynsp");
for (i = 0; i < ntups; i++)
{
amopstrategy = PQgetvalue(res, i, i_amopstrategy);
amopreqcheck = PQgetvalue(res, i, i_amopreqcheck);
amopopr = PQgetvalue(res, i, i_amopopr);
+ sortfamily = PQgetvalue(res, i, i_sortfamily);
+ sortfamilynsp = PQgetvalue(res, i, i_sortfamilynsp);
if (needComma)
appendPQExpBuffer(q, " ,\n ");
appendPQExpBuffer(q, "OPERATOR %s %s",
amopstrategy, amopopr);
+
+ if (strlen(sortfamily) > 0)
+ {
+ appendPQExpBuffer(q, " FOR ORDER BY ");
+ if (strcmp(sortfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
+ appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
+ appendPQExpBuffer(q, "%s", fmtId(sortfamily));
+ }
+
if (strcmp(amopreqcheck, "t") == 0)
appendPQExpBuffer(q, " RECHECK");
@@ -9035,15 +9079,14 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
/*
* Now fetch and print the FUNCTION entries (pg_amproc rows).
+ *
+ * Print only those opfamily members that are tied to the opclass by
+ * pg_depend entries.
*/
resetPQExpBuffer(query);
if (g_fout->remoteVersion >= 80300)
{
- /*
- * Print only those opfamily members that are tied to the opclass by
- * pg_depend entries.
- */
appendPQExpBuffer(query, "SELECT amprocnum, "
"amproc::pg_catalog.regprocedure "
"FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
@@ -9119,6 +9162,9 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
/*
* dumpOpfamily
* write out a single operator family definition
+ *
+ * Note: this also dumps any "loose" operator members that aren't bound to a
+ * specific opclass within the opfamily.
*/
static void
dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
@@ -9134,6 +9180,8 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
int i_amopstrategy;
int i_amopreqcheck;
int i_amopopr;
+ int i_sortfamily;
+ int i_sortfamilynsp;
int i_amprocnum;
int i_amproc;
int i_amproclefttype;
@@ -9142,6 +9190,8 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
char *amopstrategy;
char *amopreqcheck;
char *amopopr;
+ char *sortfamily;
+ char *sortfamilynsp;
char *amprocnum;
char *amproc;
char *amproclefttype;
@@ -9172,18 +9222,36 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
/*
* Fetch only those opfamily members that are tied directly to the
* opfamily by pg_depend entries.
+ *
+ * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
+ * an older server's opclass in which it is used. This is to avoid
+ * hard-to-detect breakage if a newer pg_dump is used to dump from an
+ * older server and then reload into that old version. This can go
+ * away once 8.3 is so old as to not be of interest to anyone.
*/
- if (g_fout->remoteVersion >= 80400)
+ if (g_fout->remoteVersion >= 90100)
{
- /*
- * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
- * an older server's opclass in which it is used. This is to avoid
- * hard-to-detect breakage if a newer pg_dump is used to dump from an
- * older server and then reload into that old version. This can go
- * away once 8.3 is so old as to not be of interest to anyone.
- */
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
- "amopopr::pg_catalog.regoperator "
+ "amopopr::pg_catalog.regoperator, "
+ "opfname AS sortfamily, "
+ "nspname AS sortfamilynsp "
+ "FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON "
+ "(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) "
+ "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily "
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
+ "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "AND refobjid = '%u'::pg_catalog.oid "
+ "AND amopfamily = '%u'::pg_catalog.oid "
+ "ORDER BY amopstrategy",
+ opfinfo->dobj.catId.oid,
+ opfinfo->dobj.catId.oid);
+ }
+ else if (g_fout->remoteVersion >= 80400)
+ {
+ appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
+ "amopopr::pg_catalog.regoperator, "
+ "NULL AS sortfamily, "
+ "NULL AS sortfamilynsp "
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
"WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
@@ -9195,7 +9263,9 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
else
{
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
- "amopopr::pg_catalog.regoperator "
+ "amopopr::pg_catalog.regoperator, "
+ "NULL AS sortfamily, "
+ "NULL AS sortfamilynsp "
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
"WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
@@ -9323,18 +9393,31 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
i_amopstrategy = PQfnumber(res_ops, "amopstrategy");
i_amopreqcheck = PQfnumber(res_ops, "amopreqcheck");
i_amopopr = PQfnumber(res_ops, "amopopr");
+ i_sortfamily = PQfnumber(res_ops, "sortfamily");
+ i_sortfamilynsp = PQfnumber(res_ops, "sortfamilynsp");
for (i = 0; i < ntups; i++)
{
amopstrategy = PQgetvalue(res_ops, i, i_amopstrategy);
amopreqcheck = PQgetvalue(res_ops, i, i_amopreqcheck);
amopopr = PQgetvalue(res_ops, i, i_amopopr);
+ sortfamily = PQgetvalue(res_ops, i, i_sortfamily);
+ sortfamilynsp = PQgetvalue(res_ops, i, i_sortfamilynsp);
if (needComma)
appendPQExpBuffer(q, " ,\n ");
appendPQExpBuffer(q, "OPERATOR %s %s",
amopstrategy, amopopr);
+
+ if (strlen(sortfamily) > 0)
+ {
+ appendPQExpBuffer(q, " FOR ORDER BY ");
+ if (strcmp(sortfamilynsp, opfinfo->dobj.namespace->dobj.name) != 0)
+ appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
+ appendPQExpBuffer(q, "%s", fmtId(sortfamily));
+ }
+
if (strcmp(amopreqcheck, "t") == 0)
appendPQExpBuffer(q, " RECHECK");
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 69f76aae0e6..8698a43371f 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201011211
+#define CATALOG_VERSION_NO 201011241
#endif
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index a3839e1e259..1542c8d5f49 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -67,7 +67,7 @@ DECLARE_UNIQUE_INDEX(pg_am_oid_index, 2652, on pg_am using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, on pg_amop using btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
#define AccessMethodStrategyIndexId 2653
-DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, on pg_amop using btree(amopopr oid_ops, amopfamily oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, on pg_amop using btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
#define AccessMethodOperatorIndexId 2654
DECLARE_UNIQUE_INDEX(pg_amop_oid_index, 2756, on pg_amop using btree(oid oid_ops));
#define AccessMethodOperatorOidIndexId 2756
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index c9b8e2d766e..5a18dee0bdb 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -40,7 +40,8 @@ CATALOG(pg_am,2601)
* assignments. */
int2 amsupport; /* total number of support functions that this
* AM uses */
- bool amcanorder; /* does AM support ordered scan results? */
+ bool amcanorder; /* does AM support order by column value? */
+ bool amcanorderbyop; /* does AM support order by operator result? */
bool amcanbackward; /* does AM support backward scan? */
bool amcanunique; /* does AM support UNIQUE indexes? */
bool amcanmulticol; /* does AM support multi-column indexes? */
@@ -76,49 +77,50 @@ typedef FormData_pg_am *Form_pg_am;
* compiler constants for pg_am
* ----------------
*/
-#define Natts_pg_am 26
+#define Natts_pg_am 27
#define Anum_pg_am_amname 1
#define Anum_pg_am_amstrategies 2
#define Anum_pg_am_amsupport 3
#define Anum_pg_am_amcanorder 4
-#define Anum_pg_am_amcanbackward 5
-#define Anum_pg_am_amcanunique 6
-#define Anum_pg_am_amcanmulticol 7
-#define Anum_pg_am_amoptionalkey 8
-#define Anum_pg_am_amindexnulls 9
-#define Anum_pg_am_amsearchnulls 10
-#define Anum_pg_am_amstorage 11
-#define Anum_pg_am_amclusterable 12
-#define Anum_pg_am_amkeytype 13
-#define Anum_pg_am_aminsert 14
-#define Anum_pg_am_ambeginscan 15
-#define Anum_pg_am_amgettuple 16
-#define Anum_pg_am_amgetbitmap 17
-#define Anum_pg_am_amrescan 18
-#define Anum_pg_am_amendscan 19
-#define Anum_pg_am_ammarkpos 20
-#define Anum_pg_am_amrestrpos 21
-#define Anum_pg_am_ambuild 22
-#define Anum_pg_am_ambulkdelete 23
-#define Anum_pg_am_amvacuumcleanup 24
-#define Anum_pg_am_amcostestimate 25
-#define Anum_pg_am_amoptions 26
+#define Anum_pg_am_amcanorderbyop 5
+#define Anum_pg_am_amcanbackward 6
+#define Anum_pg_am_amcanunique 7
+#define Anum_pg_am_amcanmulticol 8
+#define Anum_pg_am_amoptionalkey 9
+#define Anum_pg_am_amindexnulls 10
+#define Anum_pg_am_amsearchnulls 11
+#define Anum_pg_am_amstorage 12
+#define Anum_pg_am_amclusterable 13
+#define Anum_pg_am_amkeytype 14
+#define Anum_pg_am_aminsert 15
+#define Anum_pg_am_ambeginscan 16
+#define Anum_pg_am_amgettuple 17
+#define Anum_pg_am_amgetbitmap 18
+#define Anum_pg_am_amrescan 19
+#define Anum_pg_am_amendscan 20
+#define Anum_pg_am_ammarkpos 21
+#define Anum_pg_am_amrestrpos 22
+#define Anum_pg_am_ambuild 23
+#define Anum_pg_am_ambulkdelete 24
+#define Anum_pg_am_amvacuumcleanup 25
+#define Anum_pg_am_amcostestimate 26
+#define Anum_pg_am_amoptions 27
/* ----------------
* initial contents of pg_am
* ----------------
*/
-DATA(insert OID = 403 ( btree 5 1 t t t t t t t f t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate btoptions ));
+DATA(insert OID = 403 ( btree 5 1 t f t t t t t t f t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate btoptions ));
DESCR("b-tree index access method");
#define BTREE_AM_OID 403
-DATA(insert OID = 405 ( hash 1 1 f t f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions ));
+DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions ));
DESCR("hash index access method");
#define HASH_AM_OID 405
-DATA(insert OID = 783 ( gist 0 7 f f f t t t t t t 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions ));
+DATA(insert OID = 783 ( gist 0 7 f f f f t t t t t t 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions ));
DESCR("GiST index access method");
#define GIST_AM_OID 783
-DATA(insert OID = 2742 ( gin 0 5 f f f t t f f t f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ginoptions ));
+DATA(insert OID = 2742 ( gin 0 5 f f f f t t f f t f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ginoptions ));
DESCR("GIN index access method");
#define GIN_AM_OID 2742
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index a9e70a2d6a7..951f9cd6f20 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -5,7 +5,9 @@
* along with the relation's initial contents.
*
* The amop table identifies the operators associated with each index operator
- * family and operator class (classes are subsets of families).
+ * family and operator class (classes are subsets of families). An associated
+ * operator can be either a search operator or an ordering operator, as
+ * identified by amoppurpose.
*
* The primary key for this table is . amoplefttype and amoprighttype are just copies of the
@@ -16,11 +18,13 @@
* operators within a family are supposed to be compatible, in a way that is
* defined by each individual index AM.
*
- * We also keep a unique index on , so that we can use a
- * syscache to quickly answer questions of the form "is this operator in this
- * opfamily, and if so what are its semantics with respect to the family?"
- * This implies that the same operator cannot be listed for multiple strategy
- * numbers within a single opfamily.
+ * We also keep a unique index on , so that
+ * we can use a syscache to quickly answer questions of the form "is this
+ * operator in this opfamily, and if so what are its semantics with respect to
+ * the family?" This implies that the same operator cannot be listed for
+ * multiple strategy numbers within a single opfamily, with the exception that
+ * it's possible to list it for both search and ordering purposes (with
+ * different strategy numbers for the two purposes).
*
* amopmethod is a copy of the owning opfamily's opfmethod field. This is an
* intentional denormalization of the catalogs to buy lookup speed.
@@ -55,10 +59,16 @@ CATALOG(pg_amop,2602)
Oid amoplefttype; /* operator's left input data type */
Oid amoprighttype; /* operator's right input data type */
int2 amopstrategy; /* operator strategy number */
+ char amoppurpose; /* is operator for 's'earch or 'o'rdering? */
Oid amopopr; /* the operator's pg_operator OID */
Oid amopmethod; /* the index access method this entry is for */
+ Oid amopsortfamily; /* ordering opfamily OID, or 0 if search op */
} FormData_pg_amop;
+/* allowed values of amoppurpose: */
+#define AMOP_SEARCH 's' /* operator is for search */
+#define AMOP_ORDER 'o' /* operator is for ordering */
+
/* ----------------
* Form_pg_amop corresponds to a pointer to a tuple with
* the format of pg_amop relation.
@@ -70,13 +80,15 @@ typedef FormData_pg_amop *Form_pg_amop;
* compiler constants for pg_amop
* ----------------
*/
-#define Natts_pg_amop 6
+#define Natts_pg_amop 8
#define Anum_pg_amop_amopfamily 1
#define Anum_pg_amop_amoplefttype 2
#define Anum_pg_amop_amoprighttype 3
#define Anum_pg_amop_amopstrategy 4
-#define Anum_pg_amop_amopopr 5
-#define Anum_pg_amop_amopmethod 6
+#define Anum_pg_amop_amoppurpose 5
+#define Anum_pg_amop_amopopr 6
+#define Anum_pg_amop_amopmethod 7
+#define Anum_pg_amop_amopsortfamily 8
/* ----------------
* initial contents of pg_amop
@@ -88,612 +100,612 @@ typedef FormData_pg_amop *Form_pg_amop;
*/
/* default operators int2 */
-DATA(insert ( 1976 21 21 1 95 403 ));
-DATA(insert ( 1976 21 21 2 522 403 ));
-DATA(insert ( 1976 21 21 3 94 403 ));
-DATA(insert ( 1976 21 21 4 524 403 ));
-DATA(insert ( 1976 21 21 5 520 403 ));
+DATA(insert ( 1976 21 21 1 s 95 403 0 ));
+DATA(insert ( 1976 21 21 2 s 522 403 0 ));
+DATA(insert ( 1976 21 21 3 s 94 403 0 ));
+DATA(insert ( 1976 21 21 4 s 524 403 0 ));
+DATA(insert ( 1976 21 21 5 s 520 403 0 ));
/* crosstype operators int24 */
-DATA(insert ( 1976 21 23 1 534 403 ));
-DATA(insert ( 1976 21 23 2 540 403 ));
-DATA(insert ( 1976 21 23 3 532 403 ));
-DATA(insert ( 1976 21 23 4 542 403 ));
-DATA(insert ( 1976 21 23 5 536 403 ));
+DATA(insert ( 1976 21 23 1 s 534 403 0 ));
+DATA(insert ( 1976 21 23 2 s 540 403 0 ));
+DATA(insert ( 1976 21 23 3 s 532 403 0 ));
+DATA(insert ( 1976 21 23 4 s 542 403 0 ));
+DATA(insert ( 1976 21 23 5 s 536 403 0 ));
/* crosstype operators int28 */
-DATA(insert ( 1976 21 20 1 1864 403 ));
-DATA(insert ( 1976 21 20 2 1866 403 ));
-DATA(insert ( 1976 21 20 3 1862 403 ));
-DATA(insert ( 1976 21 20 4 1867 403 ));
-DATA(insert ( 1976 21 20 5 1865 403 ));
+DATA(insert ( 1976 21 20 1 s 1864 403 0 ));
+DATA(insert ( 1976 21 20 2 s 1866 403 0 ));
+DATA(insert ( 1976 21 20 3 s 1862 403 0 ));
+DATA(insert ( 1976 21 20 4 s 1867 403 0 ));
+DATA(insert ( 1976 21 20 5 s 1865 403 0 ));
/* default operators int4 */
-DATA(insert ( 1976 23 23 1 97 403 ));
-DATA(insert ( 1976 23 23 2 523 403 ));
-DATA(insert ( 1976 23 23 3 96 403 ));
-DATA(insert ( 1976 23 23 4 525 403 ));
-DATA(insert ( 1976 23 23 5 521 403 ));
+DATA(insert ( 1976 23 23 1 s 97 403 0 ));
+DATA(insert ( 1976 23 23 2 s 523 403 0 ));
+DATA(insert ( 1976 23 23 3 s 96 403 0 ));
+DATA(insert ( 1976 23 23 4 s 525 403 0 ));
+DATA(insert ( 1976 23 23 5 s 521 403 0 ));
/* crosstype operators int42 */
-DATA(insert ( 1976 23 21 1 535 403 ));
-DATA(insert ( 1976 23 21 2 541 403 ));
-DATA(insert ( 1976 23 21 3 533 403 ));
-DATA(insert ( 1976 23 21 4 543 403 ));
-DATA(insert ( 1976 23 21 5 537 403 ));
+DATA(insert ( 1976 23 21 1 s 535 403 0 ));
+DATA(insert ( 1976 23 21 2 s 541 403 0 ));
+DATA(insert ( 1976 23 21 3 s 533 403 0 ));
+DATA(insert ( 1976 23 21 4 s 543 403 0 ));
+DATA(insert ( 1976 23 21 5 s 537 403 0 ));
/* crosstype operators int48 */
-DATA(insert ( 1976 23 20 1 37 403 ));
-DATA(insert ( 1976 23 20 2 80 403 ));
-DATA(insert ( 1976 23 20 3 15 403 ));
-DATA(insert ( 1976 23 20 4 82 403 ));
-DATA(insert ( 1976 23 20 5 76 403 ));
+DATA(insert ( 1976 23 20 1 s 37 403 0 ));
+DATA(insert ( 1976 23 20 2 s 80 403 0 ));
+DATA(insert ( 1976 23 20 3 s 15 403 0 ));
+DATA(insert ( 1976 23 20 4 s 82 403 0 ));
+DATA(insert ( 1976 23 20 5 s 76 403 0 ));
/* default operators int8 */
-DATA(insert ( 1976 20 20 1 412 403 ));
-DATA(insert ( 1976 20 20 2 414 403 ));
-DATA(insert ( 1976 20 20 3 410 403 ));
-DATA(insert ( 1976 20 20 4 415 403 ));
-DATA(insert ( 1976 20 20 5 413 403 ));
+DATA(insert ( 1976 20 20 1 s 412 403 0 ));
+DATA(insert ( 1976 20 20 2 s 414 403 0 ));
+DATA(insert ( 1976 20 20 3 s 410 403 0 ));
+DATA(insert ( 1976 20 20 4 s 415 403 0 ));
+DATA(insert ( 1976 20 20 5 s 413 403 0 ));
/* crosstype operators int82 */
-DATA(insert ( 1976 20 21 1 1870 403 ));
-DATA(insert ( 1976 20 21 2 1872 403 ));
-DATA(insert ( 1976 20 21 3 1868 403 ));
-DATA(insert ( 1976 20 21 4 1873 403 ));
-DATA(insert ( 1976 20 21 5 1871 403 ));
+DATA(insert ( 1976 20 21 1 s 1870 403 0 ));
+DATA(insert ( 1976 20 21 2 s 1872 403 0 ));
+DATA(insert ( 1976 20 21 3 s 1868 403 0 ));
+DATA(insert ( 1976 20 21 4 s 1873 403 0 ));
+DATA(insert ( 1976 20 21 5 s 1871 403 0 ));
/* crosstype operators int84 */
-DATA(insert ( 1976 20 23 1 418 403 ));
-DATA(insert ( 1976 20 23 2 420 403 ));
-DATA(insert ( 1976 20 23 3 416 403 ));
-DATA(insert ( 1976 20 23 4 430 403 ));
-DATA(insert ( 1976 20 23 5 419 403 ));
+DATA(insert ( 1976 20 23 1 s 418 403 0 ));
+DATA(insert ( 1976 20 23 2 s 420 403 0 ));
+DATA(insert ( 1976 20 23 3 s 416 403 0 ));
+DATA(insert ( 1976 20 23 4 s 430 403 0 ));
+DATA(insert ( 1976 20 23 5 s 419 403 0 ));
/*
* btree oid_ops
*/
-DATA(insert ( 1989 26 26 1 609 403 ));
-DATA(insert ( 1989 26 26 2 611 403 ));
-DATA(insert ( 1989 26 26 3 607 403 ));
-DATA(insert ( 1989 26 26 4 612 403 ));
-DATA(insert ( 1989 26 26 5 610 403 ));
+DATA(insert ( 1989 26 26 1 s 609 403 0 ));
+DATA(insert ( 1989 26 26 2 s 611 403 0 ));
+DATA(insert ( 1989 26 26 3 s 607 403 0 ));
+DATA(insert ( 1989 26 26 4 s 612 403 0 ));
+DATA(insert ( 1989 26 26 5 s 610 403 0 ));
/*
* btree tid_ops
*/
-DATA(insert ( 2789 27 27 1 2799 403 ));
-DATA(insert ( 2789 27 27 2 2801 403 ));
-DATA(insert ( 2789 27 27 3 387 403 ));
-DATA(insert ( 2789 27 27 4 2802 403 ));
-DATA(insert ( 2789 27 27 5 2800 403 ));
+DATA(insert ( 2789 27 27 1 s 2799 403 0 ));
+DATA(insert ( 2789 27 27 2 s 2801 403 0 ));
+DATA(insert ( 2789 27 27 3 s 387 403 0 ));
+DATA(insert ( 2789 27 27 4 s 2802 403 0 ));
+DATA(insert ( 2789 27 27 5 s 2800 403 0 ));
/*
* btree oidvector_ops
*/
-DATA(insert ( 1991 30 30 1 645 403 ));
-DATA(insert ( 1991 30 30 2 647 403 ));
-DATA(insert ( 1991 30 30 3 649 403 ));
-DATA(insert ( 1991 30 30 4 648 403 ));
-DATA(insert ( 1991 30 30 5 646 403 ));
+DATA(insert ( 1991 30 30 1 s 645 403 0 ));
+DATA(insert ( 1991 30 30 2 s 647 403 0 ));
+DATA(insert ( 1991 30 30 3 s 649 403 0 ));
+DATA(insert ( 1991 30 30 4 s 648 403 0 ));
+DATA(insert ( 1991 30 30 5 s 646 403 0 ));
/*
* btree float_ops
*/
/* default operators float4 */
-DATA(insert ( 1970 700 700 1 622 403 ));
-DATA(insert ( 1970 700 700 2 624 403 ));
-DATA(insert ( 1970 700 700 3 620 403 ));
-DATA(insert ( 1970 700 700 4 625 403 ));
-DATA(insert ( 1970 700 700 5 623 403 ));
+DATA(insert ( 1970 700 700 1 s 622 403 0 ));
+DATA(insert ( 1970 700 700 2 s 624 403 0 ));
+DATA(insert ( 1970 700 700 3 s 620 403 0 ));
+DATA(insert ( 1970 700 700 4 s 625 403 0 ));
+DATA(insert ( 1970 700 700 5 s 623 403 0 ));
/* crosstype operators float48 */
-DATA(insert ( 1970 700 701 1 1122 403 ));
-DATA(insert ( 1970 700 701 2 1124 403 ));
-DATA(insert ( 1970 700 701 3 1120 403 ));
-DATA(insert ( 1970 700 701 4 1125 403 ));
-DATA(insert ( 1970 700 701 5 1123 403 ));
+DATA(insert ( 1970 700 701 1 s 1122 403 0 ));
+DATA(insert ( 1970 700 701 2 s 1124 403 0 ));
+DATA(insert ( 1970 700 701 3 s 1120 403 0 ));
+DATA(insert ( 1970 700 701 4 s 1125 403 0 ));
+DATA(insert ( 1970 700 701 5 s 1123 403 0 ));
/* default operators float8 */
-DATA(insert ( 1970 701 701 1 672 403 ));
-DATA(insert ( 1970 701 701 2 673 403 ));
-DATA(insert ( 1970 701 701 3 670 403 ));
-DATA(insert ( 1970 701 701 4 675 403 ));
-DATA(insert ( 1970 701 701 5 674 403 ));
+DATA(insert ( 1970 701 701 1 s 672 403 0 ));
+DATA(insert ( 1970 701 701 2 s 673 403 0 ));
+DATA(insert ( 1970 701 701 3 s 670 403 0 ));
+DATA(insert ( 1970 701 701 4 s 675 403 0 ));
+DATA(insert ( 1970 701 701 5 s 674 403 0 ));
/* crosstype operators float84 */
-DATA(insert ( 1970 701 700 1 1132 403 ));
-DATA(insert ( 1970 701 700 2 1134 403 ));
-DATA(insert ( 1970 701 700 3 1130 403 ));
-DATA(insert ( 1970 701 700 4 1135 403 ));
-DATA(insert ( 1970 701 700 5 1133 403 ));
+DATA(insert ( 1970 701 700 1 s 1132 403 0 ));
+DATA(insert ( 1970 701 700 2 s 1134 403 0 ));
+DATA(insert ( 1970 701 700 3 s 1130 403 0 ));
+DATA(insert ( 1970 701 700 4 s 1135 403 0 ));
+DATA(insert ( 1970 701 700 5 s 1133 403 0 ));
/*
* btree char_ops
*/
-DATA(insert ( 429 18 18 1 631 403 ));
-DATA(insert ( 429 18 18 2 632 403 ));
-DATA(insert ( 429 18 18 3 92 403 ));
-DATA(insert ( 429 18 18 4 634 403 ));
-DATA(insert ( 429 18 18 5 633 403 ));
+DATA(insert ( 429 18 18 1 s 631 403 0 ));
+DATA(insert ( 429 18 18 2 s 632 403 0 ));
+DATA(insert ( 429 18 18 3 s 92 403 0 ));
+DATA(insert ( 429 18 18 4 s 634 403 0 ));
+DATA(insert ( 429 18 18 5 s 633 403 0 ));
/*
* btree name_ops
*/
-DATA(insert ( 1986 19 19 1 660 403 ));
-DATA(insert ( 1986 19 19 2 661 403 ));
-DATA(insert ( 1986 19 19 3 93 403 ));
-DATA(insert ( 1986 19 19 4 663 403 ));
-DATA(insert ( 1986 19 19 5 662 403 ));
+DATA(insert ( 1986 19 19 1 s 660 403 0 ));
+DATA(insert ( 1986 19 19 2 s 661 403 0 ));
+DATA(insert ( 1986 19 19 3 s 93 403 0 ));
+DATA(insert ( 1986 19 19 4 s 663 403 0 ));
+DATA(insert ( 1986 19 19 5 s 662 403 0 ));
/*
* btree text_ops
*/
-DATA(insert ( 1994 25 25 1 664 403 ));
-DATA(insert ( 1994 25 25 2 665 403 ));
-DATA(insert ( 1994 25 25 3 98 403 ));
-DATA(insert ( 1994 25 25 4 667 403 ));
-DATA(insert ( 1994 25 25 5 666 403 ));
+DATA(insert ( 1994 25 25 1 s 664 403 0 ));
+DATA(insert ( 1994 25 25 2 s 665 403 0 ));
+DATA(insert ( 1994 25 25 3 s 98 403 0 ));
+DATA(insert ( 1994 25 25 4 s 667 403 0 ));
+DATA(insert ( 1994 25 25 5 s 666 403 0 ));
/*
* btree bpchar_ops
*/
-DATA(insert ( 426 1042 1042 1 1058 403 ));
-DATA(insert ( 426 1042 1042 2 1059 403 ));
-DATA(insert ( 426 1042 1042 3 1054 403 ));
-DATA(insert ( 426 1042 1042 4 1061 403 ));
-DATA(insert ( 426 1042 1042 5 1060 403 ));
+DATA(insert ( 426 1042 1042 1 s 1058 403 0 ));
+DATA(insert ( 426 1042 1042 2 s 1059 403 0 ));
+DATA(insert ( 426 1042 1042 3 s 1054 403 0 ));
+DATA(insert ( 426 1042 1042 4 s 1061 403 0 ));
+DATA(insert ( 426 1042 1042 5 s 1060 403 0 ));
/*
* btree bytea_ops
*/
-DATA(insert ( 428 17 17 1 1957 403 ));
-DATA(insert ( 428 17 17 2 1958 403 ));
-DATA(insert ( 428 17 17 3 1955 403 ));
-DATA(insert ( 428 17 17 4 1960 403 ));
-DATA(insert ( 428 17 17 5 1959 403 ));
+DATA(insert ( 428 17 17 1 s 1957 403 0 ));
+DATA(insert ( 428 17 17 2 s 1958 403 0 ));
+DATA(insert ( 428 17 17 3 s 1955 403 0 ));
+DATA(insert ( 428 17 17 4 s 1960 403 0 ));
+DATA(insert ( 428 17 17 5 s 1959 403 0 ));
/*
* btree abstime_ops
*/
-DATA(insert ( 421 702 702 1 562 403 ));
-DATA(insert ( 421 702 702 2 564 403 ));
-DATA(insert ( 421 702 702 3 560 403 ));
-DATA(insert ( 421 702 702 4 565 403 ));
-DATA(insert ( 421 702 702 5 563 403 ));
+DATA(insert ( 421 702 702 1 s 562 403 0 ));
+DATA(insert ( 421 702 702 2 s 564 403 0 ));
+DATA(insert ( 421 702 702 3 s 560 403 0 ));
+DATA(insert ( 421 702 702 4 s 565 403 0 ));
+DATA(insert ( 421 702 702 5 s 563 403 0 ));
/*
* btree datetime_ops
*/
/* default operators date */
-DATA(insert ( 434 1082 1082 1 1095 403 ));
-DATA(insert ( 434 1082 1082 2 1096 403 ));
-DATA(insert ( 434 1082 1082 3 1093 403 ));
-DATA(insert ( 434 1082 1082 4 1098 403 ));
-DATA(insert ( 434 1082 1082 5 1097 403 ));
+DATA(insert ( 434 1082 1082 1 s 1095 403 0 ));
+DATA(insert ( 434 1082 1082 2 s 1096 403 0 ));
+DATA(insert ( 434 1082 1082 3 s 1093 403 0 ));
+DATA(insert ( 434 1082 1082 4 s 1098 403 0 ));
+DATA(insert ( 434 1082 1082 5 s 1097 403 0 ));
/* crosstype operators vs timestamp */
-DATA(insert ( 434 1082 1114 1 2345 403 ));
-DATA(insert ( 434 1082 1114 2 2346 403 ));
-DATA(insert ( 434 1082 1114 3 2347 403 ));
-DATA(insert ( 434 1082 1114 4 2348 403 ));
-DATA(insert ( 434 1082 1114 5 2349 403 ));
+DATA(insert ( 434 1082 1114 1 s 2345 403 0 ));
+DATA(insert ( 434 1082 1114 2 s 2346 403 0 ));
+DATA(insert ( 434 1082 1114 3 s 2347 403 0 ));
+DATA(insert ( 434 1082 1114 4 s 2348 403 0 ));
+DATA(insert ( 434 1082 1114 5 s 2349 403 0 ));
/* crosstype operators vs timestamptz */
-DATA(insert ( 434 1082 1184 1 2358 403 ));
-DATA(insert ( 434 1082 1184 2 2359 403 ));
-DATA(insert ( 434 1082 1184 3 2360 403 ));
-DATA(insert ( 434 1082 1184 4 2361 403 ));
-DATA(insert ( 434 1082 1184 5 2362 403 ));
+DATA(insert ( 434 1082 1184 1 s 2358 403 0 ));
+DATA(insert ( 434 1082 1184 2 s 2359 403 0 ));
+DATA(insert ( 434 1082 1184 3 s 2360 403 0 ));
+DATA(insert ( 434 1082 1184 4 s 2361 403 0 ));
+DATA(insert ( 434 1082 1184 5 s 2362 403 0 ));
/* default operators timestamp */
-DATA(insert ( 434 1114 1114 1 2062 403 ));
-DATA(insert ( 434 1114 1114 2 2063 403 ));
-DATA(insert ( 434 1114 1114 3 2060 403 ));
-DATA(insert ( 434 1114 1114 4 2065 403 ));
-DATA(insert ( 434 1114 1114 5 2064 403 ));
+DATA(insert ( 434 1114 1114 1 s 2062 403 0 ));
+DATA(insert ( 434 1114 1114 2 s 2063 403 0 ));
+DATA(insert ( 434 1114 1114 3 s 2060 403 0 ));
+DATA(insert ( 434 1114 1114 4 s 2065 403 0 ));
+DATA(insert ( 434 1114 1114 5 s 2064 403 0 ));
/* crosstype operators vs date */
-DATA(insert ( 434 1114 1082 1 2371 403 ));
-DATA(insert ( 434 1114 1082 2 2372 403 ));
-DATA(insert ( 434 1114 1082 3 2373 403 ));
-DATA(insert ( 434 1114 1082 4 2374 403 ));
-DATA(insert ( 434 1114 1082 5 2375 403 ));
+DATA(insert ( 434 1114 1082 1 s 2371 403 0 ));
+DATA(insert ( 434 1114 1082 2 s 2372 403 0 ));
+DATA(insert ( 434 1114 1082 3 s 2373 403 0 ));
+DATA(insert ( 434 1114 1082 4 s 2374 403 0 ));
+DATA(insert ( 434 1114 1082 5 s 2375 403 0 ));
/* crosstype operators vs timestamptz */
-DATA(insert ( 434 1114 1184 1 2534 403 ));
-DATA(insert ( 434 1114 1184 2 2535 403 ));
-DATA(insert ( 434 1114 1184 3 2536 403 ));
-DATA(insert ( 434 1114 1184 4 2537 403 ));
-DATA(insert ( 434 1114 1184 5 2538 403 ));
+DATA(insert ( 434 1114 1184 1 s 2534 403 0 ));
+DATA(insert ( 434 1114 1184 2 s 2535 403 0 ));
+DATA(insert ( 434 1114 1184 3 s 2536 403 0 ));
+DATA(insert ( 434 1114 1184 4 s 2537 403 0 ));
+DATA(insert ( 434 1114 1184 5 s 2538 403 0 ));
/* default operators timestamptz */
-DATA(insert ( 434 1184 1184 1 1322 403 ));
-DATA(insert ( 434 1184 1184 2 1323 403 ));
-DATA(insert ( 434 1184 1184 3 1320 403 ));
-DATA(insert ( 434 1184 1184 4 1325 403 ));
-DATA(insert ( 434 1184 1184 5 1324 403 ));
+DATA(insert ( 434 1184 1184 1 s 1322 403 0 ));
+DATA(insert ( 434 1184 1184 2 s 1323 403 0 ));
+DATA(insert ( 434 1184 1184 3 s 1320 403 0 ));
+DATA(insert ( 434 1184 1184 4 s 1325 403 0 ));
+DATA(insert ( 434 1184 1184 5 s 1324 403 0 ));
/* crosstype operators vs date */
-DATA(insert ( 434 1184 1082 1 2384 403 ));
-DATA(insert ( 434 1184 1082 2 2385 403 ));
-DATA(insert ( 434 1184 1082 3 2386 403 ));
-DATA(insert ( 434 1184 1082 4 2387 403 ));
-DATA(insert ( 434 1184 1082 5 2388 403 ));
+DATA(insert ( 434 1184 1082 1 s 2384 403 0 ));
+DATA(insert ( 434 1184 1082 2 s 2385 403 0 ));
+DATA(insert ( 434 1184 1082 3 s 2386 403 0 ));
+DATA(insert ( 434 1184 1082 4 s 2387 403 0 ));
+DATA(insert ( 434 1184 1082 5 s 2388 403 0 ));
/* crosstype operators vs timestamp */
-DATA(insert ( 434 1184 1114 1 2540 403 ));
-DATA(insert ( 434 1184 1114 2 2541 403 ));
-DATA(insert ( 434 1184 1114 3 2542 403 ));
-DATA(insert ( 434 1184 1114 4 2543 403 ));
-DATA(insert ( 434 1184 1114 5 2544 403 ));
+DATA(insert ( 434 1184 1114 1 s 2540 403 0 ));
+DATA(insert ( 434 1184 1114 2 s 2541 403 0 ));
+DATA(insert ( 434 1184 1114 3 s 2542 403 0 ));
+DATA(insert ( 434 1184 1114 4 s 2543 403 0 ));
+DATA(insert ( 434 1184 1114 5 s 2544 403 0 ));
/*
* btree time_ops
*/
-DATA(insert ( 1996 1083 1083 1 1110 403 ));
-DATA(insert ( 1996 1083 1083 2 1111 403 ));
-DATA(insert ( 1996 1083 1083 3 1108 403 ));
-DATA(insert ( 1996 1083 1083 4 1113 403 ));
-DATA(insert ( 1996 1083 1083 5 1112 403 ));
+DATA(insert ( 1996 1083 1083 1 s 1110 403 0 ));
+DATA(insert ( 1996 1083 1083 2 s 1111 403 0 ));
+DATA(insert ( 1996 1083 1083 3 s 1108 403 0 ));
+DATA(insert ( 1996 1083 1083 4 s 1113 403 0 ));
+DATA(insert ( 1996 1083 1083 5 s 1112 403 0 ));
/*
* btree timetz_ops
*/
-DATA(insert ( 2000 1266 1266 1 1552 403 ));
-DATA(insert ( 2000 1266 1266 2 1553 403 ));
-DATA(insert ( 2000 1266 1266 3 1550 403 ));
-DATA(insert ( 2000 1266 1266 4 1555 403 ));
-DATA(insert ( 2000 1266 1266 5 1554 403 ));
+DATA(insert ( 2000 1266 1266 1 s 1552 403 0 ));
+DATA(insert ( 2000 1266 1266 2 s 1553 403 0 ));
+DATA(insert ( 2000 1266 1266 3 s 1550 403 0 ));
+DATA(insert ( 2000 1266 1266 4 s 1555 403 0 ));
+DATA(insert ( 2000 1266 1266 5 s 1554 403 0 ));
/*
* btree interval_ops
*/
-DATA(insert ( 1982 1186 1186 1 1332 403 ));
-DATA(insert ( 1982 1186 1186 2 1333 403 ));
-DATA(insert ( 1982 1186 1186 3 1330 403 ));
-DATA(insert ( 1982 1186 1186 4 1335 403 ));
-DATA(insert ( 1982 1186 1186 5 1334 403 ));
+DATA(insert ( 1982 1186 1186 1 s 1332 403 0 ));
+DATA(insert ( 1982 1186 1186 2 s 1333 403 0 ));
+DATA(insert ( 1982 1186 1186 3 s 1330 403 0 ));
+DATA(insert ( 1982 1186 1186 4 s 1335 403 0 ));
+DATA(insert ( 1982 1186 1186 5 s 1334 403 0 ));
/*
* btree macaddr
*/
-DATA(insert ( 1984 829 829 1 1222 403 ));
-DATA(insert ( 1984 829 829 2 1223 403 ));
-DATA(insert ( 1984 829 829 3 1220 403 ));
-DATA(insert ( 1984 829 829 4 1225 403 ));
-DATA(insert ( 1984 829 829 5 1224 403 ));
+DATA(insert ( 1984 829 829 1 s 1222 403 0 ));
+DATA(insert ( 1984 829 829 2 s 1223 403 0 ));
+DATA(insert ( 1984 829 829 3 s 1220 403 0 ));
+DATA(insert ( 1984 829 829 4 s 1225 403 0 ));
+DATA(insert ( 1984 829 829 5 s 1224 403 0 ));
/*
* btree network
*/
-DATA(insert ( 1974 869 869 1 1203 403 ));
-DATA(insert ( 1974 869 869 2 1204 403 ));
-DATA(insert ( 1974 869 869 3 1201 403 ));
-DATA(insert ( 1974 869 869 4 1206 403 ));
-DATA(insert ( 1974 869 869 5 1205 403 ));
+DATA(insert ( 1974 869 869 1 s 1203 403 0 ));
+DATA(insert ( 1974 869 869 2 s 1204 403 0 ));
+DATA(insert ( 1974 869 869 3 s 1201 403 0 ));
+DATA(insert ( 1974 869 869 4 s 1206 403 0 ));
+DATA(insert ( 1974 869 869 5 s 1205 403 0 ));
/*
* btree numeric
*/
-DATA(insert ( 1988 1700 1700 1 1754 403 ));
-DATA(insert ( 1988 1700 1700 2 1755 403 ));
-DATA(insert ( 1988 1700 1700 3 1752 403 ));
-DATA(insert ( 1988 1700 1700 4 1757 403 ));
-DATA(insert ( 1988 1700 1700 5 1756 403 ));
+DATA(insert ( 1988 1700 1700 1 s 1754 403 0 ));
+DATA(insert ( 1988 1700 1700 2 s 1755 403 0 ));
+DATA(insert ( 1988 1700 1700 3 s 1752 403 0 ));
+DATA(insert ( 1988 1700 1700 4 s 1757 403 0 ));
+DATA(insert ( 1988 1700 1700 5 s 1756 403 0 ));
/*
* btree bool
*/
-DATA(insert ( 424 16 16 1 58 403 ));
-DATA(insert ( 424 16 16 2 1694 403 ));
-DATA(insert ( 424 16 16 3 91 403 ));
-DATA(insert ( 424 16 16 4 1695 403 ));
-DATA(insert ( 424 16 16 5 59 403 ));
+DATA(insert ( 424 16 16 1 s 58 403 0 ));
+DATA(insert ( 424 16 16 2 s 1694 403 0 ));
+DATA(insert ( 424 16 16 3 s 91 403 0 ));
+DATA(insert ( 424 16 16 4 s 1695 403 0 ));
+DATA(insert ( 424 16 16 5 s 59 403 0 ));
/*
* btree bit
*/
-DATA(insert ( 423 1560 1560 1 1786 403 ));
-DATA(insert ( 423 1560 1560 2 1788 403 ));
-DATA(insert ( 423 1560 1560 3 1784 403 ));
-DATA(insert ( 423 1560 1560 4 1789 403 ));
-DATA(insert ( 423 1560 1560 5 1787 403 ));
+DATA(insert ( 423 1560 1560 1 s 1786 403 0 ));
+DATA(insert ( 423 1560 1560 2 s 1788 403 0 ));
+DATA(insert ( 423 1560 1560 3 s 1784 403 0 ));
+DATA(insert ( 423 1560 1560 4 s 1789 403 0 ));
+DATA(insert ( 423 1560 1560 5 s 1787 403 0 ));
/*
* btree varbit
*/
-DATA(insert ( 2002 1562 1562 1 1806 403 ));
-DATA(insert ( 2002 1562 1562 2 1808 403 ));
-DATA(insert ( 2002 1562 1562 3 1804 403 ));
-DATA(insert ( 2002 1562 1562 4 1809 403 ));
-DATA(insert ( 2002 1562 1562 5 1807 403 ));
+DATA(insert ( 2002 1562 1562 1 s 1806 403 0 ));
+DATA(insert ( 2002 1562 1562 2 s 1808 403 0 ));
+DATA(insert ( 2002 1562 1562 3 s 1804 403 0 ));
+DATA(insert ( 2002 1562 1562 4 s 1809 403 0 ));
+DATA(insert ( 2002 1562 1562 5 s 1807 403 0 ));
/*
* btree text pattern
*/
-DATA(insert ( 2095 25 25 1 2314 403 ));
-DATA(insert ( 2095 25 25 2 2315 403 ));
-DATA(insert ( 2095 25 25 3 98 403 ));
-DATA(insert ( 2095 25 25 4 2317 403 ));
-DATA(insert ( 2095 25 25 5 2318 403 ));
+DATA(insert ( 2095 25 25 1 s 2314 403 0 ));
+DATA(insert ( 2095 25 25 2 s 2315 403 0 ));
+DATA(insert ( 2095 25 25 3 s 98 403 0 ));
+DATA(insert ( 2095 25 25 4 s 2317 403 0 ));
+DATA(insert ( 2095 25 25 5 s 2318 403 0 ));
/*
* btree bpchar pattern
*/
-DATA(insert ( 2097 1042 1042 1 2326 403 ));
-DATA(insert ( 2097 1042 1042 2 2327 403 ));
-DATA(insert ( 2097 1042 1042 3 1054 403 ));
-DATA(insert ( 2097 1042 1042 4 2329 403 ));
-DATA(insert ( 2097 1042 1042 5 2330 403 ));
+DATA(insert ( 2097 1042 1042 1 s 2326 403 0 ));
+DATA(insert ( 2097 1042 1042 2 s 2327 403 0 ));
+DATA(insert ( 2097 1042 1042 3 s 1054 403 0 ));
+DATA(insert ( 2097 1042 1042 4 s 2329 403 0 ));
+DATA(insert ( 2097 1042 1042 5 s 2330 403 0 ));
/*
* btree money_ops
*/
-DATA(insert ( 2099 790 790 1 902 403 ));
-DATA(insert ( 2099 790 790 2 904 403 ));
-DATA(insert ( 2099 790 790 3 900 403 ));
-DATA(insert ( 2099 790 790 4 905 403 ));
-DATA(insert ( 2099 790 790 5 903 403 ));
+DATA(insert ( 2099 790 790 1 s 902 403 0 ));
+DATA(insert ( 2099 790 790 2 s 904 403 0 ));
+DATA(insert ( 2099 790 790 3 s 900 403 0 ));
+DATA(insert ( 2099 790 790 4 s 905 403 0 ));
+DATA(insert ( 2099 790 790 5 s 903 403 0 ));
/*
* btree reltime_ops
*/
-DATA(insert ( 2233 703 703 1 568 403 ));
-DATA(insert ( 2233 703 703 2 570 403 ));
-DATA(insert ( 2233 703 703 3 566 403 ));
-DATA(insert ( 2233 703 703 4 571 403 ));
-DATA(insert ( 2233 703 703 5 569 403 ));
+DATA(insert ( 2233 703 703 1 s 568 403 0 ));
+DATA(insert ( 2233 703 703 2 s 570 403 0 ));
+DATA(insert ( 2233 703 703 3 s 566 403 0 ));
+DATA(insert ( 2233 703 703 4 s 571 403 0 ));
+DATA(insert ( 2233 703 703 5 s 569 403 0 ));
/*
* btree tinterval_ops
*/
-DATA(insert ( 2234 704 704 1 813 403 ));
-DATA(insert ( 2234 704 704 2 815 403 ));
-DATA(insert ( 2234 704 704 3 811 403 ));
-DATA(insert ( 2234 704 704 4 816 403 ));
-DATA(insert ( 2234 704 704 5 814 403 ));
+DATA(insert ( 2234 704 704 1 s 813 403 0 ));
+DATA(insert ( 2234 704 704 2 s 815 403 0 ));
+DATA(insert ( 2234 704 704 3 s 811 403 0 ));
+DATA(insert ( 2234 704 704 4 s 816 403 0 ));
+DATA(insert ( 2234 704 704 5 s 814 403 0 ));
/*
* btree array_ops
*/
-DATA(insert ( 397 2277 2277 1 1072 403 ));
-DATA(insert ( 397 2277 2277 2 1074 403 ));
-DATA(insert ( 397 2277 2277 3 1070 403 ));
-DATA(insert ( 397 2277 2277 4 1075 403 ));
-DATA(insert ( 397 2277 2277 5 1073 403 ));
+DATA(insert ( 397 2277 2277 1 s 1072 403 0 ));
+DATA(insert ( 397 2277 2277 2 s 1074 403 0 ));
+DATA(insert ( 397 2277 2277 3 s 1070 403 0 ));
+DATA(insert ( 397 2277 2277 4 s 1075 403 0 ));
+DATA(insert ( 397 2277 2277 5 s 1073 403 0 ));
/*
* btree record_ops
*/
-DATA(insert ( 2994 2249 2249 1 2990 403 ));
-DATA(insert ( 2994 2249 2249 2 2992 403 ));
-DATA(insert ( 2994 2249 2249 3 2988 403 ));
-DATA(insert ( 2994 2249 2249 4 2993 403 ));
-DATA(insert ( 2994 2249 2249 5 2991 403 ));
+DATA(insert ( 2994 2249 2249 1 s 2990 403 0 ));
+DATA(insert ( 2994 2249 2249 2 s 2992 403 0 ));
+DATA(insert ( 2994 2249 2249 3 s 2988 403 0 ));
+DATA(insert ( 2994 2249 2249 4 s 2993 403 0 ));
+DATA(insert ( 2994 2249 2249 5 s 2991 403 0 ));
/*
* btree uuid_ops
*/
-DATA(insert ( 2968 2950 2950 1 2974 403 ));
-DATA(insert ( 2968 2950 2950 2 2976 403 ));
-DATA(insert ( 2968 2950 2950 3 2972 403 ));
-DATA(insert ( 2968 2950 2950 4 2977 403 ));
-DATA(insert ( 2968 2950 2950 5 2975 403 ));
+DATA(insert ( 2968 2950 2950 1 s 2974 403 0 ));
+DATA(insert ( 2968 2950 2950 2 s 2976 403 0 ));
+DATA(insert ( 2968 2950 2950 3 s 2972 403 0 ));
+DATA(insert ( 2968 2950 2950 4 s 2977 403 0 ));
+DATA(insert ( 2968 2950 2950 5 s 2975 403 0 ));
/*
* hash index _ops
*/
/* bpchar_ops */
-DATA(insert ( 427 1042 1042 1 1054 405 ));
+DATA(insert ( 427 1042 1042 1 s 1054 405 0 ));
/* char_ops */
-DATA(insert ( 431 18 18 1 92 405 ));
+DATA(insert ( 431 18 18 1 s 92 405 0 ));
/* date_ops */
-DATA(insert ( 435 1082 1082 1 1093 405 ));
+DATA(insert ( 435 1082 1082 1 s 1093 405 0 ));
/* float_ops */
-DATA(insert ( 1971 700 700 1 620 405 ));
-DATA(insert ( 1971 701 701 1 670 405 ));
-DATA(insert ( 1971 700 701 1 1120 405 ));
-DATA(insert ( 1971 701 700 1 1130 405 ));
+DATA(insert ( 1971 700 700 1 s 620 405 0 ));
+DATA(insert ( 1971 701 701 1 s 670 405 0 ));
+DATA(insert ( 1971 700 701 1 s 1120 405 0 ));
+DATA(insert ( 1971 701 700 1 s 1130 405 0 ));
/* network_ops */
-DATA(insert ( 1975 869 869 1 1201 405 ));
+DATA(insert ( 1975 869 869 1 s 1201 405 0 ));
/* integer_ops */
-DATA(insert ( 1977 21 21 1 94 405 ));
-DATA(insert ( 1977 23 23 1 96 405 ));
-DATA(insert ( 1977 20 20 1 410 405 ));
-DATA(insert ( 1977 21 23 1 532 405 ));
-DATA(insert ( 1977 21 20 1 1862 405 ));
-DATA(insert ( 1977 23 21 1 533 405 ));
-DATA(insert ( 1977 23 20 1 15 405 ));
-DATA(insert ( 1977 20 21 1 1868 405 ));
-DATA(insert ( 1977 20 23 1 416 405 ));
+DATA(insert ( 1977 21 21 1 s 94 405 0 ));
+DATA(insert ( 1977 23 23 1 s 96 405 0 ));
+DATA(insert ( 1977 20 20 1 s 410 405 0 ));
+DATA(insert ( 1977 21 23 1 s 532 405 0 ));
+DATA(insert ( 1977 21 20 1 s 1862 405 0 ));
+DATA(insert ( 1977 23 21 1 s 533 405 0 ));
+DATA(insert ( 1977 23 20 1 s 15 405 0 ));
+DATA(insert ( 1977 20 21 1 s 1868 405 0 ));
+DATA(insert ( 1977 20 23 1 s 416 405 0 ));
/* interval_ops */
-DATA(insert ( 1983 1186 1186 1 1330 405 ));
+DATA(insert ( 1983 1186 1186 1 s 1330 405 0 ));
/* macaddr_ops */
-DATA(insert ( 1985 829 829 1 1220 405 ));
+DATA(insert ( 1985 829 829 1 s 1220 405 0 ));
/* name_ops */
-DATA(insert ( 1987 19 19 1 93 405 ));
+DATA(insert ( 1987 19 19 1 s 93 405 0 ));
/* oid_ops */
-DATA(insert ( 1990 26 26 1 607 405 ));
+DATA(insert ( 1990 26 26 1 s 607 405 0 ));
/* oidvector_ops */
-DATA(insert ( 1992 30 30 1 649 405 ));
+DATA(insert ( 1992 30 30 1 s 649 405 0 ));
/* text_ops */
-DATA(insert ( 1995 25 25 1 98 405 ));
+DATA(insert ( 1995 25 25 1 s 98 405 0 ));
/* time_ops */
-DATA(insert ( 1997 1083 1083 1 1108 405 ));
+DATA(insert ( 1997 1083 1083 1 s 1108 405 0 ));
/* timestamptz_ops */
-DATA(insert ( 1999 1184 1184 1 1320 405 ));
+DATA(insert ( 1999 1184 1184 1 s 1320 405 0 ));
/* timetz_ops */
-DATA(insert ( 2001 1266 1266 1 1550 405 ));
+DATA(insert ( 2001 1266 1266 1 s 1550 405 0 ));
/* timestamp_ops */
-DATA(insert ( 2040 1114 1114 1 2060 405 ));
+DATA(insert ( 2040 1114 1114 1 s 2060 405 0 ));
/* bool_ops */
-DATA(insert ( 2222 16 16 1 91 405 ));
+DATA(insert ( 2222 16 16 1 s 91 405 0 ));
/* bytea_ops */
-DATA(insert ( 2223 17 17 1 1955 405 ));
+DATA(insert ( 2223 17 17 1 s 1955 405 0 ));
/* int2vector_ops */
-DATA(insert ( 2224 22 22 1 386 405 ));
+DATA(insert ( 2224 22 22 1 s 386 405 0 ));
/* xid_ops */
-DATA(insert ( 2225 28 28 1 352 405 ));
+DATA(insert ( 2225 28 28 1 s 352 405 0 ));
/* cid_ops */
-DATA(insert ( 2226 29 29 1 385 405 ));
+DATA(insert ( 2226 29 29 1 s 385 405 0 ));
/* abstime_ops */
-DATA(insert ( 2227 702 702 1 560 405 ));
+DATA(insert ( 2227 702 702 1 s 560 405 0 ));
/* reltime_ops */
-DATA(insert ( 2228 703 703 1 566 405 ));
+DATA(insert ( 2228 703 703 1 s 566 405 0 ));
/* text_pattern_ops */
-DATA(insert ( 2229 25 25 1 98 405 ));
+DATA(insert ( 2229 25 25 1 s 98 405 0 ));
/* bpchar_pattern_ops */
-DATA(insert ( 2231 1042 1042 1 1054 405 ));
+DATA(insert ( 2231 1042 1042 1 s 1054 405 0 ));
/* aclitem_ops */
-DATA(insert ( 2235 1033 1033 1 974 405 ));
+DATA(insert ( 2235 1033 1033 1 s 974 405 0 ));
/* uuid_ops */
-DATA(insert ( 2969 2950 2950 1 2972 405 ));
+DATA(insert ( 2969 2950 2950 1 s 2972 405 0 ));
/* numeric_ops */
-DATA(insert ( 1998 1700 1700 1 1752 405 ));
+DATA(insert ( 1998 1700 1700 1 s 1752 405 0 ));
/* array_ops */
-DATA(insert ( 627 2277 2277 1 1070 405 ));
+DATA(insert ( 627 2277 2277 1 s 1070 405 0 ));
/*
* gist box_ops
*/
-DATA(insert ( 2593 603 603 1 493 783 ));
-DATA(insert ( 2593 603 603 2 494 783 ));
-DATA(insert ( 2593 603 603 3 500 783 ));
-DATA(insert ( 2593 603 603 4 495 783 ));
-DATA(insert ( 2593 603 603 5 496 783 ));
-DATA(insert ( 2593 603 603 6 499 783 ));
-DATA(insert ( 2593 603 603 7 498 783 ));
-DATA(insert ( 2593 603 603 8 497 783 ));
-DATA(insert ( 2593 603 603 9 2571 783 ));
-DATA(insert ( 2593 603 603 10 2570 783 ));
-DATA(insert ( 2593 603 603 11 2573 783 ));
-DATA(insert ( 2593 603 603 12 2572 783 ));
-DATA(insert ( 2593 603 603 13 2863 783 ));
-DATA(insert ( 2593 603 603 14 2862 783 ));
+DATA(insert ( 2593 603 603 1 s 493 783 0 ));
+DATA(insert ( 2593 603 603 2 s 494 783 0 ));
+DATA(insert ( 2593 603 603 3 s 500 783 0 ));
+DATA(insert ( 2593 603 603 4 s 495 783 0 ));
+DATA(insert ( 2593 603 603 5 s 496 783 0 ));
+DATA(insert ( 2593 603 603 6 s 499 783 0 ));
+DATA(insert ( 2593 603 603 7 s 498 783 0 ));
+DATA(insert ( 2593 603 603 8 s 497 783 0 ));
+DATA(insert ( 2593 603 603 9 s 2571 783 0 ));
+DATA(insert ( 2593 603 603 10 s 2570 783 0 ));
+DATA(insert ( 2593 603 603 11 s 2573 783 0 ));
+DATA(insert ( 2593 603 603 12 s 2572 783 0 ));
+DATA(insert ( 2593 603 603 13 s 2863 783 0 ));
+DATA(insert ( 2593 603 603 14 s 2862 783 0 ));
/*
* gist point_ops
*/
-DATA(insert ( 1029 600 600 11 506 783 ));
-DATA(insert ( 1029 600 600 1 507 783 ));
-DATA(insert ( 1029 600 600 5 508 783 ));
-DATA(insert ( 1029 600 600 10 509 783 ));
-DATA(insert ( 1029 600 600 6 510 783 ));
-DATA(insert ( 1029 603 600 27 433 783 ));
-DATA(insert ( 1029 600 603 28 511 783 ));
-DATA(insert ( 1029 604 600 47 757 783 ));
-DATA(insert ( 1029 600 604 48 756 783 ));
-DATA(insert ( 1029 718 600 67 759 783 ));
-DATA(insert ( 1029 600 718 68 758 783 ));
+DATA(insert ( 1029 600 600 11 s 506 783 0 ));
+DATA(insert ( 1029 600 600 1 s 507 783 0 ));
+DATA(insert ( 1029 600 600 5 s 508 783 0 ));
+DATA(insert ( 1029 600 600 10 s 509 783 0 ));
+DATA(insert ( 1029 600 600 6 s 510 783 0 ));
+DATA(insert ( 1029 603 600 27 s 433 783 0 ));
+DATA(insert ( 1029 600 603 28 s 511 783 0 ));
+DATA(insert ( 1029 604 600 47 s 757 783 0 ));
+DATA(insert ( 1029 600 604 48 s 756 783 0 ));
+DATA(insert ( 1029 718 600 67 s 759 783 0 ));
+DATA(insert ( 1029 600 718 68 s 758 783 0 ));
/*
* gist poly_ops (supports polygons)
*/
-DATA(insert ( 2594 604 604 1 485 783 ));
-DATA(insert ( 2594 604 604 2 486 783 ));
-DATA(insert ( 2594 604 604 3 492 783 ));
-DATA(insert ( 2594 604 604 4 487 783 ));
-DATA(insert ( 2594 604 604 5 488 783 ));
-DATA(insert ( 2594 604 604 6 491 783 ));
-DATA(insert ( 2594 604 604 7 490 783 ));
-DATA(insert ( 2594 604 604 8 489 783 ));
-DATA(insert ( 2594 604 604 9 2575 783 ));
-DATA(insert ( 2594 604 604 10 2574 783 ));
-DATA(insert ( 2594 604 604 11 2577 783 ));
-DATA(insert ( 2594 604 604 12 2576 783 ));
-DATA(insert ( 2594 604 604 13 2861 783 ));
-DATA(insert ( 2594 604 604 14 2860 783 ));
+DATA(insert ( 2594 604 604 1 s 485 783 0 ));
+DATA(insert ( 2594 604 604 2 s 486 783 0 ));
+DATA(insert ( 2594 604 604 3 s 492 783 0 ));
+DATA(insert ( 2594 604 604 4 s 487 783 0 ));
+DATA(insert ( 2594 604 604 5 s 488 783 0 ));
+DATA(insert ( 2594 604 604 6 s 491 783 0 ));
+DATA(insert ( 2594 604 604 7 s 490 783 0 ));
+DATA(insert ( 2594 604 604 8 s 489 783 0 ));
+DATA(insert ( 2594 604 604 9 s 2575 783 0 ));
+DATA(insert ( 2594 604 604 10 s 2574 783 0 ));
+DATA(insert ( 2594 604 604 11 s 2577 783 0 ));
+DATA(insert ( 2594 604 604 12 s 2576 783 0 ));
+DATA(insert ( 2594 604 604 13 s 2861 783 0 ));
+DATA(insert ( 2594 604 604 14 s 2860 783 0 ));
/*
* gist circle_ops
*/
-DATA(insert ( 2595 718 718 1 1506 783 ));
-DATA(insert ( 2595 718 718 2 1507 783 ));
-DATA(insert ( 2595 718 718 3 1513 783 ));
-DATA(insert ( 2595 718 718 4 1508 783 ));
-DATA(insert ( 2595 718 718 5 1509 783 ));
-DATA(insert ( 2595 718 718 6 1512 783 ));
-DATA(insert ( 2595 718 718 7 1511 783 ));
-DATA(insert ( 2595 718 718 8 1510 783 ));
-DATA(insert ( 2595 718 718 9 2589 783 ));
-DATA(insert ( 2595 718 718 10 1515 783 ));
-DATA(insert ( 2595 718 718 11 1514 783 ));
-DATA(insert ( 2595 718 718 12 2590 783 ));
-DATA(insert ( 2595 718 718 13 2865 783 ));
-DATA(insert ( 2595 718 718 14 2864 783 ));
+DATA(insert ( 2595 718 718 1 s 1506 783 0 ));
+DATA(insert ( 2595 718 718 2 s 1507 783 0 ));
+DATA(insert ( 2595 718 718 3 s 1513 783 0 ));
+DATA(insert ( 2595 718 718 4 s 1508 783 0 ));
+DATA(insert ( 2595 718 718 5 s 1509 783 0 ));
+DATA(insert ( 2595 718 718 6 s 1512 783 0 ));
+DATA(insert ( 2595 718 718 7 s 1511 783 0 ));
+DATA(insert ( 2595 718 718 8 s 1510 783 0 ));
+DATA(insert ( 2595 718 718 9 s 2589 783 0 ));
+DATA(insert ( 2595 718 718 10 s 1515 783 0 ));
+DATA(insert ( 2595 718 718 11 s 1514 783 0 ));
+DATA(insert ( 2595 718 718 12 s 2590 783 0 ));
+DATA(insert ( 2595 718 718 13 s 2865 783 0 ));
+DATA(insert ( 2595 718 718 14 s 2864 783 0 ));
/*
* gin array_ops (these anyarray operators are used with all the opclasses
* of the family)
*/
-DATA(insert ( 2745 2277 2277 1 2750 2742 ));
-DATA(insert ( 2745 2277 2277 2 2751 2742 ));
-DATA(insert ( 2745 2277 2277 3 2752 2742 ));
-DATA(insert ( 2745 2277 2277 4 1070 2742 ));
+DATA(insert ( 2745 2277 2277 1 s 2750 2742 0 ));
+DATA(insert ( 2745 2277 2277 2 s 2751 2742 0 ));
+DATA(insert ( 2745 2277 2277 3 s 2752 2742 0 ));
+DATA(insert ( 2745 2277 2277 4 s 1070 2742 0 ));
/*
* btree enum_ops
*/
-DATA(insert ( 3522 3500 3500 1 3518 403 ));
-DATA(insert ( 3522 3500 3500 2 3520 403 ));
-DATA(insert ( 3522 3500 3500 3 3516 403 ));
-DATA(insert ( 3522 3500 3500 4 3521 403 ));
-DATA(insert ( 3522 3500 3500 5 3519 403 ));
+DATA(insert ( 3522 3500 3500 1 s 3518 403 0 ));
+DATA(insert ( 3522 3500 3500 2 s 3520 403 0 ));
+DATA(insert ( 3522 3500 3500 3 s 3516 403 0 ));
+DATA(insert ( 3522 3500 3500 4 s 3521 403 0 ));
+DATA(insert ( 3522 3500 3500 5 s 3519 403 0 ));
/*
* hash enum_ops
*/
-DATA(insert ( 3523 3500 3500 1 3516 405 ));
+DATA(insert ( 3523 3500 3500 1 s 3516 405 0 ));
/*
* btree tsvector_ops
*/
-DATA(insert ( 3626 3614 3614 1 3627 403 ));
-DATA(insert ( 3626 3614 3614 2 3628 403 ));
-DATA(insert ( 3626 3614 3614 3 3629 403 ));
-DATA(insert ( 3626 3614 3614 4 3631 403 ));
-DATA(insert ( 3626 3614 3614 5 3632 403 ));
+DATA(insert ( 3626 3614 3614 1 s 3627 403 0 ));
+DATA(insert ( 3626 3614 3614 2 s 3628 403 0 ));
+DATA(insert ( 3626 3614 3614 3 s 3629 403 0 ));
+DATA(insert ( 3626 3614 3614 4 s 3631 403 0 ));
+DATA(insert ( 3626 3614 3614 5 s 3632 403 0 ));
/*
* GiST tsvector_ops
*/
-DATA(insert ( 3655 3614 3615 1 3636 783 ));
+DATA(insert ( 3655 3614 3615 1 s 3636 783 0 ));
/*
* GIN tsvector_ops
*/
-DATA(insert ( 3659 3614 3615 1 3636 2742 ));
-DATA(insert ( 3659 3614 3615 2 3660 2742 ));
+DATA(insert ( 3659 3614 3615 1 s 3636 2742 0 ));
+DATA(insert ( 3659 3614 3615 2 s 3660 2742 0 ));
/*
* btree tsquery_ops
*/
-DATA(insert ( 3683 3615 3615 1 3674 403 ));
-DATA(insert ( 3683 3615 3615 2 3675 403 ));
-DATA(insert ( 3683 3615 3615 3 3676 403 ));
-DATA(insert ( 3683 3615 3615 4 3678 403 ));
-DATA(insert ( 3683 3615 3615 5 3679 403 ));
+DATA(insert ( 3683 3615 3615 1 s 3674 403 0 ));
+DATA(insert ( 3683 3615 3615 2 s 3675 403 0 ));
+DATA(insert ( 3683 3615 3615 3 s 3676 403 0 ));
+DATA(insert ( 3683 3615 3615 4 s 3678 403 0 ));
+DATA(insert ( 3683 3615 3615 5 s 3679 403 0 ));
/*
* GiST tsquery_ops
*/
-DATA(insert ( 3702 3615 3615 7 3693 783 ));
-DATA(insert ( 3702 3615 3615 8 3694 783 ));
+DATA(insert ( 3702 3615 3615 7 s 3693 783 0 ));
+DATA(insert ( 3702 3615 3615 8 s 3694 783 0 ));
#endif /* PG_AMOP_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index d6cfafea711..8b34b763009 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1776,6 +1776,7 @@ typedef struct CreateOpClassItem
List *name; /* operator or function name */
List *args; /* argument types */
int number; /* strategy num or support proc num */
+ List *order_family; /* only used for ordering operators */
List *class_args; /* only used for functions */
/* fields used for a storagetype item: */
TypeName *storedtype; /* datatype stored in index */
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 677134dcec9..785acc955ad 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -469,6 +469,7 @@ typedef struct IndexOptInfo
bool predOK; /* true if predicate matches query */
bool unique; /* true if a unique index */
+ bool amcanorderbyop; /* does AM support order by operator result? */
bool amoptionalkey; /* can query omit key for the first column? */
bool amsearchnulls; /* can AM search for NULL/NOT NULL entries? */
bool amhasgettuple; /* does AM have amgettuple interface? */
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 4703d497c1b..2176ea47da5 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -849,6 +849,14 @@ WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
------------+--------------
(0 rows)
+SELECT p1.amopfamily, p1.amopstrategy
+FROM pg_amop as p1
+WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
+ (p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));
+ amopfamily | amopstrategy
+------------+--------------
+(0 rows)
+
-- amoplefttype/amoprighttype must match the operator
SELECT p1.oid, p2.oid
FROM pg_amop AS p1, pg_operator AS p2
@@ -866,6 +874,25 @@ WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
-----+-----
(0 rows)
+-- amopsortfamily, if present, must reference a btree family
+SELECT p1.amopfamily, p1.amopstrategy
+FROM pg_amop AS p1
+WHERE p1.amopsortfamily <> 0 AND NOT EXISTS
+ (SELECT 1 from pg_opfamily op WHERE op.oid = p1.amopsortfamily
+ AND op.opfmethod = (SELECT oid FROM pg_am WHERE amname = 'btree'));
+ amopfamily | amopstrategy
+------------+--------------
+(0 rows)
+
+-- check for ordering operators not supported by parent AM
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.amname
+FROM pg_amop AS p1, pg_am AS p2
+WHERE p1.amopmethod = p2.oid AND
+ p1.amoppurpose = 'o' AND NOT p2.amcanorderbyop;
+ amopfamily | amopopr | oid | amname
+------------+---------+-----+--------
+(0 rows)
+
-- Cross-check amopstrategy index against parent AM
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.amname
FROM pg_amop AS p1, pg_am AS p2
@@ -885,17 +912,45 @@ WHERE p2.amopmethod = p1.oid AND
p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
WHERE p3.amopfamily = p2.amopfamily AND
p3.amoplefttype = p2.amoplefttype AND
- p3.amoprighttype = p2.amoprighttype);
+ p3.amoprighttype = p2.amoprighttype AND
+ p3.amoppurpose = 's');
amname | amoplefttype | amoprighttype
--------+--------------+---------------
(0 rows)
+-- Currently, none of the AMs with fixed strategy sets support ordering ops.
+SELECT p1.amname, p2.amopfamily, p2.amopstrategy
+FROM pg_am AS p1, pg_amop AS p2
+WHERE p2.amopmethod = p1.oid AND
+ p1.amstrategies <> 0 AND p2.amoppurpose <> 's';
+ amname | amopfamily | amopstrategy
+--------+------------+--------------
+(0 rows)
+
-- Check that amopopr points at a reasonable-looking operator, ie a binary
--- operator yielding boolean.
+-- operator. If it's a search operator it had better yield boolean,
+-- otherwise an input type of its sort opfamily.
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND
- (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype);
+ p2.oprkind != 'b';
+ amopfamily | amopopr | oid | oprname
+------------+---------+-----+---------
+(0 rows)
+
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
+FROM pg_amop AS p1, pg_operator AS p2
+WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
+ p2.oprresult != 'bool'::regtype;
+ amopfamily | amopopr | oid | oprname
+------------+---------+-----+---------
+(0 rows)
+
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
+FROM pg_amop AS p1, pg_operator AS p2
+WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 'o' AND NOT EXISTS
+ (SELECT 1 FROM pg_opclass op
+ WHERE opcfamily = p1.amopsortfamily AND opcintype = p2.oprresult);
amopfamily | amopopr | oid | oprname
------------+---------+-----+---------
(0 rows)
@@ -950,12 +1005,12 @@ ORDER BY 1, 2, 3;
2742 | 4 | =
(39 rows)
--- Check that all operators linked to by opclass entries have selectivity
--- estimators. This is not absolutely required, but it seems a reasonable
--- thing to insist on for all standard datatypes.
+-- Check that all opclass search operators have selectivity estimators.
+-- This is not absolutely required, but it seems a reasonable thing
+-- to insist on for all standard datatypes.
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
-WHERE p1.amopopr = p2.oid AND
+WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
(p2.oprrest = 0 OR p2.oprjoin = 0);
amopfamily | amopopr | oid | oprname
------------+---------+-----+---------
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index 0d084a1f7a6..1a023a088e3 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -685,6 +685,11 @@ FROM pg_amop as p1
WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
+SELECT p1.amopfamily, p1.amopstrategy
+FROM pg_amop as p1
+WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
+ (p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));
+
-- amoplefttype/amoprighttype must match the operator
SELECT p1.oid, p2.oid
@@ -698,6 +703,21 @@ SELECT p1.oid, p2.oid
FROM pg_amop AS p1, pg_opfamily AS p2
WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
+-- amopsortfamily, if present, must reference a btree family
+
+SELECT p1.amopfamily, p1.amopstrategy
+FROM pg_amop AS p1
+WHERE p1.amopsortfamily <> 0 AND NOT EXISTS
+ (SELECT 1 from pg_opfamily op WHERE op.oid = p1.amopsortfamily
+ AND op.opfmethod = (SELECT oid FROM pg_am WHERE amname = 'btree'));
+
+-- check for ordering operators not supported by parent AM
+
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.amname
+FROM pg_amop AS p1, pg_am AS p2
+WHERE p1.amopmethod = p2.oid AND
+ p1.amoppurpose = 'o' AND NOT p2.amcanorderbyop;
+
-- Cross-check amopstrategy index against parent AM
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.amname
@@ -716,15 +736,35 @@ WHERE p2.amopmethod = p1.oid AND
p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
WHERE p3.amopfamily = p2.amopfamily AND
p3.amoplefttype = p2.amoplefttype AND
- p3.amoprighttype = p2.amoprighttype);
+ p3.amoprighttype = p2.amoprighttype AND
+ p3.amoppurpose = 's');
+
+-- Currently, none of the AMs with fixed strategy sets support ordering ops.
+
+SELECT p1.amname, p2.amopfamily, p2.amopstrategy
+FROM pg_am AS p1, pg_amop AS p2
+WHERE p2.amopmethod = p1.oid AND
+ p1.amstrategies <> 0 AND p2.amoppurpose <> 's';
-- Check that amopopr points at a reasonable-looking operator, ie a binary
--- operator yielding boolean.
+-- operator. If it's a search operator it had better yield boolean,
+-- otherwise an input type of its sort opfamily.
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND
- (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype);
+ p2.oprkind != 'b';
+
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
+FROM pg_amop AS p1, pg_operator AS p2
+WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
+ p2.oprresult != 'bool'::regtype;
+
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
+FROM pg_amop AS p1, pg_operator AS p2
+WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 'o' AND NOT EXISTS
+ (SELECT 1 FROM pg_opclass op
+ WHERE opcfamily = p1.amopsortfamily AND opcintype = p2.oprresult);
-- Make a list of all the distinct operator names being used in particular
-- strategy slots. This is a bit hokey, since the list might need to change
@@ -735,13 +775,13 @@ SELECT DISTINCT amopmethod, amopstrategy, oprname
FROM pg_amop p1 LEFT JOIN pg_operator p2 ON amopopr = p2.oid
ORDER BY 1, 2, 3;
--- Check that all operators linked to by opclass entries have selectivity
--- estimators. This is not absolutely required, but it seems a reasonable
--- thing to insist on for all standard datatypes.
+-- Check that all opclass search operators have selectivity estimators.
+-- This is not absolutely required, but it seems a reasonable thing
+-- to insist on for all standard datatypes.
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
-WHERE p1.amopopr = p2.oid AND
+WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
(p2.oprrest = 0 OR p2.oprjoin = 0);
-- Check that each opclass in an opfamily has associated operators, that is