Merge sqlite-release(3.8.10.2) into prerelease-integration

This commit is contained in:
Nick Parker
2015-07-10 14:30:07 -05:00
235 changed files with 14156 additions and 4314 deletions
+390 -106
View File
@@ -24,6 +24,13 @@
#include "msvc.h"
#endif
/*
** No support for loadable extensions in VxWorks.
*/
#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
# define SQLITE_OMIT_LOAD_EXTENSION 1
#endif
/*
** Enable large-file support for fopen() and friends on unix.
*/
@@ -107,10 +114,15 @@
*/
extern int isatty(int);
/* popen and pclose are not C89 functions and so are sometimes omitted from
** the <stdio.h> header */
extern FILE *popen(const char*,const char*);
extern int pclose(FILE*);
#if !defined(__RTP__) && !defined(_WRS_KERNEL)
/* popen and pclose are not C89 functions and so are sometimes omitted from
** the <stdio.h> header */
extern FILE *popen(const char*,const char*);
extern int pclose(FILE*);
#else
# define SQLITE_OMIT_POPEN 1
#endif
#endif
#if defined(_WIN32_WCE)
@@ -126,6 +138,26 @@ extern int pclose(FILE*);
#define IsDigit(X) isdigit((unsigned char)X)
#define ToLower(X) (char)tolower((unsigned char)X)
/* On Windows, we normally run with output mode of TEXT so that \n characters
** are automatically translated into \r\n. However, this behavior needs
** to be disabled in some cases (ex: when generating CSV output and when
** rendering quoted strings that contain \n characters). The following
** routines take care of that.
*/
#if defined(_WIN32) || defined(WIN32)
static void setBinaryMode(FILE *out){
fflush(out);
_setmode(_fileno(out), _O_BINARY);
}
static void setTextMode(FILE *out){
fflush(out);
_setmode(_fileno(out), _O_TEXT);
}
#else
# define setBinaryMode(X)
# define setTextMode(X)
#endif
/* True if the timer is enabled */
static int enableTimer = 0;
@@ -145,11 +177,19 @@ static sqlite3_int64 timeOfDay(void){
return t;
}
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \
&& !defined(__minux)
#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
#include <sys/time.h>
#include <sys/resource.h>
/* VxWorks does not support getrusage() as far as we can determine */
#if defined(_WRS_KERNEL) || defined(__RTP__)
struct rusage {
struct timeval ru_utime; /* user CPU time used */
struct timeval ru_stime; /* system CPU time used */
};
#define getrusage(A,B) memset(B,0,sizeof(*B))
#endif
/* Saved resource information for the beginning of an operation */
static struct rusage sBegin; /* CPU time at start */
static sqlite3_int64 iBegin; /* Wall-clock time at start */
@@ -175,8 +215,8 @@ static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
*/
static void endTimer(void){
if( enableTimer ){
struct rusage sEnd;
sqlite3_int64 iEnd = timeOfDay();
struct rusage sEnd;
getrusage(RUSAGE_SELF, &sEnd);
printf("Run Time: real %.3f user %f sys %f\n",
(iEnd - iBegin)*0.001,
@@ -296,7 +336,7 @@ static int stdin_is_interactive = 1;
** to this database a static variable so that it can be accessed
** by the SIGINT handler to interrupt database processing.
*/
static sqlite3 *db = 0;
static sqlite3 *globalDb = 0;
/*
** True if an interrupt (Control-C) has been received.
@@ -330,7 +370,7 @@ static FILE *iotrace = 0;
** is written to iotrace.
*/
#ifdef SQLITE_ENABLE_IOTRACE
static void iotracePrintf(const char *zFormat, ...){
static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
va_list ap;
char *z;
if( iotrace==0 ) return;
@@ -487,6 +527,7 @@ struct ShellState {
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
int statsOn; /* True to display memory stats before each finalize */
int scanstatsOn; /* True to display scan stats before each finalize */
int backslashOn; /* Resolve C-style \x escapes in SQL input text */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
@@ -604,6 +645,7 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
static void output_quoted_string(FILE *out, const char *z){
int i;
int nSingle = 0;
setBinaryMode(out);
for(i=0; z[i]; i++){
if( z[i]=='\'' ) nSingle++;
}
@@ -626,6 +668,7 @@ static void output_quoted_string(FILE *out, const char *z){
}
fprintf(out,"'");
}
setTextMode(out);
}
/*
@@ -762,7 +805,7 @@ static void interrupt_handler(int NotUsed){
UNUSED_PARAMETER(NotUsed);
seenInterrupt++;
if( seenInterrupt>2 ) exit(1);
if( db ) sqlite3_interrupt(db);
if( globalDb ) sqlite3_interrupt(globalDb);
}
#endif
@@ -928,10 +971,7 @@ static int shell_callback(
break;
}
case MODE_Csv: {
#if defined(WIN32) || defined(_WIN32)
fflush(p->out);
_setmode(_fileno(p->out), _O_BINARY);
#endif
setBinaryMode(p->out);
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
@@ -944,16 +984,22 @@ static int shell_callback(
}
fprintf(p->out, "%s", p->rowSeparator);
}
#if defined(WIN32) || defined(_WIN32)
fflush(p->out);
_setmode(_fileno(p->out), _O_TEXT);
#endif
setTextMode(p->out);
break;
}
case MODE_Insert: {
p->cnt++;
if( azArg==0 ) break;
fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
fprintf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
fprintf(p->out,"(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
fprintf(p->out, "%s%s", zSep, azCol[i]);
}
fprintf(p->out,")");
}
fprintf(p->out," VALUES(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
@@ -1154,7 +1200,7 @@ static char *save_err_msg(
sqlite3 *db /* Database to query */
){
int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
char *zErrMsg = sqlite3_malloc(nErrMsg);
char *zErrMsg = sqlite3_malloc64(nErrMsg);
if( zErrMsg ){
memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
}
@@ -1391,8 +1437,8 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int));
p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
@@ -1509,7 +1555,7 @@ static int shell_exec(
if( xCallback ){
/* allocate space for col name ptr, value ptr, and type */
int nCol = sqlite3_column_count(pStmt);
void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1);
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
if( !pData ){
rc = SQLITE_NOMEM;
}else{
@@ -1735,8 +1781,10 @@ static int run_schema_dump_query(
static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
".bail on|off Stop after hitting an error. Default OFF\n"
".binary on|off Turn binary output on or off. Default OFF\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dbinfo ?DB? Show status information about the database\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
" If TABLE specified, only dump tables matching\n"
" LIKE pattern TABLE.\n"
@@ -1749,12 +1797,13 @@ static char zHelp[] =
".headers 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\n"
" If TABLE specified, only show indices for tables\n"
".indexes ?TABLE? Show names of all indexes\n"
" If TABLE specified, only show indexes for tables\n"
" matching LIKE pattern TABLE.\n"
#ifdef SQLITE_ENABLE_IOTRACE
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
#endif
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
#endif
@@ -1824,7 +1873,7 @@ static void readfileFunc(
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc( nIn );
pBuf = sqlite3_malloc64( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
}else{
@@ -1871,23 +1920,23 @@ static void open_db(ShellState *p, int keepAlive){
if( p->db==0 ){
sqlite3_initialize();
sqlite3_open(p->zDbFilename, &p->db);
db = p->db;
if( db && sqlite3_errcode(db)==SQLITE_OK ){
sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
globalDb = p->db;
if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
shellstaticFunc, 0, 0);
}
if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
p->zDbFilename, sqlite3_errmsg(db));
p->zDbFilename, sqlite3_errmsg(p->db));
if( keepAlive ) return;
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0,
readfileFunc, 0, 0);
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0,
writefileFunc, 0, 0);
}
}
@@ -1895,26 +1944,44 @@ static void open_db(ShellState *p, int keepAlive){
/*
** Do C-language style dequoting.
**
** \a -> alarm
** \b -> backspace
** \t -> tab
** \n -> newline
** \v -> vertical tab
** \f -> form feed
** \r -> carriage return
** \s -> space
** \" -> "
** \NNN -> ascii character NNN in octal
** \' -> '
** \\ -> backslash
** \NNN -> ascii character NNN in octal
*/
static void resolve_backslashes(char *z){
int i, j;
char c;
while( *z && *z!='\\' ) z++;
for(i=j=0; (c = z[i])!=0; i++, j++){
if( c=='\\' ){
if( c=='\\' && z[i+1]!=0 ){
c = z[++i];
if( c=='n' ){
c = '\n';
if( c=='a' ){
c = '\a';
}else if( c=='b' ){
c = '\b';
}else if( c=='t' ){
c = '\t';
}else if( c=='n' ){
c = '\n';
}else if( c=='v' ){
c = '\v';
}else if( c=='f' ){
c = '\f';
}else if( c=='r' ){
c = '\r';
}else if( c=='"' ){
c = '"';
}else if( c=='\'' ){
c = '\'';
}else if( c=='\\' ){
c = '\\';
}else if( c>='0' && c<='7' ){
@@ -2084,7 +2151,7 @@ struct ImportCtx {
static void import_append_char(ImportCtx *p, int c){
if( p->n+1>=p->nAlloc ){
p->nAlloc += p->nAlloc + 100;
p->z = sqlite3_realloc(p->z, p->nAlloc);
p->z = sqlite3_realloc64(p->z, p->nAlloc);
if( p->z==0 ){
fprintf(stderr, "out of memory\n");
exit(1);
@@ -2098,7 +2165,7 @@ static void import_append_char(ImportCtx *p, int c){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** from sqlite3_malloc64().
** + Use p->cSep as the column separator. The default is ",".
** + Use p->rSep as the row separator. The default is "\n".
** + Keep track of the line number in p->nLine.
@@ -2106,7 +2173,7 @@ static void import_append_char(ImportCtx *p, int c){
** EOF on end-of-file.
** + Report syntax errors on stderr
*/
static char *csv_read_one_field(ImportCtx *p){
static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
int c;
int cSep = p->cColSep;
int rSep = p->cRowSep;
@@ -2172,7 +2239,7 @@ static char *csv_read_one_field(ImportCtx *p){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** from sqlite3_malloc64().
** + Use p->cSep as the column separator. The default is "\x1F".
** + Use p->rSep as the row separator. The default is "\x1E".
** + Keep track of the row number in p->nLine.
@@ -2180,7 +2247,7 @@ static char *csv_read_one_field(ImportCtx *p){
** EOF on end-of-file.
** + Report syntax errors on stderr
*/
static char *ascii_read_one_field(ImportCtx *p){
static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
int c;
int cSep = p->cColSep;
int rSep = p->cRowSep;
@@ -2232,7 +2299,7 @@ static void tryToCloneData(
goto end_data_xfer;
}
n = sqlite3_column_count(pQuery);
zInsert = sqlite3_malloc(200 + nTable + n*3);
zInsert = sqlite3_malloc64(200 + nTable + n*3);
if( zInsert==0 ){
fprintf(stderr, "out of memory\n");
goto end_data_xfer;
@@ -2422,7 +2489,9 @@ static void tryToClone(ShellState *p, const char *zNewDb){
*/
static void output_reset(ShellState *p){
if( p->outfile[0]=='|' ){
#ifndef SQLITE_OMIT_POPEN
pclose(p->out);
#endif
}else{
output_file_close(p->out);
}
@@ -2430,6 +2499,115 @@ static void output_reset(ShellState *p){
p->out = stdout;
}
/*
** Run an SQL command and return the single integer result.
*/
static int db_int(ShellState *p, const char *zSql){
sqlite3_stmt *pStmt;
int res = 0;
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
res = sqlite3_column_int(pStmt,0);
}
sqlite3_finalize(pStmt);
return res;
}
/*
** Convert a 2-byte or 4-byte big-endian integer into a native integer
*/
unsigned int get2byteInt(unsigned char *a){
return (a[0]<<8) + a[1];
}
unsigned int get4byteInt(unsigned char *a){
return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
}
/*
** Implementation of the ".info" command.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
static const struct { const char *zName; int ofst; } aField[] = {
{ "file change counter:", 24 },
{ "database page count:", 28 },
{ "freelist page count:", 36 },
{ "schema cookie:", 40 },
{ "schema format:", 44 },
{ "default cache size:", 48 },
{ "autovacuum top root:", 52 },
{ "incremental vacuum:", 64 },
{ "text encoding:", 56 },
{ "user version:", 60 },
{ "application id:", 68 },
{ "software version:", 96 },
};
static const struct { const char *zName; const char *zSql; } aQuery[] = {
{ "number of tables:",
"SELECT count(*) FROM %s WHERE type='table'" },
{ "number of indexes:",
"SELECT count(*) FROM %s WHERE type='index'" },
{ "number of triggers:",
"SELECT count(*) FROM %s WHERE type='trigger'" },
{ "number of views:",
"SELECT count(*) FROM %s WHERE type='view'" },
{ "schema size:",
"SELECT total(length(sql)) FROM %s" },
};
sqlite3_file *pFile;
int i;
char *zSchemaTab;
char *zDb = nArg>=2 ? azArg[1] : "main";
unsigned char aHdr[100];
open_db(p, 0);
if( p->db==0 ) return 1;
sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile);
if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
return 1;
}
i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
if( i!=SQLITE_OK ){
fprintf(stderr, "unable to read database header\n");
return 1;
}
i = get2byteInt(aHdr+16);
if( i==1 ) i = 65536;
fprintf(p->out, "%-20s %d\n", "database page size:", i);
fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
for(i=0; i<sizeof(aField)/sizeof(aField[0]); i++){
int ofst = aField[i].ofst;
unsigned int val = get4byteInt(aHdr + ofst);
fprintf(p->out, "%-20s %u", aField[i].zName, val);
switch( ofst ){
case 56: {
if( val==1 ) fprintf(p->out, " (utf8)");
if( val==2 ) fprintf(p->out, " (utf16le)");
if( val==3 ) fprintf(p->out, " (utf16be)");
}
}
fprintf(p->out, "\n");
}
if( zDb==0 ){
zSchemaTab = sqlite3_mprintf("main.sqlite_master");
}else if( strcmp(zDb,"temp")==0 ){
zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
}else{
zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
}
for(i=0; i<sizeof(aQuery)/sizeof(aQuery[0]); i++){
char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
int val = db_int(p, zSql);
sqlite3_free(zSql);
fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
}
sqlite3_free(zSchemaTab);
return 0;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
@@ -2437,7 +2615,7 @@ static void output_reset(ShellState *p){
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, ShellState *p){
int i = 1;
int h = 1;
int nArg = 0;
int n, c;
int rc = 0;
@@ -2445,24 +2623,24 @@ static int do_meta_command(char *zLine, ShellState *p){
/* Parse the input line into tokens.
*/
while( zLine[i] && nArg<ArraySize(azArg) ){
while( IsSpace(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 ){
if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++;
i++;
while( zLine[h] && nArg<ArraySize(azArg) ){
while( IsSpace(zLine[h]) ){ h++; }
if( zLine[h]==0 ) break;
if( zLine[h]=='\'' || zLine[h]=='"' ){
int delim = zLine[h++];
azArg[nArg++] = &zLine[h];
while( zLine[h] && zLine[h]!=delim ){
if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
h++;
}
if( zLine[i]==delim ){
zLine[i++] = 0;
if( zLine[h]==delim ){
zLine[h++] = 0;
}
if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
}else{
azArg[nArg++] = &zLine[i];
while( zLine[i] && !IsSpace(zLine[i]) ){ i++; }
if( zLine[i] ) zLine[i++] = 0;
azArg[nArg++] = &zLine[h];
while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
if( zLine[h] ) zLine[h++] = 0;
resolve_backslashes(azArg[nArg-1]);
}
}
@@ -2537,6 +2715,19 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
setBinaryMode(p->out);
}else{
setTextMode(p->out);
}
}else{
fprintf(stderr, "Usage: .binary on|off\n");
rc = 1;
}
}else
/* The undocumented ".breakpoint" command causes a call to the no-op
** routine named test_breakpoint().
*/
@@ -2572,6 +2763,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){
rc = shell_dbinfo_command(p, nArg, azArg);
}else
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
open_db(p, 0);
/* When playing back a "dump", the content might appear in an order
@@ -2759,8 +2954,8 @@ static int do_meta_command(char *zLine, ShellState *p){
int nSep; /* Number of bytes in p->colSeparator[] */
char *zSql; /* An SQL statement */
ImportCtx sCtx; /* Reader context */
char *(*xRead)(ImportCtx*); /* Procedure to read one value */
int (*xCloser)(FILE*); /* Procedure to close th3 connection */
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
if( nArg!=3 ){
fprintf(stderr, "Usage: .import FILE TABLE\n");
@@ -2802,9 +2997,14 @@ static int do_meta_command(char *zLine, ShellState *p){
sCtx.zFile = zFile;
sCtx.nLine = 1;
if( sCtx.zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
fprintf(stderr, "Error: pipes are not supported in this OS\n");
return 1;
#else
sCtx.in = popen(sCtx.zFile+1, "r");
sCtx.zFile = "<pipe>";
xCloser = pclose;
#endif
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
xCloser = fclose;
@@ -2829,7 +3029,7 @@ static int do_meta_command(char *zLine, ShellState *p){
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
@@ -2849,7 +3049,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zCreate);
if( rc ){
fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
sqlite3_errmsg(db));
sqlite3_errmsg(p->db));
sqlite3_free(sCtx.z);
xCloser(sCtx.in);
return 1;
@@ -2859,7 +3059,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zSql);
if( rc ){
if (pStmt) sqlite3_finalize(pStmt);
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
xCloser(sCtx.in);
return 1;
}
@@ -2867,7 +3067,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_finalize(pStmt);
pStmt = 0;
if( nCol==0 ) return 0; /* no columns, no error */
zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 );
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
if( zSql==0 ){
fprintf(stderr, "Error: out of memory\n");
xCloser(sCtx.in);
@@ -2884,13 +3084,13 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
if (pStmt) sqlite3_finalize(pStmt);
xCloser(sCtx.in);
return 1;
}
needCommit = sqlite3_get_autocommit(db);
if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
needCommit = sqlite3_get_autocommit(p->db);
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
do{
int startLine = sCtx.nLine;
for(i=0; i<nCol; i++){
@@ -2911,7 +3111,7 @@ static int do_meta_command(char *zLine, ShellState *p){
fprintf(stderr, "%s:%d: expected %d columns but found %d - "
"filling the rest with NULL\n",
sCtx.zFile, startLine, nCol, i+1);
i++;
i += 2;
while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
}
}
@@ -2929,7 +3129,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK ){
fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine,
sqlite3_errmsg(db));
sqlite3_errmsg(p->db));
}
}
}while( sCtx.cTerm!=EOF );
@@ -2937,10 +3137,11 @@ static int do_meta_command(char *zLine, ShellState *p){
xCloser(sCtx.in);
sqlite3_free(sCtx.z);
sqlite3_finalize(pStmt);
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
}else
if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
if( c=='i' && (strncmp(azArg[0], "indices", n)==0
|| strncmp(azArg[0], "indexes", n)==0) ){
ShellState data;
char *zErrMsg = 0;
open_db(p, 0);
@@ -2970,7 +3171,7 @@ static int do_meta_command(char *zLine, ShellState *p){
);
zShellStatic = 0;
}else{
fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n");
fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
@@ -2986,7 +3187,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_ENABLE_IOTRACE
if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
extern void (*sqlite3IoTrace)(const char*, ...);
SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
if( iotrace && iotrace!=stdout ) fclose(iotrace);
iotrace = 0;
if( nArg<2 ){
@@ -3006,6 +3207,64 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#endif
if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
static const struct {
const char *zLimitName; /* Name of a limit */
int limitCode; /* Integer code for that limit */
} aLimit[] = {
{ "length", SQLITE_LIMIT_LENGTH },
{ "sql_length", SQLITE_LIMIT_SQL_LENGTH },
{ "column", SQLITE_LIMIT_COLUMN },
{ "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
{ "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
{ "vdbe_op", SQLITE_LIMIT_VDBE_OP },
{ "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
{ "attached", SQLITE_LIMIT_ATTACHED },
{ "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
{ "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
{ "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
};
int i, n2;
open_db(p, 0);
if( nArg==1 ){
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
printf("%20s %d\n", aLimit[i].zLimitName,
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
}
}else if( nArg>3 ){
fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
rc = 1;
goto meta_command_exit;
}else{
int iLimit = -1;
n2 = strlen30(azArg[1]);
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
if( iLimit<0 ){
iLimit = i;
}else{
fprintf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
rc = 1;
goto meta_command_exit;
}
}
}
if( iLimit<0 ){
fprintf(stderr, "unknown limit: \"%s\"\n"
"enter \".limits\" with no arguments for a list.\n",
azArg[1]);
rc = 1;
goto meta_command_exit;
}
if( nArg==3 ){
sqlite3_limit(p->db, aLimit[iLimit].limitCode,
(int)integerValue(azArg[2]));
}
printf("%20s %d\n", aLimit[iLimit].zLimitName,
sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
}
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
@@ -3126,6 +3385,11 @@ static int do_meta_command(char *zLine, ShellState *p){
}
output_reset(p);
if( zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
fprintf(stderr,"Error: pipes are not supported in this OS\n");
rc = 1;
p->out = stdout;
#else
p->out = popen(zFile + 1, "w");
if( p->out==0 ){
fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
@@ -3134,6 +3398,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
#endif
}else{
p->out = output_file_open(zFile);
if( p->out==0 ){
@@ -3333,7 +3598,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
extern int sqlite3SelectTrace;
sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
sqlite3SelectTrace = integerValue(azArg[1]);
}else
#endif
@@ -3484,13 +3749,13 @@ static int do_meta_command(char *zLine, ShellState *p){
while( sqlite3_step(pStmt)==SQLITE_ROW ){
if( nRow>=nAlloc ){
char **azNew;
int n = nAlloc*2 + 10;
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n);
int n2 = nAlloc*2 + 10;
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
if( azNew==0 ){
fprintf(stderr, "Error: out of memory\n");
break;
}
nAlloc = n;
nAlloc = n2;
azResult = azNew;
}
azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
@@ -3539,17 +3804,19 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
};
int testctrl = -1;
int rc = 0;
int i, n;
int rc2 = 0;
int i, n2;
open_db(p, 0);
/* convert testctrl text option to value. allow any unique prefix
** of the option name, or a numerical value. */
n = strlen30(azArg[1]);
n2 = strlen30(azArg[1]);
for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
if( testctrl<0 ){
testctrl = aCtrl[i].ctrlCode;
}else{
@@ -3570,8 +3837,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_RESERVE:
if( nArg==3 ){
int opt = (int)strtol(azArg[2], 0, 0);
rc = sqlite3_test_control(testctrl, p->db, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, p->db, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
@@ -3584,8 +3851,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_BYTEORDER:
if( nArg==2 ){
rc = sqlite3_test_control(testctrl);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
}
@@ -3595,8 +3862,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_PENDING_BYTE:
if( nArg==3 ){
unsigned int opt = (unsigned int)integerValue(azArg[2]);
rc = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single unsigned"
" int option\n", azArg[1]);
@@ -3605,11 +3872,12 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int, int) */
case SQLITE_TESTCTRL_ASSERT:
case SQLITE_TESTCTRL_ALWAYS:
case SQLITE_TESTCTRL_ALWAYS:
case SQLITE_TESTCTRL_NEVER_CORRUPT:
if( nArg==3 ){
int opt = booleanValue(azArg[2]);
rc = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
@@ -3621,8 +3889,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_ISKEYWORD:
if( nArg==3 ){
const char *opt = azArg[2];
rc = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
azArg[1]);
@@ -3630,6 +3898,18 @@ static int do_meta_command(char *zLine, ShellState *p){
break;
#endif
case SQLITE_TESTCTRL_IMPOSTER:
if( nArg==5 ){
rc2 = sqlite3_test_control(testctrl, p->db,
azArg[2],
integerValue(azArg[3]),
integerValue(azArg[4]));
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
}else{
fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
}
break;
case SQLITE_TESTCTRL_BITVEC_TEST:
case SQLITE_TESTCTRL_FAULT_INSTALL:
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
@@ -3662,12 +3942,12 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
open_db(p, 0);
output_file_close(p->traceOut);
if( nArg!=2 ){
fprintf(stderr, "Usage: .trace FILE|off\n");
rc = 1;
goto meta_command_exit;
}
output_file_close(p->traceOut);
p->traceOut = output_file_open(azArg[1]);
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( p->traceOut==0 ){
@@ -3932,6 +4212,7 @@ static int process_input(ShellState *p, FILE *in){
&& sqlite3_complete(zSql) ){
p->cnt = 0;
open_db(p, 0);
if( p->backslashOn ) resolve_backslashes(zSql);
BEGIN_TIMER;
rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
END_TIMER;
@@ -4043,7 +4324,7 @@ static char *find_home_dir(void){
**
** Returns the number of errors.
*/
static int process_sqliterc(
static void process_sqliterc(
ShellState *p, /* Configuration data */
const char *sqliterc_override /* Name of config file. NULL to use default */
){
@@ -4051,15 +4332,13 @@ static int process_sqliterc(
const char *sqliterc = sqliterc_override;
char *zBuf = 0;
FILE *in = NULL;
int rc = 0;
if (sqliterc == NULL) {
home_dir = find_home_dir();
if( home_dir==0 ){
#if !defined(__RTP__) && !defined(_WRS_KERNEL)
fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0);
#endif
return 1;
fprintf(stderr, "-- warning: cannot find home directory;"
" cannot read ~/.sqliterc\n");
return;
}
sqlite3_initialize();
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
@@ -4070,11 +4349,10 @@ static int process_sqliterc(
if( stdin_is_interactive ){
fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
}
rc = process_input(p,in);
process_input(p,in);
fclose(in);
}
sqlite3_free(zBuf);
return rc;
}
/*
@@ -4178,7 +4456,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){
return argv[i];
}
int main(int argc, char **argv){
int SQLITE_CDECL main(int argc, char **argv){
char *zErrMsg = 0;
ShellState data;
const char *zInitFile = 0;
@@ -4196,6 +4474,8 @@ int main(int argc, char **argv){
exit(1);
}
#endif
setBinaryMode(stdin);
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
Argv0 = argv[0];
main_init(&data);
stdin_is_interactive = isatty(0);
@@ -4348,10 +4628,7 @@ int main(int argc, char **argv){
** is given on the command line, look for a file named ~/.sqliterc and
** try to process it.
*/
rc = process_sqliterc(&data,zInitFile);
if( rc>0 ){
return rc;
}
process_sqliterc(&data,zInitFile);
/* Make a second pass through the command-line argument and set
** options. This second pass is delayed until after the initialization
@@ -4402,6 +4679,13 @@ int main(int argc, char **argv){
data.statsOn = 1;
}else if( strcmp(z,"-scanstats")==0 ){
data.scanstatsOn = 1;
}else if( strcmp(z,"-backslash")==0 ){
/* Undocumented command-line option: -backslash
** Causes C-style backslash escapes to be evaluated in SQL statements
** prior to sending the SQL into SQLite. Useful for injecting
** crazy bytes in the middle of SQL statements for testing and debugging.
*/
data.backslashOn = 1;
}else if( strcmp(z,"-bail")==0 ){
bail_on_error = 1;
}else if( strcmp(z,"-version")==0 ){