mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Make use of qsort_arg in several places that were formerly using klugy
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.
This commit is contained in:
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user