Commit ec646dbc authored by Tom Lane's avatar Tom Lane

Create a 'type cache' that keeps track of the data needed for any particular

datatype by array_eq and array_cmp; use this to solve problems with memory
leaks in array indexing support.  The parser's equality_oper and ordering_oper
routines also use the cache.  Change the operator search algorithms to look
for appropriate btree or hash index opclasses, instead of assuming operators
named '<' or '=' have the right semantics.  (ORDER BY ASC/DESC now also look
at opclasses, instead of assuming '<' and '>' are the right things.)  Add
several more index opclasses so that there is no regression in functionality
for base datatypes.  initdb forced due to catalog additions.
parent d89578cc
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.58 2003/08/04 02:39:58 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.59 2003/08/17 19:58:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -390,7 +390,6 @@ examine_attribute(Relation onerel, int attnum) ...@@ -390,7 +390,6 @@ examine_attribute(Relation onerel, int attnum)
{ {
Form_pg_attribute attr = onerel->rd_att->attrs[attnum - 1]; Form_pg_attribute attr = onerel->rd_att->attrs[attnum - 1];
Operator func_operator; Operator func_operator;
Oid oprrest;
HeapTuple typtuple; HeapTuple typtuple;
Oid eqopr = InvalidOid; Oid eqopr = InvalidOid;
Oid eqfunc = InvalidOid; Oid eqfunc = InvalidOid;
...@@ -409,12 +408,8 @@ examine_attribute(Relation onerel, int attnum) ...@@ -409,12 +408,8 @@ examine_attribute(Relation onerel, int attnum)
func_operator = equality_oper(attr->atttypid, true); func_operator = equality_oper(attr->atttypid, true);
if (func_operator != NULL) if (func_operator != NULL)
{ {
oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest; eqopr = oprid(func_operator);
if (oprrest == F_EQSEL) eqfunc = oprfuncid(func_operator);
{
eqopr = oprid(func_operator);
eqfunc = oprfuncid(func_operator);
}
ReleaseSysCache(func_operator); ReleaseSysCache(func_operator);
} }
if (!OidIsValid(eqfunc)) if (!OidIsValid(eqfunc))
...@@ -447,9 +442,7 @@ examine_attribute(Relation onerel, int attnum) ...@@ -447,9 +442,7 @@ examine_attribute(Relation onerel, int attnum)
func_operator = ordering_oper(attr->atttypid, true); func_operator = ordering_oper(attr->atttypid, true);
if (func_operator != NULL) if (func_operator != NULL)
{ {
oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest; ltopr = oprid(func_operator);
if (oprrest == F_SCALARLTSEL)
ltopr = oprid(func_operator);
ReleaseSysCache(func_operator); ReleaseSysCache(func_operator);
} }
stats->ltopr = ltopr; stats->ltopr = ltopr;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.105 2003/08/04 02:39:58 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.106 2003/08/17 19:58:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -529,7 +529,8 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId) ...@@ -529,7 +529,8 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId)
* than one exact match, then someone put bogus entries in pg_opclass. * than one exact match, then someone put bogus entries in pg_opclass.
* *
* The initial search is done by namespace.c so that we only consider * The initial search is done by namespace.c so that we only consider
* opclasses visible in the current namespace search path. * opclasses visible in the current namespace search path. (See also
* typcache.c, which applies the same logic, but over all opclasses.)
*/ */
for (opclass = OpclassGetCandidates(accessMethodId); for (opclass = OpclassGetCandidates(accessMethodId);
opclass != NULL; opclass != NULL;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.17 2003/08/04 02:39:58 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.18 2003/08/17 19:58:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -261,7 +261,9 @@ DefineOpClass(CreateOpClassStmt *stmt) ...@@ -261,7 +261,9 @@ DefineOpClass(CreateOpClassStmt *stmt)
/* /*
* If we are creating a default opclass, check there isn't one * If we are creating a default opclass, check there isn't one
* already. (XXX should we restrict this test to visible opclasses?) * already. (Note we do not restrict this test to visible opclasses;
* this ensures that typcache.c can find unique solutions to its
* questions.)
*/ */
if (stmt->isDefault) if (stmt->isDefault)
{ {
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.263 2003/08/08 21:41:43 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.264 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1402,11 +1402,12 @@ _copyTypeName(TypeName *from) ...@@ -1402,11 +1402,12 @@ _copyTypeName(TypeName *from)
return newnode; return newnode;
} }
static SortGroupBy * static SortBy *
_copySortGroupBy(SortGroupBy *from) _copySortBy(SortBy *from)
{ {
SortGroupBy *newnode = makeNode(SortGroupBy); SortBy *newnode = makeNode(SortBy);
COPY_SCALAR_FIELD(sortby_kind);
COPY_NODE_FIELD(useOp); COPY_NODE_FIELD(useOp);
COPY_NODE_FIELD(node); COPY_NODE_FIELD(node);
...@@ -2924,8 +2925,8 @@ copyObject(void *from) ...@@ -2924,8 +2925,8 @@ copyObject(void *from)
case T_TypeCast: case T_TypeCast:
retval = _copyTypeCast(from); retval = _copyTypeCast(from);
break; break;
case T_SortGroupBy: case T_SortBy:
retval = _copySortGroupBy(from); retval = _copySortBy(from);
break; break;
case T_RangeSubselect: case T_RangeSubselect:
retval = _copyRangeSubselect(from); retval = _copyRangeSubselect(from);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.207 2003/08/08 21:41:43 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.208 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1480,8 +1480,9 @@ _equalTypeCast(TypeCast *a, TypeCast *b) ...@@ -1480,8 +1480,9 @@ _equalTypeCast(TypeCast *a, TypeCast *b)
} }
static bool static bool
_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b) _equalSortBy(SortBy *a, SortBy *b)
{ {
COMPARE_SCALAR_FIELD(sortby_kind);
COMPARE_NODE_FIELD(useOp); COMPARE_NODE_FIELD(useOp);
COMPARE_NODE_FIELD(node); COMPARE_NODE_FIELD(node);
...@@ -2045,8 +2046,8 @@ equal(void *a, void *b) ...@@ -2045,8 +2046,8 @@ equal(void *a, void *b)
case T_TypeCast: case T_TypeCast:
retval = _equalTypeCast(a, b); retval = _equalTypeCast(a, b);
break; break;
case T_SortGroupBy: case T_SortBy:
retval = _equalSortGroupBy(a, b); retval = _equalSortBy(a, b);
break; break;
case T_RangeSubselect: case T_RangeSubselect:
retval = _equalRangeSubselect(a, b); retval = _equalRangeSubselect(a, b);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.154 2003/08/11 20:46:46 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.155 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -629,8 +629,9 @@ create_unique_plan(Query *root, UniquePath *best_path) ...@@ -629,8 +629,9 @@ create_unique_plan(Query *root, UniquePath *best_path)
tle = get_tle_by_resno(my_tlist, groupColIdx[groupColPos]); tle = get_tle_by_resno(my_tlist, groupColIdx[groupColPos]);
Assert(tle != NULL); Assert(tle != NULL);
sortList = addTargetToSortList(NULL, tle, sortList, sortList = addTargetToSortList(NULL, tle,
my_tlist, NIL, false); sortList, my_tlist,
SORTBY_ASC, NIL, false);
} }
plan = (Plan *) make_sort_from_sortclauses(root, my_tlist, plan = (Plan *) make_sort_from_sortclauses(root, my_tlist,
subplan, sortList); subplan, sortList);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.159 2003/08/04 02:40:01 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.160 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1327,7 +1327,9 @@ hash_safe_grouping(Query *parse) ...@@ -1327,7 +1327,9 @@ hash_safe_grouping(Query *parse)
Operator optup; Operator optup;
bool oprcanhash; bool oprcanhash;
optup = equality_oper(tle->resdom->restype, false); optup = equality_oper(tle->resdom->restype, true);
if (!optup)
return false;
oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash; oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash;
ReleaseSysCache(optup); ReleaseSysCache(optup);
if (!oprcanhash) if (!oprcanhash)
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.428 2003/08/04 02:40:01 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.429 2003/08/17 19:58:05 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -115,7 +115,7 @@ static void doNegateFloat(Value *v); ...@@ -115,7 +115,7 @@ static void doNegateFloat(Value *v);
TypeName *typnam; TypeName *typnam;
DefElem *defelt; DefElem *defelt;
SortGroupBy *sortgroupby; SortBy *sortby;
JoinExpr *jexpr; JoinExpr *jexpr;
IndexElem *ielem; IndexElem *ielem;
Alias *alias; Alias *alias;
...@@ -189,7 +189,7 @@ static void doNegateFloat(Value *v); ...@@ -189,7 +189,7 @@ static void doNegateFloat(Value *v);
database_name access_method_clause access_method attr_name database_name access_method_clause access_method attr_name
index_name name function_name file_name index_name name function_name file_name
%type <list> func_name handler_name qual_Op qual_all_Op OptUseOp %type <list> func_name handler_name qual_Op qual_all_Op
opt_class opt_validator opt_class opt_validator
%type <range> qualified_name OptConstrFromTable %type <range> qualified_name OptConstrFromTable
...@@ -278,7 +278,7 @@ static void doNegateFloat(Value *v); ...@@ -278,7 +278,7 @@ static void doNegateFloat(Value *v);
%type <value> NumericOnly FloatOnly IntegerOnly %type <value> NumericOnly FloatOnly IntegerOnly
%type <columnref> columnref %type <columnref> columnref
%type <alias> alias_clause %type <alias> alias_clause
%type <sortgroupby> sortby %type <sortby> sortby
%type <ielem> index_elem %type <ielem> index_elem
%type <node> table_ref %type <node> table_ref
%type <jexpr> joined_table %type <jexpr> joined_table
...@@ -4577,21 +4577,34 @@ sortby_list: ...@@ -4577,21 +4577,34 @@ sortby_list:
| sortby_list ',' sortby { $$ = lappend($1, $3); } | sortby_list ',' sortby { $$ = lappend($1, $3); }
; ;
sortby: a_expr OptUseOp sortby: a_expr USING qual_all_Op
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortBy);
$$->node = $1; $$->node = $1;
$$->useOp = $2; $$->sortby_kind = SORTBY_USING;
$$->useOp = $3;
}
| a_expr ASC
{
$$ = makeNode(SortBy);
$$->node = $1;
$$->sortby_kind = SORTBY_ASC;
$$->useOp = NIL;
}
| a_expr DESC
{
$$ = makeNode(SortBy);
$$->node = $1;
$$->sortby_kind = SORTBY_DESC;
$$->useOp = NIL;
}
| a_expr
{
$$ = makeNode(SortBy);
$$->node = $1;
$$->sortby_kind = SORTBY_ASC; /* default */
$$->useOp = NIL;
} }
;
OptUseOp: USING qual_all_Op { $$ = $2; }
| ASC
{ $$ = makeList1(makeString("<")); }
| DESC
{ $$ = makeList1(makeString(">")); }
| /*EMPTY*/
{ $$ = makeList1(makeString("<")); /*default*/ }
; ;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.121 2003/08/07 19:20:22 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.122 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1295,7 +1295,7 @@ transformSortClause(ParseState *pstate, ...@@ -1295,7 +1295,7 @@ transformSortClause(ParseState *pstate,
foreach(olitem, orderlist) foreach(olitem, orderlist)
{ {
SortGroupBy *sortby = lfirst(olitem); SortBy *sortby = lfirst(olitem);
TargetEntry *tle; TargetEntry *tle;
tle = findTargetlistEntry(pstate, sortby->node, tle = findTargetlistEntry(pstate, sortby->node,
...@@ -1303,7 +1303,9 @@ transformSortClause(ParseState *pstate, ...@@ -1303,7 +1303,9 @@ transformSortClause(ParseState *pstate,
sortlist = addTargetToSortList(pstate, tle, sortlist = addTargetToSortList(pstate, tle,
sortlist, targetlist, sortlist, targetlist,
sortby->useOp, resolveUnknown); sortby->sortby_kind,
sortby->useOp,
resolveUnknown);
} }
return sortlist; return sortlist;
...@@ -1409,7 +1411,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, ...@@ -1409,7 +1411,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
{ {
*sortClause = addTargetToSortList(pstate, tle, *sortClause = addTargetToSortList(pstate, tle,
*sortClause, targetlist, *sortClause, targetlist,
NIL, true); SORTBY_ASC, NIL, true);
/* /*
* Probably, the tle should always have been added at the * Probably, the tle should always have been added at the
...@@ -1457,7 +1459,8 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist, ...@@ -1457,7 +1459,8 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist,
if (!tle->resdom->resjunk) if (!tle->resdom->resjunk)
sortlist = addTargetToSortList(pstate, tle, sortlist = addTargetToSortList(pstate, tle,
sortlist, targetlist, sortlist, targetlist,
NIL, resolveUnknown); SORTBY_ASC, NIL,
resolveUnknown);
} }
return sortlist; return sortlist;
} }
...@@ -1478,7 +1481,8 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist, ...@@ -1478,7 +1481,8 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist,
List * List *
addTargetToSortList(ParseState *pstate, TargetEntry *tle, addTargetToSortList(ParseState *pstate, TargetEntry *tle,
List *sortlist, List *targetlist, List *sortlist, List *targetlist,
List *opname, bool resolveUnknown) int sortby_kind, List *sortby_opname,
bool resolveUnknown)
{ {
/* avoid making duplicate sortlist entries */ /* avoid making duplicate sortlist entries */
if (!targetIsInSortList(tle, sortlist)) if (!targetIsInSortList(tle, sortlist))
...@@ -1499,13 +1503,25 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, ...@@ -1499,13 +1503,25 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist); sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
if (opname) switch (sortby_kind)
sortcl->sortop = compatible_oper_opid(opname, {
restype, case SORTBY_ASC:
restype, sortcl->sortop = ordering_oper_opid(restype);
false); break;
else case SORTBY_DESC:
sortcl->sortop = ordering_oper_opid(restype); sortcl->sortop = reverse_ordering_oper_opid(restype);
break;
case SORTBY_USING:
Assert(sortby_opname != NIL);
sortcl->sortop = compatible_oper_opid(sortby_opname,
restype,
restype,
false);
break;
default:
elog(ERROR, "unrecognized sortby_kind: %d", sortby_kind);
break;
}
sortlist = lappend(sortlist, sortcl); sortlist = lappend(sortlist, sortcl);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.73 2003/08/04 02:40:02 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.74 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/typcache.h"
static Oid binary_oper_exact(Oid arg1, Oid arg2, static Oid binary_oper_exact(Oid arg1, Oid arg2,
...@@ -135,52 +136,49 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft, ...@@ -135,52 +136,49 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft,
Operator Operator
equality_oper(Oid argtype, bool noError) equality_oper(Oid argtype, bool noError)
{ {
TypeCacheEntry *typentry;
Oid oproid;
Operator optup; Operator optup;
Oid elem_type;
/*
* Look for an "=" operator for the datatype. We require it to be
* an exact or binary-compatible match, since most callers are not
* prepared to cope with adding any run-time type coercion steps.
*/
typentry = lookup_type_cache(argtype, TYPECACHE_EQ_OPR);
oproid = typentry->eq_opr;
/* /*
* If the datatype is an array, then we can use array_eq ... but only * If the datatype is an array, then we can use array_eq ... but only
* if there is a suitable equality operator for the element type. (We * if there is a suitable equality operator for the element type.
* must run this test first, since compatible_oper will find array_eq, * (This check is not in the raw typcache.c code ... should it be?)
* but would not notice the lack of an element operator.)
*/ */
elem_type = get_element_type(argtype); if (oproid == ARRAY_EQ_OP)
if (OidIsValid(elem_type))
{ {
optup = equality_oper(elem_type, true); Oid elem_type = get_element_type(argtype);
if (optup != NULL)
if (OidIsValid(elem_type))
{ {
ReleaseSysCache(optup); optup = equality_oper(elem_type, true);
return SearchSysCache(OPEROID, if (optup != NULL)
ObjectIdGetDatum(ARRAY_EQ_OP), ReleaseSysCache(optup);
0, 0, 0); else
oproid = InvalidOid; /* element type has no "=" */
} }
else
oproid = InvalidOid; /* bogus array type? */
} }
else
{
/*
* Look for an "=" operator for the datatype. We require it to be
* an exact or binary-compatible match, since most callers are not
* prepared to cope with adding any run-time type coercion steps.
*/
optup = compatible_oper(makeList1(makeString("=")),
argtype, argtype, true);
if (optup != NULL)
{
/*
* Only believe that it's equality if it's mergejoinable,
* hashjoinable, or uses eqsel() as oprrest.
*/
Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(optup);
if (OidIsValid(pgopform->oprlsortop) ||
pgopform->oprcanhash ||
pgopform->oprrest == F_EQSEL)
return optup;
ReleaseSysCache(optup); if (OidIsValid(oproid))
} {
optup = SearchSysCache(OPEROID,
ObjectIdGetDatum(oproid),
0, 0, 0);
if (optup == NULL) /* should not fail */
elog(ERROR, "cache lookup failed for operator %u", oproid);
return optup;
} }
if (!noError) if (!noError)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION), (errcode(ERRCODE_UNDEFINED_FUNCTION),
...@@ -197,53 +195,119 @@ equality_oper(Oid argtype, bool noError) ...@@ -197,53 +195,119 @@ equality_oper(Oid argtype, bool noError)
Operator Operator
ordering_oper(Oid argtype, bool noError) ordering_oper(Oid argtype, bool noError)
{ {
TypeCacheEntry *typentry;
Oid oproid;
Operator optup; Operator optup;
Oid elem_type;
/*
* Look for a "<" operator for the datatype. We require it to be
* an exact or binary-compatible match, since most callers are not
* prepared to cope with adding any run-time type coercion steps.
*
* Note: the search algorithm used by typcache.c ensures that if a "<"
* operator is returned, it will be consistent with the "=" operator
* returned by equality_oper. This is critical for sorting and grouping
* purposes.
*/
typentry = lookup_type_cache(argtype, TYPECACHE_LT_OPR);
oproid = typentry->lt_opr;
/* /*
* If the datatype is an array, then we can use array_lt ... but only * If the datatype is an array, then we can use array_lt ... but only
* if there is a suitable ordering operator for the element type. (We * if there is a suitable less-than operator for the element type.
* must run this test first, since the code below would find array_lt * (This check is not in the raw typcache.c code ... should it be?)
* if there's an element = operator, but would not notice the lack of
* an element < operator.)
*/ */
elem_type = get_element_type(argtype); if (oproid == ARRAY_LT_OP)
if (OidIsValid(elem_type))
{ {
optup = ordering_oper(elem_type, true); Oid elem_type = get_element_type(argtype);
if (optup != NULL)
if (OidIsValid(elem_type))
{ {
ReleaseSysCache(optup); optup = ordering_oper(elem_type, true);
return SearchSysCache(OPEROID, if (optup != NULL)
ObjectIdGetDatum(ARRAY_LT_OP), ReleaseSysCache(optup);
0, 0, 0); else
oproid = InvalidOid; /* element type has no "<" */
} }
else
oproid = InvalidOid; /* bogus array type? */
} }
else
if (OidIsValid(oproid))
{ {
/* optup = SearchSysCache(OPEROID,
* Find the type's equality operator, and use its lsortop (it ObjectIdGetDatum(oproid),
* *must* be mergejoinable). We use this definition because for 0, 0, 0);
* sorting and grouping purposes, it's important that the equality if (optup == NULL) /* should not fail */
* and ordering operators are consistent. elog(ERROR, "cache lookup failed for operator %u", oproid);
*/ return optup;
optup = equality_oper(argtype, noError); }
if (optup != NULL)
{
Oid lsortop;
lsortop = ((Form_pg_operator) GETSTRUCT(optup))->oprlsortop; if (!noError)
ReleaseSysCache(optup); ereport(ERROR,
if (OidIsValid(lsortop)) (errcode(ERRCODE_UNDEFINED_FUNCTION),
{ errmsg("could not identify an ordering operator for type %s",
optup = SearchSysCache(OPEROID, format_type_be(argtype)),
ObjectIdGetDatum(lsortop), errhint("Use an explicit ordering operator or modify the query.")));
0, 0, 0); return NULL;
if (optup != NULL) }
return optup;
} /*
* reverse_ordering_oper - identify DESC sort operator (">") for a datatype
*
* On failure, return NULL if noError, else report a standard error
*/
Operator
reverse_ordering_oper(Oid argtype, bool noError)
{
TypeCacheEntry *typentry;
Oid oproid;
Operator optup;
/*
* Look for a ">" operator for the datatype. We require it to be
* an exact or binary-compatible match, since most callers are not
* prepared to cope with adding any run-time type coercion steps.
*
* Note: the search algorithm used by typcache.c ensures that if a ">"
* operator is returned, it will be consistent with the "=" operator
* returned by equality_oper. This is critical for sorting and grouping
* purposes.
*/
typentry = lookup_type_cache(argtype, TYPECACHE_GT_OPR);
oproid = typentry->gt_opr;
/*
* If the datatype is an array, then we can use array_gt ... but only
* if there is a suitable greater-than operator for the element type.
* (This check is not in the raw typcache.c code ... should it be?)
*/
if (oproid == ARRAY_GT_OP)
{
Oid elem_type = get_element_type(argtype);
if (OidIsValid(elem_type))
{
optup = reverse_ordering_oper(elem_type, true);
if (optup != NULL)
ReleaseSysCache(optup);
else
oproid = InvalidOid; /* element type has no ">" */
} }
else
oproid = InvalidOid; /* bogus array type? */
} }
if (OidIsValid(oproid))
{
optup = SearchSysCache(OPEROID,
ObjectIdGetDatum(oproid),
0, 0, 0);
if (optup == NULL) /* should not fail */
elog(ERROR, "cache lookup failed for operator %u", oproid);
return optup;
}
if (!noError) if (!noError)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION), (errcode(ERRCODE_UNDEFINED_FUNCTION),
...@@ -286,16 +350,16 @@ ordering_oper_opid(Oid argtype) ...@@ -286,16 +350,16 @@ ordering_oper_opid(Oid argtype)
} }
/* /*
* ordering_oper_funcid - convenience routine for oprfuncid(ordering_oper()) * reverse_ordering_oper_opid - convenience routine for oprid(reverse_ordering_oper())
*/ */
Oid Oid
ordering_oper_funcid(Oid argtype) reverse_ordering_oper_opid(Oid argtype)
{ {
Operator optup; Operator optup;
Oid result; Oid result;
optup = ordering_oper(argtype, false); optup = reverse_ordering_oper(argtype, false);
result = oprfuncid(optup); result = oprid(optup);
ReleaseSysCache(optup); ReleaseSysCache(optup);
return result; return result;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.95 2003/08/14 14:19:07 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.96 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -480,6 +480,23 @@ aclitem_eq(PG_FUNCTION_ARGS) ...@@ -480,6 +480,23 @@ aclitem_eq(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(result); PG_RETURN_BOOL(result);
} }
/*
* aclitem hash function
*
* We make aclitems hashable not so much because anyone is likely to hash
* them, as because we want array equality to work on aclitem arrays, and
* with the typcache mechanism we must have a hash or btree opclass.
*/
Datum
hash_aclitem(PG_FUNCTION_ARGS)
{
AclItem *a = PG_GETARG_ACLITEM_P(0);
/* not very bright, but avoids any issue of padding in struct */
PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
}
/* /*
* acldefault() --- create an ACL describing default access permissions * acldefault() --- create an ACL describing default access permissions
* *
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.98 2003/08/15 00:22:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.99 2003/08/17 19:58:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/typcache.h"
/*---------- /*----------
...@@ -2341,6 +2342,9 @@ deconstruct_array(ArrayType *array, ...@@ -2341,6 +2342,9 @@ deconstruct_array(ArrayType *array,
* compares two arrays for equality * compares two arrays for equality
* result : * result :
* returns true if the arrays are equal, false otherwise. * returns true if the arrays are equal, false otherwise.
*
* Note: we do not use array_cmp here, since equality may be meaningful in
* datatypes that don't have a total ordering (and hence no btree support).
*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------
*/ */
Datum Datum
...@@ -2357,13 +2361,12 @@ array_eq(PG_FUNCTION_ARGS) ...@@ -2357,13 +2361,12 @@ array_eq(PG_FUNCTION_ARGS)
int nitems1 = ArrayGetNItems(ndims1, dims1); int nitems1 = ArrayGetNItems(ndims1, dims1);
int nitems2 = ArrayGetNItems(ndims2, dims2); int nitems2 = ArrayGetNItems(ndims2, dims2);
Oid element_type = ARR_ELEMTYPE(array1); Oid element_type = ARR_ELEMTYPE(array1);
FmgrInfo *ae_fmgr_info = fcinfo->flinfo;
bool result = true; bool result = true;
TypeCacheEntry *typentry;
int typlen; int typlen;
bool typbyval; bool typbyval;
char typalign; char typalign;
int i; int i;
ArrayMetaState *my_extra;
FunctionCallInfoData locfcinfo; FunctionCallInfoData locfcinfo;
if (element_type != ARR_ELEMTYPE(array2)) if (element_type != ARR_ELEMTYPE(array2))
...@@ -2379,38 +2382,31 @@ array_eq(PG_FUNCTION_ARGS) ...@@ -2379,38 +2382,31 @@ array_eq(PG_FUNCTION_ARGS)
/* /*
* We arrange to look up the equality function only once per * We arrange to look up the equality function only once per
* series of calls, assuming the element type doesn't change * series of calls, assuming the element type doesn't change
* underneath us. * underneath us. The typcache is used so that we have no
* memory leakage when being used as an index support function.
*/ */
my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra; typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
if (my_extra == NULL) if (typentry == NULL ||
typentry->type_id != element_type)
{ {
ae_fmgr_info->fn_extra = MemoryContextAlloc(ae_fmgr_info->fn_mcxt, typentry = lookup_type_cache(element_type,
sizeof(ArrayMetaState)); TYPECACHE_EQ_OPR_FINFO);
my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra; if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
my_extra->element_type = InvalidOid; ereport(ERROR,
} (errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not identify an equality operator for type %s",
if (my_extra->element_type != element_type) format_type_be(element_type))));
{ fcinfo->flinfo->fn_extra = (void *) typentry;
Oid opfuncid = equality_oper_funcid(element_type);
get_typlenbyvalalign(element_type,
&my_extra->typlen,
&my_extra->typbyval,
&my_extra->typalign);
fmgr_info_cxt(opfuncid, &my_extra->proc,
ae_fmgr_info->fn_mcxt);
my_extra->element_type = element_type;
} }
typlen = my_extra->typlen; typlen = typentry->typlen;
typbyval = my_extra->typbyval; typbyval = typentry->typbyval;
typalign = my_extra->typalign; typalign = typentry->typalign;
/* /*
* apply the operator to each pair of array elements. * apply the operator to each pair of array elements.
*/ */
MemSet(&locfcinfo, 0, sizeof(locfcinfo)); MemSet(&locfcinfo, 0, sizeof(locfcinfo));
locfcinfo.flinfo = &my_extra->proc; locfcinfo.flinfo = &typentry->eq_opr_finfo;
locfcinfo.nargs = 2; locfcinfo.nargs = 2;
/* Loop over source data */ /* Loop over source data */
...@@ -2519,23 +2515,14 @@ array_cmp(FunctionCallInfo fcinfo) ...@@ -2519,23 +2515,14 @@ array_cmp(FunctionCallInfo fcinfo)
int nitems1 = ArrayGetNItems(ndims1, dims1); int nitems1 = ArrayGetNItems(ndims1, dims1);
int nitems2 = ArrayGetNItems(ndims2, dims2); int nitems2 = ArrayGetNItems(ndims2, dims2);
Oid element_type = ARR_ELEMTYPE(array1); Oid element_type = ARR_ELEMTYPE(array1);
FmgrInfo *ac_fmgr_info = fcinfo->flinfo;
int result = 0; int result = 0;
TypeCacheEntry *typentry;
int typlen; int typlen;
bool typbyval; bool typbyval;
char typalign; char typalign;
int min_nitems; int min_nitems;
int i; int i;
typedef struct FunctionCallInfoData locfcinfo;
{
Oid element_type;
int16 typlen;
bool typbyval;
char typalign;
FmgrInfo eqproc;
FmgrInfo ordproc;
} ac_extra;
ac_extra *my_extra;
if (element_type != ARR_ELEMTYPE(array2)) if (element_type != ARR_ELEMTYPE(array2))
ereport(ERROR, ereport(ERROR,
...@@ -2543,37 +2530,34 @@ array_cmp(FunctionCallInfo fcinfo) ...@@ -2543,37 +2530,34 @@ array_cmp(FunctionCallInfo fcinfo)
errmsg("cannot compare arrays of different element types"))); errmsg("cannot compare arrays of different element types")));
/* /*
* We arrange to look up the element type info and related functions * We arrange to look up the comparison function only once per series of
* only once per series of calls, assuming the element type doesn't * calls, assuming the element type doesn't change underneath us.
* change underneath us. * The typcache is used so that we have no memory leakage when being used
* as an index support function.
*/ */
my_extra = (ac_extra *) ac_fmgr_info->fn_extra; typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
if (my_extra == NULL) if (typentry == NULL ||
typentry->type_id != element_type)
{ {
ac_fmgr_info->fn_extra = MemoryContextAlloc(ac_fmgr_info->fn_mcxt, typentry = lookup_type_cache(element_type,
sizeof(ac_extra)); TYPECACHE_CMP_PROC_FINFO);
my_extra = (ac_extra *) ac_fmgr_info->fn_extra; if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
my_extra->element_type = InvalidOid; ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not identify a comparison function for type %s",
format_type_be(element_type))));
fcinfo->flinfo->fn_extra = (void *) typentry;
} }
typlen = typentry->typlen;
typbyval = typentry->typbyval;
typalign = typentry->typalign;
if (my_extra->element_type != element_type) /*
{ * apply the operator to each pair of array elements.
Oid eqfuncid = equality_oper_funcid(element_type); */
Oid ordfuncid = ordering_oper_funcid(element_type); MemSet(&locfcinfo, 0, sizeof(locfcinfo));
locfcinfo.flinfo = &typentry->cmp_proc_finfo;
get_typlenbyvalalign(element_type, locfcinfo.nargs = 2;
&my_extra->typlen,
&my_extra->typbyval,
&my_extra->typalign);
fmgr_info_cxt(eqfuncid, &my_extra->eqproc,
ac_fmgr_info->fn_mcxt);
fmgr_info_cxt(ordfuncid, &my_extra->ordproc,
ac_fmgr_info->fn_mcxt);
my_extra->element_type = element_type;
}
typlen = my_extra->typlen;
typbyval = my_extra->typbyval;
typalign = my_extra->typalign;
/* Loop over source data */ /* Loop over source data */
min_nitems = Min(nitems1, nitems2); min_nitems = Min(nitems1, nitems2);
...@@ -2581,7 +2565,7 @@ array_cmp(FunctionCallInfo fcinfo) ...@@ -2581,7 +2565,7 @@ array_cmp(FunctionCallInfo fcinfo)
{ {
Datum elt1; Datum elt1;
Datum elt2; Datum elt2;
Datum opresult; int32 cmpresult;
/* Get element pair */ /* Get element pair */
elt1 = fetch_att(p1, typbyval, typlen); elt1 = fetch_att(p1, typbyval, typlen);
...@@ -2594,15 +2578,17 @@ array_cmp(FunctionCallInfo fcinfo) ...@@ -2594,15 +2578,17 @@ array_cmp(FunctionCallInfo fcinfo)
p2 = (char *) att_align(p2, typalign); p2 = (char *) att_align(p2, typalign);
/* Compare the pair of elements */ /* Compare the pair of elements */
locfcinfo.arg[0] = elt1;
locfcinfo.arg[1] = elt2;
locfcinfo.argnull[0] = false;
locfcinfo.argnull[1] = false;
locfcinfo.isnull = false;
cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
/* are they equal */ if (cmpresult == 0)
opresult = FunctionCall2(&my_extra->eqproc, elt1, elt2); continue; /* equal */
if (DatumGetBool(opresult))
continue;
/* nope, see if arg1 is less than arg2 */ if (cmpresult < 0)
opresult = FunctionCall2(&my_extra->ordproc, elt1, elt2);
if (DatumGetBool(opresult))
{ {
/* arg1 is less than arg2 */ /* arg1 is less than arg2 */
result = -1; result = -1;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* workings can be found in the book "Software Solutions in C" by * workings can be found in the book "Software Solutions in C" by
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7. * Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
* *
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.59 2003/07/27 04:53:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.60 2003/08/17 19:58:05 tgl Exp $
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -342,6 +342,9 @@ cash_send(PG_FUNCTION_ARGS) ...@@ -342,6 +342,9 @@ cash_send(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
} }
/*
* Comparison functions
*/
Datum Datum
cash_eq(PG_FUNCTION_ARGS) cash_eq(PG_FUNCTION_ARGS)
...@@ -397,6 +400,20 @@ cash_ge(PG_FUNCTION_ARGS) ...@@ -397,6 +400,20 @@ cash_ge(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(c1 >= c2); PG_RETURN_BOOL(c1 >= c2);
} }
Datum
cash_cmp(PG_FUNCTION_ARGS)
{
Cash c1 = PG_GETARG_CASH(0);
Cash c2 = PG_GETARG_CASH(1);
if (c1 > c2)
PG_RETURN_INT32(1);
else if (c1 == c2)
PG_RETURN_INT32(0);
else
PG_RETURN_INT32(-1);
}
/* cash_pl() /* cash_pl()
* Add two cash values. * Add two cash values.
......
This diff is collapsed.
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* *
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.54 2003/08/04 02:40:05 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.55 2003/08/17 19:58:05 tgl Exp $
* *
* ---------- * ----------
*/ */
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "parser/parse_oper.h" #include "parser/parse_oper.h"
#include "rewrite/rewriteHandler.h" #include "rewrite/rewriteHandler.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/typcache.h"
#include "miscadmin.h" #include "miscadmin.h"
...@@ -48,7 +49,6 @@ ...@@ -48,7 +49,6 @@
*/ */
#define RI_INIT_QUERYHASHSIZE 128 #define RI_INIT_QUERYHASHSIZE 128
#define RI_INIT_OPREQHASHSIZE 128
#define RI_MATCH_TYPE_UNSPECIFIED 0 #define RI_MATCH_TYPE_UNSPECIFIED 0
#define RI_MATCH_TYPE_FULL 1 #define RI_MATCH_TYPE_FULL 1
...@@ -109,20 +109,11 @@ typedef struct RI_QueryHashEntry ...@@ -109,20 +109,11 @@ typedef struct RI_QueryHashEntry
} RI_QueryHashEntry; } RI_QueryHashEntry;
typedef struct RI_OpreqHashEntry
{
Oid typeid;
FmgrInfo oprfmgrinfo;
} RI_OpreqHashEntry;
/* ---------- /* ----------
* Local data * Local data
* ---------- * ----------
*/ */
static HTAB *ri_query_cache = (HTAB *) NULL; static HTAB *ri_query_cache = (HTAB *) NULL;
static HTAB *ri_opreq_cache = (HTAB *) NULL;
/* ---------- /* ----------
...@@ -3197,8 +3188,8 @@ ri_NullCheck(Relation rel, HeapTuple tup, RI_QueryKey *key, int pairidx) ...@@ -3197,8 +3188,8 @@ ri_NullCheck(Relation rel, HeapTuple tup, RI_QueryKey *key, int pairidx)
/* ---------- /* ----------
* ri_InitHashTables - * ri_InitHashTables -
* *
* Initialize our internal hash tables for prepared * Initialize our internal hash table for prepared
* query plans and equal operators. * query plans.
* ---------- * ----------
*/ */
static void static void
...@@ -3212,12 +3203,6 @@ ri_InitHashTables(void) ...@@ -3212,12 +3203,6 @@ ri_InitHashTables(void)
ctl.hash = tag_hash; ctl.hash = tag_hash;
ri_query_cache = hash_create("RI query cache", RI_INIT_QUERYHASHSIZE, ri_query_cache = hash_create("RI query cache", RI_INIT_QUERYHASHSIZE,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_FUNCTION);
ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(RI_OpreqHashEntry);
ctl.hash = tag_hash;
ri_opreq_cache = hash_create("RI OpReq cache", RI_INIT_OPREQHASHSIZE,
&ctl, HASH_ELEM | HASH_FUNCTION);
} }
...@@ -3438,57 +3423,22 @@ ri_OneKeyEqual(Relation rel, int column, HeapTuple oldtup, HeapTuple newtup, ...@@ -3438,57 +3423,22 @@ ri_OneKeyEqual(Relation rel, int column, HeapTuple oldtup, HeapTuple newtup,
static bool static bool
ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
{ {
RI_OpreqHashEntry *entry; TypeCacheEntry *typentry;
bool found;
/* /*
* On the first call initialize the hashtable * Find the data type in the typcache, and ask for eq_opr info.
*/ */
if (!ri_opreq_cache) typentry = lookup_type_cache(typeid, TYPECACHE_EQ_OPR_FINFO);
ri_InitHashTables();
/* if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
* Try to find the '=' operator for this type in our cache ereport(ERROR,
*/ (errcode(ERRCODE_UNDEFINED_FUNCTION),
entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache, errmsg("could not identify an equality operator for type %s",
(void *) &typeid, format_type_be(typeid))));
HASH_FIND, NULL);
/*
* If not found, lookup the operator, then do the function manager
* lookup, and remember that info.
*/
if (!entry)
{
Oid opr_proc;
FmgrInfo finfo;
opr_proc = equality_oper_funcid(typeid);
/*
* Since fmgr_info could fail, call it *before* creating the
* hashtable entry --- otherwise we could ereport leaving an
* incomplete entry in the hashtable. Also, because this will be
* a permanent table entry, we must make sure any subsidiary
* structures of the fmgr record are kept in TopMemoryContext.
*/
fmgr_info_cxt(opr_proc, &finfo, TopMemoryContext);
entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
(void *) &typeid,
HASH_ENTER, &found);
if (entry == NULL)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
entry->typeid = typeid;
memcpy(&(entry->oprfmgrinfo), &finfo, sizeof(FmgrInfo));
}
/* /*
* Call the type specific '=' function * Call the type specific '=' function
*/ */
return DatumGetBool(FunctionCall2(&(entry->oprfmgrinfo), return DatumGetBool(FunctionCall2(&(typentry->eq_opr_finfo),
oldvalue, newvalue)); oldvalue, newvalue));
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.151 2003/08/11 23:04:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.152 2003/08/17 19:58:05 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
#include "utils/array.h" #include "utils/array.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/typcache.h"
/* ---------- /* ----------
...@@ -1815,21 +1816,24 @@ get_select_query_def(Query *query, deparse_context *context, ...@@ -1815,21 +1816,24 @@ get_select_query_def(Query *query, deparse_context *context,
SortClause *srt = (SortClause *) lfirst(l); SortClause *srt = (SortClause *) lfirst(l);
Node *sortexpr; Node *sortexpr;
Oid sortcoltype; Oid sortcoltype;
char *opname; TypeCacheEntry *typentry;
appendStringInfo(buf, sep); appendStringInfo(buf, sep);
sortexpr = get_rule_sortgroupclause(srt, query->targetList, sortexpr = get_rule_sortgroupclause(srt, query->targetList,
force_colno, context); force_colno, context);
sortcoltype = exprType(sortexpr); sortcoltype = exprType(sortexpr);
opname = generate_operator_name(srt->sortop, /* See whether operator is default < or > for datatype */
sortcoltype, sortcoltype); typentry = lookup_type_cache(sortcoltype,
if (strcmp(opname, "<") != 0) TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
{ if (srt->sortop == typentry->lt_opr)
if (strcmp(opname, ">") == 0) /* ASC is default, so emit nothing */ ;
appendStringInfo(buf, " DESC"); else if (srt->sortop == typentry->gt_opr)
else appendStringInfo(buf, " DESC");
appendStringInfo(buf, " USING %s", opname); else
} appendStringInfo(buf, " USING %s",
generate_operator_name(srt->sortop,
sortcoltype,
sortcoltype));
sep = ", "; sep = ", ";
} }
} }
...@@ -4032,6 +4036,15 @@ get_opclass_name(Oid opclass, Oid actual_datatype, ...@@ -4032,6 +4036,15 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
if (!HeapTupleIsValid(ht_opc)) if (!HeapTupleIsValid(ht_opc))
elog(ERROR, "cache lookup failed for opclass %u", opclass); elog(ERROR, "cache lookup failed for opclass %u", opclass);
opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc); opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
/* Special case for ARRAY_OPS: pretend it is default for any array type */
if (OidIsValid(actual_datatype))
{
if (opcrec->opcintype == ANYARRAYOID &&
OidIsValid(get_element_type(actual_datatype)))
actual_datatype = opcrec->opcintype;
}
if (actual_datatype != opcrec->opcintype || !opcrec->opcdefault) if (actual_datatype != opcrec->opcintype || !opcrec->opcdefault)
{ {
/* Okay, we need the opclass name. Do we need to qualify it? */ /* Okay, we need the opclass name. Do we need to qualify it? */
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for utils/cache # Makefile for utils/cache
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.17 2002/12/13 19:45:56 tgl Exp $ # $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.18 2003/08/17 19:58:06 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -12,7 +12,7 @@ subdir = src/backend/utils/cache ...@@ -12,7 +12,7 @@ subdir = src/backend/utils/cache
top_builddir = ../../../.. top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o typcache.o
all: SUBSYS.o all: SUBSYS.o
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.106 2003/08/11 23:04:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.107 2003/08/17 19:58:06 tgl Exp $
* *
* NOTES * NOTES
* Eventually, the index information should go through here, too. * Eventually, the index information should go through here, too.
...@@ -122,7 +122,6 @@ get_op_hash_function(Oid opno) ...@@ -122,7 +122,6 @@ get_op_hash_function(Oid opno)
{ {
CatCList *catlist; CatCList *catlist;
int i; int i;
HeapTuple tuple;
Oid opclass = InvalidOid; Oid opclass = InvalidOid;
/* /*
...@@ -137,10 +136,8 @@ get_op_hash_function(Oid opno) ...@@ -137,10 +136,8 @@ get_op_hash_function(Oid opno)
for (i = 0; i < catlist->n_members; i++) for (i = 0; i < catlist->n_members; i++)
{ {
Form_pg_amop aform; HeapTuple tuple = &catlist->members[i]->tuple;
Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
tuple = &catlist->members[i]->tuple;
aform = (Form_pg_amop) GETSTRUCT(tuple);
if (aform->amopstrategy == HTEqualStrategyNumber && if (aform->amopstrategy == HTEqualStrategyNumber &&
opclass_is_hash(aform->amopclaid)) opclass_is_hash(aform->amopclaid))
...@@ -155,20 +152,7 @@ get_op_hash_function(Oid opno) ...@@ -155,20 +152,7 @@ get_op_hash_function(Oid opno)
if (OidIsValid(opclass)) if (OidIsValid(opclass))
{ {
/* Found a suitable opclass, get its hash support function */ /* Found a suitable opclass, get its hash support function */
tuple = SearchSysCache(AMPROCNUM, return get_opclass_proc(opclass, HASHPROC);
ObjectIdGetDatum(opclass),
Int16GetDatum(HASHPROC),
0, 0);
if (HeapTupleIsValid(tuple))
{
Form_pg_amproc aform = (Form_pg_amproc) GETSTRUCT(tuple);
RegProcedure result;
result = aform->amproc;
ReleaseSysCache(tuple);
Assert(RegProcedureIsValid(result));
return result;
}
} }
/* Didn't find a match... */ /* Didn't find a match... */
...@@ -176,6 +160,35 @@ get_op_hash_function(Oid opno) ...@@ -176,6 +160,35 @@ get_op_hash_function(Oid opno)
} }
/* ---------- AMPROC CACHES ---------- */
/*
* get_opclass_proc
* Get the OID of the specified support function
* for the specified opclass.
*
* Returns InvalidOid if there is no pg_amproc entry for the given keys.
*/
Oid
get_opclass_proc(Oid opclass, int16 procnum)
{
HeapTuple tp;
Form_pg_amproc amproc_tup;
RegProcedure result;
tp = SearchSysCache(AMPROCNUM,
ObjectIdGetDatum(opclass),
Int16GetDatum(procnum),
0, 0);
if (!HeapTupleIsValid(tp))
return InvalidOid;
amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
result = amproc_tup->amproc;
ReleaseSysCache(tp);
return result;
}
/* ---------- ATTRIBUTE CACHES ---------- */ /* ---------- ATTRIBUTE CACHES ---------- */
/* /*
......
/*-------------------------------------------------------------------------
*
* typcache.c
* POSTGRES type cache code
*
* The type cache exists to speed lookup of certain information about data
* types that is not directly available from a type's pg_type row. In
* particular, we use a type's default btree opclass, or the default hash
* opclass if no btree opclass exists, to determine which operators should
* be used for grouping and sorting the type (GROUP BY, ORDER BY ASC/DESC).
*
* Several seemingly-odd choices have been made to support use of the type
* cache by the generic array comparison routines array_eq() and array_cmp().
* Because these routines are used as index support operations, they cannot
* leak memory. To allow them to execute efficiently, all information that
* either of them would like to re-use across calls is made available in the
* type cache.
*
* Once created, a type cache entry lives as long as the backend does, so
* there is no need for a call to release a cache entry. (For present uses,
* it would be okay to flush type cache entries at the ends of transactions,
* if we needed to reclaim space.)
*
* There is presently no provision for clearing out a cache entry if the
* stored data becomes obsolete. (The code will work if a type acquires
* opclasses it didn't have before while a backend runs --- but not if the
* definition of an existing opclass is altered.) However, the relcache
* doesn't cope with opclasses changing under it, either, so this seems
* a low-priority problem.
*
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/typcache.c,v 1.1 2003/08/17 19:58:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/hash.h"
#include "access/nbtree.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/pg_am.h"
#include "catalog/pg_opclass.h"
#include "parser/parse_coerce.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/hsearch.h"
#include "utils/lsyscache.h"
#include "utils/typcache.h"
static HTAB *TypeCacheHash = NULL;
static Oid lookup_default_opclass(Oid type_id, Oid am_id);
/*
* lookup_type_cache
*
* Fetch the type cache entry for the specified datatype, and make sure that
* all the fields requested by bits in 'flags' are valid.
*
* The result is never NULL --- we will elog() if the passed type OID is
* invalid. Note however that we may fail to find one or more of the
* requested opclass-dependent fields; the caller needs to check whether
* the fields are InvalidOid or not.
*/
TypeCacheEntry *
lookup_type_cache(Oid type_id, int flags)
{
TypeCacheEntry *typentry;
bool found;
if (TypeCacheHash == NULL)
{
/* First time through: initialize the hash table */
HASHCTL ctl;
if (!CacheMemoryContext)
CreateCacheMemoryContext();
MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(TypeCacheEntry);
ctl.hash = tag_hash;
TypeCacheHash = hash_create("Type information cache", 64,
&ctl, HASH_ELEM | HASH_FUNCTION);
}
/* Try to look up an existing entry */
typentry = (TypeCacheEntry *) hash_search(TypeCacheHash,
(void *) &type_id,
HASH_FIND, NULL);
if (typentry == NULL)
{
/*
* If we didn't find one, we want to make one. But first get the
* required info from the pg_type row, just to make sure we don't
* make a cache entry for an invalid type OID.
*/
int16 typlen;
bool typbyval;
char typalign;
get_typlenbyvalalign(type_id, &typlen, &typbyval, &typalign);
typentry = (TypeCacheEntry *) hash_search(TypeCacheHash,
(void *) &type_id,
HASH_ENTER, &found);
if (typentry == NULL)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
Assert(!found); /* it wasn't there a moment ago */
MemSet(typentry, 0, sizeof(TypeCacheEntry));
typentry->type_id = type_id;
typentry->typlen = typlen;
typentry->typbyval = typbyval;
typentry->typalign = typalign;
}
/* If we haven't already found the opclass, try to do so */
if (flags != 0 && typentry->btree_opc == InvalidOid)
{
typentry->btree_opc = lookup_default_opclass(type_id,
BTREE_AM_OID);
/* Only care about hash opclass if no btree opclass... */
if (typentry->btree_opc == InvalidOid)
{
if (typentry->hash_opc == InvalidOid)
typentry->hash_opc = lookup_default_opclass(type_id,
HASH_AM_OID);
}
else
{
/*
* If we find a btree opclass where previously we only found
* a hash opclass, forget the hash equality operator so we
* can use the btree operator instead.
*/
typentry->eq_opr = InvalidOid;
typentry->eq_opr_finfo.fn_oid = InvalidOid;
}
}
/* Look for requested operators and functions */
if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
typentry->eq_opr == InvalidOid)
{
if (typentry->btree_opc != InvalidOid)
typentry->eq_opr = get_opclass_member(typentry->btree_opc,
BTEqualStrategyNumber);
if (typentry->eq_opr == InvalidOid &&
typentry->hash_opc != InvalidOid)
typentry->eq_opr = get_opclass_member(typentry->hash_opc,
HTEqualStrategyNumber);
}
if ((flags & TYPECACHE_LT_OPR) && typentry->lt_opr == InvalidOid)
{
if (typentry->btree_opc != InvalidOid)
typentry->lt_opr = get_opclass_member(typentry->btree_opc,
BTLessStrategyNumber);
}
if ((flags & TYPECACHE_GT_OPR) && typentry->gt_opr == InvalidOid)
{
if (typentry->btree_opc != InvalidOid)
typentry->gt_opr = get_opclass_member(typentry->btree_opc,
BTGreaterStrategyNumber);
}
if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
typentry->cmp_proc == InvalidOid)
{
if (typentry->btree_opc != InvalidOid)
typentry->cmp_proc = get_opclass_proc(typentry->btree_opc,
BTORDER_PROC);
}
/*
* Set up fmgr lookup info as requested
*
* Note: we tell fmgr the finfo structures live in CacheMemoryContext,
* which is not quite right (they're really in DynaHashContext) but this
* will do for our purposes.
*/
if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
typentry->eq_opr_finfo.fn_oid == InvalidOid &&
typentry->eq_opr != InvalidOid)
{
Oid eq_opr_func;
eq_opr_func = get_opcode(typentry->eq_opr);
if (eq_opr_func != InvalidOid)
fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
CacheMemoryContext);
}
if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
typentry->cmp_proc != InvalidOid)
{
fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
CacheMemoryContext);
}
return typentry;
}
/*
* lookup_default_opclass
*
* Given the OIDs of a datatype and an access method, find the default
* operator class, if any. Returns InvalidOid if there is none.
*/
static Oid
lookup_default_opclass(Oid type_id, Oid am_id)
{
int nexact = 0;
int ncompatible = 0;
Oid exactOid = InvalidOid;
Oid compatibleOid = InvalidOid;
Relation rel;
ScanKeyData skey[1];
SysScanDesc scan;
HeapTuple tup;
/* If it's a domain, look at the base type instead */
type_id = getBaseType(type_id);
/*
* We scan through all the opclasses available for the access method,
* looking for one that is marked default and matches the target type
* (either exactly or binary-compatibly, but prefer an exact match).
*
* We could find more than one binary-compatible match, in which case we
* require the user to specify which one he wants. If we find more
* than one exact match, then someone put bogus entries in pg_opclass.
*
* This is the same logic as GetDefaultOpClass() in indexcmds.c, except
* that we consider all opclasses, regardless of the current search path.
*/
rel = heap_openr(OperatorClassRelationName, AccessShareLock);
ScanKeyEntryInitialize(&skey[0], 0x0,
Anum_pg_opclass_opcamid, F_OIDEQ,
ObjectIdGetDatum(am_id));
scan = systable_beginscan(rel, OpclassAmNameNspIndex, true,
SnapshotNow, 1, skey);
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
if (opclass->opcdefault)
{
if (opclass->opcintype == type_id)
{
nexact++;
exactOid = HeapTupleGetOid(tup);
}
else if (IsBinaryCoercible(type_id, opclass->opcintype))
{
ncompatible++;
compatibleOid = HeapTupleGetOid(tup);
}
}
}
systable_endscan(scan);
heap_close(rel, AccessShareLock);
if (nexact == 1)
return exactOid;
if (nexact != 0)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("there are multiple default operator classes for data type %s",
format_type_be(type_id))));
if (ncompatible == 1)
return compatibleOid;
return InvalidOid;
}
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.36 2003/08/04 02:40:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.37 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -88,7 +88,6 @@ ...@@ -88,7 +88,6 @@
#include "access/heapam.h" #include "access/heapam.h"
#include "access/nbtree.h" #include "access/nbtree.h"
#include "catalog/pg_amop.h" #include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/catcache.h" #include "utils/catcache.h"
...@@ -1754,26 +1753,17 @@ SelectSortFunction(Oid sortOperator, ...@@ -1754,26 +1753,17 @@ SelectSortFunction(Oid sortOperator,
if (OidIsValid(opclass)) if (OidIsValid(opclass))
{ {
/* Found a suitable opclass, get its comparator support function */ /* Found a suitable opclass, get its comparator support function */
tuple = SearchSysCache(AMPROCNUM, *sortFunction = get_opclass_proc(opclass, BTORDER_PROC);
ObjectIdGetDatum(opclass), Assert(RegProcedureIsValid(*sortFunction));
Int16GetDatum(BTORDER_PROC), return;
0, 0);
if (HeapTupleIsValid(tuple))
{
Form_pg_amproc aform = (Form_pg_amproc) GETSTRUCT(tuple);
*sortFunction = aform->amproc;
ReleaseSysCache(tuple);
Assert(RegProcedureIsValid(*sortFunction));
return;
}
} }
/* /*
* Can't find a comparator, so use the operator as-is. Decide whether * Can't find a comparator, so use the operator as-is. Decide whether
* it is forward or reverse sort by looking at its name (grotty, but * it is forward or reverse sort by looking at its name (grotty, but
* this only matters for deciding which end NULLs should get sorted * this only matters for deciding which end NULLs should get sorted
* to). * to). XXX possibly better idea: see whether its selectivity function
* is scalargtcmp?
*/ */
tuple = SearchSysCache(OPEROID, tuple = SearchSysCache(OPEROID,
ObjectIdGetDatum(sortOperator), ObjectIdGetDatum(sortOperator),
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.206 2003/08/04 02:40:10 momjian Exp $ * $Id: catversion.h,v 1.207 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200307301 #define CATALOG_VERSION_NO 200308171
#endif #endif
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_amop.h,v 1.54 2003/08/04 02:40:10 momjian Exp $ * $Id: pg_amop.h,v 1.55 2003/08/17 19:58:06 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -418,6 +418,36 @@ DATA(insert ( 2098 3 f 2334 )); ...@@ -418,6 +418,36 @@ DATA(insert ( 2098 3 f 2334 ));
DATA(insert ( 2098 4 f 2335 )); DATA(insert ( 2098 4 f 2335 ));
DATA(insert ( 2098 5 f 2336 )); DATA(insert ( 2098 5 f 2336 ));
/*
* btree money_ops
*/
DATA(insert ( 2099 1 f 902 ));
DATA(insert ( 2099 2 f 904 ));
DATA(insert ( 2099 3 f 900 ));
DATA(insert ( 2099 4 f 905 ));
DATA(insert ( 2099 5 f 903 ));
/*
* btree reltime_ops
*/
DATA(insert ( 2233 1 f 568 ));
DATA(insert ( 2233 2 f 570 ));
DATA(insert ( 2233 3 f 566 ));
DATA(insert ( 2233 4 f 569 ));
DATA(insert ( 2233 5 f 571 ));
/*
* btree tinterval_ops
*/
DATA(insert ( 2234 1 f 813 ));
DATA(insert ( 2234 2 f 815 ));
DATA(insert ( 2234 3 f 811 ));
DATA(insert ( 2234 4 f 814 ));
DATA(insert ( 2234 5 f 816 ));
/* /*
* btree array_ops * btree array_ops
*/ */
...@@ -496,5 +526,7 @@ DATA(insert ( 2230 1 f 2316 )); ...@@ -496,5 +526,7 @@ DATA(insert ( 2230 1 f 2316 ));
DATA(insert ( 2231 1 f 2328 )); DATA(insert ( 2231 1 f 2328 ));
/* name_pattern_ops */ /* name_pattern_ops */
DATA(insert ( 2232 1 f 2334 )); DATA(insert ( 2232 1 f 2334 ));
/* aclitem_ops */
DATA(insert ( 2235 1 f 974 ));
#endif /* PG_AMOP_H */ #endif /* PG_AMOP_H */
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_amproc.h,v 1.43 2003/08/04 02:40:11 momjian Exp $ * $Id: pg_amproc.h,v 1.44 2003/08/17 19:58:06 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -110,6 +110,9 @@ DATA(insert ( 2095 1 2166 )); ...@@ -110,6 +110,9 @@ DATA(insert ( 2095 1 2166 ));
DATA(insert ( 2096 1 2166 )); DATA(insert ( 2096 1 2166 ));
DATA(insert ( 2097 1 2180 )); DATA(insert ( 2097 1 2180 ));
DATA(insert ( 2098 1 2187 )); DATA(insert ( 2098 1 2187 ));
DATA(insert ( 2099 1 377 ));
DATA(insert ( 2233 1 380 ));
DATA(insert ( 2234 1 381 ));
/* hash */ /* hash */
...@@ -145,5 +148,6 @@ DATA(insert ( 2229 1 456 )); ...@@ -145,5 +148,6 @@ DATA(insert ( 2229 1 456 ));
DATA(insert ( 2230 1 456 )); DATA(insert ( 2230 1 456 ));
DATA(insert ( 2231 1 456 )); DATA(insert ( 2231 1 456 ));
DATA(insert ( 2232 1 455 )); DATA(insert ( 2232 1 455 ));
DATA(insert ( 2235 1 329 ));
#endif /* PG_AMPROC_H */ #endif /* PG_AMPROC_H */
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_opclass.h,v 1.56 2003/08/04 02:40:12 momjian Exp $ * $Id: pg_opclass.h,v 1.57 2003/08/17 19:58:06 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -157,6 +157,7 @@ DATA(insert OID = 2097 ( 403 bpchar_pattern_ops PGNSP PGUID 1042 f 0 )); ...@@ -157,6 +157,7 @@ DATA(insert OID = 2097 ( 403 bpchar_pattern_ops PGNSP PGUID 1042 f 0 ));
#define BPCHAR_PATTERN_BTREE_OPS_OID 2097 #define BPCHAR_PATTERN_BTREE_OPS_OID 2097
DATA(insert OID = 2098 ( 403 name_pattern_ops PGNSP PGUID 19 f 0 )); DATA(insert OID = 2098 ( 403 name_pattern_ops PGNSP PGUID 19 f 0 ));
#define NAME_PATTERN_BTREE_OPS_OID 2098 #define NAME_PATTERN_BTREE_OPS_OID 2098
DATA(insert OID = 2099 ( 403 money_ops PGNSP PGUID 790 t 0 ));
DATA(insert OID = 2222 ( 405 bool_ops PGNSP PGUID 16 t 0 )); DATA(insert OID = 2222 ( 405 bool_ops PGNSP PGUID 16 t 0 ));
DATA(insert OID = 2223 ( 405 bytea_ops PGNSP PGUID 17 t 0 )); DATA(insert OID = 2223 ( 405 bytea_ops PGNSP PGUID 17 t 0 ));
DATA(insert OID = 2224 ( 405 int2vector_ops PGNSP PGUID 22 t 0 )); DATA(insert OID = 2224 ( 405 int2vector_ops PGNSP PGUID 22 t 0 ));
...@@ -168,5 +169,8 @@ DATA(insert OID = 2229 ( 405 text_pattern_ops PGNSP PGUID 25 f 0 )); ...@@ -168,5 +169,8 @@ DATA(insert OID = 2229 ( 405 text_pattern_ops PGNSP PGUID 25 f 0 ));
DATA(insert OID = 2230 ( 405 varchar_pattern_ops PGNSP PGUID 1043 f 0 )); DATA(insert OID = 2230 ( 405 varchar_pattern_ops PGNSP PGUID 1043 f 0 ));
DATA(insert OID = 2231 ( 405 bpchar_pattern_ops PGNSP PGUID 1042 f 0 )); DATA(insert OID = 2231 ( 405 bpchar_pattern_ops PGNSP PGUID 1042 f 0 ));
DATA(insert OID = 2232 ( 405 name_pattern_ops PGNSP PGUID 19 f 0 )); DATA(insert OID = 2232 ( 405 name_pattern_ops PGNSP PGUID 19 f 0 ));
DATA(insert OID = 2233 ( 403 reltime_ops PGNSP PGUID 703 t 0 ));
DATA(insert OID = 2234 ( 403 tinterval_ops PGNSP PGUID 704 t 0 ));
DATA(insert OID = 2235 ( 405 aclitem_ops PGNSP PGUID 1033 t 0 ));
#endif /* PG_OPCLASS_H */ #endif /* PG_OPCLASS_H */
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_operator.h,v 1.120 2003/08/04 02:40:12 momjian Exp $ * $Id: pg_operator.h,v 1.121 2003/08/17 19:58:06 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -424,7 +424,7 @@ DATA(insert OID = 965 ( "^" PGNSP PGUID b f 701 701 701 0 0 0 0 0 0 dpow - ...@@ -424,7 +424,7 @@ DATA(insert OID = 965 ( "^" PGNSP PGUID b f 701 701 701 0 0 0 0 0 0 dpow -
DATA(insert OID = 966 ( "+" PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclinsert - - )); DATA(insert OID = 966 ( "+" PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclinsert - - ));
DATA(insert OID = 967 ( "-" PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclremove - - )); DATA(insert OID = 967 ( "-" PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclremove - - ));
DATA(insert OID = 968 ( "~" PGNSP PGUID b f 1034 1033 16 0 0 0 0 0 0 aclcontains - - )); DATA(insert OID = 968 ( "~" PGNSP PGUID b f 1034 1033 16 0 0 0 0 0 0 aclcontains - - ));
DATA(insert OID = 974 ( "=" PGNSP PGUID b f 1033 1033 16 974 0 0 0 0 0 aclitemeq eqsel eqjoinsel )); DATA(insert OID = 974 ( "=" PGNSP PGUID b t 1033 1033 16 974 0 0 0 0 0 aclitemeq eqsel eqjoinsel ));
/* additional geometric operators - thomas 1997-07-09 */ /* additional geometric operators - thomas 1997-07-09 */
DATA(insert OID = 969 ( "@@" PGNSP PGUID l f 0 601 600 0 0 0 0 0 0 lseg_center - - )); DATA(insert OID = 969 ( "@@" PGNSP PGUID l f 0 601 600 0 0 0 0 0 0 lseg_center - - ));
...@@ -448,6 +448,7 @@ DATA(insert OID = 1071 ( "<>" PGNSP PGUID b f 2277 2277 16 1071 1070 0 0 0 ...@@ -448,6 +448,7 @@ DATA(insert OID = 1071 ( "<>" PGNSP PGUID b f 2277 2277 16 1071 1070 0 0 0
DATA(insert OID = 1072 ( "<" PGNSP PGUID b f 2277 2277 16 1073 1075 0 0 0 0 array_lt scalarltsel scalarltjoinsel )); DATA(insert OID = 1072 ( "<" PGNSP PGUID b f 2277 2277 16 1073 1075 0 0 0 0 array_lt scalarltsel scalarltjoinsel ));
#define ARRAY_LT_OP 1072 #define ARRAY_LT_OP 1072
DATA(insert OID = 1073 ( ">" PGNSP PGUID b f 2277 2277 16 1072 1074 0 0 0 0 array_gt scalargtsel scalargtjoinsel )); DATA(insert OID = 1073 ( ">" PGNSP PGUID b f 2277 2277 16 1072 1074 0 0 0 0 array_gt scalargtsel scalargtjoinsel ));
#define ARRAY_GT_OP 1073
DATA(insert OID = 1074 ( "<=" PGNSP PGUID b f 2277 2277 16 1075 1073 0 0 0 0 array_le scalarltsel scalarltjoinsel )); DATA(insert OID = 1074 ( "<=" PGNSP PGUID b f 2277 2277 16 1075 1073 0 0 0 0 array_le scalarltsel scalarltjoinsel ));
DATA(insert OID = 1075 ( ">=" PGNSP PGUID b f 2277 2277 16 1074 1072 0 0 0 0 array_ge scalargtsel scalargtjoinsel )); DATA(insert OID = 1075 ( ">=" PGNSP PGUID b f 2277 2277 16 1074 1072 0 0 0 0 array_ge scalargtsel scalargtjoinsel ));
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_proc.h,v 1.312 2003/08/04 02:40:12 momjian Exp $ * $Id: pg_proc.h,v 1.313 2003/08/17 19:58:06 tgl Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -758,6 +758,12 @@ DATA(insert OID = 359 ( btnamecmp PGNSP PGUID 12 f f t f i 2 23 "19 19" btn ...@@ -758,6 +758,12 @@ DATA(insert OID = 359 ( btnamecmp PGNSP PGUID 12 f f t f i 2 23 "19 19" btn
DESCR("btree less-equal-greater"); DESCR("btree less-equal-greater");
DATA(insert OID = 360 ( bttextcmp PGNSP PGUID 12 f f t f i 2 23 "25 25" bttextcmp - _null_ )); DATA(insert OID = 360 ( bttextcmp PGNSP PGUID 12 f f t f i 2 23 "25 25" bttextcmp - _null_ ));
DESCR("btree less-equal-greater"); DESCR("btree less-equal-greater");
DATA(insert OID = 377 ( cash_cmp PGNSP PGUID 12 f f t f i 2 23 "790 790" cash_cmp - _null_ ));
DESCR("btree less-equal-greater");
DATA(insert OID = 380 ( btreltimecmp PGNSP PGUID 12 f f t f i 2 23 "703 703" btreltimecmp - _null_ ));
DESCR("btree less-equal-greater");
DATA(insert OID = 381 ( bttintervalcmp PGNSP PGUID 12 f f t f i 2 23 "704 704" bttintervalcmp - _null_ ));
DESCR("btree less-equal-greater");
DATA(insert OID = 382 ( btarraycmp PGNSP PGUID 12 f f t f i 2 23 "2277 2277" btarraycmp - _null_ )); DATA(insert OID = 382 ( btarraycmp PGNSP PGUID 12 f f t f i 2 23 "2277 2277" btarraycmp - _null_ ));
DESCR("btree less-equal-greater"); DESCR("btree less-equal-greater");
...@@ -844,6 +850,8 @@ DATA(insert OID = 456 ( hashvarlena PGNSP PGUID 12 f f t f i 1 23 "2281" has ...@@ -844,6 +850,8 @@ DATA(insert OID = 456 ( hashvarlena PGNSP PGUID 12 f f t f i 1 23 "2281" has
DESCR("hash any varlena type"); DESCR("hash any varlena type");
DATA(insert OID = 457 ( hashoidvector PGNSP PGUID 12 f f t f i 1 23 "30" hashoidvector - _null_ )); DATA(insert OID = 457 ( hashoidvector PGNSP PGUID 12 f f t f i 1 23 "30" hashoidvector - _null_ ));
DESCR("hash"); DESCR("hash");
DATA(insert OID = 329 ( hash_aclitem PGNSP PGUID 12 f f t f i 1 23 "1033" hash_aclitem - _null_ ));
DESCR("hash");
DATA(insert OID = 398 ( hashint2vector PGNSP PGUID 12 f f t f i 1 23 "22" hashint2vector - _null_ )); DATA(insert OID = 398 ( hashint2vector PGNSP PGUID 12 f f t f i 1 23 "22" hashint2vector - _null_ ));
DESCR("hash"); DESCR("hash");
DATA(insert OID = 399 ( hashmacaddr PGNSP PGUID 12 f f t f i 1 23 "829" hashmacaddr - _null_ )); DATA(insert OID = 399 ( hashmacaddr PGNSP PGUID 12 f f t f i 1 23 "829" hashmacaddr - _null_ ));
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: nodes.h,v 1.146 2003/08/04 02:40:13 momjian Exp $ * $Id: nodes.h,v 1.147 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -265,7 +265,7 @@ typedef enum NodeTag ...@@ -265,7 +265,7 @@ typedef enum NodeTag
T_ExprFieldSelect, T_ExprFieldSelect,
T_ResTarget, T_ResTarget,
T_TypeCast, T_TypeCast,
T_SortGroupBy, T_SortBy,
T_RangeSubselect, T_RangeSubselect,
T_RangeFunction, T_RangeFunction,
T_TypeName, T_TypeName,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.246 2003/08/08 21:42:48 momjian Exp $ * $Id: parsenodes.h,v 1.247 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -279,14 +279,19 @@ typedef struct ResTarget ...@@ -279,14 +279,19 @@ typedef struct ResTarget
} ResTarget; } ResTarget;
/* /*
* SortGroupBy - for ORDER BY clause * SortBy - for ORDER BY clause
*/ */
typedef struct SortGroupBy #define SORTBY_ASC 1
#define SORTBY_DESC 2
#define SORTBY_USING 3
typedef struct SortBy
{ {
NodeTag type; NodeTag type;
List *useOp; /* operator to use */ int sortby_kind; /* see codes above */
Node *node; /* Expression */ List *useOp; /* name of op to use, if SORTBY_USING */
} SortGroupBy; Node *node; /* expression to sort on */
} SortBy;
/* /*
* RangeSubselect - subquery appearing in a FROM clause * RangeSubselect - subquery appearing in a FROM clause
...@@ -614,7 +619,7 @@ typedef struct SelectStmt ...@@ -614,7 +619,7 @@ typedef struct SelectStmt
* These fields are used in both "leaf" SelectStmts and upper-level * These fields are used in both "leaf" SelectStmts and upper-level
* SelectStmts. * SelectStmts.
*/ */
List *sortClause; /* sort clause (a list of SortGroupBy's) */ List *sortClause; /* sort clause (a list of SortBy's) */
Node *limitOffset; /* # of result tuples to skip */ Node *limitOffset; /* # of result tuples to skip */
Node *limitCount; /* # of result tuples to return */ Node *limitCount; /* # of result tuples to return */
List *forUpdate; /* FOR UPDATE clause */ List *forUpdate; /* FOR UPDATE clause */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_clause.h,v 1.36 2003/08/07 19:20:23 tgl Exp $ * $Id: parse_clause.h,v 1.37 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -37,7 +37,8 @@ extern List *addAllTargetsToSortList(ParseState *pstate, ...@@ -37,7 +37,8 @@ extern List *addAllTargetsToSortList(ParseState *pstate,
bool resolveUnknown); bool resolveUnknown);
extern List *addTargetToSortList(ParseState *pstate, TargetEntry *tle, extern List *addTargetToSortList(ParseState *pstate, TargetEntry *tle,
List *sortlist, List *targetlist, List *sortlist, List *targetlist,
List *opname, bool resolveUnknown); int sortby_kind, List *sortby_opname,
bool resolveUnknown);
extern Index assignSortGroupRef(TargetEntry *tle, List *tlist); extern Index assignSortGroupRef(TargetEntry *tle, List *tlist);
extern bool targetIsInSortList(TargetEntry *tle, List *sortList); extern bool targetIsInSortList(TargetEntry *tle, List *sortList);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_oper.h,v 1.32 2003/08/04 02:40:14 momjian Exp $ * $Id: parse_oper.h,v 1.33 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -38,15 +38,16 @@ extern Operator compatible_oper(List *op, Oid arg1, Oid arg2, bool noError); ...@@ -38,15 +38,16 @@ extern Operator compatible_oper(List *op, Oid arg1, Oid arg2, bool noError);
/* currently no need for compatible_left_oper/compatible_right_oper */ /* currently no need for compatible_left_oper/compatible_right_oper */
/* Routines for identifying "=" and "<" operators for a type */ /* Routines for identifying "=", "<", ">" operators for a type */
extern Operator equality_oper(Oid argtype, bool noError); extern Operator equality_oper(Oid argtype, bool noError);
extern Operator ordering_oper(Oid argtype, bool noError); extern Operator ordering_oper(Oid argtype, bool noError);
extern Operator reverse_ordering_oper(Oid argtype, bool noError);
/* Convenience routines for common calls on the above */ /* Convenience routines for common calls on the above */
extern Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError); extern Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError);
extern Oid equality_oper_funcid(Oid argtype); extern Oid equality_oper_funcid(Oid argtype);
extern Oid ordering_oper_opid(Oid argtype); extern Oid ordering_oper_opid(Oid argtype);
extern Oid ordering_oper_funcid(Oid argtype); extern Oid reverse_ordering_oper_opid(Oid argtype);
/* Extract operator OID or underlying-function OID from an Operator tuple */ /* Extract operator OID or underlying-function OID from an Operator tuple */
extern Oid oprid(Operator op); extern Oid oprid(Operator op);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: acl.h,v 1.61 2003/08/08 21:42:55 momjian Exp $ * $Id: acl.h,v 1.62 2003/08/17 19:58:06 tgl Exp $
* *
* NOTES * NOTES
* For backward-compatibility purposes we have to allow there * For backward-compatibility purposes we have to allow there
...@@ -209,6 +209,7 @@ extern Datum aclremove(PG_FUNCTION_ARGS); ...@@ -209,6 +209,7 @@ extern Datum aclremove(PG_FUNCTION_ARGS);
extern Datum aclcontains(PG_FUNCTION_ARGS); extern Datum aclcontains(PG_FUNCTION_ARGS);
extern Datum makeaclitem(PG_FUNCTION_ARGS); extern Datum makeaclitem(PG_FUNCTION_ARGS);
extern Datum aclitem_eq(PG_FUNCTION_ARGS); extern Datum aclitem_eq(PG_FUNCTION_ARGS);
extern Datum hash_aclitem(PG_FUNCTION_ARGS);
/* /*
* prototypes for functions in aclchk.c * prototypes for functions in aclchk.c
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: builtins.h,v 1.227 2003/08/08 21:42:55 momjian Exp $ * $Id: builtins.h,v 1.228 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -222,6 +222,8 @@ extern Datum btfloat8cmp(PG_FUNCTION_ARGS); ...@@ -222,6 +222,8 @@ extern Datum btfloat8cmp(PG_FUNCTION_ARGS);
extern Datum btoidcmp(PG_FUNCTION_ARGS); extern Datum btoidcmp(PG_FUNCTION_ARGS);
extern Datum btoidvectorcmp(PG_FUNCTION_ARGS); extern Datum btoidvectorcmp(PG_FUNCTION_ARGS);
extern Datum btabstimecmp(PG_FUNCTION_ARGS); extern Datum btabstimecmp(PG_FUNCTION_ARGS);
extern Datum btreltimecmp(PG_FUNCTION_ARGS);
extern Datum bttintervalcmp(PG_FUNCTION_ARGS);
extern Datum btcharcmp(PG_FUNCTION_ARGS); extern Datum btcharcmp(PG_FUNCTION_ARGS);
extern Datum btnamecmp(PG_FUNCTION_ARGS); extern Datum btnamecmp(PG_FUNCTION_ARGS);
extern Datum bttextcmp(PG_FUNCTION_ARGS); extern Datum bttextcmp(PG_FUNCTION_ARGS);
......
...@@ -23,6 +23,7 @@ extern Datum cash_lt(PG_FUNCTION_ARGS); ...@@ -23,6 +23,7 @@ extern Datum cash_lt(PG_FUNCTION_ARGS);
extern Datum cash_le(PG_FUNCTION_ARGS); extern Datum cash_le(PG_FUNCTION_ARGS);
extern Datum cash_gt(PG_FUNCTION_ARGS); extern Datum cash_gt(PG_FUNCTION_ARGS);
extern Datum cash_ge(PG_FUNCTION_ARGS); extern Datum cash_ge(PG_FUNCTION_ARGS);
extern Datum cash_cmp(PG_FUNCTION_ARGS);
extern Datum cash_pl(PG_FUNCTION_ARGS); extern Datum cash_pl(PG_FUNCTION_ARGS);
extern Datum cash_mi(PG_FUNCTION_ARGS); extern Datum cash_mi(PG_FUNCTION_ARGS);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: lsyscache.h,v 1.80 2003/08/11 23:04:50 tgl Exp $ * $Id: lsyscache.h,v 1.81 2003/08/17 19:58:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -28,6 +28,7 @@ extern bool op_in_opclass(Oid opno, Oid opclass); ...@@ -28,6 +28,7 @@ extern bool op_in_opclass(Oid opno, Oid opclass);
extern bool op_requires_recheck(Oid opno, Oid opclass); extern bool op_requires_recheck(Oid opno, Oid opclass);
extern Oid get_opclass_member(Oid opclass, int16 strategy); extern Oid get_opclass_member(Oid opclass, int16 strategy);
extern Oid get_op_hash_function(Oid opno); extern Oid get_op_hash_function(Oid opno);
extern Oid get_opclass_proc(Oid opclass, int16 procnum);
extern char *get_attname(Oid relid, AttrNumber attnum); extern char *get_attname(Oid relid, AttrNumber attnum);
extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum); extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
extern AttrNumber get_attnum(Oid relid, const char *attname); extern AttrNumber get_attnum(Oid relid, const char *attname);
......
/*-------------------------------------------------------------------------
*
* typcache.h
* Type cache definitions.
*
* The type cache exists to speed lookup of certain information about data
* types that is not directly available from a type's pg_type row.
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: typcache.h,v 1.1 2003/08/17 19:58:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef TYPCACHE_H
#define TYPCACHE_H
#include "fmgr.h"
typedef struct TypeCacheEntry
{
/* typeId is the hash lookup key and MUST BE FIRST */
Oid type_id; /* OID of the data type */
/* some subsidiary information copied from the pg_type row */
int16 typlen;
bool typbyval;
char typalign;
/*
* Information obtained from opclass entries
*
* These will be InvalidOid if no match could be found, or if the
* information hasn't yet been requested.
*/
Oid btree_opc; /* OID of the default btree opclass */
Oid hash_opc; /* OID of the default hash opclass */
Oid eq_opr; /* OID of the equality operator */
Oid lt_opr; /* OID of the less-than operator */
Oid gt_opr; /* OID of the greater-than operator */
Oid cmp_proc; /* OID of the btree comparison function */
/*
* Pre-set-up fmgr call info for the equality operator and the btree
* comparison function. These are kept in the type cache to avoid
* problems with memory leaks in repeated calls to array_eq and array_cmp.
* There is not currently a need to maintain call info for the lt_opr
* or gt_opr.
*/
FmgrInfo eq_opr_finfo;
FmgrInfo cmp_proc_finfo;
} TypeCacheEntry;
/* Bit flags to indicate which fields a given caller needs to have set */
#define TYPECACHE_EQ_OPR 0x0001
#define TYPECACHE_LT_OPR 0x0002
#define TYPECACHE_GT_OPR 0x0004
#define TYPECACHE_CMP_PROC 0x0008
#define TYPECACHE_EQ_OPR_FINFO 0x0010
#define TYPECACHE_CMP_PROC_FINFO 0x0020
extern TypeCacheEntry *lookup_type_cache(Oid type_id, int flags);
#endif /* TYPCACHE_H */
...@@ -81,7 +81,7 @@ SELECT '' AS four, f1 FROM CIRCLE_TBL WHERE diameter(f1) >= 10; ...@@ -81,7 +81,7 @@ SELECT '' AS four, f1 FROM CIRCLE_TBL WHERE diameter(f1) >= 10;
SELECT '' as five, c1.f1 AS one, c2.f1 AS two, (c1.f1 <-> c2.f1) AS distance SELECT '' as five, c1.f1 AS one, c2.f1 AS two, (c1.f1 <-> c2.f1) AS distance
FROM CIRCLE_TBL c1, CIRCLE_TBL c2 FROM CIRCLE_TBL c1, CIRCLE_TBL c2
WHERE (c1.f1 < c2.f1) AND ((c1.f1 <-> c2.f1) > 0) WHERE (c1.f1 < c2.f1) AND ((c1.f1 <-> c2.f1) > 0)
ORDER BY distance, one, two; ORDER BY distance, one USING < , two USING < ;
five | one | two | distance five | one | two | distance
------+----------------+----------------+------------------ ------+----------------+----------------+------------------
| <(100,200),10> | <(100,1),115> | 74 | <(100,200),10> | <(100,1),115> | 74
......
...@@ -504,7 +504,7 @@ SELECT '' AS two, circle(f1) ...@@ -504,7 +504,7 @@ SELECT '' AS two, circle(f1)
SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance
FROM CIRCLE_TBL c1, POINT_TBL p1 FROM CIRCLE_TBL c1, POINT_TBL p1
WHERE (p1.f1 <-> c1.f1) > 0 WHERE (p1.f1 <-> c1.f1) > 0
ORDER BY distance, circle, point using <<; ORDER BY distance, circle using <, point using <<;
twentyfour | circle | point | distance twentyfour | circle | point | distance
------------+----------------+------------+--------------- ------------+----------------+------------+---------------
| <(1,2),3> | (-3,4) | 1.472135955 | <(1,2),3> | (-3,4) | 1.472135955
......
...@@ -504,7 +504,7 @@ SELECT '' AS two, circle(f1) ...@@ -504,7 +504,7 @@ SELECT '' AS two, circle(f1)
SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance
FROM CIRCLE_TBL c1, POINT_TBL p1 FROM CIRCLE_TBL c1, POINT_TBL p1
WHERE (p1.f1 <-> c1.f1) > 0 WHERE (p1.f1 <-> c1.f1) > 0
ORDER BY distance, circle, point using <<; ORDER BY distance, circle using <, point using <<;
twentyfour | circle | point | distance twentyfour | circle | point | distance
------------+----------------+------------+--------------- ------------+----------------+------------+---------------
| <(1,2),3> | (-3,4) | 1.472135955 | <(1,2),3> | (-3,4) | 1.472135955
......
...@@ -42,5 +42,4 @@ SELECT '' AS four, f1 FROM CIRCLE_TBL WHERE diameter(f1) >= 10; ...@@ -42,5 +42,4 @@ SELECT '' AS four, f1 FROM CIRCLE_TBL WHERE diameter(f1) >= 10;
SELECT '' as five, c1.f1 AS one, c2.f1 AS two, (c1.f1 <-> c2.f1) AS distance SELECT '' as five, c1.f1 AS one, c2.f1 AS two, (c1.f1 <-> c2.f1) AS distance
FROM CIRCLE_TBL c1, CIRCLE_TBL c2 FROM CIRCLE_TBL c1, CIRCLE_TBL c2
WHERE (c1.f1 < c2.f1) AND ((c1.f1 <-> c2.f1) > 0) WHERE (c1.f1 < c2.f1) AND ((c1.f1 <-> c2.f1) > 0)
ORDER BY distance, one, two; ORDER BY distance, one USING < , two USING < ;
...@@ -152,5 +152,4 @@ SELECT '' AS two, circle(f1) ...@@ -152,5 +152,4 @@ SELECT '' AS two, circle(f1)
SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance
FROM CIRCLE_TBL c1, POINT_TBL p1 FROM CIRCLE_TBL c1, POINT_TBL p1
WHERE (p1.f1 <-> c1.f1) > 0 WHERE (p1.f1 <-> c1.f1) > 0
ORDER BY distance, circle, point using <<; ORDER BY distance, circle using <, point using <<;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment