Skip to content

Commit 4380362

Browse files
committed
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>
1 parent 93ea78b commit 4380362

File tree

3 files changed

+21
-23
lines changed

3 files changed

+21
-23
lines changed

src/backend/access/gin/ginscan.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ ginNewScanKey(IndexScanDesc scan)
295295
bool *partial_matches = NULL;
296296
Pointer *extra_data = NULL;
297297
bool *nullFlags = NULL;
298+
GinNullCategory *categories;
298299
int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
299300

300301
/*
@@ -346,33 +347,29 @@ ginNewScanKey(IndexScanDesc scan)
346347
}
347348

348349
/*
349-
* If the extractQueryFn didn't create a nullFlags array, create one,
350-
* assuming that everything's non-null. Otherwise, run through the
351-
* array and make sure each value is exactly 0 or 1; this ensures
352-
* binary compatibility with the GinNullCategory representation. While
353-
* at it, detect whether any null keys are present.
350+
* Create GinNullCategory representation. If the extractQueryFn
351+
* didn't create a nullFlags array, we assume everything is non-null.
352+
* While at it, detect whether any null keys are present.
354353
*/
355-
if (nullFlags == NULL)
356-
nullFlags = (bool *) palloc0(nQueryValues * sizeof(bool));
357-
else
354+
categories = (GinNullCategory *) palloc0(nQueryValues * sizeof(GinNullCategory));
355+
if (nullFlags)
358356
{
359357
int32 j;
360358

361359
for (j = 0; j < nQueryValues; j++)
362360
{
363361
if (nullFlags[j])
364362
{
365-
nullFlags[j] = true; /* not any other nonzero value */
363+
categories[j] = GIN_CAT_NULL_KEY;
366364
hasNullQuery = true;
367365
}
368366
}
369367
}
370-
/* now we can use the nullFlags as category codes */
371368

372369
ginFillScanKey(so, skey->sk_attno,
373370
skey->sk_strategy, searchMode,
374371
skey->sk_argument, nQueryValues,
375-
queryValues, (GinNullCategory *) nullFlags,
372+
queryValues, categories,
376373
partial_matches, extra_data);
377374
}
378375

src/backend/access/gin/ginutil.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -529,19 +529,10 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
529529

530530
/*
531531
* If the extractValueFn didn't create a nullFlags array, create one,
532-
* assuming that everything's non-null. Otherwise, run through the array
533-
* and make sure each value is exactly 0 or 1; this ensures binary
534-
* compatibility with the GinNullCategory representation.
532+
* assuming that everything's non-null.
535533
*/
536534
if (nullFlags == NULL)
537535
nullFlags = (bool *) palloc0(*nentries * sizeof(bool));
538-
else
539-
{
540-
for (i = 0; i < *nentries; i++)
541-
nullFlags[i] = (nullFlags[i] ? true : false);
542-
}
543-
/* now we can use the nullFlags as category codes */
544-
*categories = (GinNullCategory *) nullFlags;
545536

546537
/*
547538
* If there's more than one key, sort and unique-ify.
@@ -600,6 +591,13 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
600591
pfree(keydata);
601592
}
602593

594+
/*
595+
* Create GinNullCategory representation from nullFlags.
596+
*/
597+
*categories = (GinNullCategory *) palloc0(*nentries * sizeof(GinNullCategory));
598+
for (i = 0; i < *nentries; i++)
599+
(*categories)[i] = (nullFlags[i] ? GIN_CAT_NULL_KEY : GIN_CAT_NORM_KEY);
600+
603601
return entries;
604602
}
605603

src/include/access/ginblock.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,11 @@ typedef struct
188188

189189
/*
190190
* Category codes to distinguish placeholder nulls from ordinary NULL keys.
191-
* Note that the datatype size and the first two code values are chosen to be
192-
* compatible with the usual usage of bool isNull flags.
191+
*
192+
* The first two code values were chosen to be compatible with the usual usage
193+
* of bool isNull flags. However, casting between bool and GinNullCategory is
194+
* risky because of the possibility of different bit patterns and type sizes,
195+
* so it is no longer done.
193196
*
194197
* GIN_CAT_EMPTY_QUERY is never stored in the index; and notice that it is
195198
* chosen to sort before not after regular key values.

0 commit comments

Comments
 (0)