aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/analyze.c27
-rw-r--r--src/backend/executor/nodeAgg.c14
-rw-r--r--src/backend/executor/nodeGroup.c13
-rw-r--r--src/backend/optimizer/path/indxpath.c4
-rw-r--r--src/backend/optimizer/plan/initsplan.c4
-rw-r--r--src/backend/parser/parse_clause.c10
-rw-r--r--src/backend/parser/parse_expr.c7
-rw-r--r--src/backend/parser/parse_oper.c149
-rw-r--r--src/include/parser/parse_oper.h24
9 files changed, 162 insertions, 90 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 5fd7793d7af..4db0068da82 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.13 2001/01/24 19:42:52 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.14 2001/02/16 03:16:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -152,7 +152,6 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
for (i = 0; i < attr_cnt; i++)
{
Operator func_operator;
- Form_pg_operator pgopform;
VacAttrStats *stats;
stats = &vacattrstats[i];
@@ -167,21 +166,25 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
stats->best_cnt = stats->guess1_cnt = stats->guess1_hits = stats->guess2_hits = 0;
stats->max_cnt = stats->min_cnt = stats->null_cnt = stats->nonnull_cnt = 0;
- func_operator = oper("=", stats->attr->atttypid, stats->attr->atttypid, true);
+ func_operator = compatible_oper("=",
+ stats->attr->atttypid,
+ stats->attr->atttypid,
+ true);
if (func_operator != NULL)
{
- pgopform = (Form_pg_operator) GETSTRUCT(func_operator);
- fmgr_info(pgopform->oprcode, &(stats->f_cmpeq));
+ fmgr_info(oprfuncid(func_operator), &(stats->f_cmpeq));
ReleaseSysCache(func_operator);
}
else
stats->f_cmpeq.fn_addr = NULL;
- func_operator = oper("<", stats->attr->atttypid, stats->attr->atttypid, true);
+ func_operator = compatible_oper("<",
+ stats->attr->atttypid,
+ stats->attr->atttypid,
+ true);
if (func_operator != NULL)
{
- pgopform = (Form_pg_operator) GETSTRUCT(func_operator);
- fmgr_info(pgopform->oprcode, &(stats->f_cmplt));
+ fmgr_info(oprfuncid(func_operator), &(stats->f_cmplt));
stats->op_cmplt = oprid(func_operator);
ReleaseSysCache(func_operator);
}
@@ -191,11 +194,13 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
stats->op_cmplt = InvalidOid;
}
- func_operator = oper(">", stats->attr->atttypid, stats->attr->atttypid, true);
+ func_operator = compatible_oper(">",
+ stats->attr->atttypid,
+ stats->attr->atttypid,
+ true);
if (func_operator != NULL)
{
- pgopform = (Form_pg_operator) GETSTRUCT(func_operator);
- fmgr_info(pgopform->oprcode, &(stats->f_cmpgt));
+ fmgr_info(oprfuncid(func_operator), &(stats->f_cmpgt));
ReleaseSysCache(func_operator);
}
else
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index bfb2646b6a6..f60f499e6be 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -46,7 +46,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.74 2001/02/15 21:47:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.75 2001/02/16 03:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -909,21 +909,19 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
* (Consider COUNT(*).)
*/
Oid inputType = exprType(aggref->target);
- Operator eq_operator;
- Form_pg_operator pgopform;
+ Oid eq_function;
peraggstate->inputType = inputType;
get_typlenbyval(inputType,
&peraggstate->inputtypeLen,
&peraggstate->inputtypeByVal);
- eq_operator = oper("=", inputType, inputType, true);
- if (!HeapTupleIsValid(eq_operator))
+ eq_function = compatible_oper_funcid("=", inputType, inputType,
+ true);
+ if (!OidIsValid(eq_function))
elog(ERROR, "Unable to identify an equality operator for type '%s'",
typeidTypeName(inputType));
- pgopform = (Form_pg_operator) GETSTRUCT(eq_operator);
- fmgr_info(pgopform->oprcode, &(peraggstate->equalfn));
- ReleaseSysCache(eq_operator);
+ fmgr_info(eq_function, &(peraggstate->equalfn));
peraggstate->sortOperator = any_ordering_op(inputType);
peraggstate->sortstate = NULL;
}
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index e98819a5d83..e4ede51852a 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -15,7 +15,7 @@
* locate group boundaries.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.40 2001/01/24 19:42:54 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.41 2001/02/16 03:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -495,16 +495,13 @@ execTuplesMatchPrepare(TupleDesc tupdesc,
{
AttrNumber att = matchColIdx[i];
Oid typid = tupdesc->attrs[att - 1]->atttypid;
- Operator eq_operator;
- Form_pg_operator pgopform;
+ Oid eq_function;
- eq_operator = oper("=", typid, typid, true);
- if (!HeapTupleIsValid(eq_operator))
+ eq_function = compatible_oper_funcid("=", typid, typid, true);
+ if (!OidIsValid(eq_function))
elog(ERROR, "Unable to identify an equality operator for type '%s'",
typeidTypeName(typid));
- pgopform = (Form_pg_operator) GETSTRUCT(eq_operator);
- fmgr_info(pgopform->oprcode, &eqfunctions[i]);
- ReleaseSysCache(eq_operator);
+ fmgr_info(eq_function, &eqfunctions[i]);
}
return eqfunctions;
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index cc408ce2820..ed5a53db0b9 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.101 2001/01/24 19:42:57 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.102 2001/02/16 03:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -878,7 +878,7 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam,
* (In theory this might find a non-semantically-comparable operator,
* but in practice that seems pretty unlikely for binary-compatible types.)
*/
- new_op = oper_oid(opname, indexkeytype, indexkeytype, true);
+ new_op = compatible_oper_opid(opname, indexkeytype, indexkeytype, true);
if (OidIsValid(new_op))
{
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index b8639b44101..1025a9b7f6b 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.56 2001/01/24 19:42:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.57 2001/02/16 03:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -617,7 +617,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
*/
ltype = exprType(item1);
rtype = exprType(item2);
- eq_operator = oper("=", ltype, rtype, true);
+ eq_operator = compatible_oper("=", ltype, rtype, true);
if (!HeapTupleIsValid(eq_operator))
{
/*
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 266b6da75b5..5d44bbefbde 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.76 2001/02/14 21:35:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.77 2001/02/16 03:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1155,10 +1155,10 @@ addTargetToSortList(TargetEntry *tle, List *sortlist, List *targetlist,
sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
if (opname)
- sortcl->sortop = oper_oid(opname,
- tle->resdom->restype,
- tle->resdom->restype,
- false);
+ sortcl->sortop = compatible_oper_opid(opname,
+ tle->resdom->restype,
+ tle->resdom->restype,
+ false);
else
sortcl->sortop = any_ordering_op(tle->resdom->restype);
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 93a986d835e..69f34c890ed 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.90 2001/02/14 21:35:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.91 2001/02/16 03:16:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -383,6 +383,11 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
lexpr = lfirst(left_list);
left_list = lnext(left_list);
+ /*
+ * It's OK to use oper() not compatible_oper() here,
+ * because make_subplan() will insert type coercion
+ * calls if needed.
+ */
optup = oper(op,
exprType(lexpr),
exprType(tent->expr),
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index e55f638765b..cd557994f17 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.46 2001/01/24 19:43:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.47 2001/02/16 03:16:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,15 +40,15 @@ static void unary_op_error(char *op, Oid arg, bool is_left_op);
/* Select an ordering operator for the given datatype */
Oid
-any_ordering_op(Oid restype)
+any_ordering_op(Oid argtype)
{
Oid order_opid;
- order_opid = oper_oid("<", restype, restype, true);
+ order_opid = compatible_oper_opid("<", argtype, argtype, true);
if (!OidIsValid(order_opid))
elog(ERROR, "Unable to identify an ordering operator '%s' for type '%s'"
"\n\tUse an explicit ordering operator or modify the query",
- "<", typeidTypeName(restype));
+ "<", typeidTypeName(argtype));
return order_opid;
}
@@ -59,6 +59,15 @@ oprid(Operator op)
return op->t_data->t_oid;
}
+/* given operator tuple, return the underlying function's OID */
+Oid
+oprfuncid(Operator op)
+{
+ Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(op);
+
+ return pgopform->oprcode;
+}
+
/* binary_oper_get_candidates()
* given opname, find all possible input type pairs for which an operator
@@ -119,7 +128,7 @@ binary_oper_get_candidates(char *opname,
/* oper_select_candidate()
- * Given the input argtype array and more than one candidate
+ * Given the input argtype array and one or more candidates
* for the function argtype array, attempt to resolve the conflict.
* Returns the selected argtype array if the conflict can be resolved,
* otherwise returns NULL.
@@ -593,34 +602,22 @@ oper_inexact(char *op, Oid arg1, Oid arg2)
if (ncandidates == 0)
return NULL;
- /* Or found exactly one? Then proceed... */
- else if (ncandidates == 1)
+ /* Otherwise, check for compatible datatypes, and then try to resolve
+ * the conflict if more than one candidate remains.
+ */
+ inputOids[0] = arg1;
+ inputOids[1] = arg2;
+ targetOids = oper_select_candidate(2, inputOids, candidates);
+ if (targetOids != NULL)
{
tup = SearchSysCache(OPERNAME,
PointerGetDatum(op),
- ObjectIdGetDatum(candidates->args[0]),
- ObjectIdGetDatum(candidates->args[1]),
+ ObjectIdGetDatum(targetOids[0]),
+ ObjectIdGetDatum(targetOids[1]),
CharGetDatum('b'));
- Assert(HeapTupleIsValid(tup));
}
-
- /* Otherwise, multiple operators of the desired types found... */
else
- {
- inputOids[0] = arg1;
- inputOids[1] = arg2;
- targetOids = oper_select_candidate(2, inputOids, candidates);
- if (targetOids != NULL)
- {
- tup = SearchSysCache(OPERNAME,
- PointerGetDatum(op),
- ObjectIdGetDatum(targetOids[0]),
- ObjectIdGetDatum(targetOids[1]),
- CharGetDatum('b'));
- }
- else
- tup = NULL;
- }
+ tup = NULL;
return (Operator) tup;
}
@@ -628,6 +625,10 @@ oper_inexact(char *op, Oid arg1, Oid arg2)
/* oper() -- search for a binary operator
* Given operator name, types of arg1 and arg2, return oper struct.
*
+ * IMPORTANT: the returned operator (if any) is only promised to be
+ * coercion-compatible with the input datatypes. Do not use this if
+ * you need an exact- or binary-compatible match; see compatible_oper.
+ *
* If no matching operator found, return NULL if noError is true,
* raise an error if it is false.
*
@@ -653,19 +654,51 @@ oper(char *opname, Oid ltypeId, Oid rtypeId, bool noError)
return (Operator) NULL;
}
-/* oper_oid() -- get OID of a binary operator
+/* compatible_oper()
+ * given an opname and input datatypes, find a compatible binary operator
+ *
+ * This is tighter than oper() because it will not return an operator that
+ * requires coercion of the input datatypes (but binary-compatible operators
+ * are accepted). Otherwise, the semantics are the same.
+ */
+Operator
+compatible_oper(char *op, Oid arg1, Oid arg2, bool noError)
+{
+ Operator optup;
+ Form_pg_operator opform;
+
+ /* oper() will find the best available match */
+ optup = oper(op, arg1, arg2, noError);
+ if (optup == (Operator) NULL)
+ return (Operator) NULL; /* must be noError case */
+
+ /* but is it good enough? */
+ opform = (Form_pg_operator) GETSTRUCT(optup);
+ if ((opform->oprleft == arg1 ||
+ IS_BINARY_COMPATIBLE(opform->oprleft, arg1)) &&
+ (opform->oprright == arg2 ||
+ IS_BINARY_COMPATIBLE(opform->oprright, arg2)))
+ return optup;
+
+ if (!noError)
+ op_error(op, arg1, arg2);
+
+ return (Operator) NULL;
+}
+
+/* compatible_oper_opid() -- get OID of a binary operator
*
* This is a convenience routine that extracts only the operator OID
- * from the result of oper(). InvalidOid is returned if the lookup
- * fails and noError is true.
+ * from the result of compatible_oper(). InvalidOid is returned if the
+ * lookup fails and noError is true.
*/
Oid
-oper_oid(char *op, Oid arg1, Oid arg2, bool noError)
+compatible_oper_opid(char *op, Oid arg1, Oid arg2, bool noError)
{
Operator optup;
Oid result;
- optup = oper(op, arg1, arg2, noError);
+ optup = compatible_oper(op, arg1, arg2, noError);
if (optup != NULL)
{
result = oprid(optup);
@@ -675,6 +708,28 @@ oper_oid(char *op, Oid arg1, Oid arg2, bool noError)
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(char *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;
+}
+
/* unary_oper_get_candidates()
* given opname, find all possible types for which
* a right/left unary operator named opname exists.
@@ -738,6 +793,10 @@ unary_oper_get_candidates(char *opname,
/* Given unary right operator (operator on right), return oper struct
*
+ * IMPORTANT: the returned operator (if any) is only promised to be
+ * coercion-compatible with the input datatype. Do not use this if
+ * you need an exact- or binary-compatible match.
+ *
* Always raises error on failure.
*
* NOTE: on success, the returned object is a syscache entry. The caller
@@ -764,16 +823,11 @@ right_oper(char *op, Oid arg)
ncandidates = unary_oper_get_candidates(op, &candidates, 'r');
if (ncandidates == 0)
unary_op_error(op, arg, FALSE);
- else if (ncandidates == 1)
- {
- tup = SearchSysCache(OPERNAME,
- PointerGetDatum(op),
- ObjectIdGetDatum(candidates->args[0]),
- ObjectIdGetDatum(InvalidOid),
- CharGetDatum('r'));
- }
else
{
+ /* We must run oper_select_candidate even if only one candidate,
+ * otherwise we may falsely return a non-type-compatible operator.
+ */
targetOid = oper_select_candidate(1, &arg, candidates);
if (targetOid != NULL)
tup = SearchSysCache(OPERNAME,
@@ -793,6 +847,10 @@ right_oper(char *op, Oid arg)
/* Given unary left operator (operator on left), return oper struct
*
+ * IMPORTANT: the returned operator (if any) is only promised to be
+ * coercion-compatible with the input datatype. Do not use this if
+ * you need an exact- or binary-compatible match.
+ *
* Always raises error on failure.
*
* NOTE: on success, the returned object is a syscache entry. The caller
@@ -819,16 +877,11 @@ left_oper(char *op, Oid arg)
ncandidates = unary_oper_get_candidates(op, &candidates, 'l');
if (ncandidates == 0)
unary_op_error(op, arg, TRUE);
- else if (ncandidates == 1)
- {
- tup = SearchSysCache(OPERNAME,
- PointerGetDatum(op),
- ObjectIdGetDatum(InvalidOid),
- ObjectIdGetDatum(candidates->args[0]),
- CharGetDatum('l'));
- }
else
{
+ /* We must run oper_select_candidate even if only one candidate,
+ * otherwise we may falsely return a non-type-compatible operator.
+ */
targetOid = oper_select_candidate(1, &arg, candidates);
if (targetOid != NULL)
tup = SearchSysCache(OPERNAME,
diff --git a/src/include/parser/parse_oper.h b/src/include/parser/parse_oper.h
index 6867addea51..069a9d5be27 100644
--- a/src/include/parser/parse_oper.h
+++ b/src/include/parser/parse_oper.h
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
- * catalog_utils.h
+ * parse_oper.h
*
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_oper.h,v 1.13 2001/01/24 19:43:27 momjian Exp $
+ * $Id: parse_oper.h,v 1.14 2001/02/16 03:16:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,13 +18,27 @@
typedef HeapTuple Operator;
+/* Routines to find operators matching a name and given input types */
+/* NB: the selected operator may require coercion of the input types! */
extern Operator oper(char *op, Oid arg1, Oid arg2, bool noError);
extern Operator right_oper(char *op, Oid arg);
extern Operator left_oper(char *op, Oid arg);
-extern Oid oper_oid(char *op, Oid arg1, Oid arg2, bool noError);
-extern Oid oprid(Operator op);
+/* Routines to find operators that DO NOT require coercion --- ie, their */
+/* input types are either exactly as given, or binary-compatible */
+extern Operator compatible_oper(char *op, Oid arg1, Oid arg2, bool noError);
+/* currently no need for compatible_left_oper/compatible_right_oper */
+
+/* Convenience routines that call compatible_oper() and return either */
+/* the operator OID or the underlying function OID, or InvalidOid if fail */
+extern Oid compatible_oper_opid(char *op, Oid arg1, Oid arg2, bool noError);
+extern Oid compatible_oper_funcid(char *op, Oid arg1, Oid arg2, bool noError);
-extern Oid any_ordering_op(Oid restype);
+/* Convenience routine that packages a specific call on compatible_oper */
+extern Oid any_ordering_op(Oid argtype);
+
+/* Extract operator OID or underlying-function OID from an Operator tuple */
+extern Oid oprid(Operator op);
+extern Oid oprfuncid(Operator op);
#endif /* PARSE_OPER_H */