mirror of
https://github.com/postgres/postgres.git
synced 2025-06-07 11:02:12 +03:00
Tighten selection of equality and ordering operators for grouping
operations: make sure we use operators that are compatible, as determined by a mergejoin link in pg_operator. Also, add code to planner to ensure we don't try to use hashed grouping when the grouping operators aren't marked hashable.
This commit is contained in:
parent
851a4c48fd
commit
f68f11928d
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.50 2002/11/13 00:39:46 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.51 2002/11/29 21:39:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -402,10 +402,7 @@ examine_attribute(Relation onerel, int attnum)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* If column has no "=" operator, we can't do much of anything */
|
/* If column has no "=" operator, we can't do much of anything */
|
||||||
func_operator = compatible_oper(makeList1(makeString("=")),
|
func_operator = equality_oper(attr->atttypid, true);
|
||||||
attr->atttypid,
|
|
||||||
attr->atttypid,
|
|
||||||
true);
|
|
||||||
if (func_operator != NULL)
|
if (func_operator != NULL)
|
||||||
{
|
{
|
||||||
oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest;
|
oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest;
|
||||||
@ -443,10 +440,7 @@ examine_attribute(Relation onerel, int attnum)
|
|||||||
stats->attr->attstattarget = default_statistics_target;
|
stats->attr->attstattarget = default_statistics_target;
|
||||||
|
|
||||||
/* Is there a "<" operator with suitable semantics? */
|
/* Is there a "<" operator with suitable semantics? */
|
||||||
func_operator = compatible_oper(makeList1(makeString("<")),
|
func_operator = ordering_oper(attr->atttypid, true);
|
||||||
attr->atttypid,
|
|
||||||
attr->atttypid,
|
|
||||||
true);
|
|
||||||
if (func_operator != NULL)
|
if (func_operator != NULL)
|
||||||
{
|
{
|
||||||
oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest;
|
oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest;
|
||||||
|
@ -45,7 +45,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/executor/nodeAgg.c,v 1.96 2002/11/19 23:21:57 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.97 2002/11/29 21:39:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1321,14 +1321,9 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
|
|||||||
&peraggstate->inputtypeLen,
|
&peraggstate->inputtypeLen,
|
||||||
&peraggstate->inputtypeByVal);
|
&peraggstate->inputtypeByVal);
|
||||||
|
|
||||||
eq_function = compatible_oper_funcid(makeList1(makeString("=")),
|
eq_function = equality_oper_funcid(inputType);
|
||||||
inputType, inputType,
|
|
||||||
true);
|
|
||||||
if (!OidIsValid(eq_function))
|
|
||||||
elog(ERROR, "Unable to identify an equality operator for type %s",
|
|
||||||
format_type_be(inputType));
|
|
||||||
fmgr_info(eq_function, &(peraggstate->equalfn));
|
fmgr_info(eq_function, &(peraggstate->equalfn));
|
||||||
peraggstate->sortOperator = any_ordering_op(inputType);
|
peraggstate->sortOperator = ordering_oper_opid(inputType);
|
||||||
peraggstate->sortstate = NULL;
|
peraggstate->sortstate = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* locate group boundaries.
|
* locate group boundaries.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.49 2002/11/06 22:31:23 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.50 2002/11/29 21:39:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -353,11 +353,7 @@ execTuplesMatchPrepare(TupleDesc tupdesc,
|
|||||||
Oid typid = tupdesc->attrs[att - 1]->atttypid;
|
Oid typid = tupdesc->attrs[att - 1]->atttypid;
|
||||||
Oid eq_function;
|
Oid eq_function;
|
||||||
|
|
||||||
eq_function = compatible_oper_funcid(makeList1(makeString("=")),
|
eq_function = equality_oper_funcid(typid);
|
||||||
typid, typid, true);
|
|
||||||
if (!OidIsValid(eq_function))
|
|
||||||
elog(ERROR, "Unable to identify an equality operator for type %s",
|
|
||||||
format_type_be(typid));
|
|
||||||
fmgr_info(eq_function, &eqfunctions[i]);
|
fmgr_info(eq_function, &eqfunctions[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.131 2002/11/26 03:01:58 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.132 2002/11/29 21:39:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
@ -36,9 +37,11 @@
|
|||||||
#include "parser/analyze.h"
|
#include "parser/analyze.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "parser/parse_expr.h"
|
#include "parser/parse_expr.h"
|
||||||
|
#include "parser/parse_oper.h"
|
||||||
#include "rewrite/rewriteManip.h"
|
#include "rewrite/rewriteManip.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/selfuncs.h"
|
#include "utils/selfuncs.h"
|
||||||
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
|
||||||
/* Expression kind codes for preprocess_expression */
|
/* Expression kind codes for preprocess_expression */
|
||||||
@ -57,6 +60,7 @@ static Node *preprocess_expression(Query *parse, Node *expr, int kind);
|
|||||||
static void preprocess_qual_conditions(Query *parse, Node *jtnode);
|
static void preprocess_qual_conditions(Query *parse, Node *jtnode);
|
||||||
static Plan *inheritance_planner(Query *parse, List *inheritlist);
|
static Plan *inheritance_planner(Query *parse, List *inheritlist);
|
||||||
static Plan *grouping_planner(Query *parse, double tuple_fraction);
|
static Plan *grouping_planner(Query *parse, double tuple_fraction);
|
||||||
|
static bool hash_safe_grouping(Query *parse);
|
||||||
static List *make_subplanTargetList(Query *parse, List *tlist,
|
static List *make_subplanTargetList(Query *parse, List *tlist,
|
||||||
AttrNumber **groupColIdx);
|
AttrNumber **groupColIdx);
|
||||||
static Plan *make_groupsortplan(Query *parse,
|
static Plan *make_groupsortplan(Query *parse,
|
||||||
@ -1252,11 +1256,14 @@ grouping_planner(Query *parse, double tuple_fraction)
|
|||||||
numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
|
numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Check can't-do-it conditions, including whether the grouping
|
||||||
|
* operators are hashjoinable.
|
||||||
|
*
|
||||||
* Executor doesn't support hashed aggregation with DISTINCT
|
* Executor doesn't support hashed aggregation with DISTINCT
|
||||||
* aggregates. (Doing so would imply storing *all* the input
|
* aggregates. (Doing so would imply storing *all* the input
|
||||||
* values in the hash table, which seems like a certain loser.)
|
* values in the hash table, which seems like a certain loser.)
|
||||||
*/
|
*/
|
||||||
if (!enable_hashagg)
|
if (!enable_hashagg || !hash_safe_grouping(parse))
|
||||||
use_hashed_grouping = false;
|
use_hashed_grouping = false;
|
||||||
else if (parse->hasAggs &&
|
else if (parse->hasAggs &&
|
||||||
(contain_distinct_agg_clause((Node *) tlist) ||
|
(contain_distinct_agg_clause((Node *) tlist) ||
|
||||||
@ -1554,6 +1561,33 @@ grouping_planner(Query *parse, double tuple_fraction)
|
|||||||
return result_plan;
|
return result_plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hash_safe_grouping - are grouping operators hashable?
|
||||||
|
*
|
||||||
|
* We assume hashed aggregation will work if the datatype's equality operator
|
||||||
|
* is marked hashjoinable.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
hash_safe_grouping(Query *parse)
|
||||||
|
{
|
||||||
|
List *gl;
|
||||||
|
|
||||||
|
foreach(gl, parse->groupClause)
|
||||||
|
{
|
||||||
|
GroupClause *grpcl = (GroupClause *) lfirst(gl);
|
||||||
|
TargetEntry *tle = get_sortgroupclause_tle(grpcl, parse->targetList);
|
||||||
|
Operator optup;
|
||||||
|
bool oprcanhash;
|
||||||
|
|
||||||
|
optup = equality_oper(tle->resdom->restype, false);
|
||||||
|
oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash;
|
||||||
|
ReleaseSysCache(optup);
|
||||||
|
if (!oprcanhash)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*---------------
|
/*---------------
|
||||||
* make_subplanTargetList
|
* make_subplanTargetList
|
||||||
* Generate appropriate target list when grouping is required.
|
* Generate appropriate target list when grouping is required.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.99 2002/11/15 02:50:08 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.100 2002/11/29 21:39:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1128,8 +1128,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* transformGroupClause -
|
* transformGroupClause -
|
||||||
* transform a Group By clause
|
* transform a GROUP BY clause
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
|
transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
|
||||||
@ -1151,7 +1150,7 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
|
|||||||
|
|
||||||
grpcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
|
grpcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
|
||||||
|
|
||||||
grpcl->sortop = any_ordering_op(tle->resdom->restype);
|
grpcl->sortop = ordering_oper_opid(tle->resdom->restype);
|
||||||
|
|
||||||
glist = lappend(glist, grpcl);
|
glist = lappend(glist, grpcl);
|
||||||
}
|
}
|
||||||
@ -1331,7 +1330,7 @@ addAllTargetsToSortList(List *sortlist, List *targetlist)
|
|||||||
* addTargetToSortList
|
* addTargetToSortList
|
||||||
* If the given targetlist entry isn't already in the ORDER BY list,
|
* If the given targetlist entry isn't already in the ORDER BY list,
|
||||||
* add it to the end of the list, using the sortop with given name
|
* add it to the end of the list, using the sortop with given name
|
||||||
* or any available sort operator if opname == NIL.
|
* or the default sort operator if opname == NIL.
|
||||||
*
|
*
|
||||||
* Returns the updated ORDER BY list.
|
* Returns the updated ORDER BY list.
|
||||||
*/
|
*/
|
||||||
@ -1352,7 +1351,7 @@ addTargetToSortList(TargetEntry *tle, List *sortlist, List *targetlist,
|
|||||||
tle->resdom->restype,
|
tle->resdom->restype,
|
||||||
false);
|
false);
|
||||||
else
|
else
|
||||||
sortcl->sortop = any_ordering_op(tle->resdom->restype);
|
sortcl->sortop = ordering_oper_opid(tle->resdom->restype);
|
||||||
|
|
||||||
sortlist = lappend(sortlist, sortcl);
|
sortlist = lappend(sortlist, sortcl);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.60 2002/09/18 21:35:22 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.61 2002/11/29 21:39:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -130,21 +130,115 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft,
|
|||||||
return operoid;
|
return operoid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/* Select an ordering operator for the given datatype */
|
* equality_oper - identify a suitable equality operator for a datatype
|
||||||
Oid
|
*
|
||||||
any_ordering_op(Oid argtype)
|
* On failure, return NULL if noError, else report a standard error
|
||||||
|
*/
|
||||||
|
Operator
|
||||||
|
equality_oper(Oid argtype, bool noError)
|
||||||
{
|
{
|
||||||
Oid order_opid;
|
Operator optup;
|
||||||
|
|
||||||
order_opid = compatible_oper_opid(makeList1(makeString("<")),
|
/*
|
||||||
|
* 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);
|
argtype, argtype, true);
|
||||||
if (!OidIsValid(order_opid))
|
if (optup != NULL)
|
||||||
elog(ERROR, "Unable to identify an ordering operator '%s' for type '%s'"
|
{
|
||||||
"\n\tUse an explicit ordering operator or modify the query",
|
/*
|
||||||
"<", format_type_be(argtype));
|
* Only believe that it's equality if it's mergejoinable,
|
||||||
return order_opid;
|
* 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 (!noError)
|
||||||
|
elog(ERROR, "Unable to identify an equality operator for type %s",
|
||||||
|
format_type_be(argtype));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ordering_oper - identify a suitable sorting operator ("<") for a datatype
|
||||||
|
*
|
||||||
|
* On failure, return NULL if noError, else report a standard error
|
||||||
|
*/
|
||||||
|
Operator
|
||||||
|
ordering_oper(Oid argtype, bool noError)
|
||||||
|
{
|
||||||
|
Operator optup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the type's equality operator, and use its lsortop (it *must*
|
||||||
|
* be mergejoinable). We use this definition because for sorting and
|
||||||
|
* grouping purposes, it's important that the equality and ordering
|
||||||
|
* operators are consistent.
|
||||||
|
*/
|
||||||
|
optup = equality_oper(argtype, noError);
|
||||||
|
if (optup != NULL)
|
||||||
|
{
|
||||||
|
Oid lsortop = ((Form_pg_operator) GETSTRUCT(optup))->oprlsortop;
|
||||||
|
|
||||||
|
ReleaseSysCache(optup);
|
||||||
|
|
||||||
|
if (OidIsValid(lsortop))
|
||||||
|
{
|
||||||
|
optup = SearchSysCache(OPEROID,
|
||||||
|
ObjectIdGetDatum(lsortop),
|
||||||
|
0, 0, 0);
|
||||||
|
if (optup != NULL)
|
||||||
|
return optup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!noError)
|
||||||
|
elog(ERROR, "Unable to identify an ordering operator for type %s"
|
||||||
|
"\n\tUse an explicit ordering operator or modify the query",
|
||||||
|
format_type_be(argtype));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* equality_oper_funcid - convenience routine for oprfuncid(equality_oper())
|
||||||
|
*/
|
||||||
|
Oid
|
||||||
|
equality_oper_funcid(Oid argtype)
|
||||||
|
{
|
||||||
|
Operator optup;
|
||||||
|
Oid result;
|
||||||
|
|
||||||
|
optup = equality_oper(argtype, false);
|
||||||
|
result = oprfuncid(optup);
|
||||||
|
ReleaseSysCache(optup);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ordering_oper_opid - convenience routine for oprid(ordering_oper())
|
||||||
|
*
|
||||||
|
* This was formerly called any_ordering_op()
|
||||||
|
*/
|
||||||
|
Oid
|
||||||
|
ordering_oper_opid(Oid argtype)
|
||||||
|
{
|
||||||
|
Operator optup;
|
||||||
|
Oid result;
|
||||||
|
|
||||||
|
optup = ordering_oper(argtype, false);
|
||||||
|
result = oprid(optup);
|
||||||
|
ReleaseSysCache(optup);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* given operator tuple, return the operator OID */
|
/* given operator tuple, return the operator OID */
|
||||||
Oid
|
Oid
|
||||||
@ -731,28 +825,6 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
|
|||||||
return InvalidOid;
|
return InvalidOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compatible_oper_funcid() -- get OID of a binary operator's function
|
|
||||||
*
|
|
||||||
* This is a convenience routine that extracts only the function OID
|
|
||||||
* from the result of compatible_oper(). InvalidOid is returned if the
|
|
||||||
* lookup fails and noError is true.
|
|
||||||
*/
|
|
||||||
Oid
|
|
||||||
compatible_oper_funcid(List *op, Oid arg1, Oid arg2, bool noError)
|
|
||||||
{
|
|
||||||
Operator optup;
|
|
||||||
Oid result;
|
|
||||||
|
|
||||||
optup = compatible_oper(op, arg1, arg2, noError);
|
|
||||||
if (optup != NULL)
|
|
||||||
{
|
|
||||||
result = oprfuncid(optup);
|
|
||||||
ReleaseSysCache(optup);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return InvalidOid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* right_oper() -- search for a unary right operator (operator on right)
|
/* right_oper() -- search for a unary right operator (operator on right)
|
||||||
* Given operator name and type of arg, return oper struct.
|
* Given operator name and type of arg, return oper struct.
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.43 2002/10/03 21:06:23 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.44 2002/11/29 21:39:11 tgl Exp $
|
||||||
*
|
*
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
@ -3669,12 +3669,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
|
|||||||
Oid opr_proc;
|
Oid opr_proc;
|
||||||
FmgrInfo finfo;
|
FmgrInfo finfo;
|
||||||
|
|
||||||
opr_proc = compatible_oper_funcid(makeList1(makeString("=")),
|
opr_proc = equality_oper_funcid(typeid);
|
||||||
typeid, typeid, true);
|
|
||||||
if (!OidIsValid(opr_proc))
|
|
||||||
elog(ERROR,
|
|
||||||
"ri_AttributesEqual(): cannot find '=' operator for type %u",
|
|
||||||
typeid);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since fmgr_info could fail, call it *before* creating the
|
* Since fmgr_info could fail, call it *before* creating the
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* parse_oper.h
|
* parse_oper.h
|
||||||
*
|
* handle operator things for parser
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, 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.22 2002/09/04 20:31:45 momjian Exp $
|
* $Id: parse_oper.h,v 1.23 2002/11/29 21:39:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -36,13 +36,14 @@ 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 */
|
||||||
|
|
||||||
/* Convenience routines that call compatible_oper() and return either */
|
/* Routines for identifying "=" and "<" operators for a type */
|
||||||
/* the operator OID or the underlying function OID, or InvalidOid if fail */
|
extern Operator equality_oper(Oid argtype, bool noError);
|
||||||
extern Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError);
|
extern Operator ordering_oper(Oid argtype, bool noError);
|
||||||
extern Oid compatible_oper_funcid(List *op, Oid arg1, Oid arg2, bool noError);
|
|
||||||
|
|
||||||
/* Convenience routine that packages a specific call on compatible_oper */
|
/* Convenience routines for common calls on the above */
|
||||||
extern Oid any_ordering_op(Oid argtype);
|
extern Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError);
|
||||||
|
extern Oid equality_oper_funcid(Oid argtype);
|
||||||
|
extern Oid 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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user