Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4ebc72a

Browse files
tglsfdcCommitfest Bot
authored and
Commitfest Bot
committed
Preliminary refactoring.
This step doesn't change any behavior. It cleans the code up slightly and documents it better. In particular, the test being used by gin_btree_compare_prefix is better explained (IMO) and there's now an Assert backing up the assumption it has to make. Discussion: https://postgr.es/m/262624.1738460652@sss.pgh.pa.us
1 parent 16acbed commit 4ebc72a

File tree

3 files changed

+60
-37
lines changed

3 files changed

+60
-37
lines changed

contrib/btree_gin/btree_gin.c

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@ PG_MODULE_MAGIC_EXT(
1919
.version = PG_VERSION
2020
);
2121

22+
/* extra data passed from gin_btree_extract_query to gin_btree_compare_prefix */
2223
typedef struct QueryInfo
2324
{
24-
StrategyNumber strategy;
25-
Datum datum;
26-
bool is_varlena;
27-
Datum (*typecmp) (FunctionCallInfo);
25+
StrategyNumber strategy; /* operator strategy number */
26+
Datum orig_datum; /* original query (comparison) datum */
27+
Datum entry_datum; /* datum we reported as the entry value */
28+
PGFunction typecmp; /* appropriate btree comparison function */
2829
} QueryInfo;
2930

31+
typedef Datum (*btree_gin_leftmost_function) (void);
32+
33+
3034
/*** GIN support functions shared by all datatypes ***/
3135

3236
static Datum
@@ -36,6 +40,7 @@ gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
3640
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
3741
Datum *entries = (Datum *) palloc(sizeof(Datum));
3842

43+
/* Ensure that values stored in the index are not toasted */
3944
if (is_varlena)
4045
datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
4146
entries[0] = datum;
@@ -44,19 +49,11 @@ gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
4449
PG_RETURN_POINTER(entries);
4550
}
4651

47-
/*
48-
* For BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, and
49-
* BTEqualStrategyNumber we want to start the index scan at the
50-
* supplied query datum, and work forward. For BTLessStrategyNumber
51-
* and BTLessEqualStrategyNumber, we need to start at the leftmost
52-
* key, and work forward until the supplied query datum (which must be
53-
* sent along inside the QueryInfo structure).
54-
*/
5552
static Datum
5653
gin_btree_extract_query(FunctionCallInfo fcinfo,
5754
bool is_varlena,
58-
Datum (*leftmostvalue) (void),
59-
Datum (*typecmp) (FunctionCallInfo))
55+
btree_gin_leftmost_function leftmostvalue,
56+
PGFunction typecmp)
6057
{
6158
Datum datum = PG_GETARG_DATUM(0);
6259
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
@@ -65,20 +62,29 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
6562
Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
6663
Datum *entries = (Datum *) palloc(sizeof(Datum));
6764
QueryInfo *data = (QueryInfo *) palloc(sizeof(QueryInfo));
68-
bool *ptr_partialmatch;
65+
bool *ptr_partialmatch = (bool *) palloc(sizeof(bool));
6966

70-
*nentries = 1;
71-
ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool));
72-
*ptr_partialmatch = false;
67+
/*
68+
* Detoast the comparison datum. This isn't necessary for correctness,
69+
* but it can save repeat detoastings within the comparison function.
70+
*/
7371
if (is_varlena)
7472
datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
75-
data->strategy = strategy;
76-
data->datum = datum;
77-
data->is_varlena = is_varlena;
78-
data->typecmp = typecmp;
79-
*extra_data = (Pointer *) palloc(sizeof(Pointer));
80-
**extra_data = (Pointer) data;
8173

