Index: tool/showdb.c ================================================================== --- tool/showdb.c +++ tool/showdb.c @@ -55,11 +55,11 @@ ** Space to hold the content is obtained from malloc() and needs to be ** freed by the caller. */ static unsigned char *getContent(int ofst, int nByte){ unsigned char *aData; - aData = malloc(nByte); + aData = malloc(nByte+32); if( aData==0 ) out_of_memory(); lseek(db, ofst, SEEK_SET); read(db, aData, nByte); return aData; } @@ -182,33 +182,37 @@ /* ** Describe cell content. */ static int describeContent( - unsigned char *a, - char *zDesc + unsigned char *a, /* Cell content */ + int nLocal, /* Bytes in a[] */ + char *zDesc /* Write description here */ ){ int nDesc = 0; int n, i, j; i64 x, v; const unsigned char *pData; + const unsigned char *pLimit; char sep = ' '; + pLimit = &a[nLocal]; n = decodeVarint(a, &x); pData = &a[x]; a += n; i = x - n; - while( i>0 ){ + while( i>0 && pData<=pLimit ){ n = decodeVarint(a, &x); a += n; i -= n; + nLocal -= n; zDesc[0] = sep; sep = ','; nDesc++; zDesc++; if( x==0 ){ - sprintf(zDesc, "null"); + sprintf(zDesc, "*"); /* NULL is a "*" */ }else if( x>=1 && x<=6 ){ v = (signed char)pData[0]; pData++; switch( x ){ case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; @@ -228,24 +232,56 @@ }else if( x>=12 ){ int size = (x-12)/2; if( (x&1)==0 ){ sprintf(zDesc, "blob(%d)", size); }else{ - sprintf(zDesc, "text(%d)", size); + sprintf(zDesc, "txt(%d)", size); } pData += size; } j = strlen(zDesc); zDesc += j; nDesc += j; } return nDesc; } + +/* +** Compute the local payload size given the total payload size and +** the page size. +*/ +static int localPayload(i64 nPayload, char cType){ + int maxLocal; + int minLocal; + int surplus; + int nLocal; + if( cType==13 ){ + /* Table leaf */ + maxLocal = pagesize-35; + minLocal = (pagesize-12)*32/255-23; + }else{ + maxLocal = (pagesize-12)*64/255-23; + minLocal = (pagesize-12)*32/255-23; + } + if( nPayload>maxLocal ){ + surplus = minLocal + (nPayload-minLocal)%(pagesize-4); + if( surplus<=maxLocal ){ + nLocal = surplus; + }else{ + nLocal = minLocal; + } + }else{ + nLocal = nPayload; + } + return nLocal; +} /* ** Create a description for a single cell. +** +** The return value is the local cell size. */ static int describeCell( unsigned char cType, /* Page type */ unsigned char *a, /* Cell content */ int showCellContent, /* Show cell content if true */ @@ -271,23 +307,26 @@ i = decodeVarint(a, &nPayload); a += i; n += i; sprintf(&zDesc[nDesc], "n: %lld ", nPayload); nDesc += strlen(&zDesc[nDesc]); + nLocal = localPayload(nPayload, cType); + }else{ + nPayload = nLocal = 0; } if( cType==5 || cType==13 ){ i = decodeVarint(a, &rowid); a += i; n += i; sprintf(&zDesc[nDesc], "r: %lld ", rowid); nDesc += strlen(&zDesc[nDesc]); } if( showCellContent && cType!=5 ){ - nDesc += describeContent(a, &zDesc[nDesc]); + nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]); } *pzDesc = zDesc; - return n; + return nLocal+n; } /* ** Decode a btree page */ @@ -297,22 +336,25 @@ int hdrSize, /* Size of the page header. 0 or 100 */ char *zArgs /* Flags to control formatting */ ){ const char *zType = "unknown"; int nCell; - int i; + int i, j; int iCellPtr; int showCellContent = 0; + int showMap = 0; + char *zMap = 0; switch( a[0] ){ case 2: zType = "index interior node"; break; case 5: zType = "table interior node"; break; case 10: zType = "index leaf"; break; case 13: zType = "table leaf"; break; } while( zArgs[0] ){ switch( zArgs[0] ){ case 'c': showCellContent = 1; break; + case 'm': showMap = 1; break; } zArgs++; } printf("Decode of btree page %d:\n", pgno); print_decode_line(a, 0, 1, zType); @@ -319,26 +361,50 @@ print_decode_line(a, 1, 2, "Offset to first freeblock"); print_decode_line(a, 3, 2, "Number of cells on this page"); nCell = a[3]*256 + a[4]; print_decode_line(a, 5, 2, "Offset to cell content area"); print_decode_line(a, 7, 1, "Fragmented byte count"); - if( nCell>0 ){ - printf(" key: lx=left-child n=payload-size r=rowid\n"); - } if( a[0]==2 || a[0]==5 ){ print_decode_line(a, 8, 4, "Right child"); iCellPtr = 12; }else{ iCellPtr = 8; } + if( nCell>0 ){ + printf(" key: lx=left-child n=payload-size r=rowid\n"); + } + if( showMap ){ + zMap = malloc(pagesize); + memset(zMap, '.', pagesize); + memset(zMap, '1', hdrSize); + memset(&zMap[hdrSize], 'H', iCellPtr); + memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell); + } for(i=0; i