PostgreSQL Source Code git master
Loading...
Searching...
No Matches
spgist_name_ops.c File Reference
#include "postgres.h"
#include "access/spgist.h"
#include "catalog/pg_type.h"
#include "utils/datum.h"
#include "varatt.h"
Include dependency graph for spgist_name_ops.c:

Go to the source code of this file.

Functions

 PG_FUNCTION_INFO_V1 (spgist_name_config)
 
Datum spgist_name_config (PG_FUNCTION_ARGS)
 
static Datum formTextDatum (const char *data, int datalen)
 
static int commonPrefix (const char *a, const char *b, int lena, int lenb)
 
static bool searchChar (const Datum *nodeLabels, int nNodes, int16 c, int *i)
 
 PG_FUNCTION_INFO_V1 (spgist_name_choose)
 
Datum spgist_name_choose (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (spgist_name_inner_consistent)
 
Datum spgist_name_inner_consistent (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (spgist_name_leaf_consistent)
 
Datum spgist_name_leaf_consistent (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (spgist_name_compress)
 
Datum spgist_name_compress (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 

Function Documentation

◆ commonPrefix()

static int commonPrefix ( const char a,
const char b,
int  lena,
int  lenb 
)
static

Definition at line 79 of file spgist_name_ops.c.

80{
81 int i = 0;
82
83 while (i < lena && i < lenb && *a == *b)
84 {
85 a++;
86 b++;
87 i++;
88 }
89
90 return i;
91}
int b
Definition isn.c:74
int a
Definition isn.c:73
int i
Definition isn.c:77
static int fb(int x)

References a, b, fb(), and i.

Referenced by spgist_name_choose().

◆ formTextDatum()

static Datum formTextDatum ( const char data,
int  datalen 
)
static

Definition at line 54 of file spgist_name_ops.c.

55{
56 char *p;
57
58 p = (char *) palloc(datalen + VARHDRSZ);
59
60 if (datalen + VARHDRSZ_SHORT <= VARATT_SHORT_MAX)
61 {
63 if (datalen)
64 memcpy(p + VARHDRSZ_SHORT, data, datalen);
65 }
66 else
67 {
68 SET_VARSIZE(p, datalen + VARHDRSZ);
69 memcpy(p + VARHDRSZ, data, datalen);
70 }
71
72 return PointerGetDatum(p);
73}
#define VARHDRSZ
Definition c.h:711
void * palloc(Size size)
Definition mcxt.c:1387
const void * data
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
#define VARHDRSZ_SHORT
Definition varatt.h:278
static void SET_VARSIZE_SHORT(void *PTR, Size len)
Definition varatt.h:439
#define VARATT_SHORT_MAX
Definition varatt.h:279
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432

References data, fb(), palloc(), PointerGetDatum(), SET_VARSIZE(), SET_VARSIZE_SHORT(), VARATT_SHORT_MAX, VARHDRSZ, and VARHDRSZ_SHORT.

Referenced by spgist_name_choose(), and spgist_name_compress().

◆ PG_FUNCTION_INFO_V1() [1/5]

PG_FUNCTION_INFO_V1 ( spgist_name_choose  )

◆ PG_FUNCTION_INFO_V1() [2/5]

PG_FUNCTION_INFO_V1 ( spgist_name_compress  )

◆ PG_FUNCTION_INFO_V1() [3/5]

PG_FUNCTION_INFO_V1 ( spgist_name_config  )

◆ PG_FUNCTION_INFO_V1() [4/5]

PG_FUNCTION_INFO_V1 ( spgist_name_inner_consistent  )

◆ PG_FUNCTION_INFO_V1() [5/5]

PG_FUNCTION_INFO_V1 ( spgist_name_leaf_consistent  )

◆ searchChar()

static bool searchChar ( const Datum nodeLabels,
int  nNodes,
int16  c,
int i 
)
static

Definition at line 99 of file spgist_name_ops.c.

100{
101 int StopLow = 0,
102 StopHigh = nNodes;
103
104 while (StopLow < StopHigh)
105 {
106 int StopMiddle = (StopLow + StopHigh) >> 1;
107 int16 middle = DatumGetInt16(nodeLabels[StopMiddle]);
108
109 if (c < middle)
111 else if (c > middle)
112 StopLow = StopMiddle + 1;
113 else
114 {
115 *i = StopMiddle;
116 return true;
117 }
118 }
119
120 *i = StopHigh;
121 return false;
122}
int16_t int16
Definition c.h:541
static int16 DatumGetInt16(Datum X)
Definition postgres.h:172
char * c

References DatumGetInt16(), fb(), and i.

Referenced by spgist_name_choose().

◆ spgist_name_choose()

Datum spgist_name_choose ( PG_FUNCTION_ARGS  )

Definition at line 126 of file spgist_name_ops.c.

127{
131 char *inStr = NameStr(*inName);
132 int inSize = strlen(inStr);
133 char *prefixStr = NULL;
134 int prefixSize = 0;
135 int commonLen = 0;
136 int16 nodeChar = 0;
137 int i = 0;
138
139 /* Check for prefix match, set nodeChar to first byte after prefix */
140 if (in->hasPrefix)
141 {
143
145 prefixSize = VARSIZE_ANY_EXHDR(prefixText);
146
148 prefixStr,
149 inSize - in->level,
150 prefixSize);
151
152 if (commonLen == prefixSize)
153 {
154 if (inSize - in->level > commonLen)
155 nodeChar = *(unsigned char *) (inStr + in->level + commonLen);
156 else
157 nodeChar = -1;
158 }
159 else
160 {
161 /* Must split tuple because incoming value doesn't match prefix */
163
164 if (commonLen == 0)
165 {
166 out->result.splitTuple.prefixHasPrefix = false;
167 }
168 else
169 {
173 }
178 Int16GetDatum(*(unsigned char *) (prefixStr + commonLen));
179
181
182 if (prefixSize - commonLen == 1)
183 {
185 }
186 else
187 {
191 prefixSize - commonLen - 1);
192 }
193
195 }
196 }
197 else if (inSize > in->level)
198 {
199 nodeChar = *(unsigned char *) (inStr + in->level);
200 }
201 else
202 {
203 nodeChar = -1;
204 }
205
206 /* Look up nodeChar in the node label array */
207 if (searchChar(in->nodeLabels, in->nNodes, nodeChar, &i))
208 {
209 /*
210 * Descend to existing node. (If in->allTheSame, the core code will
211 * ignore our nodeN specification here, but that's OK. We still have
212 * to provide the correct levelAdd and restDatum values, and those are
213 * the same regardless of which node gets chosen by core.)
214 */
215 int levelAdd;
216
218 out->result.matchNode.nodeN = i;
219 levelAdd = commonLen;
220 if (nodeChar >= 0)
221 levelAdd++;
222 out->result.matchNode.levelAdd = levelAdd;
223 if (inSize - in->level - levelAdd > 0)
225 formTextDatum(inStr + in->level + levelAdd,
226 inSize - in->level - levelAdd);
227 else
230 }
231 else if (in->allTheSame)
232 {
233 /*
234 * Can't use AddNode action, so split the tuple. The upper tuple has
235 * the same prefix as before and uses a dummy node label -2 for the
236 * lower tuple. The lower tuple has no prefix and the same node
237 * labels as the original tuple.
238 *
239 * Note: it might seem tempting to shorten the upper tuple's prefix,
240 * if it has one, then use its last byte as label for the lower tuple.
241 * But that doesn't win since we know the incoming value matches the
242 * whole prefix: we'd just end up splitting the lower tuple again.
243 */
252 }
253 else
254 {
255 /* Add a node for the not-previously-seen nodeChar value */
256 out->resultType = spgAddNode;
258 out->result.addNode.nodeN = i;
259 }
260
262}
#define NameStr(name)
Definition c.h:765
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define DatumGetTextPP(X)
Definition fmgr.h:293
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
static Name DatumGetName(Datum X)
Definition postgres.h:390
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
uint64_t Datum
Definition postgres.h:70
@ spgMatchNode
Definition spgist.h:69
@ spgAddNode
Definition spgist.h:70
@ spgSplitTuple
Definition spgist.h:71
static int commonPrefix(const char *a, const char *b, int lena, int lenb)
static Datum formTextDatum(const char *data, int datalen)
static bool searchChar(const Datum *nodeLabels, int nNodes, int16 c, int *i)
Definition c.h:760
Datum * nodeLabels
Definition spgist.h:64
bool hasPrefix
Definition spgist.h:61
Datum prefixDatum
Definition spgist.h:62
int nNodes
Definition spgist.h:63
Datum datum
Definition spgist.h:55
int level
Definition spgist.h:57
bool allTheSame
Definition spgist.h:60
bool postfixHasPrefix
Definition spgist.h:101
int childNodeN
Definition spgist.h:98
spgChooseResultType resultType
Definition spgist.h:76
struct spgChooseOut::@54::@57 splitTuple
int levelAdd
Definition spgist.h:82
struct spgChooseOut::@54::@56 addNode
Datum nodeLabel
Definition spgist.h:87
Datum * prefixNodeLabels
Definition spgist.h:96
Datum postfixPrefixDatum
Definition spgist.h:102
Datum restDatum
Definition spgist.h:83
int prefixNNodes
Definition spgist.h:95
int nodeN
Definition spgist.h:81
union spgChooseOut::@54 result
Datum prefixPrefixDatum
Definition spgist.h:94
bool prefixHasPrefix
Definition spgist.h:93
struct spgChooseOut::@54::@55 matchNode
Definition c.h:706
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486

References spgChooseOut::addNode, spgChooseIn::allTheSame, spgChooseOut::childNodeN, commonPrefix(), spgChooseIn::datum, DatumGetName(), DatumGetTextPP, fb(), formTextDatum(), spgChooseIn::hasPrefix, i, Int16GetDatum(), spgChooseIn::level, spgChooseOut::levelAdd, spgChooseOut::matchNode, NameStr, spgChooseIn::nNodes, spgChooseOut::nodeLabel, spgChooseIn::nodeLabels, spgChooseOut::nodeN, palloc_object, PG_GETARG_POINTER, PG_RETURN_VOID, spgChooseOut::postfixHasPrefix, spgChooseOut::postfixPrefixDatum, spgChooseIn::prefixDatum, spgChooseOut::prefixHasPrefix, spgChooseOut::prefixNNodes, spgChooseOut::prefixNodeLabels, spgChooseOut::prefixPrefixDatum, spgChooseOut::restDatum, spgChooseOut::result, spgChooseOut::resultType, searchChar(), spgAddNode, spgMatchNode, spgSplitTuple, spgChooseOut::splitTuple, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

◆ spgist_name_compress()

Datum spgist_name_compress ( PG_FUNCTION_ARGS  )

Definition at line 498 of file spgist_name_ops.c.

499{
501 char *inStr = NameStr(*inName);
502
504}
#define PG_GETARG_NAME(n)
Definition fmgr.h:279
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354

References fb(), formTextDatum(), NameStr, PG_GETARG_NAME, and PG_RETURN_DATUM.

◆ spgist_name_config()

Datum spgist_name_config ( PG_FUNCTION_ARGS  )

Definition at line 34 of file spgist_name_ops.c.

35{
36#ifdef NOT_USED
38#endif
40
41 cfg->prefixType = TEXTOID;
42 cfg->labelType = INT2OID;
43 cfg->leafType = TEXTOID;
44 cfg->canReturnData = true;
45 cfg->longValuesOK = true; /* suffixing will shorten long values */
47}
Oid leafType
Definition spgist.h:45
bool longValuesOK
Definition spgist.h:47
bool canReturnData
Definition spgist.h:46
Oid labelType
Definition spgist.h:44
Oid prefixType
Definition spgist.h:43

References spgConfigOut::canReturnData, fb(), spgConfigOut::labelType, spgConfigOut::leafType, spgConfigOut::longValuesOK, PG_GETARG_POINTER, PG_RETURN_VOID, and spgConfigOut::prefixType.

◆ spgist_name_inner_consistent()

Datum spgist_name_inner_consistent ( PG_FUNCTION_ARGS  )

Definition at line 268 of file spgist_name_ops.c.

269{
272 text *reconstructedValue;
274 int maxReconstrLen;
276 int prefixSize = 0;
277 int i;
278
279 /*
280 * Reconstruct values represented at this tuple, including parent data,
281 * prefix of this tuple if any, and the node label if it's non-dummy.
282 * in->level should be the length of the previously reconstructed value,
283 * and the number of bytes added here is prefixSize or prefixSize + 1.
284 *
285 * Recall that reconstructedValues are assumed to be the same type as leaf
286 * datums, so we must use "text" not "name" for them.
287 *
288 * Note: we assume that in->reconstructedValue isn't toasted and doesn't
289 * have a short varlena header. This is okay because it must have been
290 * created by a previous invocation of this routine, and we always emit
291 * long-format reconstructed values.
292 */
293 reconstructedValue = (text *) DatumGetPointer(in->reconstructedValue);
294 Assert(reconstructedValue == NULL ? in->level == 0 :
295 VARSIZE_ANY_EXHDR(reconstructedValue) == in->level);
296
297 maxReconstrLen = in->level + 1;
298 if (in->hasPrefix)
299 {
301 prefixSize = VARSIZE_ANY_EXHDR(prefixText);
302 maxReconstrLen += prefixSize;
303 }
304
307
308 if (in->level)
310 VARDATA(reconstructedValue),
311 in->level);
312 if (prefixSize)
313 memcpy(((char *) VARDATA(reconstrText)) + in->level,
315 prefixSize);
316 /* last byte of reconstrText will be filled in below */
317
318 /*
319 * Scan the child nodes. For each one, complete the reconstructed value
320 * and see if it's consistent with the query. If so, emit an entry into
321 * the output arrays.
322 */
323 out->nodeNumbers = palloc_array(int, in->nNodes);
324 out->levelAdds = palloc_array(int, in->nNodes);
326 out->nNodes = 0;
327
328 for (i = 0; i < in->nNodes; i++)
329 {
331 int thisLen;
332 bool res = true;
333 int j;
334
335 /* If nodeChar is a dummy value, don't include it in data */
336 if (nodeChar <= 0)
338 else
339 {
340 ((unsigned char *) VARDATA(reconstrText))[maxReconstrLen - 1] = nodeChar;
342 }
343
344 for (j = 0; j < in->nkeys; j++)
345 {
346 StrategyNumber strategy = in->scankeys[j].sk_strategy;
347 Name inName;
348 char *inStr;
349 int inSize;
350 int r;
351
353 inStr = NameStr(*inName);
355
357 Min(inSize, thisLen));
358
359 switch (strategy)
360 {
363 if (r > 0)
364 res = false;
365 break;
367 if (r != 0 || inSize < thisLen)
368 res = false;
369 break;
372 if (r < 0)
373 res = false;
374 break;
375 default:
376 elog(ERROR, "unrecognized strategy number: %d",
377 in->scankeys[j].sk_strategy);
378 break;
379 }
380
381 if (!res)
382 break; /* no need to consider remaining conditions */
383 }
384
385 if (res)
386 {
387 out->nodeNumbers[out->nNodes] = i;
388 out->levelAdds[out->nNodes] = thisLen - in->level;
390 out->reconstructedValues[out->nNodes] =
392 out->nNodes++;
393 }
394 }
395
397}
#define Min(x, y)
Definition c.h:997
#define Assert(condition)
Definition c.h:873
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define palloc_array(type, count)
Definition fe_memutils.h:76
int j
Definition isn.c:78
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
uint16 StrategyNumber
Definition stratnum.h:22
#define BTGreaterStrategyNumber
Definition stratnum.h:33
#define BTLessStrategyNumber
Definition stratnum.h:29
#define BTEqualStrategyNumber
Definition stratnum.h:31
#define BTLessEqualStrategyNumber
Definition stratnum.h:30
#define BTGreaterEqualStrategyNumber
Definition stratnum.h:32
Datum sk_argument
Definition skey.h:72
StrategyNumber sk_strategy
Definition skey.h:68
Datum reconstructedValue
Definition spgist.h:140
Datum * reconstructedValues
Definition spgist.h:159
static char * VARDATA(const void *PTR)
Definition varatt.h:305

References Assert, BTEqualStrategyNumber, BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, datumCopy(), DatumGetInt16(), DatumGetName(), DatumGetPointer(), DatumGetTextPP, elog, ERROR, fb(), spgInnerConsistentIn::hasPrefix, i, j, spgInnerConsistentIn::level, spgInnerConsistentOut::levelAdds, Min, NameStr, spgInnerConsistentIn::nkeys, spgInnerConsistentIn::nNodes, spgInnerConsistentOut::nNodes, spgInnerConsistentIn::nodeLabels, spgInnerConsistentOut::nodeNumbers, palloc(), palloc_array, PG_GETARG_POINTER, PG_RETURN_VOID, PointerGetDatum(), spgInnerConsistentIn::prefixDatum, spgInnerConsistentIn::reconstructedValue, spgInnerConsistentOut::reconstructedValues, spgInnerConsistentIn::scankeys, SET_VARSIZE(), ScanKeyData::sk_argument, ScanKeyData::sk_strategy, VARDATA(), VARDATA_ANY(), VARHDRSZ, and VARSIZE_ANY_EXHDR().

◆ spgist_name_leaf_consistent()

Datum spgist_name_leaf_consistent ( PG_FUNCTION_ARGS  )

Definition at line 401 of file spgist_name_ops.c.

