Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit075aade

Browse files
committed
Adjust INCLUDE index truncation comments and code.
Add several assertions that ensure that we're dealing with a pivot tuplewithout non-key attributes where that's expected. Also, remove theassertion within _bt_isequal(), restoring the v10 function signature. Asimilar check will be performed for the page highkey within_bt_moveright() in most cases. Also avoid dropping all objects withinregression tests, to increase pg_dump test coverage for INCLUDE indexes.Rather than using infrastructure that's generally intended to be usedwith reference counted heap tuple descriptors during truncation, use thesame function that was introduced to store flat TupleDescs in sharedmemory (we use a temp palloc'd buffer). This isn't strictly necessary,but seems more future-proof than the old approach. It also lets usavoid including rel.h within indextuple.c, which was arguably amodularity violation. Also, we now call index_deform_tuple() with thetruncated TupleDesc, not the source TupleDesc, since that's more robust,and saves a few cycles.In passing, fix a memory leak by pfree'ing truncated pivot tuple memoryduring CREATE INDEX. Also pfree during a page split, just to beconsistent.Refactor _bt_check_natts() to be more readable.Author: Peter Geoghegan with some editorization by meReviewed by: Alexander Korotkov, Teodor SigaevDiscussion:https://www.postgresql.org/message-id/CAH2-Wz%3DkCWuXeMrBCopC-tFs3FbiVxQNjjgNKdG2sHxZ5k2y3w%40mail.gmail.com
1 parent5372c2c commit075aade

File tree

13 files changed

+429
-330
lines changed

13 files changed

+429
-330
lines changed

‎contrib/amcheck/verify_nbtree.c

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,9 @@ bt_check_level_from_leftmost(BtreeCheckState *state, BtreeLevel level)
698698
* "real" data item on the page to the right (if such a first item is
699699
* available).
700700
*
701+
* - That tuples report that they have the expected number of attributes.
702+
* INCLUDE index pivot tuples should not contain non-key attributes.
703+
*
701704
* Furthermore, when state passed shows ShareLock held, and target page is
702705
* internal page, function also checks:
703706
*
@@ -722,43 +725,35 @@ bt_target_page_check(BtreeCheckState *state)
722725
elog(DEBUG2,"verifying %u items on %s block %u",max,
723726
P_ISLEAF(topaque) ?"leaf" :"internal",state->targetblock);
724727

725-
726-
/* Check the number of attributes in high key if any */
727-
if (!P_RIGHTMOST(topaque))
728+
/*
729+
* Check the number of attributes in high key. Note, rightmost page doesn't
730+
* contain a high key, so nothing to check
731+
*/
732+
if (!P_RIGHTMOST(topaque)&&
733+
!_bt_check_natts(state->rel,state->target,P_HIKEY))
728734
{
729-
if (!_bt_check_natts(state->rel,state->target,P_HIKEY))
730-
{
731-
ItemIditemid;
732-
IndexTupleitup;
733-
char*itid,
734-
*htid;
735+
ItemIditemid;
736+
IndexTupleitup;
735737

736-
itemid=PageGetItemId(state->target,P_HIKEY);
737-
itup= (IndexTuple)PageGetItem(state->target,itemid);
738-
itid=psprintf("(%u,%u)",state->targetblock,P_HIKEY);
739-
htid=psprintf("(%u,%u)",
740-
ItemPointerGetBlockNumberNoCheck(&(itup->t_tid)),
741-
ItemPointerGetOffsetNumberNoCheck(&(itup->t_tid)));
738+
itemid=PageGetItemId(state->target,P_HIKEY);
739+
itup= (IndexTuple)PageGetItem(state->target,itemid);
742740

743-
ereport(ERROR,
744-
(errcode(ERRCODE_INDEX_CORRUPTED),
745-
errmsg("wrong number of index tuple attributes for index \"%s\"",
746-
RelationGetRelationName(state->rel)),
747-
errdetail_internal("Index tid=%s natts=%u points to %s tid=%s page lsn=%X/%X.",
748-
itid,
749-
BTreeTupGetNAtts(itup,state->rel),
750-
P_ISLEAF(topaque) ?"heap" :"index",
751-
htid,
752-
(uint32) (state->targetlsn >>32),
753-
(uint32)state->targetlsn)));
754-
}
741+
ereport(ERROR,
742+
(errcode(ERRCODE_INDEX_CORRUPTED),
743+
errmsg("wrong number of high key index tuple attributes in index \"%s\"",
744+
RelationGetRelationName(state->rel)),
745+
errdetail_internal("Index block=%u natts=%u block type=%s page lsn=%X/%X.",
746+
state->targetblock,
747+
BTreeTupleGetNAtts(itup,state->rel),
748+
P_ISLEAF(topaque) ?"heap" :"index",
749+
(uint32) (state->targetlsn >>32),
750+
(uint32)state->targetlsn)));
755751
}
756752

757-
758753
/*
759754
* Loop over page items, starting from first non-highkey item, not high
760-
* key (if any).Also, immediately skip"negative infinity" real item (if
761-
* any).
755+
* key (if any).Most tests are not performed for the"negative infinity"
756+
*real item (ifany).
762757
*/
763758
for (offset=P_FIRSTDATAKEY(topaque);
764759
offset <=max;
@@ -791,7 +786,7 @@ bt_target_page_check(BtreeCheckState *state)
791786
tupsize,ItemIdGetLength(itemid),
792787
(uint32) (state->targetlsn >>32),
793788
(uint32)state->targetlsn),
794-
errhint("This could be a torn page problem")));
789+
errhint("This could be a torn page problem.")));
795790

796791
/* Check the number of index tuple attributes */
797792
if (!_bt_check_natts(state->rel,state->target,offset))
@@ -806,20 +801,20 @@ bt_target_page_check(BtreeCheckState *state)
806801

