Rewrite array_cmp to not depend on deconstruct_array. Should be a little
authorTom Lane <[email protected]>
Fri, 15 Aug 2003 00:22:26 +0000 (00:22 +0000)
committerTom Lane <[email protected]>
Fri, 15 Aug 2003 00:22:26 +0000 (00:22 +0000)
faster, but more importantly does not leak memory.  Still needs more work
though, per my recent note to pgsql-hackers.

src/backend/utils/adt/arrayfuncs.c

index df8265d99956380c240aa423080636e7b752ba79..37504718ad5e234f6b20a886836ec358238b13b4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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  *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;
-   Datum       opresult;
    int         result = 0;
-   Oid         element_type = InvalidOid;
    int         typlen;
    bool        typbyval;
    char        typalign;
-   Datum      *dvalues1;
-   int         nelems1;
-   Datum      *dvalues2;
-   int         nelems2;
-   int         min_nelems;
+   int         min_nitems;
    int         i;
    typedef struct
    {
@@ -2534,7 +2537,6 @@ array_cmp(FunctionCallInfo fcinfo)
    } ac_extra;
    ac_extra   *my_extra;
 
-   element_type = ARR_ELEMTYPE(array1);
    if (element_type != ARR_ELEMTYPE(array2))
        ereport(ERROR,
                (errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -2573,42 +2575,49 @@ array_cmp(FunctionCallInfo fcinfo)
    typbyval = my_extra->typbyval;
    typalign = my_extra->typalign;
 
-   /* extract a C array of arg array datums */
-   deconstruct_array(array1, element_type, typlen, typbyval, typalign,
-                     &dvalues1, &nelems1);
+   /* Loop over source data */
+   min_nitems = Min(nitems1, nitems2);
+   for (i = 0; i < min_nitems; i++)
+   {
+       Datum       elt1;
+       Datum       elt2;
+       Datum       opresult;
+
+       /* Get element pair */
+       elt1 = fetch_att(p1, typbyval, typlen);
+       elt2 = fetch_att(p2, typbyval, typlen);
 
-   deconstruct_array(array2, element_type, typlen, typbyval, typalign,
-                     &dvalues2, &nelems2);
+       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 */
 
-   min_nelems = Min(nelems1, nelems2);
-   for (i = 0; i < min_nelems; i++)
-   {
        /* are they equal */
-       opresult = FunctionCall2(&my_extra->eqproc,
-                                dvalues1[i], dvalues2[i]);
+       opresult = FunctionCall2(&my_extra->eqproc, elt1, elt2);
+       if (DatumGetBool(opresult))
+           continue;
 
-       if (!DatumGetBool(opresult))
+       /* 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 */
-           opresult = FunctionCall2(&my_extra->ordproc,
-                                    dvalues1[i], dvalues2[i]);
-           if (DatumGetBool(opresult))
-           {
-               /* arg1 is less than arg2 */
-               result = -1;
-               break;
-           }
-           else
-           {
-               /* arg1 is greater than arg2 */
-               result = 1;
-               break;
-           }
+           /* arg1 is less than arg2 */
+           result = -1;
+           break;
+       }
+       else
+       {
+           /* arg1 is greater than arg2 */
+           result = 1;
+           break;
        }
    }
 
-   if ((result == 0) && (nelems1 != nelems2))
-       result = (nelems1 < nelems2) ? -1 : 1;
+   if ((result == 0) && (nitems1 != nitems2))
+       result = (nitems1 < nitems2) ? -1 : 1;
 
    /* Avoid leaking memory when handed toasted input. */
    PG_FREE_IF_COPY(array1, 0);