402{
405 int level = in->level;
406 text *leafValue,
408 char *fullValue;
409 int fullLen;
410 bool res;
411 int j;
412
413 /* all tests are exact */
414 out->recheck = false;
415
416 leafValue = DatumGetTextPP(in->leafDatum);
417
418 /* As above, in->reconstructedValue isn't toasted or short. */
421
422 Assert(reconstrValue == NULL ? level == 0 :
424
425 /* Reconstruct the Name represented by this leaf tuple */
427 fullLen = level + VARSIZE_ANY_EXHDR(leafValue);
429 if (VARSIZE_ANY_EXHDR(leafValue) == 0 && level > 0)
430 {
433 }
434 else
435 {
436 if (level)
438 if (VARSIZE_ANY_EXHDR(leafValue) > 0)
439 memcpy(fullValue + level, VARDATA_ANY(leafValue),
440 VARSIZE_ANY_EXHDR(leafValue));
441 }
443
444 /* Perform the required comparison(s) */
445 res = true;
446 for (j = 0; j < in->nkeys; j++)
447 {
448 StrategyNumber strategy = in->scankeys[j].sk_strategy;
450 char *queryStr = NameStr(*queryName);
451 int queryLen = strlen(queryStr);
452 int r;
453
454 /* Non-collation-aware comparison */
456
457 if (r == 0)
458 {
459 if (queryLen > fullLen)
460 r = -1;
461 else if (queryLen < fullLen)
462 r = 1;
463 }
464
465 switch (strategy)
466 {
468 res = (r < 0);
469 break;
471 res = (r <= 0);
472 break;
474 res = (r == 0);
475 break;
477 res = (r >= 0);
478 break;
480 res = (r > 0);
481 break;
482 default:
483 elog(ERROR, "unrecognized strategy number: %d",
484 in->scankeys[j].sk_strategy);
485 res = false;
486 break;
487 }
488
489 if (!res)
490 break; /* no need to consider remaining conditions */
491 }
492
493 PG_RETURN_BOOL(res);
494}
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
void * palloc0(Size size)
Definition mcxt.c:1417
#define NAMEDATALEN
Datum reconstructedValue
Definition spgist.h:175

References Assert, BTEqualStrategyNumber, BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, DatumGetName(), DatumGetPointer(), DatumGetTextPP, elog, ERROR, fb(), j, spgLeafConsistentIn::leafDatum, spgLeafConsistentOut::leafValue, spgLeafConsistentIn::level, Min, NAMEDATALEN, NameStr, spgLeafConsistentIn::nkeys, palloc0(), PG_GETARG_POINTER, PG_RETURN_BOOL, PointerGetDatum(), spgLeafConsistentOut::recheck, spgLeafConsistentIn::reconstructedValue, spgLeafConsistentIn::scankeys, ScanKeyData::sk_argument, ScanKeyData::sk_strategy, VARDATA(), VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 29 of file spgist_name_ops.c.