/* FIXME This should do exactly the same checks of lp_flags as in heap.c */ uint32 check_index_tuple(Relation rel, PageHeader header, int block, int i, char *buffer) { uint32 nerrs = 0; int j, a, b, c, d; IndexTuple itup = (IndexTuple)(buffer + header->pd_linp[i].lp_off); /* FIXME This is used when checking overflowing attributes, but it's not clear what * exactly this means / how it works. Needs a bit more investigation and maybe a review * from soneone who really knows the b-tree implementation. */ int dlen = IndexTupleSize(itup) - IndexInfoFindDataOffset(itup->t_info); ereport(DEBUG2,(errmsg("[%d:%d] off=%d len=%d tid=(%d,%d)", block, (i+1), header->pd_linp[i].lp_off, header->pd_linp[i].lp_len, BlockIdGetBlockNumber(&(itup->t_tid.ip_blkid)), itup->t_tid.ip_posid ))); /* check intersection with other tuples */ /* [A,B] vs [C,D] */ a = header->pd_linp[i].lp_off; b = header->pd_linp[i].lp_off + header->pd_linp[i].lp_len; ereport(DEBUG2,(errmsg("[%d:%d] checking intersection with other tuples", block, (i+1)))); for (j = 0; j < i; j++) { /* FIXME Skip UNUSED/REDIRECT/DEAD tuples */ if (! (header->pd_linp[i].lp_flags == LP_NORMAL)) { ereport(DEBUG3,(errmsg("[%d:%d] skipped (not LP_NORMAL)", block, (j+1)))); continue; } c = header->pd_linp[j].lp_off; d = header->pd_linp[j].lp_off + header->pd_linp[j].lp_len; /* [A,C,B] or [A,D,B] or [C,A,D] or [C,B,D] */ if (((a < c) && (c < b)) || ((a < d) && (d < b)) || ((c < a) && (a < d)) || ((c < b) && (b < d))) { ereport(WARNING,(errmsg("[%d:%d] intersects with [%d:%d] (%d,%d) vs. (%d,%d)", block, (i+1), block, j, a, b, c, d))); ++nerrs; } } /* check attributes only for tuples with (lp_flags==LP_NORMAL) */ if (header->pd_linp[i].lp_flags == LP_NORMAL) { nerrs += check_index_tuple_attributes(rel, header, block, i + 1, buffer, dlen); } return nerrs; }
/* FIXME This should do exactly the same checks of lp_flags as in heap.c */ uint32 check_index_tuple(Relation rel, PageHeader header, int block, int i, char *buffer) { uint32 nerrs = 0; int j, a, b, c, d; IndexTuple itup = (IndexTuple)(buffer + header->pd_linp[i].lp_off); ereport(DEBUG2,(errmsg("[%d:%d] off=%d len=%d tid=(%d,%d)", block, (i+1), header->pd_linp[i].lp_off, header->pd_linp[i].lp_len, BlockIdGetBlockNumber(&(itup->t_tid.ip_blkid)), itup->t_tid.ip_posid ))); /* check intersection with other tuples */ /* [A,B] vs [C,D] */ a = header->pd_linp[i].lp_off; b = header->pd_linp[i].lp_off + header->pd_linp[i].lp_len; ereport(DEBUG2,(errmsg("[%d:%d] checking intersection with other tuples", block, i))); for (j = 0; j < i; j++) { /* FIXME Skip UNUSED/REDIRECT/DEAD tuples */ if (! (header->pd_linp[i].lp_flags == LP_NORMAL)) { ereport(DEBUG3,(errmsg("[%d:%d] skipped (not LP_NORMAL)", block, j))); continue; } c = header->pd_linp[j].lp_off; d = header->pd_linp[j].lp_off + header->pd_linp[j].lp_len; /* [A,C,B] or [A,D,B] or [C,A,D] or [C,B,D] */ if (((a < c) && (c < b)) || ((a < d) && (d < b)) || ((c < a) && (a < d)) || ((c < b) && (b < d))) { ereport(WARNING,(errmsg("[%d:%d] intersects with [%d:%d] (%d,%d) vs. (%d,%d)", block, (i+1), block, j, a, b, c, d))); ++nerrs; } } /* check attributes only for tuples with (lp_flags==LP_NORMAL) */ if (header->pd_linp[i].lp_flags == LP_NORMAL) { nerrs += check_index_tuple_attributes(rel, header, block, i, buffer); } return nerrs; }