1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Merge latest begin-concurrent changes into this branch.

FossilOrigin-Name: a93ca38b432e0c9fb2e00499cfc88d09f59f27f908f377d8ae99b6717e548a60
This commit is contained in:
dan
2018-12-18 17:47:53 +00:00
51 changed files with 1581 additions and 536 deletions

140
tool/dbtotxt.c Normal file
View File

@@ -0,0 +1,140 @@
/*
** Copyright 2008 D. Richard Hipp and Hipp, Wyrick & Company, Inc.
** All Rights Reserved
**
******************************************************************************
**
** This file implements a stand-alone utility program that converts
** a binary file (usually an SQLite database) into a text format that
** is compact and friendly to human-readers.
**
** Usage:
**
** dbtotxt [--pagesize N] FILENAME
**
** The translation of the database appears on standard output. If the
** --pagesize command-line option is omitted, then the page size is taken
** from the database header.
**
** Compactness is achieved by suppressing lines of all zero bytes. This
** works well at compressing test databases that are mostly empty. But
** the output will probably be lengthy for a real database containing lots
** of real content. For maximum compactness, it is suggested that test
** databases be constructed with "zeroblob()" rather than "randomblob()"
** used for filler content and with "PRAGMA secure_delete=ON" selected to
** zero-out deleted content.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Return true if the line is all zeros */
static int allZero(unsigned char *aLine){
int i;
for(i=0; i<16 && aLine[i]==0; i++){}
return i==16;
}
int main(int argc, char **argv){
int pgsz = 0; /* page size */
long szFile; /* Size of the input file in bytes */
FILE *in; /* Input file */
int i, j; /* Loop counters */
int nErr = 0; /* Number of errors */
const char *zInputFile = 0; /* Name of the input file */
const char *zBaseName = 0; /* Base name of the file */
int lastPage = 0; /* Last page number shown */
int iPage; /* Current page number */
unsigned char aLine[16]; /* A single line of the file */
unsigned char aHdr[100]; /* File header */
for(i=1; i<argc; i++){
if( argv[i][0]=='-' ){
const char *z = argv[i];
z++;
if( z[0]=='-' ) z++;
if( strcmp(z,"pagesize")==0 ){
i++;
pgsz = atoi(argv[i]);
if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
fprintf(stderr, "Page size must be a power of two between"
" 512 and 65536.\n");
nErr++;
}
continue;
}
fprintf(stderr, "Unknown option: %s\n", argv[i]);
nErr++;
}else if( zInputFile ){
fprintf(stderr, "Already using a different input file: [%s]\n", argv[i]);
nErr++;
}else{
zInputFile = argv[i];
}
}
if( zInputFile==0 ){
fprintf(stderr, "No input file specified.\n");
nErr++;
}
if( nErr ){
fprintf(stderr, "Usage: %s [--pagesize N] FILENAME\n", argv[0]);
exit(1);
}
in = fopen(zInputFile, "rb");
if( in==0 ){
fprintf(stderr, "Cannot open input file [%s]\n", zInputFile);
exit(1);
}
fseek(in, 0, SEEK_END);
szFile = ftell(in);
rewind(in);
if( szFile<512 ){
fprintf(stderr, "File too short. Minimum size is 512 bytes.\n");
exit(1);
}
if( fread(aHdr, 100, 1, in)!=1 ){
fprintf(stderr, "Cannot read file header\n");
exit(1);
}
rewind(in);
if( pgsz==0 ){
pgsz = (aHdr[16]<<8) | aHdr[17];
if( pgsz==1 ) pgsz = 65536;
if( pgsz<512 || (pgsz&(pgsz-1))!=0 ){
fprintf(stderr, "Invalid page size in header: %d\n", pgsz);
exit(1);
}
}
zBaseName = zInputFile;
for(i=0; zInputFile[i]; i++){
if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+1;
}
printf("| size %d pagesize %d filename %s\n",(int)szFile,pgsz,zBaseName);
for(i=0; i<szFile; i+=16){
int got = (int)fread(aLine, 1, 16, in);
if( got!=16 ){
static int once = 1;
if( once ){
fprintf(stderr, "Could not read input file starting at byte %d\n",
i+got);
}
memset(aLine+got, 0, 16-got);
}
if( allZero(aLine) ) continue;
iPage = i/pgsz + 1;
if( lastPage!=iPage ){
printf("| page %d offset %d\n", iPage, (iPage-1)*pgsz);
lastPage = iPage;
}
printf("| %5d:", i-(iPage-1)*pgsz);
for(j=0; j<16; j++) printf(" %02x", aLine[j]);
printf(" ");
for(j=0; j<16; j++){
char c = aLine[j];
fputc(c>=0x20 && c<=0x7e ? c : '.', stdout);
}
fputc('\n', stdout);
}
fclose(in);
printf("| end %s\n", zBaseName);
return 0;
}