74+
/* Prep single comparison key with possible partial-match flag */
75+
*nentries = 1;
76+
*partialmatch = ptr_partialmatch;
77+
*ptr_partialmatch = false;
78+
79+
/*
80+
* For BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, and
81+
* BTEqualStrategyNumber we want to start the index scan at the supplied
82+
* query datum, and work forward. For BTLessStrategyNumber and
83+
* BTLessEqualStrategyNumber, we need to start at the leftmost key, and
84+
* work forward until the supplied query datum (which we'll send along
85+
* inside the QueryInfo structure). Use partial match rules except for
86+
* BTEqualStrategyNumber.
87+
*/
8288
switch (strategy)
8389
{
8490
case BTLessStrategyNumber:
@@ -97,30 +103,42 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
97103
elog(ERROR, "unrecognized strategy number: %d", strategy);
98104
}
99105

106+
/* Fill "extra" data */
107+
data->strategy = strategy;
108+
data->orig_datum = datum;
109+
data->entry_datum = entries[0];
110+
data->typecmp = typecmp;
111+
*extra_data = (Pointer *) palloc(sizeof(Pointer));
112+
**extra_data = (Pointer) data;
113+
100114
PG_RETURN_POINTER(entries);
101115
}
102116

103-
/*
104-
* Datum a is a value from extract_query method and for BTLess*
105-
* strategy it is a left-most value. So, use original datum from QueryInfo
106-
* to decide to stop scanning or not. Datum b is always from index.
107-
*/
108117
static Datum
109118
gin_btree_compare_prefix(FunctionCallInfo fcinfo)
110119
{
111-
Datum a = PG_GETARG_DATUM(0);
112-
Datum b = PG_GETARG_DATUM(1);
120+
Datum partial_key PG_USED_FOR_ASSERTS_ONLY = PG_GETARG_DATUM(0);
121+
Datum key = PG_GETARG_DATUM(1);
113122
QueryInfo *data = (QueryInfo *) PG_GETARG_POINTER(3);
114123
int32 res,
115124
cmp;
116125

126+
/*
127+
* partial_key is only an approximation to the real comparison value,
128+
* especially if it's a leftmost value. We can get an accurate answer by
129+
* doing a possibly-cross-type comparison to the real comparison value.
130+
* But just to be sure that things are what we expect, let's assert that
131+
* partial_key is indeed what gin_btree_extract_query reported, so that
132+
* we'll notice if anyone ever changes the core code in a way that breaks
133+
* our assumptions.
134+
*/
135+
Assert(partial_key == data->entry_datum);
136+
117137
cmp = DatumGetInt32(CallerFInfoFunctionCall2(data->typecmp,
118138
fcinfo->flinfo,
119139
PG_GET_COLLATION(),
120-
(data->strategy == BTLessStrategyNumber ||
121-
data->strategy == BTLessEqualStrategyNumber)
122-
? data->datum : a,
123-
b));
140+
data->orig_datum,
141+
key));
124142

125143
switch (data->strategy)
126144
{
@@ -152,7 +170,7 @@ gin_btree_compare_prefix(FunctionCallInfo fcinfo)
152170
res = 1;
153171
break;
154172
case BTGreaterStrategyNumber:
155-
/* If original datum <= indexed one then return match */
173+
/* If original datum < indexed one then return match */
156174
/* If original datum == indexed one then continue scan */
157175
if (cmp < 0)
158176
res = 0;

doc/src/sgml/gin.sgml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,11 @@
394394
Pointer extra_data)</function></term>
395395
<listitem>
396396
<para>
397-
Compare a partial-match query key to an index key. Returns an integer
397+
Compare a partial-match query key to an index key.
398+
<literal>partial_key</literal> is a query key that was returned
399+
by <function>extractQuery</function> with an indication that it
400+
requires partial match, and <literal>key</literal> is an index entry.
401+
Returns an integer
398402
whose sign indicates the result: less than zero means the index key
399403
does not match the query, but the index scan should continue; zero
400404
means that the index key does match the query; greater than zero

src/tools/pgindent/typedefs.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3463,6 +3463,7 @@ bloom_filter
34633463
boolKEY
34643464
brin_column_state
34653465
brin_serialize_callback_type
3466+
btree_gin_leftmost_function
34663467
bytea
34673468
cached_re_str
34683469
canonicalize_state

0 commit comments

Comments
 (0)