PostgreSQL Source Code: src/backend/access/gist/gistutil.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
15
16#include <math.h>
17
24#include "utils/fmgrprotos.h"
29
30
31
32
33void
35{
36 int i;
37
41
43 {
46
49 elog(ERROR, "failed to add item to GiST index page, item %d out of %d, size %d bytes",
51 off++;
52 }
53}
54
55
56
57
58bool
60{
61 unsigned int size = freespace,
62 deleted = 0;
63 int i;
64
67
69 {
71
73 }
74
76}
77
78bool
80{
81 int i;
82 Size size = 0;
83
86
87
89}
90
91
92
93
96{
98 maxoff;
100
102 *len = maxoff;
106
107 return itvec;
108}
109
110
111
112
115{
117 memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen);
118 *len += addlen;
119 return itvec;
120}
121
122
123
124
125
128{
129 char *ptr,
130 *ret;
131 int i;
132
133 *memlen = 0;
134
135 for (i = 0; i < veclen; i++)
137
138 ptr = ret = palloc(*memlen);
139
140 for (i = 0; i < veclen; i++)
141 {
144 }
145
147}
148
149
150
151
152
153
154void
156 Datum *attr, bool *isnull)
157{
158 int i;
160 int attrsize;
161
163
165 {
166 int j;
167
168
169 evec->n = 0;
171 {
173 bool IsNull;
174
176 &IsNull);
177 if (IsNull)
178 continue;
179
182 datum,
184 false, IsNull);
185 evec->n++;
186 }
187
188
189 if (evec->n == 0)
190 {
192 isnull[i] = true;
193 }
194 else
195 {
196 if (evec->n == 1)
197 {
198
199 evec->n = 2;
201 }
202
203
208
209 isnull[i] = false;
210 }
211 }
212}
213
214
215
216
217
220{
223
225
226 return gistFormTuple(giststate, r, attr, isnull, false);
227}
228
229
230
231
232void
236 Datum *dst, bool *dstisnull)
237{
238
239 union
240 {
245 int dstsize;
246
247 evec->n = 2;
248
249 if (isnull1 && isnull2)
250 {
251 *dstisnull = true;
252 *dst = (Datum) 0;
253 }
254 else
255 {
256 if (isnull1 == false && isnull2 == false)
257 {
258 evec->vector[0] = *entry1;
259 evec->vector[1] = *entry2;
260 }
261 else if (isnull1 == false)
262 {
263 evec->vector[0] = *entry1;
264 evec->vector[1] = *entry1;
265 }
266 else
267 {
268 evec->vector[0] = *entry2;
269 evec->vector[1] = *entry2;
270 }
271
272 *dstisnull = false;
277 }
278}
279
280bool
282{
283 bool result = false;
284
289 return result;
290}
291
292
293
294
295void
298{
299 int i;
300
302 {
304
307 datum, r, p, o,
308 false, isnull[i]);
309 }
310}
311
312
313
314
317{
318 bool neednew = false;
326 int i;
327
330
333
335 {
337 oldentries + i, oldisnull[i],
338 addentries + i, addisnull[i],
340
341 if (neednew)
342
343 continue;
344
345 if (isnull[i])
346
347 continue;
348
349 if (!addisnull[i])
350 {
351 if (oldisnull[i] ||
353 neednew = true;
354 }
355 }
356
357 if (neednew)
358 {
359
360 newtup = gistFormTuple(giststate, r, attr, isnull, false);
362 }
363
364 return newtup;
365}
366
367
368
369
370
371
372
376{
384 int keep_current_best;
385
387
390 identry, isnull);
391
392
394
395
396
397
398
399
400
401
402
403
404
405 best_penalty[0] = -1;
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 keep_current_best = -1;
431
432
433
434
437
439 {
441 bool zero_penalty;
442 int j;
443
444 zero_penalty = true;
445
446
448 {
450 float usize;
451 bool IsNull;
452
453
455 &IsNull);
457 false, IsNull);
458 usize = gistpenalty(giststate, j, &entry, IsNull,
460 if (usize > 0)
461 zero_penalty = false;
462
463 if (best_penalty[j] < 0 || usize < best_penalty[j])
464 {
465
466
467
468
469
470
471
472
473 result = i;
474 best_penalty[j] = usize;
475
477 best_penalty[j + 1] = -1;
478
479
480 keep_current_best = -1;
481 }
482 else if (best_penalty[j] == usize)
483 {
484
485
486
487
488
489 }
490 else
491 {
492
493
494
495
496
497 zero_penalty = false;
498 break;
499 }
500 }
501
502
503
504
505
507 {
508 if (keep_current_best == -1)
509 {
510
512 }
513 if (keep_current_best == 0)
514 {
515
516 result = i;
517
518 keep_current_best = -1;
519 }
520 }
521
522
523
524
525
526
527
528 if (zero_penalty)
529 {
530 if (keep_current_best == -1)
531 {
532
534 }
535 if (keep_current_best == 1)
536 break;
537 }
538 }
539
540 return result;
541}
542
543
544
545
546void
549 bool l, bool isNull)
550{
551 if (!isNull)
552 {
554
556
557
559 return;
560
565
566 if (dep != e)
569 }
570 else
572}
573
576 const Datum *attdata, const bool *isnull, bool isleaf)
577{
580
582
585 compatt, isnull);
586
587
588
589
590
592 return res;
593}
594
595void
597 const Datum *attdata, const bool *isnull, bool isleaf, Datum *compatt)
598{
599 int i;
600
601
602
603
605 {
606 if (isnull[i])
608 else
609 {
612
614 isleaf);
615
621 else
622 cep = ¢ry;
624 }
625 }
626
627 if (isleaf)
628 {
629
630
631
633 {
634 if (isnull[i])
636 else
638 }
639 }
640}
641
642
643
644
647{
650
652
657
658
659 return fep->key;
660}
661
662
663
664
665
668{
672 int i;
673
675 {
677
679
681 {
682 if (!isnull[i])
684 else
686 }
688 {
689
690
691
692
693 if (!isnull[i])
695 else
697 }
698 else
699 {
700
701
702
703
704
705 isnull[i] = true;
707 }
708 }
709
710
711
712
714 {
716 &isnull[i]);
717 }
719
721}
722
723float
725 GISTENTRY *orig, bool isNullOrig,
727{
728 float penalty = 0.0;
729
731 (isNullOrig == false && isNullAdd == false))
732 {
738
739 if (isnan(penalty) || penalty < 0.0)
740 penalty = 0.0;
741 }
742 else if (isNullOrig && isNullAdd)
743 penalty = 0.0;
744 else
745 {
746
748 }
749
750 return penalty;
751}
752
753
754
755
756void
758{
760
762
765 opaque->flags = f;
767}
768
769
770
771
772void
774{
776
779}
780
781
782
783
784void
786{
788
789
790
791
792
793
794
797 (errcode(ERRCODE_INDEX_CORRUPTED),
798 errmsg("index \"%s\" contains unexpected zero page at block %u",
801 errhint("Please REINDEX it.")));
802
803
804
805
808 (errcode(ERRCODE_INDEX_CORRUPTED),
809 errmsg("index \"%s\" contains corrupted page at block %u",
812 errhint("Please REINDEX it.")));
813}
814
815
816
817
818
819
820
821
822
825{
827
828
829 for (;;)
830 {
832
834 break;
835
837
838
839
840
841
843 {
845
846
847
848
850 return buffer;
851
853
854
855
856
857
859 {
860
861
862
863
864
865
868
869 return buffer;
870 }
871
873 }
874
875
877 }
878
879
882
883 return buffer;
884}
885
886
887bool
889{
891 return true;
893 {
894
895
896
897
898
899
900
901
902
903
905
907 }
908 return false;
909}
910
913{
917 };
918
923}
924
925
926
927
928
929
930
931
932bool
935 bool *res, bool *isnull)
936{
937 Oid opclass,
938 opfamily,
939 opcintype;
941
942
943 if (attno == 0)
944 return false;
945
946
947
948
949
950
951
952
953
954
955
956
957 switch (prop)
958 {
961 break;
964 break;
965 default:
966 return false;
967 }
968
969
972 {
973 *isnull = true;
974 return true;
975 }
976
977
979 {
980 *isnull = true;
981 return true;
982 }
983
984
985
991
992
993
994
995
997 {
1003 }
1004
1005 *isnull = false;
1006
1007 return true;
1008}
1009
1010
1011
1012
1013
1014
1017{
1018 if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
1019 {
1020
1021
1022
1023
1025
1026 return counter++;
1027 }
1029 {
1030
1031
1032
1033
1034
1035
1038
1039
1041
1042
1045
1046 lastlsn = currlsn;
1047 return currlsn;
1048 }
1049 else
1050 {
1051
1052
1053
1054
1055 Assert(rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED);
1057 }
1058}
1059
1060
1061
1062
1063
1066{
1068
1069 switch (cmptype)
1070 {
1085 default:
1087 }
1088}
1089
1090
1091
1092
1093
1094
1095
1096
1099{
1100 Oid funcid;
1102
1103
1107
1108
1111}
@ AMPROP_DISTANCE_ORDERABLE
static bool validate(Port *port, const char *auth)
#define InvalidBlockNumber
BlockNumber BufferGetBlockNumber(Buffer buffer)
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
bool ConditionalLockBuffer(Buffer buffer)
void ReleaseBuffer(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
static Page BufferGetPage(Buffer buffer)
Size PageGetFreeSpace(const PageData *page)
void PageInit(Page page, Size pageSize, Size specialSize)
static bool PageIsEmpty(const PageData *page)
static uint16 PageGetSpecialSize(const PageData *page)
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
static bool PageIsNew(const PageData *page)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
#define OidIsValid(objectId)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
static float4 get_float4_infinity(void)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
#define PG_GETARG_INT32(n)
#define PG_RETURN_UINT16(x)
#define GIST_STRATNUM_PROC
struct GISTENTRY GISTENTRY
#define GIST_COMPRESS_PROC
#define GistPageIsLeaf(page)
#define GIST_DISTANCE_PROC
static FullTransactionId GistPageGetDeleteXid(Page page)
#define GistPageIsDeleted(page)
#define GistPageGetOpaque(page)
#define gistentryinit(e, k, r, pg, o, l)
void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p, OffsetNumber o, GISTENTRY *attdata, bool *isnull)
bytea * gistoptions(Datum reloptions, bool validate)
Buffer gistNewBuffer(Relation r, Relation heaprel)
bool gistproperty(Oid index_oid, int attno, IndexAMProperty prop, const char *propname, bool *res, bool *isnull)
bool gistPageRecyclable(Page page)
void gistMakeUnionKey(GISTSTATE *giststate, int attno, GISTENTRY *entry1, bool isnull1, GISTENTRY *entry2, bool isnull2, Datum *dst, bool *dstisnull)
void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, Datum *attr, bool *isnull)
bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace)
HeapTuple gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b)
static Datum gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
void gistfillbuffer(Page page, IndexTuple *itup, int len, OffsetNumber off)
IndexTuple gistFormTuple(GISTSTATE *giststate, Relation r, const Datum *attdata, const bool *isnull, bool isleaf)
IndexTuple * gistextractpage(Page page, int *len)
void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, Datum k, Relation r, Page pg, OffsetNumber o, bool l, bool isNull)
bool gistfitpage(IndexTuple *itvec, int len)
Datum gist_stratnum_common(PG_FUNCTION_ARGS)
IndexTuple gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate)
OffsetNumber gistchoose(Relation r, Page p, IndexTuple it, GISTSTATE *giststate)
XLogRecPtr gistGetFakeLSN(Relation rel)
void gistCompressValues(GISTSTATE *giststate, Relation r, const Datum *attdata, const bool *isnull, bool isleaf, Datum *compatt)
IndexTuple * gistjoinvector(IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen)
void gistinitpage(Page page, uint32 f)
IndexTuple gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
void GISTInitBuffer(Buffer b, uint32 f)
StrategyNumber gisttranslatecmptype(CompareType cmptype, Oid opfamily)
void gistcheckpage(Relation rel, Buffer buf)
IndexTupleData * gistfillitupvec(IndexTuple *vec, int veclen, int *memlen)
float gistpenalty(GISTSTATE *giststate, int attno, GISTENTRY *orig, bool isNullOrig, GISTENTRY *add, bool isNullAdd)
XLogRecPtr gistXLogAssignLSN(void)
void gistXLogPageReuse(Relation rel, Relation heaprel, BlockNumber blkno, FullTransactionId deleteXid)
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
BlockNumber GetFreeIndexPage(Relation rel)
IndexTuple index_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
struct ItemIdData ItemIdData
static void ItemPointerSetOffsetNumber(ItemPointerData *pointer, OffsetNumber offsetNumber)
IndexTupleData * IndexTuple
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static Size IndexTupleSize(const IndexTupleData *itup)
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Oid get_index_column_opclass(Oid index_oid, int attno)
void * repalloc(void *pointer, Size size)
#define InvalidOffsetNumber
#define OffsetNumberNext(offsetNumber)
#define FirstOffsetNumber
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
pg_prng_state pg_global_prng_state
bool pg_prng_bool(pg_prng_state *state)
static Datum PointerGetDatum(const void *X)
static Datum Int16GetDatum(int16 X)
static Datum ObjectIdGetDatum(Oid X)
static uint16 DatumGetUInt16(Datum X)
static Pointer DatumGetPointer(Datum X)
static Datum Int32GetDatum(int32 X)
bool GlobalVisCheckRemovableFullXid(Relation rel, FullTransactionId fxid)
#define RelationGetRelationName(relation)
#define RelationNeedsWAL(relation)
#define IndexRelationGetNumberOfKeyAttributes(relation)
#define RelationIsPermanent(relation)
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
#define RTOverlapStrategyNumber
#define RTEqualStrategyNumber
#define RTLessEqualStrategyNumber
#define RTGreaterEqualStrategyNumber
#define RTGreaterStrategyNumber
#define RTContainedByStrategyNumber
#define RTLessStrategyNumber
FmgrInfo fetchFn[INDEX_MAX_KEYS]
FmgrInfo penaltyFn[INDEX_MAX_KEYS]
Oid supportCollation[INDEX_MAX_KEYS]
FmgrInfo decompressFn[INDEX_MAX_KEYS]
FmgrInfo compressFn[INDEX_MAX_KEYS]
FmgrInfo equalFn[INDEX_MAX_KEYS]
FmgrInfo unionFn[INDEX_MAX_KEYS]
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
XLogRecPtr GetXLogInsertRecPtr(void)
XLogRecPtr GetFakeLSNForUnloggedRel(void)
#define XLogStandbyInfoActive()
#define FirstNormalUnloggedLSN
#define XLogRecPtrIsInvalid(r)
#define InvalidXLogRecPtr