diff options
Diffstat (limited to 'src/backend/parser')
| -rw-r--r-- | src/backend/parser/parse_coerce.c | 10 | ||||
| -rw-r--r-- | src/backend/parser/parse_expr.c | 4 | ||||
| -rw-r--r-- | src/backend/parser/parse_oper.c | 122 |
3 files changed, 101 insertions, 35 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 987d129027..eba6f5a133 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.100 2003/06/25 21:30:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.101 2003/06/27 00:33:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1145,7 +1145,8 @@ IsPreferredType(CATEGORY category, Oid type) * invokable, no-function-needed pg_cast entry. Also, a domain is always * binary-coercible to its base type, though *not* vice versa (in the other * direction, one must apply domain constraint checks before accepting the - * value as legitimate). + * value as legitimate). We also need to special-case the polymorphic + * ANYARRAY type. * * This function replaces IsBinaryCompatible(), which was an inherently * symmetric test. Since the pg_cast entries aren't necessarily symmetric, @@ -1170,6 +1171,11 @@ IsBinaryCoercible(Oid srctype, Oid targettype) if (srctype == targettype) return true; + /* Also accept any array type as coercible to ANYARRAY */ + if (targettype == ANYARRAYOID) + if (get_element_type(srctype) != InvalidOid) + return true; + /* Else look in pg_cast */ tuple = SearchSysCache(CASTSOURCETARGET, ObjectIdGetDatum(srctype), diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 1e65521710..415242bc7a 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.150 2003/06/25 21:30:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.151 2003/06/27 00:33:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -743,7 +743,7 @@ transformExpr(ParseState *pstate, Node *expr) ArrayExpr *e = (ArrayExpr *) lfirst(element); if (!IsA(e, ArrayExpr)) - elog(ERROR, "Multi-dimensional ARRAY[] must be built from nested array expressions"); + elog(ERROR, "Multidimensional ARRAY[] must be built from nested array expressions"); if (ndims == 0) ndims = e->ndims; else if (e->ndims != ndims) diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 69edb4b85b..983041eb45 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.66 2003/06/25 21:30:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.67 2003/06/27 00:33:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -137,28 +137,50 @@ Operator equality_oper(Oid argtype, bool noError) { 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. + * 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 must run this test first, since compatible_oper will find + * array_eq, but would not notice the lack of an element operator.) */ - optup = compatible_oper(makeList1(makeString("=")), - argtype, argtype, true); - if (optup != NULL) + elem_type = get_element_type(argtype); + if (OidIsValid(elem_type)) + { + optup = equality_oper(elem_type, true); + if (optup != NULL) + { + ReleaseSysCache(optup); + return SearchSysCache(OPEROID, + ObjectIdGetDatum(ARRAY_EQ_OP), + 0, 0, 0); + } + } + else { /* - * Only believe that it's equality if it's mergejoinable, - * hashjoinable, or uses eqsel() as oprrest. + * 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. */ - Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(optup); + 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; + if (OidIsValid(pgopform->oprlsortop) || + pgopform->oprcanhash || + pgopform->oprrest == F_EQSEL) + return optup; - ReleaseSysCache(optup); + ReleaseSysCache(optup); + } } if (!noError) elog(ERROR, "Unable to identify an equality operator for type %s", @@ -175,27 +197,50 @@ Operator ordering_oper(Oid argtype, bool noError) { Operator optup; + Oid elem_type; /* - * 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. + * 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 must run this test first, since the code below would find + * array_lt if there's an element = operator, but would not notice the + * lack of an element < operator.) */ - optup = equality_oper(argtype, noError); - if (optup != NULL) + elem_type = get_element_type(argtype); + if (OidIsValid(elem_type)) { - Oid lsortop = ((Form_pg_operator) GETSTRUCT(optup))->oprlsortop; - - ReleaseSysCache(optup); - - if (OidIsValid(lsortop)) + optup = ordering_oper(elem_type, true); + if (optup != NULL) { - optup = SearchSysCache(OPEROID, - ObjectIdGetDatum(lsortop), - 0, 0, 0); - if (optup != NULL) - return optup; + ReleaseSysCache(optup); + return SearchSysCache(OPEROID, + ObjectIdGetDatum(ARRAY_LT_OP), + 0, 0, 0); + } + } + else + { + /* + * 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; + + 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) @@ -237,6 +282,21 @@ ordering_oper_opid(Oid argtype) return result; } +/* + * ordering_oper_funcid - convenience routine for oprfuncid(ordering_oper()) + */ +Oid +ordering_oper_funcid(Oid argtype) +{ + Operator optup; + Oid result; + + optup = ordering_oper(argtype, false); + result = oprfuncid(optup); + ReleaseSysCache(optup); + return result; +} + /* given operator tuple, return the operator OID */ Oid |
