|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.60 2002/09/18 21:35:22 tgl Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.61 2002/11/29 21:39:11 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -130,22 +130,116 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft,
|
130 | 130 | return operoid;
|
131 | 131 | }
|
132 | 132 |
|
| 133 | +/* |
| 134 | + * equality_oper - identify a suitable equality operator for a datatype |
| 135 | + * |
| 136 | + * On failure, return NULL if noError, else report a standard error |
| 137 | + */ |
| 138 | +Operator |
| 139 | +equality_oper(Oid argtype, bool noError) |
| 140 | +{ |
| 141 | + Operator optup; |
133 | 142 |
|
134 |
| -/* Select an ordering operator for the given datatype */ |
135 |
| -Oid |
136 |
| -any_ordering_op(Oid argtype) |
| 143 | + /* |
| 144 | + * Look for an "=" operator for the datatype. We require it to be |
| 145 | + * an exact or binary-compatible match, since most callers are not |
| 146 | + * prepared to cope with adding any run-time type coercion steps. |
| 147 | + */ |
| 148 | + optup = compatible_oper(makeList1(makeString("=")), |
| 149 | + argtype, argtype, true); |
| 150 | + if (optup != NULL) |
| 151 | + { |
| 152 | + /* |
| 153 | + * Only believe that it's equality if it's mergejoinable, |
| 154 | + * hashjoinable, or uses eqsel() as oprrest. |
| 155 | + */ |
| 156 | + Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(optup); |
| 157 | + |
| 158 | + if (OidIsValid(pgopform->oprlsortop) || |
| 159 | + pgopform->oprcanhash || |
| 160 | + pgopform->oprrest == F_EQSEL) |
| 161 | + return optup; |
| 162 | + |
| 163 | + ReleaseSysCache(optup); |
| 164 | + } |
| 165 | + if (!noError) |
| 166 | + elog(ERROR, "Unable to identify an equality operator for type %s", |
| 167 | + format_type_be(argtype)); |
| 168 | + return NULL; |
| 169 | +} |
| 170 | + |
| 171 | +/* |
| 172 | + * ordering_oper - identify a suitable sorting operator ("<") for a datatype |
| 173 | + * |
| 174 | + * On failure, return NULL if noError, else report a standard error |
| 175 | + */ |
| 176 | +Operator |
| 177 | +ordering_oper(Oid argtype, bool noError) |
137 | 178 | {
|
138 |
| - Oid order_opid; |
| 179 | + Operator optup; |
139 | 180 |
|
140 |
| - order_opid = compatible_oper_opid(makeList1(makeString("<")), |
141 |
| - argtype, argtype, true); |
142 |
| - if (!OidIsValid(order_opid)) |
143 |
| - elog(ERROR, "Unable to identify an ordering operator '%s' for type '%s'" |
| 181 | + /* |
| 182 | + * Find the type's equality operator, and use its lsortop (it *must* |
| 183 | + * be mergejoinable). We use this definition because for sorting and |
| 184 | + * grouping purposes, it's important that the equality and ordering |
| 185 | + * operators are consistent. |
| 186 | + */ |
| 187 | + optup = equality_oper(argtype, noError); |
| 188 | + if (optup != NULL) |
| 189 | + { |
| 190 | + Oid lsortop = ((Form_pg_operator) GETSTRUCT(optup))->oprlsortop; |
| 191 | + |
| 192 | + ReleaseSysCache(optup); |
| 193 | + |
| 194 | + if (OidIsValid(lsortop)) |
| 195 | + { |
| 196 | + optup = SearchSysCache(OPEROID, |
| 197 | + ObjectIdGetDatum(lsortop), |
| 198 | + 0, 0, 0); |
| 199 | + if (optup != NULL) |
| 200 | + return optup; |
| 201 | + } |
| 202 | + } |
| 203 | + if (!noError) |
| 204 | + elog(ERROR, "Unable to identify an ordering operator for type %s" |
144 | 205 | "\n\tUse an explicit ordering operator or modify the query",
|
145 |
| - "<", format_type_be(argtype)); |
146 |
| - return order_opid; |
| 206 | + format_type_be(argtype)); |
| 207 | + return NULL; |
| 208 | +} |
| 209 | + |
| 210 | +/* |
| 211 | + * equality_oper_funcid - convenience routine for oprfuncid(equality_oper()) |
| 212 | + */ |
| 213 | +Oid |
| 214 | +equality_oper_funcid(Oid argtype) |
| 215 | +{ |
| 216 | + Operator optup; |
| 217 | + Oid result; |
| 218 | + |
| 219 | + optup = equality_oper(argtype, false); |
| 220 | + result = oprfuncid(optup); |
| 221 | + ReleaseSysCache(optup); |
| 222 | + return result; |
| 223 | +} |
| 224 | + |
| 225 | +/* |
| 226 | + * ordering_oper_opid - convenience routine for oprid(ordering_oper()) |
| 227 | + * |
| 228 | + * This was formerly called any_ordering_op() |
| 229 | + */ |
| 230 | +Oid |
| 231 | +ordering_oper_opid(Oid argtype) |
| 232 | +{ |
| 233 | + Operator optup; |
| 234 | + Oid result; |
| 235 | + |
| 236 | + optup = ordering_oper(argtype, false); |
| 237 | + result = oprid(optup); |
| 238 | + ReleaseSysCache(optup); |
| 239 | + return result; |
147 | 240 | }
|
148 | 241 |
|
| 242 | + |
149 | 243 | /* given operator tuple, return the operator OID */
|
150 | 244 | Oid
|
151 | 245 | oprid(Operator op)
|
@@ -731,28 +825,6 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
|
731 | 825 | return InvalidOid;
|
732 | 826 | }
|
733 | 827 |
|
734 |
| -/* compatible_oper_funcid() -- get OID of a binary operator's function |
735 |
| - * |
736 |
| - * This is a convenience routine that extracts only the function OID |
737 |
| - * from the result of compatible_oper(). InvalidOid is returned if the |
738 |
| - * lookup fails and noError is true. |
739 |
| - */ |
740 |
| -Oid |
741 |
| -compatible_oper_funcid(List *op, Oid arg1, Oid arg2, bool noError) |
742 |
| -{ |
743 |
| - Operator optup; |
744 |
| - Oid result; |
745 |
| - |
746 |
| - optup = compatible_oper(op, arg1, arg2, noError); |
747 |
| - if (optup != NULL) |
748 |
| - { |
749 |
| - result = oprfuncid(optup); |
750 |
| - ReleaseSysCache(optup); |
751 |
| - return result; |
752 |
| - } |
753 |
| - return InvalidOid; |
754 |
| -} |
755 |
| - |
756 | 828 |
|
757 | 829 | /* right_oper() -- search for a unary right operator (operator on right)
|
758 | 830 | * Given operator name and type of arg, return oper struct.
|
|
0 commit comments