807802
ereport(ERROR,
808803
(errcode(ERRCODE_INDEX_CORRUPTED),
809-
errmsg("wrong number of index tuple attributesfor index \"%s\"",
804+
errmsg("wrong number of index tuple attributesin index \"%s\"",
810805
RelationGetRelationName(state->rel)),
811806
errdetail_internal("Index tid=%s natts=%u points to %s tid=%s page lsn=%X/%X.",
812807
itid,
813-
BTreeTupGetNAtts(itup,state->rel),
808+
BTreeTupleGetNAtts(itup,state->rel),
814809
P_ISLEAF(topaque) ?"heap" :"index",
815810
htid,
816811
(uint32) (state->targetlsn >>32),
817812
(uint32)state->targetlsn)));
818813
}
819814

820815
/*
821-
* Don't try to generate scankey using "negative infinity"garbage
822-
*data oninternal pages
816+
* Don't try to generate scankey using "negative infinity"item on
817+
* internal pages. They are always truncated to zero attributes.
823818
*/
824819
if (offset_is_negative_infinity(topaque,offset))
825820
continue;
@@ -1430,9 +1425,9 @@ offset_is_negative_infinity(BTPageOpaque opaque, OffsetNumber offset)
14301425
* infinity item is either first or second line item, or there is none
14311426
* within page.
14321427
*
1433-
*"Negative infinity" tuple is a specialcornercaseof pivot tuples,
1434-
*it has zero attributes whilerest of pivot tupleshave nkeyatts number
1435-
*of attributes.
1428+
* Negative infinity items are a special caseamong pivot tuples. They
1429+
*always have zero attributes, whileall other pivot tuplesalways have
1430+
*nkeyatts attributes.
14361431
*
14371432
* Right-most pages don't have a high key, but could be said to
14381433
* conceptually have a "positive infinity" high key. Thus, there is a

‎src/backend/access/common/indextuple.c

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include"access/heapam.h"
2020
#include"access/itup.h"
2121
#include"access/tuptoaster.h"
22-
#include"utils/rel.h"
2322

2423

2524
/* ----------------------------------------------------------------
@@ -32,6 +31,9 @@
3231
*
3332
*This shouldn't leak any memory; otherwise, callers such as
3433
*tuplesort_putindextuplevalues() will be very unhappy.
34+
*
35+
*This shouldn't perform external table access provided caller
36+
*does not pass values that are stored EXTERNAL.
3537
* ----------------
3638
*/
3739
IndexTuple
@@ -448,30 +450,49 @@ CopyIndexTuple(IndexTuple source)
448450
}
449451

450452
/*
451-
* Truncate tailing attributes from given index tuple leaving it with
452-
* new_indnatts number of attributes.
453+
* Create a palloc'd copy of an index tuple, leaving only the first
454+
* leavenatts attributes remaining.
455+
*
456+
* Truncation is guaranteed to result in an index tuple that is no
457+
* larger than the original. It is safe to use the IndexTuple with
458+
* the original tuple descriptor, but caller must avoid actually
459+
* accessing truncated attributes from returned tuple! In practice
460+
* this means that index_getattr() must be called with special care,
461+
* and that the truncated tuple should only ever be accessed by code
462+
* under caller's direct control.
463+
*
464+
* It's safe to call this function with a buffer lock held, since it
465+
* never performs external table access. If it ever became possible
466+
* for index tuples to contain EXTERNAL TOAST values, then this would
467+
* have to be revisited.
453468
*/
454469
IndexTuple
455-
index_truncate_tuple(TupleDesctupleDescriptor,IndexTupleolditup,
456-
intnew_indnatts)
470+
index_truncate_tuple(TupleDescsourceDescriptor,IndexTuplesource,
471+
intleavenatts)
457472
{
458-
TupleDescitupdesc=CreateTupleDescCopyConstr(tupleDescriptor);
473+
TupleDesctruncdesc;
459474
Datumvalues[INDEX_MAX_KEYS];
460475
boolisnull[INDEX_MAX_KEYS];
461-
IndexTuplenewitup;
476+
IndexTupletruncated;
462477

463-
Assert(tupleDescriptor->natts <=INDEX_MAX_KEYS);
464-
Assert(new_indnatts>0);
465-
Assert(new_indnatts<tupleDescriptor->natts);
478+
Assert(leavenatts<sourceDescriptor->natts);
466479

467-
index_deform_tuple(olditup,tupleDescriptor,values,isnull);
480+
/* Create temporary descriptor to scribble on */
481+
truncdesc=palloc(TupleDescSize(sourceDescriptor));
482+
TupleDescCopy(truncdesc,sourceDescriptor);
483+
truncdesc->natts=leavenatts;
468484

469-
/* form new tuple that will contain only key attributes */
470-
itupdesc->natts=new_indnatts;
471-
newitup=index_form_tuple(itupdesc,values,isnull);
472-
newitup->t_tid=olditup->t_tid;
485+
/* Deform, form copy of tuple with fewer attributes */
486+
index_deform_tuple(source,truncdesc,values,isnull);
487+
truncated=index_form_tuple(truncdesc,values,isnull);
488+
truncated->t_tid=source->t_tid;
489+
Assert(IndexTupleSize(truncated) <=IndexTupleSize(source));
490+
491+
/*
492+
* Cannot leak memory here, TupleDescCopy() doesn't allocate any
493+
* inner structure, so, plain pfree() should clean all allocated memory
494+
*/
495+
pfree(truncdesc);
473496

474-
FreeTupleDesc(itupdesc);
475-
Assert(IndexTupleSize(newitup) <=IndexTupleSize(olditup));
476-
returnnewitup;
497+
returntruncated;
477498
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp