mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Create real array comparison functions (that use the element datatype's
comparison functions), replacing the highly bogus bitwise array_eq. Create a btree index opclass for ANYARRAY --- it is now possible to create indexes on array columns. Arrange to cache the results of catalog lookups across multiple array operations, instead of repeating the lookups on every call. Add string_to_array and array_to_string functions. Remove singleton_array, array_accum, array_assign, and array_subscript functions, since these were for proof-of-concept and not intended to become supported functions. Minor adjustments to behavior in some corner cases with empty or zero-dimensional arrays. Joe Conway (with some editorializing by Tom Lane).
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user