1
0

showdb.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. /*
  2. ** A utility for printing all or part of an SQLite database file.
  3. */
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #if !defined(_MSC_VER)
  10. #include <unistd.h>
  11. #endif
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "sqlite3.h"
  15. static int pagesize = 1024; /* Size of a database page */
  16. static int db = -1; /* File descriptor for reading the DB */
  17. static int mxPage = 0; /* Last page number */
  18. static int perLine = 16; /* HEX elements to print per line */
  19. typedef long long int i64; /* Datatype for 64-bit integers */
  20. /*
  21. ** Convert the var-int format into i64. Return the number of bytes
  22. ** in the var-int. Write the var-int value into *pVal.
  23. */
  24. static int decodeVarint(const unsigned char *z, i64 *pVal){
  25. i64 v = 0;
  26. int i;
  27. for(i=0; i<8; i++){
  28. v = (v<<7) + (z[i]&0x7f);
  29. if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
  30. }
  31. v = (v<<8) + (z[i]&0xff);
  32. *pVal = v;
  33. return 9;
  34. }
  35. /*
  36. ** Extract a big-endian 32-bit integer
  37. */
  38. static unsigned int decodeInt32(const unsigned char *z){
  39. return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3];
  40. }
  41. /* Report an out-of-memory error and die.
  42. */
  43. static void out_of_memory(void){
  44. fprintf(stderr,"Out of memory...\n");
  45. exit(1);
  46. }
  47. /*
  48. ** Read content from the file.
  49. **
  50. ** Space to hold the content is obtained from malloc() and needs to be
  51. ** freed by the caller.
  52. */
  53. static unsigned char *getContent(int ofst, int nByte){
  54. unsigned char *aData;
  55. aData = malloc(nByte+32);
  56. if( aData==0 ) out_of_memory();
  57. memset(aData, 0, nByte+32);
  58. lseek(db, ofst, SEEK_SET);
  59. read(db, aData, nByte);
  60. return aData;
  61. }
  62. /*
  63. ** Print a range of bytes as hex and as ascii.
  64. */
  65. static unsigned char *print_byte_range(
  66. int ofst, /* First byte in the range of bytes to print */
  67. int nByte, /* Number of bytes to print */
  68. int printOfst /* Add this amount to the index on the left column */
  69. ){
  70. unsigned char *aData;
  71. int i, j;
  72. const char *zOfstFmt;
  73. if( ((printOfst+nByte)&~0xfff)==0 ){
  74. zOfstFmt = " %03x: ";
  75. }else if( ((printOfst+nByte)&~0xffff)==0 ){
  76. zOfstFmt = " %04x: ";
  77. }else if( ((printOfst+nByte)&~0xfffff)==0 ){
  78. zOfstFmt = " %05x: ";
  79. }else if( ((printOfst+nByte)&~0xffffff)==0 ){
  80. zOfstFmt = " %06x: ";
  81. }else{
  82. zOfstFmt = " %08x: ";
  83. }
  84. aData = getContent(ofst, nByte);
  85. for(i=0; i<nByte; i += perLine){
  86. fprintf(stdout, zOfstFmt, i+printOfst);
  87. for(j=0; j<perLine; j++){
  88. if( i+j>nByte ){
  89. fprintf(stdout, " ");
  90. }else{
  91. fprintf(stdout,"%02x ", aData[i+j]);
  92. }
  93. }
  94. for(j=0; j<perLine; j++){
  95. if( i+j>nByte ){
  96. fprintf(stdout, " ");
  97. }else{
  98. fprintf(stdout,"%c", isprint(aData[i+j]) ? aData[i+j] : '.');
  99. }
  100. }
  101. fprintf(stdout,"\n");
  102. }
  103. return aData;
  104. }
  105. /*
  106. ** Print an entire page of content as hex
  107. */
  108. static print_page(int iPg){
  109. int iStart;
  110. unsigned char *aData;
  111. iStart = (iPg-1)*pagesize;
  112. fprintf(stdout, "Page %d: (offsets 0x%x..0x%x)\n",
  113. iPg, iStart, iStart+pagesize-1);
  114. aData = print_byte_range(iStart, pagesize, 0);
  115. free(aData);
  116. }
  117. /* Print a line of decode output showing a 4-byte integer.
  118. */
  119. static print_decode_line(
  120. unsigned char *aData, /* Content being decoded */
  121. int ofst, int nByte, /* Start and size of decode */
  122. const char *zMsg /* Message to append */
  123. ){
  124. int i, j;
  125. int val = aData[ofst];
  126. char zBuf[100];
  127. sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
  128. i = strlen(zBuf);
  129. for(j=1; j<4; j++){
  130. if( j>=nByte ){
  131. sprintf(&zBuf[i], " ");
  132. }else{
  133. sprintf(&zBuf[i], " %02x", aData[ofst+j]);
  134. val = val*256 + aData[ofst+j];
  135. }
  136. i += strlen(&zBuf[i]);
  137. }
  138. sprintf(&zBuf[i], " %9d", val);
  139. printf("%s %s\n", zBuf, zMsg);
  140. }
  141. /*
  142. ** Decode the database header.
  143. */
  144. static void print_db_header(void){
  145. unsigned char *aData;
  146. aData = print_byte_range(0, 100, 0);
  147. printf("Decoded:\n");
  148. print_decode_line(aData, 16, 2, "Database page size");
  149. print_decode_line(aData, 18, 1, "File format write version");
  150. print_decode_line(aData, 19, 1, "File format read version");
  151. print_decode_line(aData, 20, 1, "Reserved space at end of page");
  152. print_decode_line(aData, 24, 4, "File change counter");
  153. print_decode_line(aData, 28, 4, "Size of database in pages");
  154. print_decode_line(aData, 32, 4, "Page number of first freelist page");
  155. print_decode_line(aData, 36, 4, "Number of freelist pages");
  156. print_decode_line(aData, 40, 4, "Schema cookie");
  157. print_decode_line(aData, 44, 4, "Schema format version");
  158. print_decode_line(aData, 48, 4, "Default page cache size");
  159. print_decode_line(aData, 52, 4, "Largest auto-vac root page");
  160. print_decode_line(aData, 56, 4, "Text encoding");
  161. print_decode_line(aData, 60, 4, "User version");
  162. print_decode_line(aData, 64, 4, "Incremental-vacuum mode");
  163. print_decode_line(aData, 68, 4, "Application ID");
  164. print_decode_line(aData, 72, 4, "meta[8]");
  165. print_decode_line(aData, 76, 4, "meta[9]");
  166. print_decode_line(aData, 80, 4, "meta[10]");
  167. print_decode_line(aData, 84, 4, "meta[11]");
  168. print_decode_line(aData, 88, 4, "meta[12]");
  169. print_decode_line(aData, 92, 4, "Change counter for version number");
  170. print_decode_line(aData, 96, 4, "SQLite version number");
  171. }
  172. /*
  173. ** Describe cell content.
  174. */
  175. static int describeContent(
  176. unsigned char *a, /* Cell content */
  177. int nLocal, /* Bytes in a[] */
  178. char *zDesc /* Write description here */
  179. ){
  180. int nDesc = 0;
  181. int n, i, j;
  182. i64 x, v;
  183. const unsigned char *pData;
  184. const unsigned char *pLimit;
  185. char sep = ' ';
  186. pLimit = &a[nLocal];
  187. n = decodeVarint(a, &x);
  188. pData = &a[x];
  189. a += n;
  190. i = x - n;
  191. while( i>0 && pData<=pLimit ){
  192. n = decodeVarint(a, &x);
  193. a += n;
  194. i -= n;
  195. nLocal -= n;
  196. zDesc[0] = sep;
  197. sep = ',';
  198. nDesc++;
  199. zDesc++;
  200. if( x==0 ){
  201. sprintf(zDesc, "*"); /* NULL is a "*" */
  202. }else if( x>=1 && x<=6 ){
  203. v = (signed char)pData[0];
  204. pData++;
  205. switch( x ){
  206. case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
  207. case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
  208. case 4: v = (v<<8) + pData[0]; pData++;
  209. case 3: v = (v<<8) + pData[0]; pData++;
  210. case 2: v = (v<<8) + pData[0]; pData++;
  211. }
  212. sprintf(zDesc, "%lld", v);
  213. }else if( x==7 ){
  214. sprintf(zDesc, "real");
  215. pData += 8;
  216. }else if( x==8 ){
  217. sprintf(zDesc, "0");
  218. }else if( x==9 ){
  219. sprintf(zDesc, "1");
  220. }else if( x>=12 ){
  221. int size = (x-12)/2;
  222. if( (x&1)==0 ){
  223. sprintf(zDesc, "blob(%d)", size);
  224. }else{
  225. sprintf(zDesc, "txt(%d)", size);
  226. }
  227. pData += size;
  228. }
  229. j = strlen(zDesc);
  230. zDesc += j;
  231. nDesc += j;
  232. }
  233. return nDesc;
  234. }
  235. /*
  236. ** Compute the local payload size given the total payload size and
  237. ** the page size.
  238. */
  239. static int localPayload(i64 nPayload, char cType){
  240. int maxLocal;
  241. int minLocal;
  242. int surplus;
  243. int nLocal;
  244. if( cType==13 ){
  245. /* Table leaf */
  246. maxLocal = pagesize-35;
  247. minLocal = (pagesize-12)*32/255-23;
  248. }else{
  249. maxLocal = (pagesize-12)*64/255-23;
  250. minLocal = (pagesize-12)*32/255-23;
  251. }
  252. if( nPayload>maxLocal ){
  253. surplus = minLocal + (nPayload-minLocal)%(pagesize-4);
  254. if( surplus<=maxLocal ){
  255. nLocal = surplus;
  256. }else{
  257. nLocal = minLocal;
  258. }
  259. }else{
  260. nLocal = nPayload;
  261. }
  262. return nLocal;
  263. }
  264. /*
  265. ** Create a description for a single cell.
  266. **
  267. ** The return value is the local cell size.
  268. */
  269. static int describeCell(
  270. unsigned char cType, /* Page type */
  271. unsigned char *a, /* Cell content */
  272. int showCellContent, /* Show cell content if true */
  273. char **pzDesc /* Store description here */
  274. ){
  275. int i;
  276. int nDesc = 0;
  277. int n = 0;
  278. int leftChild;
  279. i64 nPayload;
  280. i64 rowid;
  281. int nLocal;
  282. static char zDesc[1000];
  283. i = 0;
  284. if( cType<=5 ){
  285. leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
  286. a += 4;
  287. n += 4;
  288. sprintf(zDesc, "lx: %d ", leftChild);
  289. nDesc = strlen(zDesc);
  290. }
  291. if( cType!=5 ){
  292. i = decodeVarint(a, &nPayload);
  293. a += i;
  294. n += i;
  295. sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
  296. nDesc += strlen(&zDesc[nDesc]);
  297. nLocal = localPayload(nPayload, cType);
  298. }else{
  299. nPayload = nLocal = 0;
  300. }
  301. if( cType==5 || cType==13 ){
  302. i = decodeVarint(a, &rowid);
  303. a += i;
  304. n += i;
  305. sprintf(&zDesc[nDesc], "r: %lld ", rowid);
  306. nDesc += strlen(&zDesc[nDesc]);
  307. }
  308. if( nLocal<nPayload ){
  309. int ovfl;
  310. unsigned char *b = &a[nLocal];
  311. ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
  312. sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
  313. nDesc += strlen(&zDesc[nDesc]);
  314. n += 4;
  315. }
  316. if( showCellContent && cType!=5 ){
  317. nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
  318. }
  319. *pzDesc = zDesc;
  320. return nLocal+n;
  321. }
  322. /*
  323. ** Decode a btree page
  324. */
  325. static void decode_btree_page(
  326. unsigned char *a, /* Page content */
  327. int pgno, /* Page number */
  328. int hdrSize, /* Size of the page header. 0 or 100 */
  329. char *zArgs /* Flags to control formatting */
  330. ){
  331. const char *zType = "unknown";
  332. int nCell;
  333. int i, j;
  334. int iCellPtr;
  335. int showCellContent = 0;
  336. int showMap = 0;
  337. char *zMap = 0;
  338. switch( a[0] ){
  339. case 2: zType = "index interior node"; break;
  340. case 5: zType = "table interior node"; break;
  341. case 10: zType = "index leaf"; break;
  342. case 13: zType = "table leaf"; break;
  343. }
  344. while( zArgs[0] ){
  345. switch( zArgs[0] ){
  346. case 'c': showCellContent = 1; break;
  347. case 'm': showMap = 1; break;
  348. }
  349. zArgs++;
  350. }
  351. printf("Decode of btree page %d:\n", pgno);
  352. print_decode_line(a, 0, 1, zType);
  353. print_decode_line(a, 1, 2, "Offset to first freeblock");
  354. print_decode_line(a, 3, 2, "Number of cells on this page");
  355. nCell = a[3]*256 + a[4];
  356. print_decode_line(a, 5, 2, "Offset to cell content area");
  357. print_decode_line(a, 7, 1, "Fragmented byte count");
  358. if( a[0]==2 || a[0]==5 ){
  359. print_decode_line(a, 8, 4, "Right child");
  360. iCellPtr = 12;
  361. }else{
  362. iCellPtr = 8;
  363. }
  364. if( nCell>0 ){
  365. printf(" key: lx=left-child n=payload-size r=rowid\n");
  366. }
  367. if( showMap ){
  368. zMap = malloc(pagesize);
  369. memset(zMap, '.', pagesize);
  370. memset(zMap, '1', hdrSize);
  371. memset(&zMap[hdrSize], 'H', iCellPtr);
  372. memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
  373. }
  374. for(i=0; i<nCell; i++){
  375. int cofst = iCellPtr + i*2;
  376. char *zDesc;
  377. int n;
  378. cofst = a[cofst]*256 + a[cofst+1];
  379. n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
  380. if( showMap ){
  381. char zBuf[30];
  382. memset(&zMap[cofst], '*', n);
  383. zMap[cofst] = '[';
  384. zMap[cofst+n-1] = ']';
  385. sprintf(zBuf, "%d", i);
  386. j = strlen(zBuf);
  387. if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
  388. }
  389. printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
  390. }
  391. if( showMap ){
  392. for(i=0; i<pagesize; i+=64){
  393. printf(" %03x: %.64s\n", i, &zMap[i]);
  394. }
  395. free(zMap);
  396. }
  397. }
  398. /*
  399. ** Decode a freelist trunk page.
  400. */
  401. static void decode_trunk_page(
  402. int pgno, /* The page number */
  403. int pagesize, /* Size of each page */
  404. int detail, /* Show leaf pages if true */
  405. int recursive /* Follow the trunk change if true */
  406. ){
  407. int n, i, k;
  408. unsigned char *a;
  409. while( pgno>0 ){
  410. a = getContent((pgno-1)*pagesize, pagesize);
  411. printf("Decode of freelist trunk page %d:\n", pgno);
  412. print_decode_line(a, 0, 4, "Next freelist trunk page");
  413. print_decode_line(a, 4, 4, "Number of entries on this page");
  414. if( detail ){
  415. n = (int)decodeInt32(&a[4]);
  416. for(i=0; i<n; i++){
  417. unsigned int x = decodeInt32(&a[8+4*i]);
  418. char zIdx[10];
  419. sprintf(zIdx, "[%d]", i);
  420. printf(" %5s %7u", zIdx, x);
  421. if( i%5==4 ) printf("\n");
  422. }
  423. if( i%5!=0 ) printf("\n");
  424. }
  425. if( !recursive ){
  426. pgno = 0;
  427. }else{
  428. pgno = (int)decodeInt32(&a[0]);
  429. }
  430. free(a);
  431. }
  432. }
  433. /*
  434. ** A short text comment on the use of each page.
  435. */
  436. static char **zPageUse;
  437. /*
  438. ** Add a comment on the use of a page.
  439. */
  440. static void page_usage_msg(int pgno, const char *zFormat, ...){
  441. va_list ap;
  442. char *zMsg;
  443. va_start(ap, zFormat);
  444. zMsg = sqlite3_vmprintf(zFormat, ap);
  445. va_end(ap);
  446. if( pgno<=0 || pgno>mxPage ){
  447. printf("ERROR: page %d out of range 1..%d: %s\n",
  448. pgno, mxPage, zMsg);
  449. sqlite3_free(zMsg);
  450. return;
  451. }
  452. if( zPageUse[pgno]!=0 ){
  453. printf("ERROR: page %d used multiple times:\n", pgno);
  454. printf("ERROR: previous: %s\n", zPageUse[pgno]);
  455. printf("ERROR: current: %s\n", zMsg);
  456. sqlite3_free(zPageUse[pgno]);
  457. }
  458. zPageUse[pgno] = zMsg;
  459. }
  460. /*
  461. ** Find overflow pages of a cell and describe their usage.
  462. */
  463. static void page_usage_cell(
  464. unsigned char cType, /* Page type */
  465. unsigned char *a, /* Cell content */
  466. int pgno, /* page containing the cell */
  467. int cellno /* Index of the cell on the page */
  468. ){
  469. int i;
  470. int nDesc = 0;
  471. int n = 0;
  472. i64 nPayload;
  473. i64 rowid;
  474. int nLocal;
  475. i = 0;
  476. if( cType<=5 ){
  477. a += 4;
  478. n += 4;
  479. }
  480. if( cType!=5 ){
  481. i = decodeVarint(a, &nPayload);
  482. a += i;
  483. n += i;
  484. nLocal = localPayload(nPayload, cType);
  485. }else{
  486. nPayload = nLocal = 0;
  487. }
  488. if( cType==5 || cType==13 ){
  489. i = decodeVarint(a, &rowid);
  490. a += i;
  491. n += i;
  492. }
  493. if( nLocal<nPayload ){
  494. int ovfl = decodeInt32(a+nLocal);
  495. int cnt = 0;
  496. while( ovfl && (cnt++)<mxPage ){
  497. page_usage_msg(ovfl, "overflow %d from cell %d of page %d",
  498. cnt, cellno, pgno);
  499. a = getContent((ovfl-1)*pagesize, 4);
  500. ovfl = decodeInt32(a);
  501. free(a);
  502. }
  503. }
  504. }
  505. /*
  506. ** Describe the usages of a b-tree page
  507. */
  508. static void page_usage_btree(
  509. int pgno, /* Page to describe */
  510. int parent, /* Parent of this page. 0 for root pages */
  511. int idx, /* Which child of the parent */
  512. const char *zName /* Name of the table */
  513. ){
  514. unsigned char *a;
  515. const char *zType = "corrupt node";
  516. int nCell;
  517. int i;
  518. int hdr = pgno==1 ? 100 : 0;
  519. if( pgno<=0 || pgno>mxPage ) return;
  520. a = getContent((pgno-1)*pagesize, pagesize);
  521. switch( a[hdr] ){
  522. case 2: zType = "interior node of index"; break;
  523. case 5: zType = "interior node of table"; break;
  524. case 10: zType = "leaf of index"; break;
  525. case 13: zType = "leaf of table"; break;
  526. }
  527. if( parent ){
  528. page_usage_msg(pgno, "%s [%s], child %d of page %d",
  529. zType, zName, idx, parent);
  530. }else{
  531. page_usage_msg(pgno, "root %s [%s]", zType, zName);
  532. }
  533. nCell = a[hdr+3]*256 + a[hdr+4];
  534. if( a[hdr]==2 || a[hdr]==5 ){
  535. int cellstart = hdr+12;
  536. unsigned int child;
  537. for(i=0; i<nCell; i++){
  538. int ofst;
  539. ofst = cellstart + i*2;
  540. ofst = a[ofst]*256 + a[ofst+1];
  541. child = decodeInt32(a+ofst);
  542. page_usage_btree(child, pgno, i, zName);
  543. }
  544. child = decodeInt32(a+cellstart-4);
  545. page_usage_btree(child, pgno, i, zName);
  546. }
  547. if( a[hdr]==2 || a[hdr]==10 || a[hdr]==13 ){
  548. int cellstart = hdr + 8 + 4*(a[hdr]<=5);
  549. for(i=0; i<nCell; i++){
  550. int ofst;
  551. ofst = cellstart + i*2;
  552. ofst = a[ofst]*256 + a[ofst+1];
  553. page_usage_cell(a[hdr], a+ofst, pgno, i);
  554. }
  555. }
  556. free(a);
  557. }
  558. /*
  559. ** Determine page usage by the freelist
  560. */
  561. static void page_usage_freelist(int pgno){
  562. unsigned char *a;
  563. int cnt = 0;
  564. int i;
  565. int n;
  566. int iNext;
  567. int parent = 1;
  568. while( pgno>0 && pgno<=mxPage && (cnt++)<mxPage ){
  569. page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent);
  570. a = getContent((pgno-1)*pagesize, pagesize);
  571. iNext = decodeInt32(a);
  572. n = decodeInt32(a+4);
  573. for(i=0; i<n; i++){
  574. int child = decodeInt32(a + (i*4+8));
  575. page_usage_msg(child, "freelist leaf, child %d of trunk page %d",
  576. i, pgno);
  577. }
  578. free(a);
  579. parent = pgno;
  580. pgno = iNext;
  581. }
  582. }
  583. /*
  584. ** Determine pages used as PTRMAP pages
  585. */
  586. static void page_usage_ptrmap(unsigned char *a){
  587. if( a[55] ){
  588. int usable = pagesize - a[20];
  589. int pgno = 2;
  590. int perPage = usable/5;
  591. while( pgno<=mxPage ){
  592. page_usage_msg(pgno, "PTRMAP page covering %d..%d",
  593. pgno+1, pgno+perPage);
  594. pgno += perPage + 1;
  595. }
  596. }
  597. }
  598. /*
  599. ** Try to figure out how every page in the database file is being used.
  600. */
  601. static void page_usage_report(const char *zDbName){
  602. int i, j;
  603. int rc;
  604. sqlite3 *db;
  605. sqlite3_stmt *pStmt;
  606. unsigned char *a;
  607. char zQuery[200];
  608. /* Avoid the pathological case */
  609. if( mxPage<1 ){
  610. printf("empty database\n");
  611. return;
  612. }
  613. /* Open the database file */
  614. rc = sqlite3_open(zDbName, &db);
  615. if( rc ){
  616. printf("cannot open database: %s\n", sqlite3_errmsg(db));
  617. sqlite3_close(db);
  618. return;
  619. }
  620. /* Set up global variables zPageUse[] and mxPage to record page
  621. ** usages */
  622. zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(mxPage+1) );
  623. if( zPageUse==0 ) out_of_memory();
  624. memset(zPageUse, 0, sizeof(zPageUse[0])*(mxPage+1));
  625. /* Discover the usage of each page */
  626. a = getContent(0, 100);
  627. page_usage_freelist(decodeInt32(a+32));
  628. page_usage_ptrmap(a);
  629. free(a);
  630. page_usage_btree(1, 0, 0, "sqlite_master");
  631. sqlite3_exec(db, "PRAGMA writable_schema=ON", 0, 0, 0);
  632. for(j=0; j<2; j++){
  633. sqlite3_snprintf(sizeof(zQuery), zQuery,
  634. "SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage"
  635. " ORDER BY rowid %s", j?"DESC":"");
  636. rc = sqlite3_prepare_v2(db, zQuery, -1, &pStmt, 0);
  637. if( rc==SQLITE_OK ){
  638. while( sqlite3_step(pStmt)==SQLITE_ROW ){
  639. int pgno = sqlite3_column_int(pStmt, 2);
  640. page_usage_btree(pgno, 0, 0, sqlite3_column_text(pStmt, 1));
  641. }
  642. }else{
  643. printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
  644. }
  645. rc = sqlite3_finalize(pStmt);
  646. if( rc==SQLITE_OK ) break;
  647. }
  648. sqlite3_close(db);
  649. /* Print the report and free memory used */
  650. for(i=1; i<=mxPage; i++){
  651. printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???");
  652. sqlite3_free(zPageUse[i]);
  653. }
  654. sqlite3_free(zPageUse);
  655. zPageUse = 0;
  656. }
  657. /*
  658. ** Try to figure out how every page in the database file is being used.
  659. */
  660. static void ptrmap_coverage_report(const char *zDbName){
  661. unsigned int pgno;
  662. unsigned char *aHdr;
  663. unsigned char *a;
  664. int usable;
  665. int perPage;
  666. unsigned int i;
  667. /* Avoid the pathological case */
  668. if( mxPage<1 ){
  669. printf("empty database\n");
  670. return;
  671. }
  672. /* Make sure PTRMAPs are used in this database */
  673. aHdr = getContent(0, 100);
  674. if( aHdr[55]==0 ){
  675. printf("database does not use PTRMAP pages\n");
  676. return;
  677. }
  678. usable = pagesize - aHdr[20];
  679. perPage = usable/5;
  680. free(aHdr);
  681. printf("%5d: root of sqlite_master\n", 1);
  682. for(pgno=2; pgno<=mxPage; pgno += perPage+1){
  683. printf("%5d: PTRMAP page covering %d..%d\n", pgno,
  684. pgno+1, pgno+perPage);
  685. a = getContent((pgno-1)*pagesize, usable);
  686. for(i=0; i+5<=usable && pgno+1+i/5<=mxPage; i+=5){
  687. const char *zType = "???";
  688. unsigned int iFrom = decodeInt32(&a[i+1]);
  689. switch( a[i] ){
  690. case 1: zType = "b-tree root page"; break;
  691. case 2: zType = "freelist page"; break;
  692. case 3: zType = "first page of overflow"; break;
  693. case 4: zType = "later page of overflow"; break;
  694. case 5: zType = "b-tree non-root page"; break;
  695. }
  696. printf("%5d: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
  697. }
  698. free(a);
  699. }
  700. }
  701. /*
  702. ** Print a usage comment
  703. */
  704. static void usage(const char *argv0){
  705. fprintf(stderr, "Usage %s FILENAME ?args...?\n\n", argv0);
  706. fprintf(stderr,
  707. "args:\n"
  708. " dbheader Show database header\n"
  709. " pgidx Index of how each page is used\n"
  710. " ptrmap Show all PTRMAP page content\n"
  711. " NNN..MMM Show hex of pages NNN through MMM\n"
  712. " NNN..end Show hex of pages NNN through end of file\n"
  713. " NNNb Decode btree page NNN\n"
  714. " NNNbc Decode btree page NNN and show content\n"
  715. " NNNbm Decode btree page NNN and show a layout map\n"
  716. " NNNt Decode freelist trunk page NNN\n"
  717. " NNNtd Show leaf freelist pages on the decode\n"
  718. " NNNtr Recurisvely decode freelist starting at NNN\n"
  719. );
  720. }
  721. int main(int argc, char **argv){
  722. struct stat sbuf;
  723. unsigned char zPgSz[2];
  724. if( argc<2 ){
  725. usage(argv[0]);
  726. exit(1);
  727. }
  728. db = open(argv[1], O_RDONLY);
  729. if( db<0 ){
  730. fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
  731. exit(1);
  732. }
  733. zPgSz[0] = 0;
  734. zPgSz[1] = 0;
  735. lseek(db, 16, SEEK_SET);
  736. read(db, zPgSz, 2);
  737. pagesize = zPgSz[0]*256 + zPgSz[1]*65536;
  738. if( pagesize==0 ) pagesize = 1024;
  739. printf("Pagesize: %d\n", pagesize);
  740. fstat(db, &sbuf);
  741. mxPage = sbuf.st_size/pagesize;
  742. printf("Available pages: 1..%d\n", mxPage);
  743. if( argc==2 ){
  744. int i;
  745. for(i=1; i<=mxPage; i++) print_page(i);
  746. }else{
  747. int i;
  748. for(i=2; i<argc; i++){
  749. int iStart, iEnd;
  750. char *zLeft;
  751. if( strcmp(argv[i], "dbheader")==0 ){
  752. print_db_header();
  753. continue;
  754. }
  755. if( strcmp(argv[i], "pgidx")==0 ){
  756. page_usage_report(argv[1]);
  757. continue;
  758. }
  759. if( strcmp(argv[i], "ptrmap")==0 ){
  760. ptrmap_coverage_report(argv[1]);
  761. continue;
  762. }
  763. if( strcmp(argv[i], "help")==0 ){
  764. usage(argv[0]);
  765. continue;
  766. }
  767. if( !isdigit(argv[i][0]) ){
  768. fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
  769. continue;
  770. }
  771. iStart = strtol(argv[i], &zLeft, 0);
  772. if( zLeft && strcmp(zLeft,"..end")==0 ){
  773. iEnd = mxPage;
  774. }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
  775. iEnd = strtol(&zLeft[2], 0, 0);
  776. }else if( zLeft && zLeft[0]=='b' ){
  777. int ofst, nByte, hdrSize;
  778. unsigned char *a;
  779. if( iStart==1 ){
  780. ofst = hdrSize = 100;
  781. nByte = pagesize-100;
  782. }else{
  783. hdrSize = 0;
  784. ofst = (iStart-1)*pagesize;
  785. nByte = pagesize;
  786. }
  787. a = getContent(ofst, nByte);
  788. decode_btree_page(a, iStart, hdrSize, &zLeft[1]);
  789. free(a);
  790. continue;
  791. }else if( zLeft && zLeft[0]=='t' ){
  792. unsigned char *a;
  793. int detail = 0;
  794. int recursive = 0;
  795. int i;
  796. for(i=1; zLeft[i]; i++){
  797. if( zLeft[i]=='r' ) recursive = 1;
  798. if( zLeft[i]=='d' ) detail = 1;
  799. }
  800. decode_trunk_page(iStart, pagesize, detail, recursive);
  801. continue;
  802. }else{
  803. iEnd = iStart;
  804. }
  805. if( iStart<1 || iEnd<iStart || iEnd>mxPage ){
  806. fprintf(stderr,
  807. "Page argument should be LOWER?..UPPER?. Range 1 to %d\n",
  808. mxPage);
  809. exit(1);
  810. }
  811. while( iStart<=iEnd ){
  812. print_page(iStart);
  813. iStart++;
  814. }
  815. }
  816. }
  817. close(db);
  818. }