From: dan Date: Mon, 3 Aug 2015 17:03:31 +0000 (+0000) Subject: Add the "--uri" option to utility program "showdb". This option causes showdb to... X-Git-Tag: version-3.9.0~240^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=871f6e34f6ecc3e03e8e2f18a721c9d8e4e2fefb;p=thirdparty%2Fsqlite.git Add the "--uri" option to utility program "showdb". This option causes showdb to use sqlite with the SQLITE_OPEN_URI option to open the database file, instead of opening it directly using the OS open() function. FossilOrigin-Name: 90e34d5119f720496e86a3a6de7771ea87b7dcbb --- diff --git a/manifest b/manifest index b1755902f2..a955e956d3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sa\sVIEW\sto\sreference\sundefined\stables\sand\sfunctions\swhen\sinitially\ncreated.\s\sThe\serror\sreport\sis\sdeferred\suntil\sthe\sVIEW\sis\sused.\s\sThis\sallows\nviews\sto\sbe\screated\sbefore\ssubviews\sand\stables\sthat\sthe\sview\sreferences. -D 2015-08-03T13:44:45.941 +C Add\sthe\s"--uri"\soption\sto\sutility\sprogram\s"showdb".\sThis\soption\scauses\sshowdb\sto\suse\ssqlite\swith\sthe\sSQLITE_OPEN_URI\soption\sto\sopen\sthe\sdatabase\sfile,\sinstead\sof\sopening\sit\sdirectly\susing\sthe\sOS\sopen()\sfunction. +D 2015-08-03T17:03:31.462 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 4de3ef40c8b3b75c0c55ff4242a43c8ce1ad90ee F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1343,7 +1343,7 @@ F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5 -F tool/showdb.c 3b5d335d537e4dc44d0c86967023819453c87dc6 +F tool/showdb.c 8b65966a80f30b95d3dcd9d7c13caaeb4dc21473 F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5 F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68 F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a @@ -1368,7 +1368,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3419044967258e3ed65f71528e06952ee102dcc7 -R a7ce110cce77b8da537a48fa80ac6f4f -U drh -Z 0cbd7829b00ada6a24c23b51a4093668 +P 70b57dafb3216feb21091883196831fa1252e7bf +R 16122b1df3219db3f18abec519d4455c +T *branch * showdb-uri-option +T *sym-showdb-uri-option * +T -sym-trunk * +U dan +Z 0bf8c605dcc175d4e077bbfb11ad015a diff --git a/manifest.uuid b/manifest.uuid index d5b4bd14a8..7c6c134c80 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -70b57dafb3216feb21091883196831fa1252e7bf \ No newline at end of file +90e34d5119f720496e86a3a6de7771ea87b7dcbb \ No newline at end of file diff --git a/tool/showdb.c b/tool/showdb.c index c90f410d95..8f5f533293 100644 --- a/tool/showdb.c +++ b/tool/showdb.c @@ -15,13 +15,21 @@ #include #include +#include #include "sqlite3.h" -static int pagesize = 1024; /* Size of a database page */ -static int db = -1; /* File descriptor for reading the DB */ -static int mxPage = 0; /* Last page number */ -static int perLine = 16; /* HEX elements to print per line */ +static struct GlobalData { + int pagesize; /* Size of a database page */ + int dbfd; /* File descriptor for reading the DB */ + int mxPage; /* Last page number */ + int perLine; /* HEX elements to print per line */ + + int bUri; /* True for URI mode */ + sqlite3_file *pFd; /* File descriptor for URI mode */ + sqlite3 *pDb; /* Database handle that owns pFd */ +} g = {1024, -1, 0, 16, 0, 0, 0}; + typedef long long int i64; /* Datatype for 64-bit integers */ @@ -56,24 +64,122 @@ static void out_of_memory(void){ exit(1); } +/* +** Open a database connection. +*/ +static sqlite3 *openDatabase(const char *zPrg, const char *zName){ + sqlite3 *db = 0; + int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI; + int rc = sqlite3_open_v2(zName, &db, flags, 0); + if( rc!=SQLITE_OK ){ + const char *zErr = sqlite3_errmsg(db); + fprintf(stderr, "%s: can't open %s (%s)\n", zPrg, zName, zErr); + sqlite3_close(db); + exit(1); + } + return db; +} + +/************************************************************************** +** Beginning of low-level file access functions. +** +** All low-level access to the database file read by this program is +** performed using the following four functions: +** +** fileOpen() - open the db file +** fileClose() - close the db file +** fileRead() - read raw data from the db file +** fileGetsize() - return the size of the db file in bytes +*/ + +/* +** Open the database file. +*/ +static void fileOpen(const char *zPrg, const char *zName){ + assert( g.dbfd<0 ); + if( g.bUri ){ + int rc; + void *pArg = (void *)(&g.pFd); + g.pDb = openDatabase(zPrg, zName); + rc = sqlite3_file_control(g.pDb, "main", SQLITE_FCNTL_FILE_POINTER, pArg); + if( rc!=SQLITE_OK ){ + fprintf(stderr, + "%s: failed to obtain fd for %s (SQLite too old?)\n", zPrg, zName + ); + exit(1); + } + }else{ + g.dbfd = open(zName, O_RDONLY); + if( g.dbfd<0 ){ + fprintf(stderr,"%s: can't open %s\n", zPrg, zName); + exit(1); + } + } +} + +/* +** Close the database file opened by fileOpen() +*/ +static void fileClose(){ + if( g.bUri ){ + sqlite3_close(g.pDb); + g.pDb = 0; + g.pFd = 0; + }else{ + close(g.dbfd); + g.dbfd = -1; + } +} + /* ** Read content from the file. ** -** Space to hold the content is obtained from malloc() and needs to be -** freed by the caller. +** Space to hold the content is obtained from sqlite3_malloc() and needs +** to be freed by the caller. */ -static unsigned char *getContent(int ofst, int nByte){ +static unsigned char *fileRead(sqlite3_int64 ofst, int nByte){ unsigned char *aData; int got; - aData = malloc(nByte+32); + aData = sqlite3_malloc(nByte+32); if( aData==0 ) out_of_memory(); memset(aData, 0, nByte+32); - lseek(db, ofst, SEEK_SET); - got = read(db, aData, nByte); - if( got>0 && gotpMethods->xRead(g.pFd, (void*)aData, nByte, ofst); + if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ + fprintf(stderr, "error in xRead() - %d\n", rc); + exit(1); + } + }else{ + lseek(g.dbfd, ofst, SEEK_SET); + got = read(g.dbfd, aData, nByte); + if( got>0 && gotpMethods->xFileSize(g.pFd, &res); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "error in xFileSize() - %d\n", rc); + exit(1); + } + }else{ + struct stat sbuf; + fstat(g.dbfd, &sbuf); + res = (sqlite3_int64)(sbuf.st_size); + } + return res; +} + +/* +** End of low-level file access functions. +**************************************************************************/ + /* ** Print a range of bytes as hex and as ascii. */ @@ -98,17 +204,17 @@ static unsigned char *print_byte_range( zOfstFmt = " %08x: "; } - aData = getContent(ofst, nByte); - for(i=0; inByte ){ fprintf(stdout, " "); }else{ fprintf(stdout,"%02x ", aData[i+j]); } } - for(j=0; jnByte ){ fprintf(stdout, " "); }else{ @@ -126,11 +232,11 @@ static unsigned char *print_byte_range( static void print_page(int iPg){ int iStart; unsigned char *aData; - iStart = (iPg-1)*pagesize; + iStart = (iPg-1)*g.pagesize; fprintf(stdout, "Page %d: (offsets 0x%x..0x%x)\n", - iPg, iStart, iStart+pagesize-1); - aData = print_byte_range(iStart, pagesize, 0); - free(aData); + iPg, iStart, iStart+g.pagesize-1); + aData = print_byte_range(iStart, g.pagesize, 0); + sqlite3_free(aData); } @@ -267,14 +373,14 @@ static i64 localPayload(i64 nPayload, char cType){ i64 nLocal; if( cType==13 ){ /* Table leaf */ - maxLocal = pagesize-35; - minLocal = (pagesize-12)*32/255-23; + maxLocal = g.pagesize-35; + minLocal = (g.pagesize-12)*32/255-23; }else{ - maxLocal = (pagesize-12)*64/255-23; - minLocal = (pagesize-12)*32/255-23; + maxLocal = (g.pagesize-12)*64/255-23; + minLocal = (g.pagesize-12)*32/255-23; } if( nPayload>maxLocal ){ - surplus = minLocal + (nPayload-minLocal)%(pagesize-4); + surplus = minLocal + (nPayload-minLocal)%(g.pagesize-4); if( surplus<=maxLocal ){ nLocal = surplus; }else{ @@ -581,8 +687,8 @@ static void decode_btree_page( printf(" key: lx=left-child n=payload-size r=rowid\n"); } if( showMap ){ - zMap = malloc(pagesize); - memset(zMap, '.', pagesize); + zMap = sqlite3_malloc(g.pagesize); + memset(zMap, '.', g.pagesize); memset(zMap, '1', hdrSize); memset(&zMap[hdrSize], 'H', iCellPtr); memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell); @@ -611,10 +717,10 @@ static void decode_btree_page( } if( showMap ){ printf("Page map: (H=header P=cell-index 1=page-1-header .=free-space)\n"); - for(i=0; i0 ){ - a = getContent((pgno-1)*pagesize, pagesize); + a = fileRead((pgno-1)*g.pagesize, g.pagesize); printf("Decode of freelist trunk page %d:\n", pgno); print_decode_line(a, 0, 4, "Next freelist trunk page"); print_decode_line(a, 4, 4, "Number of entries on this page"); @@ -650,7 +755,7 @@ static void decode_trunk_page( }else{ pgno = (int)decodeInt32(&a[0]); } - free(a); + sqlite3_free(a); } } @@ -669,9 +774,9 @@ static void page_usage_msg(int pgno, const char *zFormat, ...){ va_start(ap, zFormat); zMsg = sqlite3_vmprintf(zFormat, ap); va_end(ap); - if( pgno<=0 || pgno>mxPage ){ + if( pgno<=0 || pgno>g.mxPage ){ printf("ERROR: page %d out of range 1..%d: %s\n", - pgno, mxPage, zMsg); + pgno, g.mxPage, zMsg); sqlite3_free(zMsg); return; } @@ -719,12 +824,12 @@ static void page_usage_cell( if( nLocalmxPage ) return; - a = getContent((pgno-1)*pagesize, pagesize); + if( pgno<=0 || pgno>g.mxPage ) return; + a = fileRead((pgno-1)*g.pagesize, g.pagesize); switch( a[hdr] ){ case 2: zType = "interior node of index"; break; case 5: zType = "interior node of table"; break; @@ -783,7 +888,7 @@ static void page_usage_btree( page_usage_cell(a[hdr], a+ofst, pgno, i); } } - free(a); + sqlite3_free(a); } /* @@ -797,9 +902,9 @@ static void page_usage_freelist(int pgno){ int iNext; int parent = 1; - while( pgno>0 && pgno<=mxPage && (cnt++)0 && pgno<=g.mxPage && (cnt++)1 ){ + if( sqlite3_stricmp("-uri", azArg[1])==0 + || sqlite3_stricmp("--uri", azArg[1])==0 + ){ + g.bUri = 1; + azArg++; + nArg--; + } } - db = open(argv[1], O_RDONLY); - if( db<0 ){ - fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]); + + if( nArg<2 ){ + usage(zPrg); exit(1); } - zPgSz[0] = 0; - zPgSz[1] = 0; - lseek(db, 16, SEEK_SET); - if( read(db, zPgSz, 2)<2 ) memset(zPgSz, 0, 2); - pagesize = zPgSz[0]*256 + zPgSz[1]*65536; - if( pagesize==0 ) pagesize = 1024; - printf("Pagesize: %d\n", pagesize); - fstat(db, &sbuf); - mxPage = (sbuf.st_size+pagesize-1)/pagesize; - printf("Available pages: 1..%d\n", mxPage); - if( argc==2 ){ + + fileOpen(azArg[0], azArg[1]); + szFile = fileGetsize(); + + zPgSz = fileRead(16, 2); + g.pagesize = zPgSz[0]*256 + zPgSz[1]*65536; + if( g.pagesize==0 ) g.pagesize = 1024; + sqlite3_free(zPgSz); + + printf("Pagesize: %d\n", g.pagesize); + g.mxPage = (szFile+g.pagesize-1)/g.pagesize; + + printf("Available pages: 1..%d\n", g.mxPage); + if( nArg==2 ){ int i; - for(i=1; i<=mxPage; i++) print_page(i); + for(i=1; i<=g.mxPage; i++) print_page(i); }else{ int i; - for(i=2; imxPage ){ + if( iStart<1 || iEndg.mxPage ){ fprintf(stderr, "Page argument should be LOWER?..UPPER?. Range 1 to %d\n", - mxPage); + g.mxPage); exit(1); } while( iStart<=iEnd ){ @@ -1058,6 +1173,6 @@ int main(int argc, char **argv){ } } } - close(db); + fileClose(); return 0; }