=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/sqlite3/Attic/shell.c,v retrieving revision 1.1.1.9 retrieving revision 1.1.1.10 diff -c -r1.1.1.9 -r1.1.1.10 *** src/usr.bin/sqlite3/Attic/shell.c 2014/09/29 22:58:46 1.1.1.9 --- src/usr.bin/sqlite3/Attic/shell.c 2015/03/16 00:08:48 1.1.1.10 *************** *** 33,38 **** --- 33,41 ---- #include #include #include "sqlite3.h" + #if SQLITE_USER_AUTHENTICATION + # include "sqlite3userauth.h" + #endif #include #include *************** *** 432,450 **** return zResult; } ! struct previous_mode_data { ! int valid; /* Is there legit data in here? */ ! int mode; ! 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 ! ** state and mode information. */ ! struct callback_data { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ --- 435,458 ---- return zResult; } ! /* ! ** Shell output mode information from before ".explain on", ! ** saved so that it can be restored by ".explain off" ! */ ! typedef struct SavedModeInfo SavedModeInfo; ! struct SavedModeInfo { ! int valid; /* Is there legit data in here? */ ! int mode; /* Mode prior to ".explain on" */ ! int showHeader; /* The ".header" setting prior to ".explain on" */ ! int colWidth[100]; /* Column widths prior to ".explain on" */ }; /* ! ** State information about the database connection is contained in an ! ** instance of the following structure. */ ! typedef struct ShellState ShellState; ! struct ShellState { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ *************** *** 457,462 **** --- 465,471 ---- 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 */ + unsigned shellFlgs; /* Various flags */ char *zDestTable; /* Name of destination table when MODE_Insert */ char separator[20]; /* Separator character for MODE_List */ char newline[20]; /* Record separator in MODE_Csv */ *************** *** 464,472 **** int actualWidth[100]; /* Actual width of each column */ char nullvalue[20]; /* The text to print when a NULL comes back from ** the database */ ! struct previous_mode_data explainPrev; ! /* Holds the mode information just before ! ** .explain ON */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ char *zFreeOnClose; /* Filename to free when closing */ --- 473,479 ---- int actualWidth[100]; /* Actual width of each column */ char nullvalue[20]; /* The text to print when a NULL comes back from ** the database */ ! SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ char *zFreeOnClose; /* Filename to free when closing */ *************** *** 479,484 **** --- 486,498 ---- }; /* + ** These are the allowed shellFlgs values + */ + #define SHFLG_Scratch 0x00001 /* The --scratch option is used */ + #define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ + #define SHFLG_Lookaside 0x00004 /* Lookaside memory is used */ + + /* ** These are the allowed modes. */ #define MODE_Line 0 /* One column per line. Blank line between records */ *************** *** 522,528 **** ** A callback for the sqlite3_log() interface. */ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ! struct callback_data *p = (struct callback_data*)pArg; if( p->pLog==0 ) return; fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); fflush(p->pLog); --- 536,542 ---- ** A callback for the sqlite3_log() interface. */ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ! ShellState *p = (ShellState*)pArg; if( p->pLog==0 ) return; fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); fflush(p->pLog); *************** *** 664,670 **** ** the null value. Strings are quoted if necessary. The separator ** is only issued if bSep is true. */ ! static void output_csv(struct callback_data *p, const char *z, int bSep){ FILE *out = p->out; if( z==0 ){ fprintf(out,"%s",p->nullvalue); --- 678,684 ---- ** the null value. Strings are quoted if necessary. The separator ** is only issued if bSep is true. */ ! static void output_csv(ShellState *p, const char *z, int bSep){ FILE *out = p->out; if( z==0 ){ fprintf(out,"%s",p->nullvalue); *************** *** 713,719 **** */ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ int i; ! struct callback_data *p = (struct callback_data*)pArg; switch( p->mode ){ case MODE_Line: { --- 727,733 ---- */ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ int i; ! ShellState *p = (ShellState*)pArg; switch( p->mode ){ case MODE_Line: { *************** *** 923,933 **** } /* ! ** Set the destination table field of the callback_data structure to ** the name of the table given. Escape any quote characters in the ** table name. */ ! static void set_table_name(struct callback_data *p, const char *zName){ int i, n; int needQuote; char *z; --- 937,947 ---- } /* ! ** Set the destination table field of the ShellState structure to ** the name of the table given. Escape any quote characters in the ** table name. */ ! static void set_table_name(ShellState *p, const char *zName){ int i, n; int needQuote; char *z; *************** *** 1017,1023 **** ** won't consume the semicolon terminator. */ static int run_table_dump_query( ! struct callback_data *p, /* Query context */ const char *zSelect, /* SELECT statement to extract content */ const char *zFirstRow /* Print before first row, if not NULL */ ){ --- 1031,1037 ---- ** won't consume the semicolon terminator. */ static int run_table_dump_query( ! ShellState *p, /* Query context */ const char *zSelect, /* SELECT statement to extract content */ const char *zFirstRow /* Print before first row, if not NULL */ ){ *************** *** 1080,1086 **** */ static int display_stats( sqlite3 *db, /* Database to query */ ! struct callback_data *pArg, /* Pointer to struct callback_data */ int bReset /* True to reset the stats */ ){ int iCur; --- 1094,1100 ---- */ static int display_stats( sqlite3 *db, /* Database to query */ ! ShellState *pArg, /* Pointer to ShellState */ int bReset /* True to reset the stats */ ){ int iCur; *************** *** 1094,1114 **** iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr); ! /* ! ** Not currently used by the CLI. ! ** iHiwtr = iCur = -1; ! ** sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); ! ** fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr); ! */ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); ! /* ! ** Not currently used by the CLI. ! ** iHiwtr = iCur = -1; ! ** sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); ! ** fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr); ! */ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); --- 1108,1126 ---- iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr); ! if( pArg->shellFlgs & SHFLG_Pagecache ){ ! iHiwtr = iCur = -1; ! sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); ! fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr); ! } iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); ! if( pArg->shellFlgs & SHFLG_Scratch ){ ! iHiwtr = iCur = -1; ! sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); ! fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr); ! } iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); *************** *** 1129,1144 **** } if( pArg && pArg->out && db ){ iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); - fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset); - fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr); - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset); - fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr); - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset); - fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr); - iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); --- 1141,1158 ---- } if( pArg && pArg->out && db ){ + if( pArg->shellFlgs & SHFLG_Lookaside ){ + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr); + } iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); *************** *** 1187,1193 **** /* ** If compiled statement pSql appears to be an EXPLAIN statement, allocate ! ** and populate the callback_data.aiIndent[] array with the number of ** spaces each opcode should be indented before it is output. ** ** The indenting rules are: --- 1201,1207 ---- /* ** If compiled statement pSql appears to be an EXPLAIN statement, allocate ! ** and populate the ShellState.aiIndent[] array with the number of ** spaces each opcode should be indented before it is output. ** ** The indenting rules are: *************** *** 1203,1209 **** ** then indent all opcodes between the earlier instruction ** and "Goto" by 2 spaces. */ ! static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ const char *zSql; /* The text of the SQL statement */ const char *z; /* Used to check if this is an EXPLAIN */ int *abYield = 0; /* True if op is an OP_Yield */ --- 1217,1223 ---- ** then indent all opcodes between the earlier instruction ** and "Goto" by 2 spaces. */ ! static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ const char *zSql; /* The text of the SQL statement */ const char *z; /* Used to check if this is an EXPLAIN */ int *abYield = 0; /* True if op is an OP_Yield */ *************** *** 1263,1269 **** /* ** Free the array allocated by explain_data_prepare(). */ ! static void explain_data_delete(struct callback_data *p){ sqlite3_free(p->aiIndent); p->aiIndent = 0; p->nIndent = 0; --- 1277,1283 ---- /* ** Free the array allocated by explain_data_prepare(). */ ! static void explain_data_delete(ShellState *p){ sqlite3_free(p->aiIndent); p->aiIndent = 0; p->nIndent = 0; *************** *** 1280,1291 **** ** and callback data argument. */ static int shell_exec( ! sqlite3 *db, /* An open database */ ! const char *zSql, /* SQL to be evaluated */ int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ ! /* (not the same as sqlite3_exec) */ ! struct callback_data *pArg, /* Pointer to struct callback_data */ ! char **pzErrMsg /* Error msg written here */ ){ sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ int rc = SQLITE_OK; /* Return Code */ --- 1294,1305 ---- ** and callback data argument. */ static int shell_exec( ! sqlite3 *db, /* An open database */ ! const char *zSql, /* SQL to be evaluated */ int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ ! /* (not the same as sqlite3_exec) */ ! ShellState *pArg, /* Pointer to ShellState */ ! char **pzErrMsg /* Error msg written here */ ){ sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ int rc = SQLITE_OK; /* Return Code */ *************** *** 1339,1353 **** sqlite3_free(zEQP); } - /* Output TESTCTRL_EXPLAIN text of requested */ - if( pArg && pArg->mode==MODE_Explain ){ - const char *zExplain = 0; - sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain); - if( zExplain && zExplain[0] ){ - fprintf(pArg->out, "%s", zExplain); - } - } - /* If the shell is currently in ".explain" mode, gather the extra ** data required to add indents to the output.*/ if( pArg && pArg->mode==MODE_Explain ){ --- 1353,1358 ---- *************** *** 1453,1459 **** const char *zType; const char *zSql; const char *zPrepStmt = 0; ! struct callback_data *p = (struct callback_data *)pArg; UNUSED_PARAMETER(azCol); if( nArg!=3 ) return 1; --- 1458,1464 ---- const char *zType; const char *zSql; const char *zPrepStmt = 0; ! ShellState *p = (ShellState *)pArg; UNUSED_PARAMETER(azCol); if( nArg!=3 ) return 1; *************** *** 1549,1555 **** ** "ORDER BY rowid DESC" to the end. */ static int run_schema_dump_query( ! struct callback_data *p, const char *zQuery ){ int rc; --- 1554,1560 ---- ** "ORDER BY rowid DESC" to the end. */ static int run_schema_dump_query( ! ShellState *p, const char *zQuery ){ int rc; *************** *** 1649,1655 **** ; /* Forward reference */ ! static int process_input(struct callback_data *p, FILE *in); /* ** Implementation of the "readfile(X)" SQL function. The entire content ** of the file named X is read and returned as a BLOB. NULL is returned --- 1654,1660 ---- ; /* Forward reference */ ! static int process_input(ShellState *p, FILE *in); /* ** Implementation of the "readfile(X)" SQL function. The entire content ** of the file named X is read and returned as a BLOB. NULL is returned *************** *** 1715,1721 **** ** 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, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); --- 1720,1726 ---- ** 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(ShellState *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); *************** *** 1896,1902 **** */ static void sql_trace_callback(void *pArg, const char *z){ FILE *f = (FILE*)pArg; ! if( f ) fprintf(f, "%s\n", z); } /* --- 1901,1911 ---- */ static void sql_trace_callback(void *pArg, const char *z){ FILE *f = (FILE*)pArg; ! if( f ){ ! int i = (int)strlen(z); ! while( i>0 && z[i-1]==';' ){ i--; } ! fprintf(f, "%.*s;\n", i, z); ! } } /* *************** *** 2014,2020 **** ** work for WITHOUT ROWID tables. */ static void tryToCloneData( ! struct callback_data *p, sqlite3 *newDb, const char *zTable ){ --- 2023,2029 ---- ** work for WITHOUT ROWID tables. */ static void tryToCloneData( ! ShellState *p, sqlite3 *newDb, const char *zTable ){ *************** *** 2127,2136 **** ** sqlite_master table, try again moving backwards. */ static void tryToCloneSchema( ! struct callback_data *p, sqlite3 *newDb, const char *zWhere, ! void (*xForEach)(struct callback_data*,sqlite3*,const char*) ){ sqlite3_stmt *pQuery = 0; char *zQuery = 0; --- 2136,2145 ---- ** sqlite_master table, try again moving backwards. */ static void tryToCloneSchema( ! ShellState *p, sqlite3 *newDb, const char *zWhere, ! void (*xForEach)(ShellState*,sqlite3*,const char*) ){ sqlite3_stmt *pQuery = 0; char *zQuery = 0; *************** *** 2201,2207 **** ** as possible out of the main database (which might be corrupt) and write it ** into zNewDb. */ ! static void tryToClone(struct callback_data *p, const char *zNewDb){ int rc; sqlite3 *newDb = 0; if( access(zNewDb,0)==0 ){ --- 2210,2216 ---- ** as possible out of the main database (which might be corrupt) and write it ** into zNewDb. */ ! static void tryToClone(ShellState *p, const char *zNewDb){ int rc; sqlite3 *newDb = 0; if( access(zNewDb,0)==0 ){ *************** *** 2226,2232 **** /* ** Change the output file back to stdout */ ! static void output_reset(struct callback_data *p){ if( p->outfile[0]=='|' ){ pclose(p->out); }else{ --- 2235,2241 ---- /* ** Change the output file back to stdout */ ! static void output_reset(ShellState *p){ if( p->outfile[0]=='|' ){ pclose(p->out); }else{ *************** *** 2242,2248 **** ** ** 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; --- 2251,2257 ---- ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ ! static int do_meta_command(char *zLine, ShellState *p){ int i = 1; int nArg = 0; int n, c; *************** *** 2360,2366 **** }else if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ ! struct callback_data data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); --- 2369,2375 ---- }else if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ ! ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); *************** *** 2458,2468 **** 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 --- 2467,2477 ---- if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ int val = nArg>=2 ? booleanValue(azArg[1]) : 1; if(val == 1) { ! if(!p->normalMode.valid) { ! p->normalMode.valid = 1; ! p->normalMode.mode = p->mode; ! p->normalMode.showHeader = p->showHeader; ! memcpy(p->normalMode.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 *************** *** 2482,2497 **** 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=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ ! struct callback_data data; char *zErrMsg = 0; int doStats = 0; if( nArg!=1 ){ --- 2491,2506 ---- p->colWidth[5] = 13; /* P4 */ p->colWidth[6] = 2; /* P5 */ p->colWidth[7] = 13; /* Comment */ ! }else if (p->normalMode.valid) { ! p->normalMode.valid = 0; ! p->mode = p->normalMode.mode; ! p->showHeader = p->normalMode.showHeader; ! memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth)); } }else if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ ! ShellState data; char *zErrMsg = 0; int doStats = 0; if( nArg!=1 ){ *************** *** 2508,2514 **** " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " ! "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" "ORDER BY rowid", callback, &data, &zErrMsg ); --- 2517,2523 ---- " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " ! "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " "ORDER BY rowid", callback, &data, &zErrMsg ); *************** *** 2712,2718 **** }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ ! struct callback_data data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); --- 2721,2727 ---- }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ ! ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); *************** *** 3006,3012 **** }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ ! struct callback_data data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); --- 3015,3021 ---- }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ ! ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); *************** *** 3062,3068 **** " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " ! "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" "ORDER BY rowid", callback, &data, &zErrMsg ); --- 3071,3077 ---- " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " ! "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " "ORDER BY rowid", callback, &data, &zErrMsg ); *************** *** 3083,3088 **** --- 3092,3106 ---- } }else + + #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; + }else + #endif + + #ifdef SQLITE_DEBUG /* Undocumented commands for internal testing. Subject to change ** without notice. */ *************** *** 3148,3154 **** } fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); ! fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); fprintf(p->out,"%9.9s: ", "nullvalue"); --- 3166,3172 ---- } fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); ! fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off"); fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); fprintf(p->out,"%9.9s: ", "nullvalue"); *************** *** 3420,3425 **** --- 3438,3508 ---- #endif }else + #if SQLITE_USER_AUTHENTICATION + if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ + if( nArg<2 ){ + fprintf(stderr, "Usage: .user SUBCOMMAND ...\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + if( strcmp(azArg[1],"login")==0 ){ + if( nArg!=4 ){ + fprintf(stderr, "Usage: .user login USER PASSWORD\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], + (int)strlen(azArg[3])); + if( rc ){ + fprintf(stderr, "Authentication failed for user %s\n", azArg[2]); + rc = 1; + } + }else if( strcmp(azArg[1],"add")==0 ){ + if( nArg!=5 ){ + fprintf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_add(p->db, azArg[2], + azArg[3], (int)strlen(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + fprintf(stderr, "User-Add failed: %d\n", rc); + rc = 1; + } + }else if( strcmp(azArg[1],"edit")==0 ){ + if( nArg!=5 ){ + fprintf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_change(p->db, azArg[2], + azArg[3], (int)strlen(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + fprintf(stderr, "User-Edit failed: %d\n", rc); + rc = 1; + } + }else if( strcmp(azArg[1],"delete")==0 ){ + if( nArg!=3 ){ + fprintf(stderr, "Usage: .user delete USER\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_delete(p->db, azArg[2]); + if( rc ){ + fprintf(stderr, "User-Delete failed: %d\n", rc); + rc = 1; + } + }else{ + fprintf(stderr, "Usage: .user login|add|edit|delete ...\n"); + rc = 1; + goto meta_command_exit; + } + }else + #endif /* SQLITE_USER_AUTHENTICATION */ + if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/, sqlite3_libversion(), sqlite3_sourceid()); *************** *** 3540,3546 **** ** ** Return the number of errors. */ ! static int process_input(struct callback_data *p, FILE *in){ char *zLine = 0; /* A single input line */ char *zSql = 0; /* Accumulated SQL text */ int nLine; /* Length of current line */ --- 3623,3629 ---- ** ** Return the number of errors. */ ! static int process_input(ShellState *p, FILE *in){ char *zLine = 0; /* A single input line */ char *zSql = 0; /* Accumulated SQL text */ int nLine; /* Length of current line */ *************** *** 3642,3647 **** --- 3725,3731 ---- if( nSql ){ if( !_all_whitespace(zSql) ){ fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); + errCnt++; } free(zSql); } *************** *** 3719,3725 **** ** Returns the number of errors. */ static int process_sqliterc( ! struct callback_data *p, /* Configuration data */ const char *sqliterc_override /* Name of config file. NULL to use default */ ){ char *home_dir = NULL; --- 3803,3809 ---- ** Returns the number of errors. */ static int process_sqliterc( ! ShellState *p, /* Configuration data */ const char *sqliterc_override /* Name of config file. NULL to use default */ ){ char *home_dir = NULL; *************** *** 3772,3783 **** --- 3856,3870 ---- " -interactive force interactive I/O\n" " -line set output mode to 'line'\n" " -list set output mode to 'list'\n" + " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n" " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif " -newline SEP set newline character(s) for CSV\n" " -nullvalue TEXT set text string for NULL values. Default ''\n" + " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" + " -scratch SIZE N use N slots of SZ bytes each for scratch memory\n" " -separator SEP set output field separator. Default: '|'\n" " -stats print memory stats before each finalize\n" " -version show SQLite version\n" *************** *** 3802,3818 **** /* ** Initialize the state information in data */ ! static void main_init(struct callback_data *data) { memset(data, 0, sizeof(*data)); data->mode = MODE_List; memcpy(data->separator,"|", 2); memcpy(data->newline,"\r\n", 3); data->showHeader = 0; sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); - sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); } /* --- 3889,3906 ---- /* ** Initialize the state information in data */ ! static void main_init(ShellState *data) { memset(data, 0, sizeof(*data)); data->mode = MODE_List; memcpy(data->separator,"|", 2); memcpy(data->newline,"\r\n", 3); data->showHeader = 0; + data->shellFlgs = SHFLG_Lookaside; sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); + sqlite3_config(SQLITE_CONFIG_MULTITHREAD); sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); } /* *************** *** 3850,3856 **** int main(int argc, char **argv){ char *zErrMsg = 0; ! struct callback_data data; const char *zInitFile = 0; char *zFirstCmd = 0; int i; --- 3938,3944 ---- int main(int argc, char **argv){ char *zErrMsg = 0; ! ShellState data; const char *zInitFile = 0; char *zFirstCmd = 0; int i; *************** *** 3921,3926 **** --- 4009,4041 ---- if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); #endif + }else if( strcmp(z,"-scratch")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( sz>400000 ) sz = 400000; + if( sz<2500 ) sz = 2500; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( n>10 ) n = 10; + if( n<1 ) n = 1; + sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n); + data.shellFlgs |= SHFLG_Scratch; + }else if( strcmp(z,"-pagecache")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( sz>70000 ) sz = 70000; + if( sz<800 ) sz = 800; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( n<10 ) n = 10; + sqlite3_config(SQLITE_CONFIG_PAGECACHE, malloc(n*sz+1), sz, n); + data.shellFlgs |= SHFLG_Pagecache; + }else if( strcmp(z,"-lookaside")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( sz<0 ) sz = 0; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( n<0 ) n = 0; + sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n); + if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside; #ifdef SQLITE_ENABLE_VFSTRACE }else if( strcmp(z,"-vfstrace")==0 ){ extern int vfstrace_register( *************** *** 4036,4041 **** --- 4151,4162 ---- stdin_is_interactive = 0; }else if( strcmp(z,"-heap")==0 ){ i++; + }else if( strcmp(z,"-scratch")==0 ){ + i+=2; + }else if( strcmp(z,"-pagecache")==0 ){ + i+=2; + }else if( strcmp(z,"-lookaside")==0 ){ + i+=2; }else if( strcmp(z,"-mmap")==0 ){ i++; }else if( strcmp(z,"-vfs")==0 ){