?? cryptshell.c
字號:
}else{
zSelect = appendText(zSelect, ") ", 0);
}
}
rc = sqlite3_finalize(pTableInfo);
if( rc!=SQLITE_OK ){
if( zSelect ) free(zSelect);
return 1;
}
zSelect = appendText(zSelect, "|| ')' FROM ", 0);
zSelect = appendText(zSelect, zTable, '"');
rc = run_table_dump_query(p->out, p->db, zSelect);
if( rc==SQLITE_CORRUPT ){
zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
rc = run_table_dump_query(p->out, p->db, zSelect);
}
if( zSelect ) free(zSelect);
}
return 0;
}
/*
** Run zQuery. Use dump_callback() as the callback routine so that
** the contents of the query are output as SQL statements.
**
** If we get a SQLITE_CORRUPT error, rerun the query after appending
** "ORDER BY rowid DESC" to the end.
*/
static int run_schema_dump_query(
struct callback_data *p,
const char *zQuery,
char **pzErrMsg
){
int rc;
rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
if( rc==SQLITE_CORRUPT ){
char *zQ2;
int len = strlen(zQuery);
if( pzErrMsg ) sqlite3_free(*pzErrMsg);
zQ2 = malloc( len+100 );
if( zQ2==0 ) return rc;
sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery);
rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
free(zQ2);
}
return rc;
}
/*
** Text of a help message
*/
static char zHelp[] =
".bail ON|OFF Stop after hitting an error. Default OFF\n"
".databases List names and files of attached databases\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
".echo ON|OFF Turn command echo on or off\n"
".exit Exit this program\n"
".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
".header(s) ON|OFF Turn display of headers on or off\n"
".help Show this message\n"
".import FILE TABLE Import data from FILE into TABLE\n"
".indices TABLE Show names of all indices on TABLE\n"
#ifdef SQLITE_ENABLE_IOTRACE
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
#endif
".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
" csv Comma-separated values\n"
" column Left-aligned columns. (See .width)\n"
" html HTML <table> code\n"
" insert SQL insert statements for TABLE\n"
" line One value per line\n"
" list Values delimited by .separator string\n"
" tabs Tab-separated values\n"
" tcl TCL list elements\n"
".nullvalue STRING Print STRING in place of NULL values\n"
".output FILENAME Send output to FILENAME\n"
".output stdout Send output to the screen\n"
".prompt MAIN CONTINUE Replace the standard prompts\n"
".quit Exit this program\n"
".read FILENAME Execute SQL in FILENAME\n"
#ifdef SQLITE_HAS_CODEC
".rekey OLD NEW NEW Change the encryption key\n"
#endif
".schema ?TABLE? Show the CREATE statements\n"
".separator STRING Change separator used by output mode and .import\n"
".show Show the current values for various settings\n"
".tables ?PATTERN? List names of tables matching a LIKE pattern\n"
".timeout MS Try opening locked tables for MS milliseconds\n"
#if HAS_TIMER
".timer ON|OFF Turn the CPU timer measurement on or off\n"
#endif
".width NUM NUM ... Set column widths for \"column\" mode\n"
;
/* Forward reference */
static int process_input(struct callback_data *p, FILE *in);
/*
** Make sure the database is open. If it is not, then open it. If
** the database fails to open, print an error message and exit.
*/
static void open_db(struct callback_data *p){
if( p->db==0 ){
sqlite3_open(p->zDbFilename, &p->db);
db = p->db;
#ifdef SQLITE_HAS_CODEC
sqlite3_key(p->db, p->zKey, p->zKey ? strlen(p->zKey) : 0);
#endif
if( db && sqlite3_errcode(db)==SQLITE_OK ){
sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
shellstaticFunc, 0, 0);
}
if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
fprintf(stderr,"Unable to open database \"%s\": %s\n",
p->zDbFilename, sqlite3_errmsg(db));
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
}
}
/*
** Do C-language style dequoting.
**
** \t -> tab
** \n -> newline
** \r -> carriage return
** \NNN -> ascii character NNN in octal
** \\ -> backslash
*/
static void resolve_backslashes(char *z){
int i, j, c;
for(i=j=0; (c = z[i])!=0; i++, j++){
if( c=='\\' ){
c = z[++i];
if( c=='n' ){
c = '\n';
}else if( c=='t' ){
c = '\t';
}else if( c=='r' ){
c = '\r';
}else if( c>='0' && c<='7' ){
c -= '0';
if( z[i+1]>='0' && z[i+1]<='7' ){
i++;
c = (c<<3) + z[i] - '0';
if( z[i+1]>='0' && z[i+1]<='7' ){
i++;
c = (c<<3) + z[i] - '0';
}
}
}
}
z[j] = c;
}
z[j] = 0;
}
/*
** Interpret zArg as a boolean value. Return either 0 or 1.
*/
static int booleanValue(char *zArg){
int val = atoi(zArg);
int j;
for(j=0; zArg[j]; j++){
zArg[j] = tolower(zArg[j]);
}
if( strcmp(zArg,"on")==0 ){
val = 1;
}else if( strcmp(zArg,"yes")==0 ){
val = 1;
}
return val;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, struct callback_data *p){
int i = 1;
int nArg = 0;
int n, c;
int rc = 0;
char *azArg[50];
/* Parse the input line into tokens.
*/
while( zLine[i] && nArg<ArraySize(azArg) ){
while( isspace((unsigned char)zLine[i]) ){ i++; }
if( zLine[i]==0 ) break;
if( zLine[i]=='\'' || zLine[i]=='"' ){
int delim = zLine[i++];
azArg[nArg++] = &zLine[i];
while( zLine[i] && zLine[i]!=delim ){ i++; }
if( zLine[i]==delim ){
zLine[i++] = 0;
}
if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
}else{
azArg[nArg++] = &zLine[i];
while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; }
if( zLine[i] ) zLine[i++] = 0;
resolve_backslashes(azArg[nArg-1]);
}
}
/* Process the input line.
*/
if( nArg==0 ) return rc;
n = strlen(azArg[0]);
c = azArg[0][0];
if( c=='b' && n>1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
bail_on_error = booleanValue(azArg[1]);
}else
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
struct callback_data data;
char *zErrMsg = 0;
open_db(p);
memcpy(&data, p, sizeof(data));
data.showHeader = 1;
data.mode = MODE_Column;
data.colWidth[0] = 3;
data.colWidth[1] = 15;
data.colWidth[2] = 58;
data.cnt = 0;
sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
if( zErrMsg ){
fprintf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
}else
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
char *zErrMsg = 0;
open_db(p);
fprintf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 0;
sqlite3_exec(p->db, "PRAGMA writable_schema=ON", 0, 0, 0);
if( nArg==1 ){
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type=='table'", 0
);
run_table_dump_query(p->out, p->db,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL AND type IN ('index','trigger','view')"
);
}else{
int i;
for(i=1; i<nArg; i++){
zShellStatic = azArg[i];
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE tbl_name LIKE shellstatic() AND type=='table'"
" AND sql NOT NULL", 0);
run_table_dump_query(p->out, p->db,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL"
" AND type IN ('index','trigger','view')"
" AND tbl_name LIKE shellstatic()"
);
zShellStatic = 0;
}
}
if( p->writableSchema ){
fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
p->writableSchema = 0;
}
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF", 0, 0, 0);
if( zErrMsg ){
fprintf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(p->out, "COMMIT;\n");
}
}else
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
p->echoOn = booleanValue(azArg[1]);
}else
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
rc = 2;
}else
if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
if(val == 1) {
if(!p->explainPrev.valid) {
p->explainPrev.valid = 1;
p->explainPrev.mode = p->mode;
p->explainPrev.showHeader = p->showHeader;
memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
}
/* We could put this code under the !p->explainValid
** condition so that it does not execute if we are already in
** explain mode. However, always executing it allows us an easy
** was to reset to explain mode in case the user previously
** did an .explain followed by a .width, .mode or .header
** command.
*/
p->mode = MODE_Explain;
p->showHeader = 1;
memset(p->colWidth,0,ArraySize(p->colWidth));
p->colWidth[0] = 4; /* addr */
p->colWidth[1] = 13; /* opcode */
p->colWidth[2] = 4; /* P1 */
p->colWidth[3] = 4; /* P2 */
p->colWidth[4] = 4; /* P3 */
p->colWidth[5] = 13; /* P4 */
p->colWidth[6] = 2; /* P5 */
p->colWidth[7] = 13; /* Comment */
}else if (p->explainPrev.valid) {
p->explainPrev.valid = 0;
p->mode = p->explainPrev.mode;
p->showHeader = p->explainPrev.showHeader;
memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
}
}else
if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
p->showHeader = booleanValue(azArg[1]);
}else
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
fprintf(stderr,zHelp);
}else
if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
char *zTable = azArg[2]; /* Insert data into this table */
char *zFile = azArg[1]; /* The file from which to extract data */
sqlite3_stmt *pStmt; /* A statement */
int rc; /* Result code */
int nCol; /* Number of columns in the table */
int nByte; /* Number of bytes in an SQL string */
int i, j; /* Loop counters */
int nSep; /* Number of bytes in p->separator[] */
char *zSql; /* An SQL statement */
char *zLine; /* A single line of input from the file */
char **azCol; /* zLine[] broken up into columns */
char *zCommit; /* How to commit changes */
FILE *in; /* The input file */
int lineno = 0; /* Line number of input file */
open_db(p);
nSep = strlen(p->separator);
if( nSep==0 ){
fprintf(stderr, "non-null separator required for import\n");
return 0;
}
zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
if( zSql==0 ) return 0;
nByte = strlen(zSql);
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
nCol = 0;
rc = 1;
}else{
nCol = sqlite3_column_count(pStmt);
}
sqlite3_finalize(pStmt);
if( nCol==0 ) return 0;
zSql = malloc( nByte + 20 + nCol*2 );
if( zSql==0 ) return 0;
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
j = strlen(zSql);
for(i=1; i<nCol; i++){
zSql[j++] = ',';
zSql[j++] = '?';
}
zSql[j++] = ')';
zSql[j] = 0;
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
free(zSql);
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
return 1;
}
in = fopen(zFile, "rb");
if( in==0 ){
fprintf(stderr, "cannot open file: %s\n", zFile);
sqlite3_finalize(pStmt);
return 0;
}
azCol = malloc( sizeof(azCol[0])*(nCol+1) );
if( azCol==0 ){
fclose(in);
return 0;
}
sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
zCommit = "COMMIT";
while( (zLine = local_getline(0, in))!=0 ){
char *z;
i = 0;
lineno++;
azCol[0] = zLine;
for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){
if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){
*z = 0;
i++;
if( i<nCol ){
azCol[i] = &z[nSep];
z += nSep-1;
}
}
}
*z = 0;
if( i+1!=nCol ){
fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n",
zFile, lineno, nCol, i+1);
zCommit = "ROLLBACK";
break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -