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
This commit is contained in:
@@ -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
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
70b57dafb3216feb21091883196831fa1252e7bf
|
||||
90e34d5119f720496e86a3a6de7771ea87b7dcbb
|
||||
+224
-109
@@ -15,13 +15,21 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#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 && got<nByte ) memset(aData+got, 0, nByte-got);
|
||||
if( g.bUri ){
|
||||
int rc = g.pFd->pMethods->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 && got<nByte ) memset(aData+got, 0, nByte-got);
|
||||
}
|
||||
return aData;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size of the file in byte.
|
||||
*/
|
||||
static sqlite3_int64 fileGetsize(void){
|
||||
sqlite3_int64 res = 0;
|
||||
if( g.bUri ){
|
||||
int rc = g.pFd->pMethods->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; i<nByte; i += perLine){
|
||||
aData = fileRead(ofst, nByte);
|
||||
for(i=0; i<nByte; i += g.perLine){
|
||||
fprintf(stdout, zOfstFmt, i+printOfst);
|
||||
for(j=0; j<perLine; j++){
|
||||
for(j=0; j<g.perLine; j++){
|
||||
if( i+j>nByte ){
|
||||
fprintf(stdout, " ");
|
||||
}else{
|
||||
fprintf(stdout,"%02x ", aData[i+j]);
|
||||
}
|
||||
}
|
||||
for(j=0; j<perLine; j++){
|
||||
for(j=0; j<g.perLine; j++){
|
||||
if( i+j>nByte ){
|
||||
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; i<pagesize; i+=64){
|
||||
for(i=0; i<g.pagesize; i+=64){
|
||||
printf(" %03x: %.64s\n", i, &zMap[i]);
|
||||
}
|
||||
free(zMap);
|
||||
sqlite3_free(zMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,14 +729,13 @@ static void decode_btree_page(
|
||||
*/
|
||||
static void decode_trunk_page(
|
||||
int pgno, /* The page number */
|
||||
int pagesize, /* Size of each page */
|
||||
int detail, /* Show leaf pages if true */
|
||||
int recursive /* Follow the trunk change if true */
|
||||
){
|
||||
int n, i;
|
||||
unsigned char *a;
|
||||
while( pgno>0 ){
|
||||
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( nLocal<nPayload ){
|
||||
int ovfl = decodeInt32(a+nLocal);
|
||||
int cnt = 0;
|
||||
while( ovfl && (cnt++)<mxPage ){
|
||||
while( ovfl && (cnt++)<g.mxPage ){
|
||||
page_usage_msg(ovfl, "overflow %d from cell %d of page %d",
|
||||
cnt, cellno, pgno);
|
||||
a = getContent((ovfl-1)*pagesize, 4);
|
||||
a = fileRead((ovfl-1)*g.pagesize, 4);
|
||||
ovfl = decodeInt32(a);
|
||||
free(a);
|
||||
sqlite3_free(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -745,8 +850,8 @@ static void page_usage_btree(
|
||||
int i;
|
||||
int hdr = pgno==1 ? 100 : 0;
|
||||
|
||||
if( pgno<=0 || pgno>mxPage ) 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++)<mxPage ){
|
||||
while( pgno>0 && pgno<=g.mxPage && (cnt++)<g.mxPage ){
|
||||
page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent);
|
||||
a = getContent((pgno-1)*pagesize, pagesize);
|
||||
a = fileRead((pgno-1)*g.pagesize, g.pagesize);
|
||||
iNext = decodeInt32(a);
|
||||
n = decodeInt32(a+4);
|
||||
for(i=0; i<n; i++){
|
||||
@@ -807,7 +912,7 @@ static void page_usage_freelist(int pgno){
|
||||
page_usage_msg(child, "freelist leaf, child %d of trunk page %d",
|
||||
i, pgno);
|
||||
}
|
||||
free(a);
|
||||
sqlite3_free(a);
|
||||
parent = pgno;
|
||||
pgno = iNext;
|
||||
}
|
||||
@@ -818,10 +923,10 @@ static void page_usage_freelist(int pgno){
|
||||
*/
|
||||
static void page_usage_ptrmap(unsigned char *a){
|
||||
if( a[55] ){
|
||||
int usable = pagesize - a[20];
|
||||
int usable = g.pagesize - a[20];
|
||||
int pgno = 2;
|
||||
int perPage = usable/5;
|
||||
while( pgno<=mxPage ){
|
||||
while( pgno<=g.mxPage ){
|
||||
page_usage_msg(pgno, "PTRMAP page covering %d..%d",
|
||||
pgno+1, pgno+perPage);
|
||||
pgno += perPage + 1;
|
||||
@@ -832,7 +937,7 @@ static void page_usage_ptrmap(unsigned char *a){
|
||||
/*
|
||||
** Try to figure out how every page in the database file is being used.
|
||||
*/
|
||||
static void page_usage_report(const char *zDbName){
|
||||
static void page_usage_report(const char *zPrg, const char *zDbName){
|
||||
int i, j;
|
||||
int rc;
|
||||
sqlite3 *db;
|
||||
@@ -841,30 +946,25 @@ static void page_usage_report(const char *zDbName){
|
||||
char zQuery[200];
|
||||
|
||||
/* Avoid the pathological case */
|
||||
if( mxPage<1 ){
|
||||
if( g.mxPage<1 ){
|
||||
printf("empty database\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Open the database file */
|
||||
rc = sqlite3_open(zDbName, &db);
|
||||
if( rc ){
|
||||
printf("cannot open database: %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
db = openDatabase(zPrg, zDbName);
|
||||
|
||||
/* Set up global variables zPageUse[] and mxPage to record page
|
||||
/* Set up global variables zPageUse[] and g.mxPage to record page
|
||||
** usages */
|
||||
zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(mxPage+1) );
|
||||
zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(g.mxPage+1) );
|
||||
if( zPageUse==0 ) out_of_memory();
|
||||
memset(zPageUse, 0, sizeof(zPageUse[0])*(mxPage+1));
|
||||
memset(zPageUse, 0, sizeof(zPageUse[0])*(g.mxPage+1));
|
||||
|
||||
/* Discover the usage of each page */
|
||||
a = getContent(0, 100);
|
||||
a = fileRead(0, 100);
|
||||
page_usage_freelist(decodeInt32(a+32));
|
||||
page_usage_ptrmap(a);
|
||||
free(a);
|
||||
sqlite3_free(a);
|
||||
page_usage_btree(1, 0, 0, "sqlite_master");
|
||||
sqlite3_exec(db, "PRAGMA writable_schema=ON", 0, 0, 0);
|
||||
for(j=0; j<2; j++){
|
||||
@@ -886,7 +986,7 @@ static void page_usage_report(const char *zDbName){
|
||||
sqlite3_close(db);
|
||||
|
||||
/* Print the report and free memory used */
|
||||
for(i=1; i<=mxPage; i++){
|
||||
for(i=1; i<=g.mxPage; i++){
|
||||
printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???");
|
||||
sqlite3_free(zPageUse[i]);
|
||||
}
|
||||
@@ -906,26 +1006,26 @@ static void ptrmap_coverage_report(const char *zDbName){
|
||||
int i;
|
||||
|
||||
/* Avoid the pathological case */
|
||||
if( mxPage<1 ){
|
||||
if( g.mxPage<1 ){
|
||||
printf("empty database\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure PTRMAPs are used in this database */
|
||||
aHdr = getContent(0, 100);
|
||||
aHdr = fileRead(0, 100);
|
||||
if( aHdr[55]==0 ){
|
||||
printf("database does not use PTRMAP pages\n");
|
||||
return;
|
||||
}
|
||||
usable = pagesize - aHdr[20];
|
||||
usable = g.pagesize - aHdr[20];
|
||||
perPage = usable/5;
|
||||
free(aHdr);
|
||||
sqlite3_free(aHdr);
|
||||
printf("%5d: root of sqlite_master\n", 1);
|
||||
for(pgno=2; pgno<=mxPage; pgno += perPage+1){
|
||||
for(pgno=2; pgno<=g.mxPage; pgno += perPage+1){
|
||||
printf("%5d: PTRMAP page covering %d..%d\n", pgno,
|
||||
pgno+1, pgno+perPage);
|
||||
a = getContent((pgno-1)*pagesize, usable);
|
||||
for(i=0; i+5<=usable && pgno+1+i/5<=mxPage; i+=5){
|
||||
a = fileRead((pgno-1)*g.pagesize, usable);
|
||||
for(i=0; i+5<=usable && pgno+1+i/5<=g.mxPage; i+=5){
|
||||
const char *zType = "???";
|
||||
unsigned int iFrom = decodeInt32(&a[i+1]);
|
||||
switch( a[i] ){
|
||||
@@ -937,7 +1037,7 @@ static void ptrmap_coverage_report(const char *zDbName){
|
||||
}
|
||||
printf("%5d: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
|
||||
}
|
||||
free(a);
|
||||
sqlite3_free(a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,8 +1045,10 @@ static void ptrmap_coverage_report(const char *zDbName){
|
||||
** Print a usage comment
|
||||
*/
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr, "Usage %s FILENAME ?args...?\n\n", argv0);
|
||||
fprintf(stderr, "Usage %s ?--uri? FILENAME ?args...?\n\n", argv0);
|
||||
fprintf(stderr,
|
||||
"switches:\n"
|
||||
" --uri FILENAME is a URI\n"
|
||||
"args:\n"
|
||||
" dbheader Show database header\n"
|
||||
" pgidx Index of how each page is used\n"
|
||||
@@ -964,58 +1066,71 @@ static void usage(const char *argv0){
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
struct stat sbuf;
|
||||
unsigned char zPgSz[2];
|
||||
if( argc<2 ){
|
||||
usage(argv[0]);
|
||||
sqlite3_int64 szFile;
|
||||
unsigned char *zPgSz;
|
||||
const char *zPrg = argv[0]; /* Name of this executable */
|
||||
char **azArg = argv;
|
||||
int nArg = argc;
|
||||
|
||||
/* Check for the "--uri" or "-uri" switch. */
|
||||
if( nArg>1 ){
|
||||
if( sqlite3_stricmp("-uri", azArg[1])==0
|
||||
|| sqlite3_stricmp("--uri", azArg[1])==0
|
||||
){
|
||||
g.bUri = 1;
|
||||
azArg++;
|
||||
nArg--;
|
||||
}
|
||||
}
|
||||
|
||||
if( nArg<2 ){
|
||||
usage(zPrg);
|
||||
exit(1);
|
||||
}
|
||||
db = open(argv[1], O_RDONLY);
|
||||
if( db<0 ){
|
||||
fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
|
||||
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; i<argc; i++){
|
||||
for(i=2; i<nArg; i++){
|
||||
int iStart, iEnd;
|
||||
char *zLeft;
|
||||
if( strcmp(argv[i], "dbheader")==0 ){
|
||||
if( strcmp(azArg[i], "dbheader")==0 ){
|
||||
print_db_header();
|
||||
continue;
|
||||
}
|
||||
if( strcmp(argv[i], "pgidx")==0 ){
|
||||
page_usage_report(argv[1]);
|
||||
if( strcmp(azArg[i], "pgidx")==0 ){
|
||||
page_usage_report(zPrg, azArg[1]);
|
||||
continue;
|
||||
}
|
||||
if( strcmp(argv[i], "ptrmap")==0 ){
|
||||
ptrmap_coverage_report(argv[1]);
|
||||
if( strcmp(azArg[i], "ptrmap")==0 ){
|
||||
ptrmap_coverage_report(azArg[1]);
|
||||
continue;
|
||||
}
|
||||
if( strcmp(argv[i], "help")==0 ){
|
||||
usage(argv[0]);
|
||||
if( strcmp(azArg[i], "help")==0 ){
|
||||
usage(azArg[0]);
|
||||
continue;
|
||||
}
|
||||
if( !isdigit(argv[i][0]) ){
|
||||
fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
|
||||
if( !isdigit(azArg[i][0]) ){
|
||||
fprintf(stderr, "%s: unknown option: [%s]\n", azArg[0], azArg[i]);
|
||||
continue;
|
||||
}
|
||||
iStart = strtol(argv[i], &zLeft, 0);
|
||||
iStart = strtol(azArg[i], &zLeft, 0);
|
||||
if( zLeft && strcmp(zLeft,"..end")==0 ){
|
||||
iEnd = mxPage;
|
||||
iEnd = g.mxPage;
|
||||
}else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
|
||||
iEnd = strtol(&zLeft[2], 0, 0);
|
||||
}else if( zLeft && zLeft[0]=='b' ){
|
||||
@@ -1023,15 +1138,15 @@ int main(int argc, char **argv){
|
||||
unsigned char *a;
|
||||
if( iStart==1 ){
|
||||
ofst = hdrSize = 100;
|
||||
nByte = pagesize-100;
|
||||
nByte = g.pagesize-100;
|
||||
}else{
|
||||
hdrSize = 0;
|
||||
ofst = (iStart-1)*pagesize;
|
||||
nByte = pagesize;
|
||||
ofst = (iStart-1)*g.pagesize;
|
||||
nByte = g.pagesize;
|
||||
}
|
||||
a = getContent(ofst, nByte);
|
||||
a = fileRead(ofst, nByte);
|
||||
decode_btree_page(a, iStart, hdrSize, &zLeft[1]);
|
||||
free(a);
|
||||
sqlite3_free(a);
|
||||
continue;
|
||||
}else if( zLeft && zLeft[0]=='t' ){
|
||||
int detail = 0;
|
||||
@@ -1041,15 +1156,15 @@ int main(int argc, char **argv){
|
||||
if( zLeft[i]=='r' ) recursive = 1;
|
||||
if( zLeft[i]=='d' ) detail = 1;
|
||||
}
|
||||
decode_trunk_page(iStart, pagesize, detail, recursive);
|
||||
decode_trunk_page(iStart, detail, recursive);
|
||||
continue;
|
||||
}else{
|
||||
iEnd = iStart;
|
||||
}
|
||||
if( iStart<1 || iEnd<iStart || iEnd>mxPage ){
|
||||
if( iStart<1 || iEnd<iStart || iEnd>g.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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user