Make use of qsort_arg in several places that were formerly using klugy
authorTom Lane
Thu, 5 Oct 2006 17:57:40 +0000 (17:57 +0000)
committerTom Lane
Thu, 5 Oct 2006 17:57:40 +0000 (17:57 +0000)
static variables.  This avoids any risk of potential non-reentrancy,
and in particular offers a much cleaner workaround for the Intel compiler
bug that was affecting ginutil.c.

contrib/btree_gist/btree_utils_var.c
contrib/tsearch2/rank.c
contrib/tsearch2/tsvector.c
src/backend/access/gin/ginutil.c
src/backend/commands/analyze.c
src/include/access/gin.h

index 1f5ea126920a19e95bbd62759451df271bc0d206..ae44e754913a080f1e0b3dd148e80044610b0d83 100644 (file)
@@ -439,18 +439,14 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree
 }
 
 
-/*
- * Fortunately, this sort comparison routine needn't be reentrant...
- */
-static const gbtree_vinfo *gbt_vsrt_cmp_tinfo;
-
 static int
-gbt_vsrt_cmp(const void *a, const void *b)
+gbt_vsrt_cmp(const void *a, const void *b, void *arg)
 {
    GBT_VARKEY_R ar = gbt_var_key_readable(((const Vsrt *) a)->t);
    GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->t);
+   const gbtree_vinfo *tinfo = (const gbtree_vinfo *) arg;
 
-   return (*gbt_vsrt_cmp_tinfo->f_cmp) (ar.lower, br.lower);
+   return (*tinfo->f_cmp) (ar.lower, br.lower);
 }
 
 GIST_SPLITVEC *
@@ -496,11 +492,11 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
    }
 
    /* sort */
-   gbt_vsrt_cmp_tinfo = tinfo;
-   qsort((void *) &arr[FirstOffsetNumber],
-         maxoff - FirstOffsetNumber + 1,
-         sizeof(Vsrt),
-         gbt_vsrt_cmp);
+   qsort_arg((void *) &arr[FirstOffsetNumber],
+             maxoff - FirstOffsetNumber + 1,
+             sizeof(Vsrt),
+             gbt_vsrt_cmp,
+             (void *) tinfo);
 
    /* We do simply create two parts */
 
index 41e633580d59207bf84ad1406b3a9e488e075608..f8a7d5f2f063e97e5bb612d3097d1389b81aeb5e 100644 (file)
@@ -122,14 +122,14 @@ find_wordentry(tsvector * t, QUERYTYPE * q, ITEM * item)
 }
 
 
-static char *SortAndUniqOperand = NULL;
-
 static int
-compareITEM(const void *a, const void *b)
+compareITEM(const void *a, const void *b, void *arg)
 {
+   char *operand = (char *) arg;
+
    if ((*(ITEM **) a)->length == (*(ITEM **) b)->length)
-       return strncmp(SortAndUniqOperand + (*(ITEM **) a)->distance,
-                      SortAndUniqOperand + (*(ITEM **) b)->distance,
+       return strncmp(operand + (*(ITEM **) a)->distance,
+                      operand + (*(ITEM **) b)->distance,
                       (*(ITEM **) b)->length);
 
    return ((*(ITEM **) a)->length > (*(ITEM **) b)->length) ? 1 : -1;
@@ -158,15 +158,14 @@ SortAndUniqItems(char *operand, ITEM * item, int *size)
    if (*size < 2)
        return res;
 
-   SortAndUniqOperand = operand;
-   qsort(res, *size, sizeof(ITEM **), compareITEM);
+   qsort_arg(res, *size, sizeof(ITEM **), compareITEM, (void *) operand);
 
    ptr = res + 1;
    prevptr = res;
 
    while (ptr - res < *size)
    {
-       if (compareITEM((void *) ptr, (void *) prevptr) != 0)
+       if (compareITEM((void *) ptr, (void *) prevptr, (void *) operand) != 0)
        {
            prevptr++;
            *prevptr = *ptr;
@@ -551,10 +550,11 @@ get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen)
    int         len = query->size * 4,
                cur = 0;
    DocRepresentation *doc;
+   char       *operand;
 
    *(uint16 *) POSNULL = lengthof(POSNULL) - 1;
    doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len);
-   SortAndUniqOperand = GETOPERAND(query);
+   operand = GETOPERAND(query);
    reset_istrue_flag(query);
 
    for (i = 0; i < query->size; i++)
@@ -598,7 +598,9 @@ get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen)
                for (k = 0; k < query->size; k++)
                {
                    kptr = item + k;
-                   if (k == i || (item[k].type == VAL && compareITEM(&kptr, &iptr) == 0))
+                   if (k == i ||
+                       (item[k].type == VAL &&
+                        compareITEM(&kptr, &iptr, operand) == 0))
                    {
                        doc[cur].item[doc[cur].nitem] = item + k;
                        doc[cur].nitem++;
index a4a9d57d64556017a594b1950b6e780832cc8ed7..1abf1914e3392fb056b94ed544b76b6cc2121e65 100644 (file)
@@ -85,14 +85,14 @@ uniquePos(WordEntryPos * a, int4 l)
    return res + 1 - a;
 }
 
-static char *BufferStr;
 static int
-compareentry(const void *a, const void *b)
+compareentry(const void *a, const void *b, void *arg)
 {
+   char *BufferStr = (char *) arg;
+
    if (((WordEntryIN *) a)->entry.len == ((WordEntryIN *) b)->entry.len)
    {
-       return strncmp(
-                      &BufferStr[((WordEntryIN *) a)->entry.pos],
+       return strncmp(&BufferStr[((WordEntryIN *) a)->entry.pos],
                       &BufferStr[((WordEntryIN *) b)->entry.pos],
                       ((WordEntryIN *) a)->entry.len);
    }
@@ -117,8 +117,7 @@ uniqueentry(WordEntryIN * a, int4 l, char *buf, int4 *outbuflen)
    }
 
    ptr = a + 1;
-   BufferStr = buf;
-   qsort((void *) a, l, sizeof(WordEntryIN), compareentry);
+   qsort_arg((void *) a, l, sizeof(WordEntryIN), compareentry, (void *) buf);
 
    while (ptr - a < l)
    {
index e64137a10621a259a0566d2e9660773e8fe9c0a5..7b3c75db0d8621b3d9ab19851b64886bf677dbf2 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *         $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.7 2006/10/04 00:29:48 momjian Exp $
+ *         $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.8 2006/10/05 17:57:40 tgl Exp $
  *-------------------------------------------------------------------------
  */
 
@@ -129,62 +129,48 @@ compareEntries(GinState *ginstate, Datum a, Datum b)
    );
 }
 
-static FmgrInfo *cmpDatumPtr = NULL;
-
-#if defined(__INTEL_COMPILER) && (defined(__ia64__) || defined(__ia64))
-/*
- * Intel Compiler on Intel Itanium with -O2 has a bug around
- * change static variable by user function called from
- * libc func: it doesn't change. So mark it as volatile.
- *
- * It's a pity, but it's impossible to define optimization
- * level here.
- */
-#define VOLATILE   volatile
-#else
-#define VOLATILE
-#endif
-
-static bool VOLATILE needUnique = FALSE;
+typedef struct
+{
+   FmgrInfo   *cmpDatumFunc;
+   bool       *needUnique;
+} cmpEntriesData;
 
 static int
-cmpEntries(const void *a, const void *b)
+cmpEntries(const Datum *a, const Datum *b, cmpEntriesData *arg)
 {
-   int         res = DatumGetInt32(
-                                   FunctionCall2(
-                                                 cmpDatumPtr,
-                                                 *(Datum *) a,
-                                                 *(Datum *) b
-                                                 )
-   );
+   int         res = DatumGetInt32(FunctionCall2(arg->cmpDatumFunc,
+                                                 *a, *b));
 
    if (res == 0)
-       needUnique = TRUE;
+       *(arg->needUnique) = TRUE;
 
    return res;
 }
 
 Datum *
-extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries)
+extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries,
+               bool *needUnique)
 {
    Datum      *entries;
 
-   entries = (Datum *) DatumGetPointer(
-                                       FunctionCall2(
+   entries = (Datum *) DatumGetPointer(FunctionCall2(
                                                   &ginstate->extractValueFn,
                                                      value,
                                                    PointerGetDatum(nentries)
-                                                     )
-       );
+                                                     ));
 
    if (entries == NULL)
        *nentries = 0;
 
+   *needUnique = FALSE;
    if (*nentries > 1)
    {
-       cmpDatumPtr = &ginstate->compareFn;
-       needUnique = FALSE;
-       qsort(entries, *nentries, sizeof(Datum), cmpEntries);
+       cmpEntriesData arg;
+
+       arg.cmpDatumFunc = &ginstate->compareFn;
+       arg.needUnique = needUnique;
+       qsort_arg(entries, *nentries, sizeof(Datum),
+                 (qsort_arg_comparator) cmpEntries, (void *) &arg);
    }
 
    return entries;
@@ -194,9 +180,11 @@ extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries)
 Datum *
 extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries)
 {
-   Datum      *entries = extractEntriesS(ginstate, value, nentries);
+   bool        needUnique;
+   Datum      *entries = extractEntriesS(ginstate, value, nentries,
+                                         &needUnique);
 
-   if (*nentries > 1 && needUnique)
+   if (needUnique)
    {
        Datum      *ptr,
                   *res;
index 1ce768f0463ae09f0fdb88475a4d03eb79c6d813..cb538bdd42b52d62bfa320c1c6ca2f54791ad934 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.99 2006/10/04 00:29:50 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.100 2006/10/05 17:57:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1294,11 +1294,12 @@ typedef struct
    int         first;          /* values[] index of first occurrence */
 } ScalarMCVItem;
 
-
-/* context information for compare_scalars() */
-static FmgrInfo *datumCmpFn;
-static SortFunctionKind datumCmpFnKind;
-static int *datumCmpTupnoLink;
+typedef struct
+{
+   FmgrInfo   *cmpFn;
+   SortFunctionKind cmpFnKind;
+   int        *tupnoLink;
+} CompareScalarsContext;
 
 
 static void compute_minimal_stats(VacAttrStatsP stats,
@@ -1309,7 +1310,7 @@ static void compute_scalar_stats(VacAttrStatsP stats,
                     AnalyzeAttrFetchFunc fetchfunc,
                     int samplerows,
                     double totalrows);
-static int compare_scalars(const void *a, const void *b);
+static int compare_scalars(const void *a, const void *b, void *arg);
 static int compare_mcvs(const void *a, const void *b);
 
 
@@ -1828,13 +1829,14 @@ compute_scalar_stats(VacAttrStatsP stats,
                    num_hist,
                    dups_cnt;
        int         slot_idx = 0;
+       CompareScalarsContext cxt;
 
        /* Sort the collected values */
-       datumCmpFn = &f_cmpfn;
-       datumCmpFnKind = cmpFnKind;
-       datumCmpTupnoLink = tupnoLink;
-       qsort((void *) values, values_cnt,
-             sizeof(ScalarItem), compare_scalars);
+       cxt.cmpFn = &f_cmpfn;
+       cxt.cmpFnKind = cmpFnKind;
+       cxt.tupnoLink = tupnoLink;
+       qsort_arg((void *) values, values_cnt, sizeof(ScalarItem),
+                 compare_scalars, (void *) &cxt);
 
        /*
         * Now scan the values in order, find the most common ones, and also
@@ -2183,35 +2185,36 @@ compute_scalar_stats(VacAttrStatsP stats,
 }
 
 /*
- * qsort comparator for sorting ScalarItems
+ * qsort_arg comparator for sorting ScalarItems
  *
- * Aside from sorting the items, we update the datumCmpTupnoLink[] array
+ * Aside from sorting the items, we update the tupnoLink[] array
  * whenever two ScalarItems are found to contain equal datums. The array
  * is indexed by tupno; for each ScalarItem, it contains the highest
  * tupno that that item's datum has been found to be equal to.  This allows
  * us to avoid additional comparisons in compute_scalar_stats().
  */
 static int
-compare_scalars(const void *a, const void *b)
+compare_scalars(const void *a, const void *b, void *arg)
 {
    Datum       da = ((ScalarItem *) a)->value;
    int         ta = ((ScalarItem *) a)->tupno;
    Datum       db = ((ScalarItem *) b)->value;
    int         tb = ((ScalarItem *) b)->tupno;
+   CompareScalarsContext *cxt = (CompareScalarsContext *) arg;
    int32       compare;
 
-   compare = ApplySortFunction(datumCmpFn, datumCmpFnKind,
+   compare = ApplySortFunction(cxt->cmpFn, cxt->cmpFnKind,
                                da, false, db, false);
    if (compare != 0)
        return compare;
 
    /*
-    * The two datums are equal, so update datumCmpTupnoLink[].
+    * The two datums are equal, so update cxt->tupnoLink[].
     */
-   if (datumCmpTupnoLink[ta] < tb)
-       datumCmpTupnoLink[ta] = tb;
-   if (datumCmpTupnoLink[tb] < ta)
-       datumCmpTupnoLink[tb] = ta;
+   if (cxt->tupnoLink[ta] < tb)
+       cxt->tupnoLink[ta] = tb;
+   if (cxt->tupnoLink[tb] < ta)
+       cxt->tupnoLink[tb] = ta;
 
    /*
     * For equal datums, sort by tupno
index 7035635e68650b6993c1abdd4461fa34749d4789..c37b3672781772d62b79fbe65f46fd2d7766815d 100644 (file)
@@ -3,7 +3,7 @@
  *   header file for postgres inverted index access method implementation.
  *
  * Copyright (c) 2006, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/src/include/access/gin.h,v 1.8 2006/10/04 00:30:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/gin.h,v 1.9 2006/10/05 17:57:40 tgl Exp $
  *--------------------------------------------------------------------------
  */
 
@@ -232,7 +232,8 @@ extern Buffer GinNewBuffer(Relation index);
 extern void GinInitBuffer(Buffer b, uint32 f);
 extern void GinInitPage(Page page, uint32 f, Size pageSize);
 extern int compareEntries(GinState *ginstate, Datum a, Datum b);
-extern Datum *extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries);
+extern Datum *extractEntriesS(GinState *ginstate, Datum value,
+                             uint32 *nentries, bool *needUnique);
 extern Datum *extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries);
 extern Page GinPageGetCopyPage(Page page);