mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Don't cast between GinNullCategory and bool
The original idea was that we could use an isNull-style bool array directly as a GinNullCategory array. However, the existing code already acknowledges that that doesn't really work, because of the possibility that bool as currently defined can have arbitrary bit patterns for true values. So it has to loop through the nullFlags array to set each bool value to an acceptable value. But if we are looping through the whole array anyway, we might as well build a proper GinNullCategory array instead and abandon the type casting. That makes the code much safer in case bool is ever changed to something else. Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
This commit is contained in:
@ -295,6 +295,7 @@ ginNewScanKey(IndexScanDesc scan)
|
|||||||
bool *partial_matches = NULL;
|
bool *partial_matches = NULL;
|
||||||
Pointer *extra_data = NULL;
|
Pointer *extra_data = NULL;
|
||||||
bool *nullFlags = NULL;
|
bool *nullFlags = NULL;
|
||||||
|
GinNullCategory *categories;
|
||||||
int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
|
int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -346,15 +347,12 @@ ginNewScanKey(IndexScanDesc scan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the extractQueryFn didn't create a nullFlags array, create one,
|
* Create GinNullCategory representation. If the extractQueryFn
|
||||||
* assuming that everything's non-null. Otherwise, run through the
|
* didn't create a nullFlags array, we assume everything is non-null.
|
||||||
* array and make sure each value is exactly 0 or 1; this ensures
|
* While at it, detect whether any null keys are present.
|
||||||
* binary compatibility with the GinNullCategory representation. While
|
|
||||||
* at it, detect whether any null keys are present.
|
|
||||||
*/
|
*/
|
||||||
if (nullFlags == NULL)
|
categories = (GinNullCategory *) palloc0(nQueryValues * sizeof(GinNullCategory));
|
||||||
nullFlags = (bool *) palloc0(nQueryValues * sizeof(bool));
|
if (nullFlags)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
int32 j;
|
int32 j;
|
||||||
|
|
||||||
@ -362,17 +360,16 @@ ginNewScanKey(IndexScanDesc scan)
|
|||||||
{
|
{
|
||||||
if (nullFlags[j])
|
if (nullFlags[j])
|
||||||
{
|
{
|
||||||
nullFlags[j] = true; /* not any other nonzero value */
|
categories[j] = GIN_CAT_NULL_KEY;
|
||||||
hasNullQuery = true;
|
hasNullQuery = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* now we can use the nullFlags as category codes */
|
|
||||||
|
|
||||||
ginFillScanKey(so, skey->sk_attno,
|
ginFillScanKey(so, skey->sk_attno,
|
||||||
skey->sk_strategy, searchMode,
|
skey->sk_strategy, searchMode,
|
||||||
skey->sk_argument, nQueryValues,
|
skey->sk_argument, nQueryValues,
|
||||||
queryValues, (GinNullCategory *) nullFlags,
|
queryValues, categories,
|
||||||
partial_matches, extra_data);
|
partial_matches, extra_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,19 +529,10 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If the extractValueFn didn't create a nullFlags array, create one,
|
* If the extractValueFn didn't create a nullFlags array, create one,
|
||||||
* assuming that everything's non-null. Otherwise, run through the array
|
* assuming that everything's non-null.
|
||||||
* and make sure each value is exactly 0 or 1; this ensures binary
|
|
||||||
* compatibility with the GinNullCategory representation.
|
|
||||||
*/
|
*/
|
||||||
if (nullFlags == NULL)
|
if (nullFlags == NULL)
|
||||||
nullFlags = (bool *) palloc0(*nentries * sizeof(bool));
|
nullFlags = (bool *) palloc0(*nentries * sizeof(bool));
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < *nentries; i++)
|
|
||||||
nullFlags[i] = (nullFlags[i] ? true : false);
|
|
||||||
}
|
|
||||||
/* now we can use the nullFlags as category codes */
|
|
||||||
*categories = (GinNullCategory *) nullFlags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there's more than one key, sort and unique-ify.
|
* If there's more than one key, sort and unique-ify.
|
||||||
@ -600,6 +591,13 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
|
|||||||
pfree(keydata);
|
pfree(keydata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create GinNullCategory representation from nullFlags.
|
||||||
|
*/
|
||||||
|
*categories = (GinNullCategory *) palloc0(*nentries * sizeof(GinNullCategory));
|
||||||
|
for (i = 0; i < *nentries; i++)
|
||||||
|
(*categories)[i] = (nullFlags[i] ? GIN_CAT_NULL_KEY : GIN_CAT_NORM_KEY);
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,8 +188,11 @@ typedef struct
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Category codes to distinguish placeholder nulls from ordinary NULL keys.
|
* Category codes to distinguish placeholder nulls from ordinary NULL keys.
|
||||||
* Note that the datatype size and the first two code values are chosen to be
|
*
|
||||||
* compatible with the usual usage of bool isNull flags.
|
* The first two code values were chosen to be compatible with the usual usage
|
||||||
|
* of bool isNull flags. However, casting between bool and GinNullCategory is
|
||||||
|
* risky because of the possibility of different bit patterns and type sizes,
|
||||||
|
* so it is no longer done.
|
||||||
*
|
*
|
||||||
* GIN_CAT_EMPTY_QUERY is never stored in the index; and notice that it is
|
* GIN_CAT_EMPTY_QUERY is never stored in the index; and notice that it is
|
||||||
* chosen to sort before not after regular key values.
|
* chosen to sort before not after regular key values.
|
||||||
|
Reference in New Issue
Block a user