56
tool/dbtotxt.md Normal file
View File

@@ -0,0 +1,56 @@
<h1 align="center">The dbtotxt Tool</h1>
The dbtotxt utility program reads an SQLite database file and writes its
raw binary content to screen as a hex dump for testing and debugging
purposes.
The hex-dump output is formatted in such a way as to be easily readable
both by humans and by software. The dbtotxt utility has long been a part
of the TH3 test suite. The output of dbtotxt can be embedded in TH3 test
scripts and used to generate very specific database files, perhaps with
deliberately introduced corruption. The cov1/corrupt*.test modules in
TH3 make extensive use of dbtotxt.
More recently (2018-12-13) the dbtotxt utility has been added to the SQLite
core and the command-line shell (CLI) has been augmented to be able to read
dbtotxt output. The CLI dot-command is:
> .open --hexdb ?OPTIONAL-FILENAME?
If the OPTIONAL-FILENAME is included, then content is read from that file.
If OPTIONAL-FILENAME is omitted, then the text is taken from the input stream,
terminated by the "| end" line of the dbtotxt text. This allows small test
databases to be embedded directly in scripts. Consider this example:
>
.open --hexdb
| size 8192 pagesize 4096 filename x9.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 04 00 00 00 02 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................
| 96: 00 2e 30 38 0d 00 00 00 01 0f c0 00 0f c0 00 00 ..08............
| 4032: 3e 01 06 17 11 11 01 69 74 61 62 6c 65 74 31 74 >......itablet1t
| 4048: 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 1.CREATE TABLE t
| 4064: 31 28 78 2c 79 20 44 45 46 41 55 4c 54 20 78 27 1(x,y DEFAULT x'
| 4080: 66 66 27 2c 7a 20 44 45 46 41 55 4c 54 20 30 29 ff',z DEFAULT 0)
| page 2 offset 4096
| 0: 0d 08 14 00 04 00 10 00 0e 05 0a 0f 04 15 00 10 ................
| 16: 88 02 03 05 90 04 0e 08 00 00 00 00 00 00 00 00 ................
| 1040: 00 00 00 00 ff 87 7c 02 05 8f 78 0e 08 00 00 00 ......|...x.....
| 2064: 00 00 00 ff 0c 0a 01 fb 00 00 00 00 00 00 00 00 ................
| 2560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 83 ................
| 2576: 78 01 05 87 70 0e 08 00 00 00 00 00 00 00 00 00 x...p...........
| 3072: 00 00 00 00 00 00 00 00 00 ff 00 00 01 fb 00 00 ................
| 3584: 00 00 00 00 00 83 78 00 05 87 70 0e 08 00 00 00 ......x...p.....
| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ................
| end x9.db
SELECT rowid FROM t1;
PRAGMA integrity_check;
You can run this script to see that the database file is correctly decoded
and loaded. Furthermore, you can make subtle corruptions to the input
database simply by editing the hexadecimal description, then rerun the
script to verify that SQLite correctly handles the corruption.