mirror of
https://github.com/postgres/postgres.git
synced 2025-04-20 00:42:27 +03:00
Rewrite array_cmp to not depend on deconstruct_array. Should be a little
faster, but more importantly does not leak memory. Still needs more work though, per my recent note to pgsql-hackers.
This commit is contained in:
parent
43bb02863f
commit
432ca9116b
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.97 2003/08/08 21:42:04 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.98 2003/08/15 00:22:26 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2510,18 +2510,21 @@ array_cmp(FunctionCallInfo fcinfo)
|
|||||||
{
|
{
|
||||||
ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0);
|
ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0);
|
||||||
ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1);
|
ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1);
|
||||||
|
char *p1 = (char *) ARR_DATA_PTR(array1);
|
||||||
|
char *p2 = (char *) ARR_DATA_PTR(array2);
|
||||||
|
int ndims1 = ARR_NDIM(array1);
|
||||||
|
int ndims2 = ARR_NDIM(array2);
|
||||||
|
int *dims1 = ARR_DIMS(array1);
|
||||||
|
int *dims2 = ARR_DIMS(array2);
|
||||||
|
int nitems1 = ArrayGetNItems(ndims1, dims1);
|
||||||
|
int nitems2 = ArrayGetNItems(ndims2, dims2);
|
||||||
|
Oid element_type = ARR_ELEMTYPE(array1);
|
||||||
FmgrInfo *ac_fmgr_info = fcinfo->flinfo;
|
FmgrInfo *ac_fmgr_info = fcinfo->flinfo;
|
||||||
Datum opresult;
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
Oid element_type = InvalidOid;
|
|
||||||
int typlen;
|
int typlen;
|
||||||
bool typbyval;
|
bool typbyval;
|
||||||
char typalign;
|
char typalign;
|
||||||
Datum *dvalues1;
|
int min_nitems;
|
||||||
int nelems1;
|
|
||||||
Datum *dvalues2;
|
|
||||||
int nelems2;
|
|
||||||
int min_nelems;
|
|
||||||
int i;
|
int i;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -2534,7 +2537,6 @@ array_cmp(FunctionCallInfo fcinfo)
|
|||||||
} ac_extra;
|
} ac_extra;
|
||||||
ac_extra *my_extra;
|
ac_extra *my_extra;
|
||||||
|
|
||||||
element_type = ARR_ELEMTYPE(array1);
|
|
||||||
if (element_type != ARR_ELEMTYPE(array2))
|
if (element_type != ARR_ELEMTYPE(array2))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||||
@ -2573,42 +2575,49 @@ array_cmp(FunctionCallInfo fcinfo)
|
|||||||
typbyval = my_extra->typbyval;
|
typbyval = my_extra->typbyval;
|
||||||
typalign = my_extra->typalign;
|
typalign = my_extra->typalign;
|
||||||
|
|
||||||
/* extract a C array of arg array datums */
|
/* Loop over source data */
|
||||||
deconstruct_array(array1, element_type, typlen, typbyval, typalign,
|
min_nitems = Min(nitems1, nitems2);
|
||||||
&dvalues1, &nelems1);
|
for (i = 0; i < min_nitems; i++)
|
||||||
|
|
||||||
deconstruct_array(array2, element_type, typlen, typbyval, typalign,
|
|
||||||
&dvalues2, &nelems2);
|
|
||||||
|
|
||||||
min_nelems = Min(nelems1, nelems2);
|
|
||||||
for (i = 0; i < min_nelems; i++)
|
|
||||||
{
|
{
|
||||||
/* are they equal */
|
Datum elt1;
|
||||||
opresult = FunctionCall2(&my_extra->eqproc,
|
Datum elt2;
|
||||||
dvalues1[i], dvalues2[i]);
|
Datum opresult;
|
||||||
|
|
||||||
if (!DatumGetBool(opresult))
|
/* Get element pair */
|
||||||
|
elt1 = fetch_att(p1, typbyval, typlen);
|
||||||
|
elt2 = fetch_att(p2, typbyval, typlen);
|
||||||
|
|
||||||
|
p1 = att_addlength(p1, typlen, PointerGetDatum(p1));
|
||||||
|
p1 = (char *) att_align(p1, typalign);
|
||||||
|
|
||||||
|
p2 = att_addlength(p2, typlen, PointerGetDatum(p2));
|
||||||
|
p2 = (char *) att_align(p2, typalign);
|
||||||
|
|
||||||
|
/* Compare the pair of elements */
|
||||||
|
|
||||||
|
/* are they equal */
|
||||||
|
opresult = FunctionCall2(&my_extra->eqproc, elt1, elt2);
|
||||||
|
if (DatumGetBool(opresult))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* nope, see if arg1 is less than arg2 */
|
||||||
|
opresult = FunctionCall2(&my_extra->ordproc, elt1, elt2);
|
||||||
|
if (DatumGetBool(opresult))
|
||||||
{
|
{
|
||||||
/* nope, see if arg1 is less than arg2 */
|
/* arg1 is less than arg2 */
|
||||||
opresult = FunctionCall2(&my_extra->ordproc,
|
result = -1;
|
||||||
dvalues1[i], dvalues2[i]);
|
break;
|
||||||
if (DatumGetBool(opresult))
|
}
|
||||||
{
|
else
|
||||||
/* arg1 is less than arg2 */
|
{
|
||||||
result = -1;
|
/* arg1 is greater than arg2 */
|
||||||
break;
|
result = 1;
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
/* arg1 is greater than arg2 */
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result == 0) && (nelems1 != nelems2))
|
if ((result == 0) && (nitems1 != nitems2))
|
||||||
result = (nelems1 < nelems2) ? -1 : 1;
|
result = (nitems1 < nitems2) ? -1 : 1;
|
||||||
|
|
||||||
/* Avoid leaking memory when handed toasted input. */
|
/* Avoid leaking memory when handed toasted input. */
|
||||||
PG_FREE_IF_COPY(array1, 0);
|
PG_FREE_IF_COPY(array1, 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user