/ Check-in [306b461d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the ability to decode the headers of individual cells, byte-by-byte, in the "showdb.exe" utility.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 306b461d7c0643b6ac4df944759ecc9ce8581634
User & Date: drh 2014-06-19 23:38:53
Context
2014-06-20
01:32
In the showdb.exe utility, for the "NNNbd" command, also show data fields in addition to header fields on each record decoded. Improvements to formatting. check-in: b451fe0c user: drh tags: trunk
2014-06-19
23:38
Add the ability to decode the headers of individual cells, byte-by-byte, in the "showdb.exe" utility. check-in: 306b461d user: drh tags: trunk
2014-06-18
18:10
Add the "LogEst" and "LogEst.exe" target to the makefiles. check-in: 7b91b058 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to tool/showdb.c.

   124    124     unsigned char *aData;
   125    125     iStart = (iPg-1)*pagesize;
   126    126     fprintf(stdout, "Page %d:   (offsets 0x%x..0x%x)\n",
   127    127             iPg, iStart, iStart+pagesize-1);
   128    128     aData = print_byte_range(iStart, pagesize, 0);
   129    129     free(aData);
   130    130   }
          131  +
   131    132   
   132    133   /* Print a line of decode output showing a 4-byte integer.
   133    134   */
   134    135   static void print_decode_line(
   135    136     unsigned char *aData,      /* Content being decoded */
   136    137     int ofst, int nByte,       /* Start and size of decode */
   137    138     const char *zMsg           /* Message to append */
................................................................................
   336    337     }
   337    338     if( showCellContent && cType!=5 ){
   338    339       nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
   339    340     }
   340    341     *pzDesc = zDesc;
   341    342     return nLocal+n;
   342    343   }
          344  +
          345  +/* Print an offset followed by nByte bytes.  Add extra white-space
          346  +** at the end so that subsequent text is aligned.
          347  +*/
          348  +static void printBytes(
          349  +  unsigned char *aData,      /* Content being decoded */
          350  +  unsigned char *aStart,     /* Start of content to be printed */
          351  +  int nByte                  /* Number of bytes to print */
          352  +){
          353  +  int j;
          354  +  printf(" %03x: ", (int)(aStart-aData));
          355  +  for(j=0; j<9; j++){
          356  +    if( j>=nByte ){
          357  +      printf("   ");
          358  +    }else{
          359  +      printf("%02x ", aStart[j]);
          360  +    }
          361  +  }
          362  +}
          363  +
          364  +
          365  +/*
          366  +** Write a full decode on stdout for the cell at a[ofst].
          367  +** Assume the page contains a header of size szPgHdr bytes.
          368  +*/
          369  +static void decodeCell(
          370  +  unsigned char *a,       /* Page content (without the page-1 header) */
          371  +  unsigned pgno,          /* Page number */
          372  +  int iCell,              /* Cell index */
          373  +  int szPgHdr,            /* Size of the page header.  0 or 100 */
          374  +  int ofst                /* Cell begins at a[ofst] */
          375  +){
          376  +  int i, j, k;
          377  +  int leftChild;
          378  +  i64 nPayload;
          379  +  i64 rowid;
          380  +  i64 nHdr;
          381  +  i64 iType;
          382  +  int nLocal;
          383  +  unsigned char *x = a + ofst;
          384  +  unsigned char *end;
          385  +  unsigned char cType = a[0];
          386  +
          387  +  printf("Decode cell[%d] on page %d offset %04x....\n",
          388  +         iCell, pgno, szPgHdr+ofst);
          389  +  if( cType<=5 ){
          390  +    leftChild = ((x[0]*256 + x[1])*256 + x[2])*256 + x[3];
          391  +    printBytes(a, x, 4);
          392  +    printf("left child page:: %d\n", leftChild);
          393  +    x += 4;
          394  +  }
          395  +  if( cType!=5 ){
          396  +    i = decodeVarint(x, &nPayload);
          397  +    printBytes(a, x, i);
          398  +    nLocal = localPayload(nPayload, cType);
          399  +    printf("bytes of payload: %d  (local: %d)\n", (int)nPayload, nLocal);
          400  +    x += i;
          401  +  }else{
          402  +    nPayload = nLocal = 0;
          403  +  }
          404  +  end = x + nLocal;
          405  +  if( cType==5 || cType==13 ){
          406  +    i = decodeVarint(x, &rowid);
          407  +    printBytes(a, x, i);
          408  +    printf("rowid: %lld\n", rowid);
          409  +    x += i;
          410  +  }
          411  +  if( nLocal>0 ){
          412  +    i = decodeVarint(x, &nHdr);
          413  +    printBytes(a, x, i);
          414  +    printf("record header size: %d\n", (int)nHdr);
          415  +    j = i;
          416  +    k = 0;
          417  +    while( x+j<end && j<nHdr ){
          418  +       const char *zTypeName;
          419  +       int sz = 0;
          420  +       char zNm[30];
          421  +       i = decodeVarint(x+j, &iType);
          422  +       printBytes(a, x+j, i);
          423  +       printf("column[%d] type code: %d - ", k++, (int)iType);
          424  +       switch( iType ){
          425  +         case 0:  zTypeName = "NULL";    sz = 0;  break;
          426  +         case 1:  zTypeName = "int8";    sz = 1;  break;
          427  +         case 2:  zTypeName = "int16";   sz = 2;  break;
          428  +         case 3:  zTypeName = "int24";   sz = 3;  break;
          429  +         case 4:  zTypeName = "int32";   sz = 4;  break;
          430  +         case 5:  zTypeName = "int48";   sz = 6;  break;
          431  +         case 6:  zTypeName = "int64";   sz = 8;  break;
          432  +         case 7:  zTypeName = "double";  sz = 8;  break;
          433  +         case 8:  zTypeName = "zero";    sz = 0;  break;
          434  +         case 9:  zTypeName = "one";     sz = 0;  break;
          435  +         case 10:
          436  +         case 11: zTypeName = "error";   sz = 0;  break;
          437  +         default: {
          438  +           sz = (int)(iType-12)/2;
          439  +           sprintf(zNm, (iType&1)==0 ? "blob(%d)" : "text(%d)", sz);
          440  +           zTypeName = zNm;
          441  +           break;
          442  +         }
          443  +       }
          444  +       printf("%s\n", zTypeName);
          445  +       j += i;
          446  +    }
          447  +  }
          448  +  if( j<nLocal ){
          449  +    printBytes(a, x+j, 0);
          450  +    printf("%d bytes of content\n", nLocal-j);
          451  +  }
          452  +  if( nLocal<nPayload ){
          453  +    printBytes(a, x+nLocal, 4);
          454  +    printf("first overflow page: %d\n", decodeInt32(x+nLocal));
          455  +  }
          456  +}
          457  +
   343    458   
   344    459   /*
   345    460   ** Decode a btree page
   346    461   */
   347    462   static void decode_btree_page(
   348    463     unsigned char *a,   /* Page content */
   349    464     int pgno,           /* Page number */
................................................................................
   352    467   ){
   353    468     const char *zType = "unknown";
   354    469     int nCell;
   355    470     int i, j;
   356    471     int iCellPtr;
   357    472     int showCellContent = 0;
   358    473     int showMap = 0;
          474  +  int cellToDecode = -2;
   359    475     char *zMap = 0;
   360    476     switch( a[0] ){
   361    477       case 2:  zType = "index interior node";  break;
   362    478       case 5:  zType = "table interior node";  break;
   363    479       case 10: zType = "index leaf";           break;
   364    480       case 13: zType = "table leaf";           break;
   365    481     }
   366    482     while( zArgs[0] ){
   367    483       switch( zArgs[0] ){
   368    484         case 'c': showCellContent = 1;  break;
   369    485         case 'm': showMap = 1;          break;
          486  +      case 'd': {
          487  +        if( !isdigit(zArgs[1]) ){
          488  +          cellToDecode = -1;
          489  +        }else{
          490  +          cellToDecode = 0;
          491  +          while( isdigit(zArgs[1]) ){
          492  +            zArgs++;
          493  +            cellToDecode = cellToDecode*10 + zArgs[0] - '0';
          494  +          }
          495  +        }
          496  +        break;
          497  +      }
   370    498       }
   371    499       zArgs++;
   372    500     }
   373         -  printf("Decode of btree page %d:\n", pgno);
   374         -  print_decode_line(a, 0, 1, zType);
   375         -  print_decode_line(a, 1, 2, "Offset to first freeblock");
   376         -  print_decode_line(a, 3, 2, "Number of cells on this page");
   377    501     nCell = a[3]*256 + a[4];
   378         -  print_decode_line(a, 5, 2, "Offset to cell content area");
   379         -  print_decode_line(a, 7, 1, "Fragmented byte count");
   380         -  if( a[0]==2 || a[0]==5 ){
   381         -    print_decode_line(a, 8, 4, "Right child");
   382         -    iCellPtr = 12;
   383         -  }else{
   384         -    iCellPtr = 8;
   385         -  }
   386         -  if( nCell>0 ){
   387         -    printf(" key: lx=left-child n=payload-size r=rowid\n");
          502  +  iCellPtr = (a[0]==2 || a[0]==5) ? 12 : 8;
          503  +  if( cellToDecode==(-2) ){
          504  +    printf("Decode of btree page %d:\n", pgno);
          505  +    print_decode_line(a, 0, 1, zType);
          506  +    print_decode_line(a, 1, 2, "Offset to first freeblock");
          507  +    print_decode_line(a, 3, 2, "Number of cells on this page");
          508  +    print_decode_line(a, 5, 2, "Offset to cell content area");
          509  +    print_decode_line(a, 7, 1, "Fragmented byte count");
          510  +    if( a[0]==2 || a[0]==5 ){
          511  +      print_decode_line(a, 8, 4, "Right child");
          512  +    }
          513  +    if( nCell>0 ){
          514  +      printf(" key: lx=left-child n=payload-size r=rowid\n");
          515  +    }
          516  +  }else if( cellToDecode>=nCell ){
          517  +    printf("Page %d has only %d cells\n", pgno, nCell);
          518  +    return;
   388    519     }
   389    520     if( showMap ){
   390    521       zMap = malloc(pagesize);
   391    522       memset(zMap, '.', pagesize);
   392    523       memset(zMap, '1', hdrSize);
   393    524       memset(&zMap[hdrSize], 'H', iCellPtr);
   394    525       memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
................................................................................
   405    536         memset(&zMap[cofst], '*', n);
   406    537         zMap[cofst] = '[';
   407    538         zMap[cofst+n-1] = ']';
   408    539         sprintf(zBuf, "%d", i);
   409    540         j = strlen(zBuf);
   410    541         if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
   411    542       }
   412         -    printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
          543  +    if( cellToDecode==(-2) ){
          544  +      printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
          545  +    }else if( cellToDecode==(-1) || cellToDecode==i ){
          546  +      decodeCell(a, pgno, i, hdrSize, cofst-hdrSize);
          547  +    }
   413    548     }
   414    549     if( showMap ){
   415    550       for(i=0; i<pagesize; i+=64){
   416    551         printf(" %03x: %.64s\n", i, &zMap[i]);
   417    552       }
   418    553       free(zMap);
   419         -  }  
          554  +  }
   420    555   }
   421    556   
   422    557   /*
   423    558   ** Decode a freelist trunk page.
   424    559   */
   425    560   static void decode_trunk_page(
   426    561     int pgno,             /* The page number */
................................................................................
   753    888       "    pgidx           Index of how each page is used\n"
   754    889       "    ptrmap          Show all PTRMAP page content\n"
   755    890       "    NNN..MMM        Show hex of pages NNN through MMM\n"
   756    891       "    NNN..end        Show hex of pages NNN through end of file\n"
   757    892       "    NNNb            Decode btree page NNN\n"
   758    893       "    NNNbc           Decode btree page NNN and show content\n"
   759    894       "    NNNbm           Decode btree page NNN and show a layout map\n"
          895  +    "    NNNbdCCC        Decode cell CCC on btree page NNN\n"
   760    896       "    NNNt            Decode freelist trunk page NNN\n"
   761    897       "    NNNtd           Show leaf freelist pages on the decode\n"
   762    898       "    NNNtr           Recurisvely decode freelist starting at NNN\n"
   763    899     );
   764    900   }
   765    901   
   766    902   int main(int argc, char **argv){