Updated SQLite to 3.3.13 - why? I have no idea

This commit is contained in:
Scott Ehlert
2007-03-21 20:19:37 +00:00
parent eaa4122c5a
commit a004e906dd
55 changed files with 9336 additions and 3963 deletions

View File

@ -21,7 +21,7 @@
#include "sqlite3.h"
#include <ctype.h>
#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
# include <signal.h>
# include <pwd.h>
# include <unistd.h>
@ -37,6 +37,10 @@
# include <Folders.h>
#endif
#ifdef __OS2__
# include <unistd.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include <readline/readline.h>
# include <readline/history.h>
@ -48,9 +52,25 @@
# define stifle_history(X)
#endif
#if defined(_WIN32) || defined(WIN32)
# include <io.h>
#else
/* Make sure isatty() has a prototype.
*/
extern int isatty();
#endif
/*
** If the following flag is set, then command execution stops
** at an error if we are not interactive.
*/
static int bail_on_error = 0;
/*
** Threat stdin as an interactive input if the following variable
** is true. Otherwise, assume stdin is connected to a file or pipe.
*/
static int stdin_is_interactive = 1;
/*
** The following is the open SQLite database. We make a pointer
@ -176,10 +196,7 @@ static char *local_getline(char *zPrompt, FILE *in){
}
/*
** Retrieve a single line of input text. "isatty" is true if text
** is coming from a terminal. In that case, we issue a prompt and
** attempt to use "readline" for command-line editing. If "isatty"
** is false, use "local_getline" instead of "readline" and issue no prompt.
** Retrieve a single line of input text.
**
** zPrior is a string of prior text retrieved. If not the empty
** string, then issue a continuation prompt.
@ -197,7 +214,7 @@ static char *one_input_line(const char *zPrior, FILE *in){
}
zResult = readline(zPrompt);
#if defined(HAVE_READLINE) && HAVE_READLINE==1
if( zResult ) add_history(zResult);
if( zResult && *zResult ) add_history(zResult);
#endif
return zResult;
}
@ -208,6 +225,7 @@ struct previous_mode_data {
int showHeader;
int colWidth[100];
};
/*
** An pointer to an instance of this structure is passed from
** the main program to the callback. This is used to communicate
@ -219,6 +237,7 @@ struct callback_data {
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
int mode; /* An output mode setting */
int writableSchema; /* True if PRAGMA writable_schema=ON */
int showHeader; /* True to show column names in List or Column mode */
char *zDestTable; /* Name of destination table when MODE_Insert */
char separator[20]; /* Separator character for MODE_List */
@ -231,7 +250,6 @@ struct callback_data {
** .explain ON */
char outfile[FILENAME_MAX]; /* Filename for *out */
const char *zDbFilename; /* name of the database file */
char *zKey; /* Encryption key */
};
/*
@ -343,6 +361,29 @@ static void output_html_string(FILE *out, const char *z){
}
}
/*
** If a field contains any character identified by a 1 in the following
** array, then the string must be quoted for CSV.
*/
static const char needCsvQuote[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
/*
** Output a single term of CSV. Actually, p->separator is used for
** the separator, which may or may not be a comma. p->nullvalue is
@ -350,12 +391,27 @@ static void output_html_string(FILE *out, const char *z){
** appear outside of quotes.
*/
static void output_csv(struct callback_data *p, const char *z, int bSep){
FILE *out = p->out;
if( z==0 ){
fprintf(p->out,"%s",p->nullvalue);
}else if( isNumber(z, 0) ){
fprintf(p->out,"%s",z);
fprintf(out,"%s",p->nullvalue);
}else{
output_c_string(p->out, z);
int i;
for(i=0; z[i]; i++){
if( needCsvQuote[((unsigned char*)z)[i]] ){
i = 0;
break;
}
}
if( i==0 ){
putc('"', out);
for(i=0; z[i]; i++){
if( z[i]=='"' ) putc('"', out);
putc(z[i], out);
}
putc('"', out);
}else{
fprintf(out, "%s", z);
}
}
if( bSep ){
fprintf(p->out, p->separator);
@ -384,12 +440,12 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
int w = 5;
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
int len = strlen(azCol[i]);
int len = strlen(azCol[i] ? azCol[i] : "");
if( len>w ) w = len;
}
if( p->cnt++>0 ) fprintf(p->out,"\n");
for(i=0; i<nArg; i++){
fprintf(p->out,"%*s = %s\n", w, azCol[i],
fprintf(p->out,"%*s = %s\n", w, azCol[i],
azArg[i] ? azArg[i] : p->nullvalue);
}
break;
@ -486,7 +542,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
case MODE_Tcl: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_c_string(p->out,azCol[i]);
output_c_string(p->out,azCol[i] ? azCol[i] : "");
fprintf(p->out, "%s", p->separator);
}
fprintf(p->out,"\n");
@ -502,7 +558,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
case MODE_Csv: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_csv(p, azCol[i], i<nArg-1);
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
}
fprintf(p->out,"\n");
}
@ -580,7 +636,7 @@ static void set_table_name(struct callback_data *p, const char *zName){
** If the third argument, quote, is not '\0', then it is used as a
** quote character for zAppend.
*/
static char * appendText(char *zIn, char const *zAppend, char quote){
static char *appendText(char *zIn, char const *zAppend, char quote){
int len;
int i;
int nAppend = strlen(zAppend);
@ -621,6 +677,9 @@ static char * appendText(char *zIn, char const *zAppend, char quote){
/*
** Execute a query statement that has a single result column. Print
** that result column on a line by itself with a semicolon terminator.
**
** This is used, for example, to show the schema of the database by
** querying the SQLITE_MASTER table.
*/
static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){
sqlite3_stmt *pSelect;
@ -662,6 +721,19 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
fprintf(p->out, "ANALYZE sqlite_master;\n");
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
char *zIns;
if( !p->writableSchema ){
fprintf(p->out, "PRAGMA writable_schema=ON;\n");
p->writableSchema = 1;
}
zIns = sqlite3_mprintf(
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
"VALUES('table','%q','%q',0,'%q');",
zTable, zTable, zSql);
fprintf(p->out, "%s\n", zIns);
sqlite3_free(zIns);
return 0;
}else{
fprintf(p->out, "%s;\n", zSql);
}
@ -695,7 +767,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
zSelect = appendText(zSelect, zText, '"');
rc = sqlite3_step(pTableInfo);
if( rc==SQLITE_ROW ){
zSelect = appendText(zSelect, ") || ', ' || ", 0);
zSelect = appendText(zSelect, ") || ',' || ", 0);
}else{
zSelect = appendText(zSelect, ") ", 0);
}
@ -714,15 +786,14 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
rc = run_table_dump_query(p->out, p->db, zSelect);
}
if( zSelect ) free(zSelect);
if( rc!=SQLITE_OK ){
return 1;
}
}
return 0;
}
/*
** Run zQuery. Update dump_callback() as the callback routine.
** 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.
*/
@ -750,6 +821,7 @@ static int run_schema_dump_query(
** 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"
@ -759,6 +831,9 @@ static char zHelp[] =
".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"
#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"
@ -783,7 +858,7 @@ static char zHelp[] =
;
/* Forward reference */
static void process_input(struct callback_data *p, FILE *in);
static int process_input(struct callback_data *p, FILE *in);
/*
** Make sure the database is open. If it is not, then open it. If
@ -800,6 +875,9 @@ static void open_db(struct callback_data *p){
p->zDbFilename, sqlite3_errmsg(db));
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
}
}
@ -840,11 +918,28 @@ static void resolve_backslashes(char *z){
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 to exit and 0 to continue.
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, struct callback_data *p){
int i = 1;
@ -879,6 +974,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
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;
@ -901,14 +1000,15 @@ static int do_meta_command(char *zLine, struct callback_data *p){
char *zErrMsg = 0;
open_db(p);
fprintf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 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_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type!='table' AND type!='meta'", 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;
@ -918,13 +1018,19 @@ static int do_meta_command(char *zLine, struct callback_data *p){
"SELECT name, type, sql FROM sqlite_master "
"WHERE tbl_name LIKE shellstatic() AND type=='table'"
" AND sql NOT NULL", 0);
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE tbl_name LIKE shellstatic() AND type!='table'"
" AND type!='meta' 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;
}
if( zErrMsg ){
fprintf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
@ -934,37 +1040,15 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}else
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
int j;
char *z = azArg[1];
int val = atoi(azArg[1]);
for(j=0; z[j]; j++){
z[j] = tolower((unsigned char)z[j]);
}
if( strcmp(z,"on")==0 ){
val = 1;
}else if( strcmp(z,"yes")==0 ){
val = 1;
}
p->echoOn = val;
p->echoOn = booleanValue(azArg[1]);
}else
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
rc = 1;
rc = 2;
}else
if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
int j;
static char zOne[] = "1";
char *z = nArg>=2 ? azArg[1] : zOne;
int val = atoi(z);
for(j=0; z[j]; j++){
z[j] = tolower((unsigned char)z[j]);
}
if( strcmp(z,"on")==0 ){
val = 1;
}else if( strcmp(z,"yes")==0 ){
val = 1;
}
int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
if(val == 1) {
if(!p->explainPrev.valid) {
p->explainPrev.valid = 1;
@ -995,21 +1079,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
}else
if( c=='h' && (strncmp(azArg[0], "header", n)==0
||
if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
int j;
char *z = azArg[1];
int val = atoi(azArg[1]);
for(j=0; z[j]; j++){
z[j] = tolower((unsigned char)z[j]);
}
if( strcmp(z,"on")==0 ){
val = 1;
}else if( strcmp(z,"yes")==0 ){
val = 1;
}
p->showHeader = val;
p->showHeader = booleanValue(azArg[1]);
}else
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
@ -1032,6 +1104,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
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");
@ -1045,6 +1118,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( rc ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
nCol = 0;
rc = 1;
}else{
nCol = sqlite3_column_count(pStmt);
}
@ -1065,7 +1139,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
return 0;
return 1;
}
in = fopen(zFile, "rb");
if( in==0 ){
@ -1111,6 +1185,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( rc!=SQLITE_OK ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
zCommit = "ROLLBACK";
rc = 1;
break;
}
}
@ -1144,6 +1219,23 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
const char *zFile, *zProc;
char *zErrMsg = 0;
int rc;
zFile = azArg[1];
zProc = nArg>=3 ? azArg[2] : 0;
open_db(p);
rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "%s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}
}else
#endif
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
int n2 = strlen(azArg[1]);
if( strncmp(azArg[1],"line",n2)==0
@ -1174,7 +1266,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
set_table_name(p, "table");
}
}else {
fprintf(stderr,"mode should be on of: "
fprintf(stderr,"mode should be one of: "
"column csv html insert line list tabs tcl\n");
}
}else
@ -1211,7 +1303,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}else
if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
rc = 1;
rc = 2;
}else
if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
@ -1363,6 +1455,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
printf("\n");
}
}else{
rc = 1;
}
sqlite3_free_table(azResult);
}else
@ -1442,24 +1536,40 @@ static int _is_command_terminator(const char *zLine){
** is coming from a file or device. A prompt is issued and history
** is saved only if input is interactive. An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
**
** Return the number of errors.
*/
static void process_input(struct callback_data *p, FILE *in){
static int process_input(struct callback_data *p, FILE *in){
char *zLine;
char *zSql = 0;
int nSql = 0;
char *zErrMsg;
int rc;
while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
int errCnt = 0;
int lineno = 0;
int startline = 0;
while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
fflush(p->out);
zLine = one_input_line(zSql, in);
if( zLine==0 ){
break; /* We have reached EOF */
}
if( seenInterrupt ){
if( in!=0 ) break;
seenInterrupt = 0;
}
lineno++;
if( p->echoOn ) printf("%s\n", zLine);
if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
if( zLine && zLine[0]=='.' && nSql==0 ){
int rc = do_meta_command(zLine, p);
rc = do_meta_command(zLine, p);
free(zLine);
if( rc ) break;
if( rc==2 ){
break;
}else if( rc ){
errCnt++;
}
continue;
}
if( _is_command_terminator(zLine) ){
@ -1471,7 +1581,12 @@ static void process_input(struct callback_data *p, FILE *in){
if( zLine[i]!=0 ){
nSql = strlen(zLine);
zSql = malloc( nSql+1 );
if( zSql==0 ){
fprintf(stderr, "out of memory\n");
exit(1);
}
strcpy(zSql, zLine);
startline = lineno;
}
}else{
int len = strlen(zLine);
@ -1490,14 +1605,20 @@ static void process_input(struct callback_data *p, FILE *in){
open_db(p);
rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);
if( rc || zErrMsg ){
/* if( in!=0 && !p->echoOn ) printf("%s\n",zSql); */
char zPrefix[100];
if( in!=0 || !stdin_is_interactive ){
sprintf(zPrefix, "SQL error near line %d:", startline);
}else{
sprintf(zPrefix, "SQL error:");
}
if( zErrMsg!=0 ){
printf("SQL error: %s\n", zErrMsg);
printf("%s %s\n", zPrefix, zErrMsg);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}else{
printf("SQL error: %s\n", sqlite3_errmsg(p->db));
printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db));
}
errCnt++;
}
free(zSql);
zSql = 0;
@ -1508,6 +1629,7 @@ static void process_input(struct callback_data *p, FILE *in){
if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
free(zSql);
}
return errCnt;
}
/*
@ -1519,7 +1641,7 @@ static void process_input(struct callback_data *p, FILE *in){
static char *find_home_dir(void){
char *home_dir = NULL;
#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
struct passwd *pwent;
uid_t uid = getuid();
if( (pwent=getpwuid(uid)) != NULL) {
@ -1532,16 +1654,30 @@ static char *find_home_dir(void){
home_dir = getcwd(home_path, _MAX_PATH);
#endif
#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
if (!home_dir) {
home_dir = getenv("USERPROFILE");
}
#endif
if (!home_dir) {
home_dir = getenv("HOME");
if (!home_dir) {
home_dir = getenv("HOMEPATH"); /* Windows? */
}
}
#if defined(_WIN32) || defined(WIN32)
#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
if (!home_dir) {
home_dir = "c:";
char *zDrive, *zPath;
int n;
zDrive = getenv("HOMEDRIVE");
zPath = getenv("HOMEPATH");
if( zDrive && zPath ){
n = strlen(zDrive) + strlen(zPath) + 1;
home_dir = malloc( n );
if( home_dir==0 ) return 0;
sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
return home_dir;
}
home_dir = "c:\\";
}
#endif
@ -1584,7 +1720,7 @@ static void process_sqliterc(
}
in = fopen(sqliterc,"rb");
if( in ){
if( isatty(fileno(stdout)) ){
if( stdin_is_interactive ){
printf("Loading resources from %s\n",sqliterc);
}
process_input(p,in);
@ -1601,19 +1737,25 @@ static const char zOptions[] =
" -init filename read/process named file\n"
" -echo print commands before execution\n"
" -[no]header turn headers on or off\n"
" -bail stop after hitting an error\n"
" -interactive force interactive I/O\n"
" -batch force batch I/O\n"
" -column set output mode to 'column'\n"
" -csv set output mode to 'csv'\n"
" -html set output mode to HTML\n"
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
" -separator 'x' set output field separator (|)\n"
" -nullvalue 'text' set text string for NULL values\n"
" -version show SQLite version\n"
" -help show this text, also show dot-commands\n"
;
static void usage(int showDetail){
fprintf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n", Argv0);
fprintf(stderr,
"Usage: %s [OPTIONS] FILENAME [SQL]\n"
"FILENAME is the name of an SQLite database. A new database is created\n"
"if the file does not previously exist.\n", Argv0);
if( showDetail ){
fprintf(stderr, "Options are:\n%s", zOptions);
fprintf(stderr, "OPTIONS include:\n%s", zOptions);
}else{
fprintf(stderr, "Use the -help option for additional information\n");
}
@ -1638,6 +1780,7 @@ int main(int argc, char **argv){
const char *zInitFile = 0;
char *zFirstCmd = 0;
int i;
int rc = 0;
#ifdef __MACOS__
argc = ccommand(&argv);
@ -1645,6 +1788,7 @@ int main(int argc, char **argv){
Argv0 = argv[0];
main_init(&data);
stdin_is_interactive = isatty(0);
/* Make sure we have a valid signal handler early, before anything
** else is done.
@ -1658,15 +1802,15 @@ int main(int argc, char **argv){
** and the first command to execute.
*/
for(i=1; i<argc-1; i++){
char *z;
if( argv[i][0]!='-' ) break;
z = argv[i];
if( z[0]=='-' && z[1]=='-' ) z++;
if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
i++;
}else if( strcmp(argv[i],"-init")==0 ){
i++;
zInitFile = argv[i];
}else if( strcmp(argv[i],"-key")==0 ){
i++;
data.zKey = sqlite3_mprintf("%s",argv[i]);
}
}
if( i<argc ){
@ -1712,7 +1856,8 @@ int main(int argc, char **argv){
*/
for(i=1; i<argc && argv[i][0]=='-'; i++){
char *z = argv[i];
if( strcmp(z,"-init")==0 || strcmp(z,"-key")==0 ){
if( z[1]=='-' ){ z++; }
if( strcmp(z,"-init")==0 ){
i++;
}else if( strcmp(z,"-html")==0 ){
data.mode = MODE_Html;
@ -1722,6 +1867,9 @@ int main(int argc, char **argv){
data.mode = MODE_Line;
}else if( strcmp(z,"-column")==0 ){
data.mode = MODE_Column;
}else if( strcmp(z,"-csv")==0 ){
data.mode = MODE_Csv;
strcpy(data.separator,",");
}else if( strcmp(z,"-separator")==0 ){
i++;
sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
@ -1734,10 +1882,16 @@ int main(int argc, char **argv){
data.showHeader = 0;
}else if( strcmp(z,"-echo")==0 ){
data.echoOn = 1;
}else if( strcmp(z,"-bail")==0 ){
bail_on_error = 1;
}else if( strcmp(z,"-version")==0 ){
printf("%s\n", sqlite3_libversion());
return 1;
}else if( strcmp(z,"-help")==0 ){
return 0;
}else if( strcmp(z,"-interactive")==0 ){
stdin_is_interactive = 1;
}else if( strcmp(z,"-batch")==0 ){
stdin_is_interactive = 0;
}else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
usage(1);
}else{
fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
@ -1764,7 +1918,7 @@ int main(int argc, char **argv){
}else{
/* Run commands received from standard input
*/
if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){
if( stdin_is_interactive ){
char *zHome;
char *zHistory = 0;
printf(
@ -1779,16 +1933,22 @@ int main(int argc, char **argv){
#if defined(HAVE_READLINE) && HAVE_READLINE==1
if( zHistory ) read_history(zHistory);
#endif
process_input(&data, 0);
rc = process_input(&data, 0);
if( zHistory ){
stifle_history(100);
write_history(zHistory);
free(zHistory);
}
free(zHome);
}else{
process_input(&data, stdin);
rc = process_input(&data, stdin);
}
}
set_table_name(&data, 0);
if( db ) sqlite3_close(db);
return 0;
if( db ){
if( sqlite3_close(db)!=SQLITE_OK ){
fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db));
}
}
return rc;
}