mirror of
https://github.com/postgres/postgres.git
synced 2025-06-03 00:02:26 -04: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:
parent
f2332ea1e9
commit
e378f82e00
@ -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
|
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 ar = gbt_var_key_readable(((const Vsrt *) a)->t);
|
||||||
GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->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 *
|
GIST_SPLITVEC *
|
||||||
@ -496,11 +492,11 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* sort */
|
/* sort */
|
||||||
gbt_vsrt_cmp_tinfo = tinfo;
|
qsort_arg((void *) &arr[FirstOffsetNumber],
|
||||||
qsort((void *) &arr[FirstOffsetNumber],
|
maxoff - FirstOffsetNumber + 1,
|
||||||
maxoff - FirstOffsetNumber + 1,
|
sizeof(Vsrt),
|
||||||
sizeof(Vsrt),
|
gbt_vsrt_cmp,
|
||||||
gbt_vsrt_cmp);
|
(void *) tinfo);
|
||||||
|
|
||||||
/* We do simply create two parts */
|
/* We do simply create two parts */
|
||||||
|
|
||||||
|
@ -122,14 +122,14 @@ find_wordentry(tsvector * t, QUERYTYPE * q, ITEM * item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *SortAndUniqOperand = NULL;
|
|
||||||
|
|
||||||
static int
|
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)
|
if ((*(ITEM **) a)->length == (*(ITEM **) b)->length)
|
||||||
return strncmp(SortAndUniqOperand + (*(ITEM **) a)->distance,
|
return strncmp(operand + (*(ITEM **) a)->distance,
|
||||||
SortAndUniqOperand + (*(ITEM **) b)->distance,
|
operand + (*(ITEM **) b)->distance,
|
||||||
(*(ITEM **) b)->length);
|
(*(ITEM **) b)->length);
|
||||||
|
|
||||||
return ((*(ITEM **) a)->length > (*(ITEM **) b)->length) ? 1 : -1;
|
return ((*(ITEM **) a)->length > (*(ITEM **) b)->length) ? 1 : -1;
|
||||||
@ -158,15 +158,14 @@ SortAndUniqItems(char *operand, ITEM * item, int *size)
|
|||||||
if (*size < 2)
|
if (*size < 2)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
SortAndUniqOperand = operand;
|
qsort_arg(res, *size, sizeof(ITEM **), compareITEM, (void *) operand);
|
||||||
qsort(res, *size, sizeof(ITEM **), compareITEM);
|
|
||||||
|
|
||||||
ptr = res + 1;
|
ptr = res + 1;
|
||||||
prevptr = res;
|
prevptr = res;
|
||||||
|
|
||||||
while (ptr - res < *size)
|
while (ptr - res < *size)
|
||||||
{
|
{
|
||||||
if (compareITEM((void *) ptr, (void *) prevptr) != 0)
|
if (compareITEM((void *) ptr, (void *) prevptr, (void *) operand) != 0)
|
||||||
{
|
{
|
||||||
prevptr++;
|
prevptr++;
|
||||||
*prevptr = *ptr;
|
*prevptr = *ptr;
|
||||||
@ -551,10 +550,11 @@ get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen)
|
|||||||
int len = query->size * 4,
|
int len = query->size * 4,
|
||||||
cur = 0;
|
cur = 0;
|
||||||
DocRepresentation *doc;
|
DocRepresentation *doc;
|
||||||
|
char *operand;
|
||||||
|
|
||||||
*(uint16 *) POSNULL = lengthof(POSNULL) - 1;
|
*(uint16 *) POSNULL = lengthof(POSNULL) - 1;
|
||||||
doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len);
|
doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len);
|
||||||
SortAndUniqOperand = GETOPERAND(query);
|
operand = GETOPERAND(query);
|
||||||
reset_istrue_flag(query);
|
reset_istrue_flag(query);
|
||||||
|
|
||||||
for (i = 0; i < query->size; i++)
|
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++)
|
for (k = 0; k < query->size; k++)
|
||||||
{
|
{
|
||||||
kptr = item + 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].item[doc[cur].nitem] = item + k;
|
||||||
doc[cur].nitem++;
|
doc[cur].nitem++;
|
||||||
|
@ -85,14 +85,14 @@ uniquePos(WordEntryPos * a, int4 l)
|
|||||||
return res + 1 - a;
|
return res + 1 - a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *BufferStr;
|
|
||||||
static int
|
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)
|
if (((WordEntryIN *) a)->entry.len == ((WordEntryIN *) b)->entry.len)
|
||||||
{
|
{
|
||||||
return strncmp(
|
return strncmp(&BufferStr[((WordEntryIN *) a)->entry.pos],
|
||||||
&BufferStr[((WordEntryIN *) a)->entry.pos],
|
|
||||||
&BufferStr[((WordEntryIN *) b)->entry.pos],
|
&BufferStr[((WordEntryIN *) b)->entry.pos],
|
||||||
((WordEntryIN *) a)->entry.len);
|
((WordEntryIN *) a)->entry.len);
|
||||||
}
|
}
|
||||||
@ -117,8 +117,7 @@ uniqueentry(WordEntryIN * a, int4 l, char *buf, int4 *outbuflen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ptr = a + 1;
|
ptr = a + 1;
|
||||||
BufferStr = buf;
|
qsort_arg((void *) a, l, sizeof(WordEntryIN), compareentry, (void *) buf);
|
||||||
qsort((void *) a, l, sizeof(WordEntryIN), compareentry);
|
|
||||||
|
|
||||||
while (ptr - a < l)
|
while (ptr - a < l)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
typedef struct
|
||||||
|
{
|
||||||
#if defined(__INTEL_COMPILER) && (defined(__ia64__) || defined(__ia64))
|
FmgrInfo *cmpDatumFunc;
|
||||||
/*
|
bool *needUnique;
|
||||||
* Intel Compiler on Intel Itanium with -O2 has a bug around
|
} cmpEntriesData;
|
||||||
* 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;
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmpEntries(const void *a, const void *b)
|
cmpEntries(const Datum *a, const Datum *b, cmpEntriesData *arg)
|
||||||
{
|
{
|
||||||
int res = DatumGetInt32(
|
int res = DatumGetInt32(FunctionCall2(arg->cmpDatumFunc,
|
||||||
FunctionCall2(
|
*a, *b));
|
||||||
cmpDatumPtr,
|
|
||||||
*(Datum *) a,
|
|
||||||
*(Datum *) b
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
needUnique = TRUE;
|
*(arg->needUnique) = TRUE;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum *
|
Datum *
|
||||||
extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries)
|
extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries,
|
||||||
|
bool *needUnique)
|
||||||
{
|
{
|
||||||
Datum *entries;
|
Datum *entries;
|
||||||
|
|
||||||
entries = (Datum *) DatumGetPointer(
|
entries = (Datum *) DatumGetPointer(FunctionCall2(
|
||||||
FunctionCall2(
|
|
||||||
&ginstate->extractValueFn,
|
&ginstate->extractValueFn,
|
||||||
value,
|
value,
|
||||||
PointerGetDatum(nentries)
|
PointerGetDatum(nentries)
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
||||||
if (entries == NULL)
|
if (entries == NULL)
|
||||||
*nentries = 0;
|
*nentries = 0;
|
||||||
|
|
||||||
|
*needUnique = FALSE;
|
||||||
if (*nentries > 1)
|
if (*nentries > 1)
|
||||||
{
|
{
|
||||||
cmpDatumPtr = &ginstate->compareFn;
|
cmpEntriesData arg;
|
||||||
needUnique = FALSE;
|
|
||||||
qsort(entries, *nentries, sizeof(Datum), cmpEntries);
|
arg.cmpDatumFunc = &ginstate->compareFn;
|
||||||
|
arg.needUnique = needUnique;
|
||||||
|
qsort_arg(entries, *nentries, sizeof(Datum),
|
||||||
|
(qsort_arg_comparator) cmpEntries, (void *) &arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
@ -194,9 +180,11 @@ extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries)
|
|||||||
Datum *
|
Datum *
|
||||||
extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries)
|
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,
|
Datum *ptr,
|
||||||
*res;
|
*res;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 */
|
int first; /* values[] index of first occurrence */
|
||||||
} ScalarMCVItem;
|
} ScalarMCVItem;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
/* context information for compare_scalars() */
|
{
|
||||||
static FmgrInfo *datumCmpFn;
|
FmgrInfo *cmpFn;
|
||||||
static SortFunctionKind datumCmpFnKind;
|
SortFunctionKind cmpFnKind;
|
||||||
static int *datumCmpTupnoLink;
|
int *tupnoLink;
|
||||||
|
} CompareScalarsContext;
|
||||||
|
|
||||||
|
|
||||||
static void compute_minimal_stats(VacAttrStatsP stats,
|
static void compute_minimal_stats(VacAttrStatsP stats,
|
||||||
@ -1309,7 +1310,7 @@ static void compute_scalar_stats(VacAttrStatsP stats,
|
|||||||
AnalyzeAttrFetchFunc fetchfunc,
|
AnalyzeAttrFetchFunc fetchfunc,
|
||||||
int samplerows,
|
int samplerows,
|
||||||
double totalrows);
|
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);
|
static int compare_mcvs(const void *a, const void *b);
|
||||||
|
|
||||||
|
|
||||||
@ -1828,13 +1829,14 @@ compute_scalar_stats(VacAttrStatsP stats,
|
|||||||
num_hist,
|
num_hist,
|
||||||
dups_cnt;
|
dups_cnt;
|
||||||
int slot_idx = 0;
|
int slot_idx = 0;
|
||||||
|
CompareScalarsContext cxt;
|
||||||
|
|
||||||
/* Sort the collected values */
|
/* Sort the collected values */
|
||||||
datumCmpFn = &f_cmpfn;
|
cxt.cmpFn = &f_cmpfn;
|
||||||
datumCmpFnKind = cmpFnKind;
|
cxt.cmpFnKind = cmpFnKind;
|
||||||
datumCmpTupnoLink = tupnoLink;
|
cxt.tupnoLink = tupnoLink;
|
||||||
qsort((void *) values, values_cnt,
|
qsort_arg((void *) values, values_cnt, sizeof(ScalarItem),
|
||||||
sizeof(ScalarItem), compare_scalars);
|
compare_scalars, (void *) &cxt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now scan the values in order, find the most common ones, and also
|
* 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
|
* whenever two ScalarItems are found to contain equal datums. The array
|
||||||
* is indexed by tupno; for each ScalarItem, it contains the highest
|
* 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
|
* tupno that that item's datum has been found to be equal to. This allows
|
||||||
* us to avoid additional comparisons in compute_scalar_stats().
|
* us to avoid additional comparisons in compute_scalar_stats().
|
||||||
*/
|
*/
|
||||||
static int
|
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;
|
Datum da = ((ScalarItem *) a)->value;
|
||||||
int ta = ((ScalarItem *) a)->tupno;
|
int ta = ((ScalarItem *) a)->tupno;
|
||||||
Datum db = ((ScalarItem *) b)->value;
|
Datum db = ((ScalarItem *) b)->value;
|
||||||
int tb = ((ScalarItem *) b)->tupno;
|
int tb = ((ScalarItem *) b)->tupno;
|
||||||
|
CompareScalarsContext *cxt = (CompareScalarsContext *) arg;
|
||||||
int32 compare;
|
int32 compare;
|
||||||
|
|
||||||
compare = ApplySortFunction(datumCmpFn, datumCmpFnKind,
|
compare = ApplySortFunction(cxt->cmpFn, cxt->cmpFnKind,
|
||||||
da, false, db, false);
|
da, false, db, false);
|
||||||
if (compare != 0)
|
if (compare != 0)
|
||||||
return compare;
|
return compare;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The two datums are equal, so update datumCmpTupnoLink[].
|
* The two datums are equal, so update cxt->tupnoLink[].
|
||||||
*/
|
*/
|
||||||
if (datumCmpTupnoLink[ta] < tb)
|
if (cxt->tupnoLink[ta] < tb)
|
||||||
datumCmpTupnoLink[ta] = tb;
|
cxt->tupnoLink[ta] = tb;
|
||||||
if (datumCmpTupnoLink[tb] < ta)
|
if (cxt->tupnoLink[tb] < ta)
|
||||||
datumCmpTupnoLink[tb] = ta;
|
cxt->tupnoLink[tb] = ta;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For equal datums, sort by tupno
|
* For equal datums, sort by tupno
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* header file for postgres inverted index access method implementation.
|
* header file for postgres inverted index access method implementation.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2006, PostgreSQL Global Development Group
|
* 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 GinInitBuffer(Buffer b, uint32 f);
|
||||||
extern void GinInitPage(Page page, uint32 f, Size pageSize);
|
extern void GinInitPage(Page page, uint32 f, Size pageSize);
|
||||||
extern int compareEntries(GinState *ginstate, Datum a, Datum b);
|
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 Datum *extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries);
|
||||||
extern Page GinPageGetCopyPage(Page page);
|
extern Page GinPageGetCopyPage(Page page);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user