From ce64d6105016e56ea60c7f02534eb44cdf505a77 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 14 Aug 2014 18:31:56 +0000 Subject: [PATCH 01/42] Fix compiler warnings on WinCE. FossilOrigin-Name: cc910b8e0c45e7387024f3a729003e2fef08b198 --- manifest | 21 ++++++++++++--------- manifest.uuid | 2 +- src/mutex_w32.c | 2 +- src/os_win.c | 8 ++++---- src/os_win.h | 10 ++++++++++ 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index a9e401b96b..44902dc52f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypos\sin\scomments\sused\sto\shelp\sgenerate\sdocumentation.\s\sNo\schanges\sto\scode. -D 2014-08-14T13:06:25.245 +C Fix\scompiler\swarnings\son\sWinCE. +D 2014-08-14T18:31:56.425 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -201,15 +201,15 @@ F src/mutex.c 84a073c9a23a8d7bdd2ea832522d1730df18812c F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea F src/mutex_noop.c f3f09fd7a2eb4287cfc799753ffc30380e7b71a1 F src/mutex_unix.c 1b10d5413dfc794364a8adf3eb3a192926b43fa3 -F src/mutex_w32.c c50939b72368f1cfbddb58520372081a50558548 +F src/mutex_w32.c 06bfff9a3a83b53389a51a967643db3967032e1e F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542 -F src/os_win.c 1c936c7b0659d0eb12b868e2cd710a570e78873e -F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25 +F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e +F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 @@ -1186,7 +1186,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f5cce9db109a2bbe9a05b4c01b076a51d5fad8ba -R b4842944a4c3679f5b3af787e9b322df -U drh -Z 52db703ea373cd617fd2c598672c0ab8 +P 13a2d90a2869c53b79754de39045bbbdbc7688e3 +R 9127229654219d70056c71e11a62fce3 +T *branch * winCeWarn +T *sym-winCeWarn * +T -sym-trunk * +U mistachkin +Z 13b8e5c3b082e69ddfa9c76704e89cbc diff --git a/manifest.uuid b/manifest.uuid index 5d1e011162..8ce24171cb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -13a2d90a2869c53b79754de39045bbbdbc7688e3 \ No newline at end of file +cc910b8e0c45e7387024f3a729003e2fef08b198 \ No newline at end of file diff --git a/src/mutex_w32.c b/src/mutex_w32.c index 218342d2b9..da7d73f7c5 100644 --- a/src/mutex_w32.c +++ b/src/mutex_w32.c @@ -99,7 +99,7 @@ static int winMutex_isNt = -1; /* <0 means "need to query" */ ** of the sqlite3_initialize() and sqlite3_shutdown() processing, the ** "interlocked" magic used here is probably not strictly necessary. */ -static LONG volatile winMutex_lock = 0; +static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; int sqlite3_win32_is_nt(void); /* os_win.c */ void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ diff --git a/src/os_win.c b/src/os_win.c index f479de3a1b..b9f13becd6 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -410,9 +410,9 @@ const sqlite3_mem_methods *sqlite3MemGetWin32(void); ** can manually set this value to 1 to emulate Win98 behavior. */ #ifdef SQLITE_TEST -LONG volatile sqlite3_os_type = 0; +LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; #else -static LONG volatile sqlite3_os_type = 0; +static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; #endif #ifndef SYSCALL @@ -1055,8 +1055,8 @@ static struct win_syscall { #else { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, -#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \ - LONG,LONG))aSyscall[76].pCurrent) +#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ + SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) #endif /* defined(InterlockedCompareExchange) */ }; /* End of the overrideable system calls */ diff --git a/src/os_win.h b/src/os_win.h index d662cd467d..5174ac7781 100644 --- a/src/os_win.h +++ b/src/os_win.h @@ -64,4 +64,14 @@ # define SQLITE_OS_WINRT 0 #endif +/* +** For WinCE, some API function parameters do not appear to be declared as +** volatile. +*/ +#if SQLITE_OS_WINCE +# define SQLITE_WIN32_VOLATILE +#else +# define SQLITE_WIN32_VOLATILE volatile +#endif + #endif /* _OS_WIN_H_ */ From dcd87a9dd3b18148cf6444a53797840a3243d01b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 18 Aug 2014 13:45:42 +0000 Subject: [PATCH 02/42] Refactor the names of state objects in the command-line shell implementation.. FossilOrigin-Name: 11a70e1ae7f05d06e4e09c9d20db0444b8881584 --- manifest | 13 +++--- manifest.uuid | 2 +- src/shell.c | 115 ++++++++++++++++++++++++++------------------------ 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/manifest b/manifest index c1d7bb58d6..6b5562f42e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scompiler\swarnings\son\sWinCE. -D 2014-08-15T16:13:07.749 +C Refactor\sthe\snames\sof\sstate\sobjects\sin\sthe\scommand-line\sshell\simplementation.. +D 2014-08-18T13:45:42.156 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -223,7 +223,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c ea48e891406ccdf748f3eb02893e056d134a0fea -F src/shell.c 75bb7bd2c80bb44861598f322a417c4bafe98fd7 +F src/shell.c 41df1103617331e023301d943977f8c06bd1486f F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1186,8 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9491ba7d738528f168657adb43a198238abde19e cc910b8e0c45e7387024f3a729003e2fef08b198 -R ad15e862b2dc4bc2854071509d952976 -T +closed cc910b8e0c45e7387024f3a729003e2fef08b198 +P 28a379fcd43389ad3249eff51a621d0bb7c81640 +R ef518fe403795d3b06bbe754ecf5c125 U drh -Z 7367bc305ed9789e95517eb698c37af7 +Z e00f86954fa90c49bf5a476ef91fbb0c diff --git a/manifest.uuid b/manifest.uuid index d364d2f83d..e975bd8d97 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -28a379fcd43389ad3249eff51a621d0bb7c81640 \ No newline at end of file +11a70e1ae7f05d06e4e09c9d20db0444b8881584 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index a74dcdb85d..87b335fbb1 100644 --- a/src/shell.c +++ b/src/shell.c @@ -432,19 +432,24 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ return zResult; } -struct previous_mode_data { - int valid; /* Is there legit data in here? */ - int mode; - int showHeader; - int colWidth[100]; +/* +** 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" */ }; /* -** 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. +** State information about the database connection is contained in an +** instance of the following structure. */ -struct callback_data { +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 */ @@ -464,9 +469,7 @@ struct callback_data { 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 */ + 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 */ @@ -522,7 +525,7 @@ static int strlen30(const char *z){ ** 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; + ShellState *p = (ShellState*)pArg; if( p->pLog==0 ) return; fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); fflush(p->pLog); @@ -664,7 +667,7 @@ static const char needCsvQuote[] = { ** 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){ +static void output_csv(ShellState *p, const char *z, int bSep){ FILE *out = p->out; if( z==0 ){ fprintf(out,"%s",p->nullvalue); @@ -713,7 +716,7 @@ static void interrupt_handler(int NotUsed){ */ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ int i; - struct callback_data *p = (struct callback_data*)pArg; + ShellState *p = (ShellState*)pArg; switch( p->mode ){ case MODE_Line: { @@ -923,11 +926,11 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ } /* -** Set the destination table field of the callback_data structure to +** 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(struct callback_data *p, const char *zName){ +static void set_table_name(ShellState *p, const char *zName){ int i, n; int needQuote; char *z; @@ -1017,7 +1020,7 @@ static char *appendText(char *zIn, char const *zAppend, char quote){ ** won't consume the semicolon terminator. */ static int run_table_dump_query( - struct callback_data *p, /* Query context */ + ShellState *p, /* Query context */ const char *zSelect, /* SELECT statement to extract content */ const char *zFirstRow /* Print before first row, if not NULL */ ){ @@ -1080,7 +1083,7 @@ static char *save_err_msg( */ static int display_stats( sqlite3 *db, /* Database to query */ - struct callback_data *pArg, /* Pointer to struct callback_data */ + ShellState *pArg, /* Pointer to ShellState */ int bReset /* True to reset the stats */ ){ int iCur; @@ -1187,7 +1190,7 @@ static int str_in_array(const char *zStr, const char **azArray){ /* ** If compiled statement pSql appears to be an EXPLAIN statement, allocate -** and populate the callback_data.aiIndent[] array with the number of +** 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,7 +1206,7 @@ static int str_in_array(const char *zStr, const char **azArray){ ** 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){ +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,7 +1266,7 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ /* ** Free the array allocated by explain_data_prepare(). */ -static void explain_data_delete(struct callback_data *p){ +static void explain_data_delete(ShellState *p){ sqlite3_free(p->aiIndent); p->aiIndent = 0; p->nIndent = 0; @@ -1280,12 +1283,12 @@ static void explain_data_delete(struct callback_data *p){ ** and callback data argument. */ static int shell_exec( - sqlite3 *db, /* An open database */ - const char *zSql, /* SQL to be evaluated */ + 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 */ + /* (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 */ @@ -1453,7 +1456,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ const char *zType; const char *zSql; const char *zPrepStmt = 0; - struct callback_data *p = (struct callback_data *)pArg; + ShellState *p = (ShellState *)pArg; UNUSED_PARAMETER(azCol); if( nArg!=3 ) return 1; @@ -1549,7 +1552,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ ** "ORDER BY rowid DESC" to the end. */ static int run_schema_dump_query( - struct callback_data *p, + ShellState *p, const char *zQuery ){ int rc; @@ -1649,7 +1652,7 @@ static char zHelp[] = ; /* Forward reference */ -static int process_input(struct callback_data *p, FILE *in); +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,7 +1718,7 @@ static void writefileFunc( ** 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){ +static void open_db(ShellState *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); @@ -2014,7 +2017,7 @@ static char *csv_read_one_field(CSVReader *p){ ** work for WITHOUT ROWID tables. */ static void tryToCloneData( - struct callback_data *p, + ShellState *p, sqlite3 *newDb, const char *zTable ){ @@ -2127,10 +2130,10 @@ end_data_xfer: ** sqlite_master table, try again moving backwards. */ static void tryToCloneSchema( - struct callback_data *p, + ShellState *p, sqlite3 *newDb, const char *zWhere, - void (*xForEach)(struct callback_data*,sqlite3*,const char*) + void (*xForEach)(ShellState*,sqlite3*,const char*) ){ sqlite3_stmt *pQuery = 0; char *zQuery = 0; @@ -2201,7 +2204,7 @@ end_schema_xfer: ** 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){ +static void tryToClone(ShellState *p, const char *zNewDb){ int rc; sqlite3 *newDb = 0; if( access(zNewDb,0)==0 ){ @@ -2226,7 +2229,7 @@ static void tryToClone(struct callback_data *p, const char *zNewDb){ /* ** Change the output file back to stdout */ -static void output_reset(struct callback_data *p){ +static void output_reset(ShellState *p){ if( p->outfile[0]=='|' ){ pclose(p->out); }else{ @@ -2242,7 +2245,7 @@ static void output_reset(struct callback_data *p){ ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ -static int do_meta_command(char *zLine, struct callback_data *p){ +static int do_meta_command(char *zLine, ShellState *p){ int i = 1; int nArg = 0; int n, c; @@ -2360,7 +2363,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ - struct callback_data data; + ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); @@ -2458,11 +2461,11 @@ static int do_meta_command(char *zLine, struct callback_data *p){ 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)); + 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,16 +2485,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){ 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 (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 ){ - struct callback_data data; + ShellState data; char *zErrMsg = 0; int doStats = 0; if( nArg!=1 ){ @@ -2712,7 +2715,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ - struct callback_data data; + ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); @@ -3006,7 +3009,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ - struct callback_data data; + ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); @@ -3148,7 +3151,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } 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","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"); @@ -3540,7 +3543,7 @@ static int line_is_complete(char *zSql, int nSql){ ** ** Return the number of errors. */ -static int process_input(struct callback_data *p, FILE *in){ +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 */ @@ -3719,7 +3722,7 @@ static char *find_home_dir(void){ ** Returns the number of errors. */ static int process_sqliterc( - struct callback_data *p, /* Configuration data */ + ShellState *p, /* Configuration data */ const char *sqliterc_override /* Name of config file. NULL to use default */ ){ char *home_dir = NULL; @@ -3802,7 +3805,7 @@ static void usage(int showDetail){ /* ** Initialize the state information in data */ -static void main_init(struct callback_data *data) { +static void main_init(ShellState *data) { memset(data, 0, sizeof(*data)); data->mode = MODE_List; memcpy(data->separator,"|", 2); @@ -3850,7 +3853,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){ int main(int argc, char **argv){ char *zErrMsg = 0; - struct callback_data data; + ShellState data; const char *zInitFile = 0; char *zFirstCmd = 0; int i; From edf5b1657dc1fc1301de36de3b353295c383a064 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 19 Aug 2014 09:15:41 +0000 Subject: [PATCH 03/42] Minor changes to do with the Tcl tea extension package autoconf system. FossilOrigin-Name: f10a6111262ce6ee6984c64fa0e0023642eca27d --- autoconf/tea/Makefile.in | 1 + autoconf/tea/configure.in | 6 ++++-- autoconf/tea/tclconfig/tcl.m4 | 21 ++++++++++++--------- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/tclsqlite.c | 2 +- tool/mkautoconfamal.sh | 2 +- 7 files changed, 31 insertions(+), 25 deletions(-) diff --git a/autoconf/tea/Makefile.in b/autoconf/tea/Makefile.in index 08b1a44182..a8708974b0 100644 --- a/autoconf/tea/Makefile.in +++ b/autoconf/tea/Makefile.in @@ -73,6 +73,7 @@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ +datarootdir = @datarootdir@ datadir = @datadir@ mandir = @mandir@ includedir = @includedir@ diff --git a/autoconf/tea/configure.in b/autoconf/tea/configure.in index ec9c565c6f..8df0af6195 100644 --- a/autoconf/tea/configure.in +++ b/autoconf/tea/configure.in @@ -166,8 +166,10 @@ AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) #-------------------------------------------------------------------- # Redefine fdatasync as fsync on systems that lack fdatasync #-------------------------------------------------------------------- - -AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync)) +# +#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync)) +# Check for library functions that SQLite can optionally use. +AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r]) AC_FUNC_STRERROR_R diff --git a/autoconf/tea/tclconfig/tcl.m4 b/autoconf/tea/tclconfig/tcl.m4 index 66214e78a2..4b4bd1e888 100644 --- a/autoconf/tea/tclconfig/tcl.m4 +++ b/autoconf/tea/tclconfig/tcl.m4 @@ -1641,6 +1641,7 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [ SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -shared" TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]" + TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]" SHLIB_SUFFIX=".so" LDFLAGS="" AS_IF([test $doRpath = yes], [ @@ -1651,11 +1652,15 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [ LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) - # Version numbers are dot-stripped by system policy. - TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .` - UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' - SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' - TCL_LIB_VERSIONS_OK=nodots + case $system in + FreeBSD-3.*) + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' + TCL_LIB_VERSIONS_OK=nodots + ;; + esac ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" @@ -1826,8 +1831,8 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [ SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" ], [ - SHLIB_CFLAGS="-Kpic -belf" - LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ]) SHLIB_LD="ld -G" SHLIB_LD_LIBS="" @@ -4158,8 +4163,6 @@ AC_DEFUN([TEA_PATH_CELIB], [ fi fi ]) - - # Local Variables: # mode: autoconf # End: diff --git a/manifest b/manifest index 6b5562f42e..963d794593 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Refactor\sthe\snames\sof\sstate\sobjects\sin\sthe\scommand-line\sshell\simplementation.. -D 2014-08-18T13:45:42.156 +C Minor\schanges\sto\sdo\swith\sthe\sTcl\stea\sextension\spackage\sautoconf\ssystem. +D 2014-08-19T09:15:41.141 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -23,15 +23,15 @@ F autoconf/depcomp 0b26f101e3bc9fd1ff0be1da9fb4a82371142f92 x F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1 F autoconf/missing d7c9981a81af13370d4ed152b24c0a82b7028585 x -F autoconf/tea/Makefile.in 5c3b0bdfb66c20d55ebff59d1718864461570ca9 +F autoconf/tea/Makefile.in d55bcc63832caf0309c2ff80358756116618cfca F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43 -F autoconf/tea/configure.in e0466b881b53f31f5a4a69e7a91ad130902fb359 +F autoconf/tea/configure.in 93d43c79e936fb16556e22498177d7e8571efa04 F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523 F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00 -F autoconf/tea/tclconfig/tcl.m4 f035b86539a5ab30689e997a11ae9e7fd2e65570 +F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5 F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928 F autoconf/tea/win/nmakehlp.c 2070e086f39866b353a482d3a14dedaf26196506 F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 @@ -231,7 +231,7 @@ F src/sqliteInt.h 641f8fbb65ca2084c8df95b525f6f82c7a1e91ae F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd +F src/tclsqlite.c 7d100e2e7aad614bb3d7026a41a0e3827dbaaebc F src/test1.c 14409a611e9c27c6c522c610bbff5561f05c1558 F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712 F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c @@ -1148,7 +1148,7 @@ F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 3ff0fec22f92dfb54e62eeb48772eddffdbeb0d6 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 -F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383 +F tool/mkautoconfamal.sh 5dc5010e2e748a9e1bba67baca5956a2c2deda7b F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460 @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 28a379fcd43389ad3249eff51a621d0bb7c81640 -R ef518fe403795d3b06bbe754ecf5c125 -U drh -Z e00f86954fa90c49bf5a476ef91fbb0c +P 11a70e1ae7f05d06e4e09c9d20db0444b8881584 +R aa6c5df3344dab5b287c6351a237958f +U dan +Z b3667514ef51eabff2a360098e935ae4 diff --git a/manifest.uuid b/manifest.uuid index e975bd8d97..a39201275a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -11a70e1ae7f05d06e4e09c9d20db0444b8881584 \ No newline at end of file +f10a6111262ce6ee6984c64fa0e0023642eca27d \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 9b977e54ae..2b98b6aab4 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2381,7 +2381,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ if( rc==TCL_OK ){ rc = createIncrblobChannel( - interp, pDb, zDb, zTable, zColumn, iRow, isReadonly + interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly ); } #endif diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index c13f7c999a..4829277234 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -62,7 +62,7 @@ mkdir -p tea/generic echo "#ifdef USE_SYSTEM_SQLITE" > tea/generic/tclsqlite3.c echo "# include " >> tea/generic/tclsqlite3.c echo "#else" >> tea/generic/tclsqlite3.c -echo "#include \"../../sqlite3.c\"" >> tea/generic/tclsqlite3.c +echo "#include \"sqlite3.c\"" >> tea/generic/tclsqlite3.c echo "#endif" >> tea/generic/tclsqlite3.c cat $TOP/src/tclsqlite.c >> tea/generic/tclsqlite3.c From 4b2590e44b422eb0445220624c2438d74d17ed06 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Aug 2014 19:28:00 +0000 Subject: [PATCH 04/42] Improvements to output formatting with the ".trace" command in the command-line shell. FossilOrigin-Name: d09d63c07748839e9b778a769b183bdd614c6c13 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 10 +++++++--- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 963d794593..1735f35740 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\schanges\sto\sdo\swith\sthe\sTcl\stea\sextension\spackage\sautoconf\ssystem. -D 2014-08-19T09:15:41.141 +C Improvements\sto\soutput\sformatting\swith\sthe\s".trace"\scommand\sin\sthe\ncommand-line\sshell. +D 2014-08-19T19:28:00.623 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -223,7 +223,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c ea48e891406ccdf748f3eb02893e056d134a0fea -F src/shell.c 41df1103617331e023301d943977f8c06bd1486f +F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 11a70e1ae7f05d06e4e09c9d20db0444b8881584 -R aa6c5df3344dab5b287c6351a237958f -U dan -Z b3667514ef51eabff2a360098e935ae4 +P f10a6111262ce6ee6984c64fa0e0023642eca27d +R 257d241ab9ebe5fc3f4654d7f2e169ae +U drh +Z 211a00cac8127ca939f7e6f32071c25c diff --git a/manifest.uuid b/manifest.uuid index a39201275a..1cf4ead3de 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f10a6111262ce6ee6984c64fa0e0023642eca27d \ No newline at end of file +d09d63c07748839e9b778a769b183bdd614c6c13 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 87b335fbb1..68478a19ba 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1899,7 +1899,11 @@ static FILE *output_file_open(const char *zFile){ */ static void sql_trace_callback(void *pArg, const char *z){ FILE *f = (FILE*)pArg; - if( f ) fprintf(f, "%s\n", z); + if( f ){ + int i = (int)strlen(z); + while( i>0 && z[i-1]==';' ){ i--; } + fprintf(f, "%.*s;\n", i, z); + } } /* @@ -2511,7 +2515,7 @@ static int do_meta_command(char *zLine, ShellState *p){ " (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_%'" + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " "ORDER BY rowid", callback, &data, &zErrMsg ); @@ -3065,7 +3069,7 @@ static int do_meta_command(char *zLine, ShellState *p){ " (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_%'" + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " "ORDER BY rowid", callback, &data, &zErrMsg ); From 2c7946a485b6e19072506e40203af4cc10b0848d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Aug 2014 20:27:40 +0000 Subject: [PATCH 05/42] Make sure the sqlite3_trace() callback is invoked, even if the prepared statement was marked "expired" before it ever entered sqlite3_step(). Ticket [11d5aa455e0d98f3c1e6a08]. FossilOrigin-Name: 0d4d3df4bc5e75ce1543b5539a1e9e279d2a062f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbeapi.c | 8 +++++--- test/trace.test | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 1735f35740..c307f54e8f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\soutput\sformatting\swith\sthe\s".trace"\scommand\sin\sthe\ncommand-line\sshell. -D 2014-08-19T19:28:00.623 +C Make\ssure\sthe\ssqlite3_trace()\scallback\sis\sinvoked,\seven\sif\sthe\sprepared\nstatement\swas\smarked\s"expired"\sbefore\sit\sever\sentered\ssqlite3_step().\nTicket\s[11d5aa455e0d98f3c1e6a08]. +D 2014-08-19T20:27:40.455 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -286,7 +286,7 @@ F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df -F src/vdbeapi.c 24e40422382beb774daab11fe9fe9d37e8a04949 +F src/vdbeapi.c ce75e452dfd9c6ba4f8c6c76be6399c88bce3142 F src/vdbeaux.c 25d62ef82cf1be2a1255eacac636fa0d943d8b3d F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 @@ -1017,7 +1017,7 @@ F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4 -F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5 +F test/trace.test 73a5508100f7fccfbc3f8018d5f6963ed478eea0 F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382 F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f10a6111262ce6ee6984c64fa0e0023642eca27d -R 257d241ab9ebe5fc3f4654d7f2e169ae +P d09d63c07748839e9b778a769b183bdd614c6c13 +R dc4a84c1e3dbc4c500aead2f870904cc U drh -Z 211a00cac8127ca939f7e6f32071c25c +Z 8ee9013dcfb943fe42c807d90f81accd diff --git a/manifest.uuid b/manifest.uuid index 1cf4ead3de..b804f56674 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d09d63c07748839e9b778a769b183bdd614c6c13 \ No newline at end of file +0d4d3df4bc5e75ce1543b5539a1e9e279d2a062f \ No newline at end of file diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 5e5bb81366..568f67296c 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -513,10 +513,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){ sqlite3_mutex_enter(db->mutex); v->doingRerun = 0; while( (rc = sqlite3Step(v))==SQLITE_SCHEMA - && cnt++ < SQLITE_MAX_SCHEMA_RETRY - && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ + && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ + int savedPc = v->pc; + rc2 = rc = sqlite3Reprepare(v); + if( rc!=SQLITE_OK) break; sqlite3_reset(pStmt); - v->doingRerun = 1; + v->doingRerun = savedPc>=0; assert( v->expired==0 ); } if( rc2!=SQLITE_OK ){ diff --git a/test/trace.test b/test/trace.test index ce5a2d712a..a64cc333fa 100644 --- a/test/trace.test +++ b/test/trace.test @@ -48,6 +48,22 @@ do_test trace-1.5 { db trace {} db trace } {} +do_test trace-1.6 { + db eval { + CREATE TABLE t1b(x TEXT PRIMARY KEY, y); + INSERT INTO t1b VALUES('abc','def'),('ghi','jkl'),('mno','pqr'); + } + set ::stmtlist {} + set xyzzy a* + db trace trace_proc + db eval { + SELECT y FROM t1b WHERE x GLOB $xyzzy + } +} {def} +do_test trace-1.7 { + set ::stmtlist +} {{SELECT y FROM t1b WHERE x GLOB 'a*'}} +db trace {} # If we prepare a statement and execute it multiple times, the trace # happens on each execution. From 5f58ae75c91e1ec56f41e0d465224a6625152f24 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Aug 2014 20:41:36 +0000 Subject: [PATCH 06/42] A better fix for the sqlite3_trace() problem. Ticket [11d5aa455e0d98f3c1e6a] FossilOrigin-Name: 44d5bd4cc3f76e9a151ba0abae1092bd184af264 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeapi.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index c307f54e8f..d226fa4f96 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\ssqlite3_trace()\scallback\sis\sinvoked,\seven\sif\sthe\sprepared\nstatement\swas\smarked\s"expired"\sbefore\sit\sever\sentered\ssqlite3_step().\nTicket\s[11d5aa455e0d98f3c1e6a08]. -D 2014-08-19T20:27:40.455 +C A\sbetter\sfix\sfor\sthe\ssqlite3_trace()\sproblem.\nTicket\s[11d5aa455e0d98f3c1e6a] +D 2014-08-19T20:41:36.374 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -286,7 +286,7 @@ F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df -F src/vdbeapi.c ce75e452dfd9c6ba4f8c6c76be6399c88bce3142 +F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 F src/vdbeaux.c 25d62ef82cf1be2a1255eacac636fa0d943d8b3d F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d09d63c07748839e9b778a769b183bdd614c6c13 -R dc4a84c1e3dbc4c500aead2f870904cc +P 0d4d3df4bc5e75ce1543b5539a1e9e279d2a062f +R 3e9fe87a97e756aac5d53e0b321cfb1c U drh -Z 8ee9013dcfb943fe42c807d90f81accd +Z dae8e8935ea979fe699fbe5ad58485b9 diff --git a/manifest.uuid b/manifest.uuid index b804f56674..270766200f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0d4d3df4bc5e75ce1543b5539a1e9e279d2a062f \ No newline at end of file +44d5bd4cc3f76e9a151ba0abae1092bd184af264 \ No newline at end of file diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 568f67296c..f6cc2d8c05 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -518,7 +518,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ rc2 = rc = sqlite3Reprepare(v); if( rc!=SQLITE_OK) break; sqlite3_reset(pStmt); - v->doingRerun = savedPc>=0; + if( savedPc>=0 ) v->doingRerun = 1; assert( v->expired==0 ); } if( rc2!=SQLITE_OK ){ From dfd1547b482f8f3cc75382934575cea4c624f005 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Aug 2014 23:04:49 +0000 Subject: [PATCH 07/42] Modify the memsubsys1-3.1.4 test so that it does not fail arbitrarily due to variations in the behavior of system malloc(). FossilOrigin-Name: d280157da0b5275f3e3c875d2dcfb9998d374ac0 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/memsubsys1.test | 8 +++++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d226fa4f96..c6aee7c716 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C A\sbetter\sfix\sfor\sthe\ssqlite3_trace()\sproblem.\nTicket\s[11d5aa455e0d98f3c1e6a] -D 2014-08-19T20:41:36.374 +C Modify\sthe\smemsubsys1-3.1.4\stest\sso\sthat\sit\sdoes\snot\sfail\sarbitrarily\sdue\nto\svariations\sin\sthe\sbehavior\sof\ssystem\smalloc(). +D 2014-08-19T23:04:49.204 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -702,7 +702,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test fcb5297b321b562084fc79d64d5a12a1cd2b639b F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 -F test/memsubsys1.test f97cfd0b30e85c2f1ed16d642e7ac58006be84b2 +F test/memsubsys1.test bf270964ab83bc2da5927960f78304a866fb9a9d F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9 F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0d4d3df4bc5e75ce1543b5539a1e9e279d2a062f -R 3e9fe87a97e756aac5d53e0b321cfb1c +P 44d5bd4cc3f76e9a151ba0abae1092bd184af264 +R da9b4e10fd35ea0494fda63ca4df66ec U drh -Z dae8e8935ea979fe699fbe5ad58485b9 +Z 375791abd440beaccbf3e162957d1a64 diff --git a/manifest.uuid b/manifest.uuid index 270766200f..a915b839b0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -44d5bd4cc3f76e9a151ba0abae1092bd184af264 \ No newline at end of file +d280157da0b5275f3e3c875d2dcfb9998d374ac0 \ No newline at end of file diff --git a/test/memsubsys1.test b/test/memsubsys1.test index 76b79d00f6..8cc7c2afc1 100644 --- a/test/memsubsys1.test +++ b/test/memsubsys1.test @@ -124,7 +124,13 @@ do_test memsubsys1-3.1.3 { } 0 do_test memsubsys1-3.1.4 { set overflow [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] -} $max_pagecache + # Note: The measured PAGECACHE_OVERFLOW is amount malloc() returns, not what + # was requested. System malloc() implementations might (arbitrarily) return + # slightly different oversize buffers, which can result in slightly different + # PAGECACHE_OVERFLOW sizes between consecutive runs. So we cannot do an + # exact comparison. Simply verify that the amount is within 5%. + expr {$overflow>=$max_pagecache*0.95 && $overflow<=$max_pagecache*1.05} +} 1 do_test memsubsys1-3.1.5 { set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] } 0 From 75b31dc9adcd78576b8d89064c1d03f2164336ba Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 00:54:46 +0000 Subject: [PATCH 08/42] Minor performance improvement and size reduction for the btree-page space allocator. FossilOrigin-Name: 73637d12e31f5489efe37d8cf4ab50a1911d4c75 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 17 +++++++++++------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index c6aee7c716..91db86833d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\smemsubsys1-3.1.4\stest\sso\sthat\sit\sdoes\snot\sfail\sarbitrarily\sdue\nto\svariations\sin\sthe\sbehavior\sof\ssystem\smalloc(). -D 2014-08-19T23:04:49.204 +C Minor\sperformance\simprovement\sand\ssize\sreduction\sfor\sthe\sbtree-page\sspace\nallocator. +D 2014-08-20T00:54:46.809 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c fa057e30794bfd867963b44a3a42710a45c335a1 +F src/btree.c c580f3fb3b3d1bf968e5c7e6a0ad48b7b0bd4366 F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 44d5bd4cc3f76e9a151ba0abae1092bd184af264 -R da9b4e10fd35ea0494fda63ca4df66ec +P d280157da0b5275f3e3c875d2dcfb9998d374ac0 +R 020501de111b3b2380806f2152969bc3 U drh -Z 375791abd440beaccbf3e162957d1a64 +Z 17df18c00e8e514c309dda1b0357fb11 diff --git a/manifest.uuid b/manifest.uuid index a915b839b0..0e6072d88f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d280157da0b5275f3e3c875d2dcfb9998d374ac0 \ No newline at end of file +73637d12e31f5489efe37d8cf4ab50a1911d4c75 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 60bc7de41e..2ed304d04b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1197,7 +1197,6 @@ static int defragmentPage(MemPage *pPage){ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ - int nFrag; /* Number of fragmented bytes on pPage */ int top; /* First byte of cell content area */ int gap; /* First byte of gap between cell pointers and cell content */ int rc; /* Integer return code */ @@ -1212,16 +1211,22 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ usableSize = pPage->pBt->usableSize; assert( nByte < usableSize-8 ); - nFrag = data[hdr+7]; assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); gap = pPage->cellOffset + 2*pPage->nCell; - top = get2byteNotZero(&data[hdr+5]); - if( gap>top ) return SQLITE_CORRUPT_BKPT; + assert( gap<=65536 ); + top = get2byte(&data[hdr+5]); + if( gap>top ){ + if( top==0 ){ + top = 65536; + }else{ + return SQLITE_CORRUPT_BKPT; + } + } testcase( gap+2==top ); testcase( gap+1==top ); testcase( gap==top ); - if( nFrag>=60 ){ + if( data[hdr+7]>=60 ){ /* Always defragment highly fragmented pages */ rc = defragmentPage(pPage); if( rc ) return rc; @@ -1246,7 +1251,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ /* Remove the slot from the free-list. Update the number of ** fragmented bytes within the page. */ memcpy(&data[addr], &data[pc], 2); - data[hdr+7] = (u8)(nFrag + x); + data[hdr+7] += (u8)x; }else if( size+pc > usableSize ){ return SQLITE_CORRUPT_BKPT; }else{ From 53d89cdfe98e7c5b07527ff65cffa91798fa3ed9 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 20 Aug 2014 10:42:16 +0000 Subject: [PATCH 09/42] Fix a typo in the showdb usage message. FossilOrigin-Name: 6c66beae97ba1799c908d3a33371dedbc7f3f58c --- manifest | 14 +++++++------- manifest.uuid | 2 +- tool/showdb.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 91db86833d..e9f109a9a7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\sperformance\simprovement\sand\ssize\sreduction\sfor\sthe\sbtree-page\sspace\nallocator. -D 2014-08-20T00:54:46.809 +C Fix\sa\stypo\sin\sthe\sshowdb\susage\smessage. +D 2014-08-20T10:42:16.102 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1164,7 +1164,7 @@ F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5 -F tool/showdb.c b9ee6b6c81a094bf33badbf7e9da34cdbc0cce25 +F tool/showdb.c bd073a78bce714a0e42d92ea474b3eb8cb53be5d F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5 F tool/showstat4.c c39279d6bd37cb999b634f0064f6f86ad7af008f F tool/showwal.c 3209120269cdf9380f091459e47b776b4f81dfd3 @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d280157da0b5275f3e3c875d2dcfb9998d374ac0 -R 020501de111b3b2380806f2152969bc3 -U drh -Z 17df18c00e8e514c309dda1b0357fb11 +P 73637d12e31f5489efe37d8cf4ab50a1911d4c75 +R d268dbd0231a0e3f9784dd51ed74231a +U dan +Z b16b223d7974024b463d42100aaa47bd diff --git a/manifest.uuid b/manifest.uuid index 0e6072d88f..45aa98f21f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -73637d12e31f5489efe37d8cf4ab50a1911d4c75 \ No newline at end of file +6c66beae97ba1799c908d3a33371dedbc7f3f58c \ No newline at end of file diff --git a/tool/showdb.c b/tool/showdb.c index 1a51e9d1a2..82b8c9f14f 100644 --- a/tool/showdb.c +++ b/tool/showdb.c @@ -957,7 +957,7 @@ static void usage(const char *argv0){ " NNNbdCCC Decode cell CCC on btree page NNN\n" " NNNt Decode freelist trunk page NNN\n" " NNNtd Show leaf freelist pages on the decode\n" - " NNNtr Recurisvely decode freelist starting at NNN\n" + " NNNtr Recursively decode freelist starting at NNN\n" ); } From 4c04f3c8bd1edb345186ae80d8539a684d676d74 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 11:56:14 +0000 Subject: [PATCH 10/42] Further size reduction and performance improvement in btree.c:allocateSpace(). FossilOrigin-Name: 1cb1cd64930a6bc371143f7d2e77eb1c51498cb0 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 24 +++++++++++------------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index e9f109a9a7..6883385671 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sthe\sshowdb\susage\smessage. -D 2014-08-20T10:42:16.102 +C Further\ssize\sreduction\sand\sperformance\simprovement\sin\sbtree.c:allocateSpace(). +D 2014-08-20T11:56:14.338 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c c580f3fb3b3d1bf968e5c7e6a0ad48b7b0bd4366 +F src/btree.c 398ecbdb4a19230940955c10b4f35de958e9a05c F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 73637d12e31f5489efe37d8cf4ab50a1911d4c75 -R d268dbd0231a0e3f9784dd51ed74231a -U dan -Z b16b223d7974024b463d42100aaa47bd +P 6c66beae97ba1799c908d3a33371dedbc7f3f58c +R 28706ecaca72a1e3574ba7b8d51854c6 +U drh +Z ca9532aeb7742cb91c75177cb9ee4fbc diff --git a/manifest.uuid b/manifest.uuid index 45aa98f21f..d1bf93d7a5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c66beae97ba1799c908d3a33371dedbc7f3f58c \ No newline at end of file +1cb1cd64930a6bc371143f7d2e77eb1c51498cb0 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 2ed304d04b..61848dcb83 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1222,20 +1222,15 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ return SQLITE_CORRUPT_BKPT; } } + + /* If there is enough space between gap and top for one more cell pointer + ** array entry offset, and if the freelist is not empty, then search the + ** freelist looking for a free slot big enough to satisfy the request. + */ testcase( gap+2==top ); testcase( gap+1==top ); testcase( gap==top ); - - if( data[hdr+7]>=60 ){ - /* Always defragment highly fragmented pages */ - rc = defragmentPage(pPage); - if( rc ) return rc; - top = get2byteNotZero(&data[hdr+5]); - }else if( gap+2<=top ){ - /* Search the freelist looking for a free slot big enough to satisfy - ** the request. The allocation is made from the first free slot in - ** the list that is large enough to accommodate it. - */ + if( gap+2<=top && (data[hdr+1] || data[hdr+2]) ){ int pc, addr; for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ int size; /* Size of the free slot */ @@ -1248,6 +1243,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ testcase( x==4 ); testcase( x==3 ); if( x<4 ){ + if( data[hdr+7]>=60 ) goto defragment_page; /* Remove the slot from the free-list. Update the number of ** fragmented bytes within the page. */ memcpy(&data[addr], &data[pc], 2); @@ -1265,11 +1261,13 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ } } - /* Check to make sure there is enough space in the gap to satisfy - ** the allocation. If not, defragment. + /* The request could not be fulfilled using a freelist slot. Check + ** to see if defragmentation is necessary. */ testcase( gap+2+nByte==top ); if( gap+2+nByte>top ){ +defragment_page: + assert( pPage->nCell>0 ); rc = defragmentPage(pPage); if( rc ) return rc; top = get2byteNotZero(&data[hdr+5]); From 905552628c4812e47ab9172911650ef5e4778e64 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 13:17:43 +0000 Subject: [PATCH 11/42] Change an assert() added by the previous commit into a testcase(). Fix a separate assert() in btree.c:freeSpace(). FossilOrigin-Name: fe51d3aa0ce7021213293a0647e31164073e78f7 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 6883385671..7a156440dc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\ssize\sreduction\sand\sperformance\simprovement\sin\sbtree.c:allocateSpace(). -D 2014-08-20T11:56:14.338 +C Change\san\sassert()\sadded\sby\sthe\sprevious\scommit\sinto\sa\stestcase().\nFix\sa\sseparate\sassert()\sin\sbtree.c:freeSpace(). +D 2014-08-20T13:17:43.884 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 398ecbdb4a19230940955c10b4f35de958e9a05c +F src/btree.c 53eb576f72093d5138f5b7468994121c6eb6fe98 F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6c66beae97ba1799c908d3a33371dedbc7f3f58c -R 28706ecaca72a1e3574ba7b8d51854c6 +P 1cb1cd64930a6bc371143f7d2e77eb1c51498cb0 +R 2da2148faf73b1d43a764ae813ef9e60 U drh -Z ca9532aeb7742cb91c75177cb9ee4fbc +Z 36b8d62cf946d2fc64ee098831079eb8 diff --git a/manifest.uuid b/manifest.uuid index d1bf93d7a5..4a04c24fb1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1cb1cd64930a6bc371143f7d2e77eb1c51498cb0 \ No newline at end of file +fe51d3aa0ce7021213293a0647e31164073e78f7 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 61848dcb83..a09b82fe5e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1267,7 +1267,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ testcase( gap+2+nByte==top ); if( gap+2+nByte>top ){ defragment_page: - assert( pPage->nCell>0 ); + testcase( pPage->nCell==0 ); rc = defragmentPage(pPage); if( rc ) return rc; top = get2byteNotZero(&data[hdr+5]); @@ -1306,7 +1306,7 @@ static int freeSpace(MemPage *pPage, int start, int size){ assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); assert( (start + size) <= (int)pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( size>=0 ); /* Minimum cell size is 4 */ + assert( size>=4 ); /* Minimum cell size is 4 */ if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){ /* Overwrite deleted information with zeros when the secure_delete From fb90841adf94e9edbfa02d4506a26d2a05da11e9 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 13:25:06 +0000 Subject: [PATCH 12/42] Add SQLITE_API macros in front of interface routines in the test_intarray.c extension. FossilOrigin-Name: eea0661798e10018615854c871f24be0f8bb2ff9 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/test_intarray.c | 4 ++-- src/test_intarray.h | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index e9f109a9a7..bee5fb1b55 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sthe\sshowdb\susage\smessage. -D 2014-08-20T10:42:16.102 +C Add\sSQLITE_API\smacros\sin\sfront\sof\sinterface\sroutines\sin\sthe\stest_intarray.c\nextension. +D 2014-08-20T13:25:06.147 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -252,8 +252,8 @@ F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f F src/test_func.c d3013ce36f19ac72a99c73864930fd1fa41832f8 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 -F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61 -F src/test_intarray.h 2ece66438cfd177b78d1bfda7a4180cd3a10844d +F src/test_intarray.c db4614c2262a06abc4409dc048d59c580c38320f +F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202 F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64 F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4 F src/test_malloc.c 1ff5b1243d96124c9a180f3b89424820a1f337f3 @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 73637d12e31f5489efe37d8cf4ab50a1911d4c75 -R d268dbd0231a0e3f9784dd51ed74231a -U dan -Z b16b223d7974024b463d42100aaa47bd +P 6c66beae97ba1799c908d3a33371dedbc7f3f58c +R 0e361fd9748a232cee30a1097c2f8f6b +U drh +Z c85b6dec89d4d1dc359d8501fa41031d diff --git a/manifest.uuid b/manifest.uuid index 45aa98f21f..bf670ea860 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c66beae97ba1799c908d3a33371dedbc7f3f58c \ No newline at end of file +eea0661798e10018615854c871f24be0f8bb2ff9 \ No newline at end of file diff --git a/src/test_intarray.c b/src/test_intarray.c index f5c3d9e405..efcd21d404 100644 --- a/src/test_intarray.c +++ b/src/test_intarray.c @@ -216,7 +216,7 @@ static sqlite3_module intarrayModule = { ** explicitly by the application, the virtual table will be dropped implicitly ** by the system when the database connection is closed. */ -int sqlite3_intarray_create( +SQLITE_API int sqlite3_intarray_create( sqlite3 *db, const char *zName, sqlite3_intarray **ppReturn @@ -250,7 +250,7 @@ int sqlite3_intarray_create( ** any query against the corresponding virtual table. If the integer ** array does change or is deallocated undefined behavior will result. */ -int sqlite3_intarray_bind( +SQLITE_API int sqlite3_intarray_bind( sqlite3_intarray *pIntArray, /* The intarray object to bind to */ int nElements, /* Number of elements in the intarray */ sqlite3_int64 *aElements, /* Content of the intarray */ diff --git a/src/test_intarray.h b/src/test_intarray.h index 6d26235a87..84b1f3fe66 100644 --- a/src/test_intarray.h +++ b/src/test_intarray.h @@ -102,7 +102,7 @@ typedef struct sqlite3_intarray sqlite3_intarray; ** explicitly by the application, the virtual table will be dropped implicitly ** by the system when the database connection is closed. */ -int sqlite3_intarray_create( +SQLITE_API int sqlite3_intarray_create( sqlite3 *db, const char *zName, sqlite3_intarray **ppReturn @@ -115,7 +115,7 @@ int sqlite3_intarray_create( ** any query against the corresponding virtual table. If the integer ** array does change or is deallocated undefined behavior will result. */ -int sqlite3_intarray_bind( +SQLITE_API int sqlite3_intarray_bind( sqlite3_intarray *pIntArray, /* The intarray object to bind to */ int nElements, /* Number of elements in the intarray */ sqlite3_int64 *aElements, /* Content of the intarray */ From 7fb91646b56fb33bad80abd34a8d34938fb461c5 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 14:37:09 +0000 Subject: [PATCH 13/42] Refactor local variable names in the freeSpace() routine of btree.c for improved understandability. FossilOrigin-Name: 7e63089a191f29aefde05e89bb612f3036cfa034 --- manifest | 13 ++++---- manifest.uuid | 2 +- src/btree.c | 85 +++++++++++++++++++++++++++------------------------ 3 files changed, 52 insertions(+), 48 deletions(-) diff --git a/manifest b/manifest index c03b96d1a8..c1cbe5415f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Size\sreduction\sand\sperformance\simprovements\sin\sbtree.c\sand\sthe\nallocateSpace()\sroutine.\s\sAlso\sfix\san\sassert()\sin\sfreeSpace(). -D 2014-08-20T13:35:45.034 +C Refactor\slocal\svariable\snames\sin\sthe\sfreeSpace()\sroutine\sof\sbtree.c\sfor\nimproved\sunderstandability. +D 2014-08-20T14:37:09.167 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 53eb576f72093d5138f5b7468994121c6eb6fe98 +F src/btree.c c1235eacb8d4de12850daccb1636763218da3381 F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b @@ -1186,8 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P eea0661798e10018615854c871f24be0f8bb2ff9 fe51d3aa0ce7021213293a0647e31164073e78f7 -R 3c51b363f531f6f6895a1e7e29ea4492 -T +closed fe51d3aa0ce7021213293a0647e31164073e78f7 +P 121308fa869ad490a6924798d276c0ff32759acc +R 332118792b6ef82f7eceb02b0d545622 U drh -Z 25da1aeccb4d6e0fa0390c2ee1a22b6e +Z accc32db7c4714707b5e7cc22312c49c diff --git a/manifest.uuid b/manifest.uuid index aa49654c6a..1b60255c36 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -121308fa869ad490a6924798d276c0ff32759acc \ No newline at end of file +7e63089a191f29aefde05e89bb612f3036cfa034 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index a09b82fe5e..ac13b0f3da 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1290,28 +1290,30 @@ defragment_page: /* ** Return a section of the pPage->aData to the freelist. -** The first byte of the new free block is pPage->aDisk[start] -** and the size of the block is "size" bytes. +** The first byte of the new free block is pPage->aData[iStart] +** and the size of the block is iSize bytes. ** ** Most of the effort here is involved in coalesing adjacent ** free blocks into a single big free block. */ -static int freeSpace(MemPage *pPage, int start, int size){ - int addr, pbegin, hdr; - int iLast; /* Largest possible freeblock offset */ - unsigned char *data = pPage->aData; +static int freeSpace(MemPage *pPage, int iStart, int iSize){ + int iPtr; /* Address of pointer to next freeblock */ + int iFreeBlk; /* Address of the next freeblock */ + int hdr; /* Page header size. 0 or 100 */ + int iLast; /* Largest possible freeblock offset */ + unsigned char *data = pPage->aData; /* Page content */ assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); - assert( (start + size) <= (int)pPage->pBt->usableSize ); + assert( iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); + assert( (iStart + iSize) <= (int)pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( size>=4 ); /* Minimum cell size is 4 */ + assert( iSize>=4 ); /* Minimum cell size is 4 */ if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){ /* Overwrite deleted information with zeros when the secure_delete ** option is enabled */ - memset(&data[start], 0, size); + memset(&data[iStart], 0, iSize); } /* Add the space back into the linked list of freeblocks. Note that @@ -1324,53 +1326,56 @@ static int freeSpace(MemPage *pPage, int start, int size){ ** the freelist. */ hdr = pPage->hdrOffset; - addr = hdr + 1; + iPtr = hdr + 1; iLast = pPage->pBt->usableSize - 4; - assert( start<=iLast ); - while( (pbegin = get2byte(&data[addr]))0 ){ - if( pbegin0 ){ + if( iFreeBlkiLast ){ + if( iFreeBlk>iLast ){ return SQLITE_CORRUPT_BKPT; } - assert( pbegin>addr || pbegin==0 ); - put2byte(&data[addr], start); - put2byte(&data[start], pbegin); - put2byte(&data[start+2], size); - pPage->nFree = pPage->nFree + (u16)size; + assert( iFreeBlk>iPtr || iFreeBlk==0 ); + put2byte(&data[iPtr], iStart); + put2byte(&data[iStart], iFreeBlk); + put2byte(&data[iStart+2], iSize); + pPage->nFree = pPage->nFree + (u16)iSize; /* Coalesce adjacent free blocks */ - addr = hdr + 1; - while( (pbegin = get2byte(&data[addr]))>0 ){ - int pnext, psize, x; - assert( pbegin>addr ); - assert( pbegin <= (int)pPage->pBt->usableSize-4 ); - pnext = get2byte(&data[pbegin]); - psize = get2byte(&data[pbegin+2]); - if( pbegin + psize + 3 >= pnext && pnext>0 ){ - int frag = pnext - (pbegin+psize); - if( (frag<0) || (frag>(int)data[hdr+7]) ){ + iPtr = hdr + 1; + while( (iFreeBlk = get2byte(&data[iPtr]))>0 ){ + int iNextBlk; /* Next freeblock after iFreeBlk */ + int szFreeBlk; /* Size of iFreeBlk */ + assert( iFreeBlk>iPtr ); + assert( iFreeBlk <= (int)pPage->pBt->usableSize-4 ); + iNextBlk = get2byte(&data[iFreeBlk]); + szFreeBlk = get2byte(&data[iFreeBlk+2]); + if( iFreeBlk + szFreeBlk + 3 >= iNextBlk && iNextBlk>0 ){ + int nFrag; /* Fragment bytes in between iFreeBlk and iNextBlk */ + int x; /* Temp value */ + nFrag = iNextBlk - (iFreeBlk+szFreeBlk); + if( (nFrag<0) || (nFrag>(int)data[hdr+7]) ){ return SQLITE_CORRUPT_BKPT; } - data[hdr+7] -= (u8)frag; - x = get2byte(&data[pnext]); - put2byte(&data[pbegin], x); - x = pnext + get2byte(&data[pnext+2]) - pbegin; - put2byte(&data[pbegin+2], x); + data[hdr+7] -= (u8)nFrag; + x = get2byte(&data[iNextBlk]); + put2byte(&data[iFreeBlk], x); + x = iNextBlk + get2byte(&data[iNextBlk+2]) - iFreeBlk; + put2byte(&data[iFreeBlk+2], x); }else{ - addr = pbegin; + iPtr = iFreeBlk; } } /* If the cell content area begins with a freeblock, remove it. */ if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ int top; - pbegin = get2byte(&data[hdr+1]); - memcpy(&data[hdr+1], &data[pbegin], 2); - top = get2byte(&data[hdr+5]) + get2byte(&data[pbegin+2]); + iFreeBlk = get2byte(&data[hdr+1]); + memcpy(&data[hdr+1], &data[iFreeBlk], 2); + top = get2byte(&data[hdr+5]) + get2byte(&data[iFreeBlk+2]); put2byte(&data[hdr+5], top); } assert( sqlite3PagerIswriteable(pPage->pDbPage) ); From 5f5c753efbbe23df1e52a0560c2b7abbc0f3c334 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 17:56:27 +0000 Subject: [PATCH 14/42] Reimplement the freeSpace() routine in btree.c so that it runs faster. FossilOrigin-Name: fe4fd014b42b7b158ca968f1535b5636c67769f6 --- manifest | 12 ++--- manifest.uuid | 2 +- src/btree.c | 125 +++++++++++++++++++++++++------------------------- 3 files changed, 70 insertions(+), 69 deletions(-) diff --git a/manifest b/manifest index c1cbe5415f..4fe8e5ec20 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Refactor\slocal\svariable\snames\sin\sthe\sfreeSpace()\sroutine\sof\sbtree.c\sfor\nimproved\sunderstandability. -D 2014-08-20T14:37:09.167 +C Reimplement\sthe\sfreeSpace()\sroutine\sin\sbtree.c\sso\sthat\sit\sruns\sfaster. +D 2014-08-20T17:56:27.585 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c c1235eacb8d4de12850daccb1636763218da3381 +F src/btree.c fe2d11c8c0d99e324614141ad012b37d0601cf59 F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 121308fa869ad490a6924798d276c0ff32759acc -R 332118792b6ef82f7eceb02b0d545622 +P 7e63089a191f29aefde05e89bb612f3036cfa034 +R cbff1ae81d05ca3b78b420deaaa6083f U drh -Z accc32db7c4714707b5e7cc22312c49c +Z d684bbbc1bfe7cdee532398c2232ddf8 diff --git a/manifest.uuid b/manifest.uuid index 1b60255c36..238682a66d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7e63089a191f29aefde05e89bb612f3036cfa034 \ No newline at end of file +fe4fd014b42b7b158ca968f1535b5636c67769f6 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index ac13b0f3da..c10e2f1c32 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1293,92 +1293,93 @@ defragment_page: ** The first byte of the new free block is pPage->aData[iStart] ** and the size of the block is iSize bytes. ** -** Most of the effort here is involved in coalesing adjacent -** free blocks into a single big free block. +** Adjacent freeblocks are coalesced. +** +** Note that even though the freeblock list was checked by btreeInitPage(), +** that routine will not detect overlap between cells or freeblocks. Nor +** does it detect cells or freeblocks that encrouch into the reserved bytes +** at the end of the page. So do additional corruption checks inside this +** routine and return SQLITE_CORRUPT if any problems are found. */ -static int freeSpace(MemPage *pPage, int iStart, int iSize){ - int iPtr; /* Address of pointer to next freeblock */ - int iFreeBlk; /* Address of the next freeblock */ - int hdr; /* Page header size. 0 or 100 */ - int iLast; /* Largest possible freeblock offset */ +static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ + u16 iPtr; /* Address of pointer to next freeblock */ + u16 iFreeBlk; /* Address of the next freeblock */ + u8 hdr; /* Page header size. 0 or 100 */ + u8 nFrag = 0; /* Reduction in fragmentation */ + u16 iOrigSize = iSize; /* Original value of iSize */ + u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */ + u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ unsigned char *data = pPage->aData; /* Page content */ assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); - assert( (iStart + iSize) <= (int)pPage->pBt->usableSize ); + assert( iEnd <= pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( iSize>=4 ); /* Minimum cell size is 4 */ + assert( iStart<=iLast ); + /* Overwrite deleted information with zeros when the secure_delete + ** option is enabled */ if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){ - /* Overwrite deleted information with zeros when the secure_delete - ** option is enabled */ memset(&data[iStart], 0, iSize); } - /* Add the space back into the linked list of freeblocks. Note that - ** even though the freeblock list was checked by btreeInitPage(), - ** btreeInitPage() did not detect overlapping cells or - ** freeblocks that overlapped cells. Nor does it detect when the - ** cell content area exceeds the value in the page header. If these - ** situations arise, then subsequent insert operations might corrupt - ** the freelist. So we do need to check for corruption while scanning - ** the freelist. + /* The list of freeblocks must be in ascending order. Find the + ** spot on the list where iStart should be inserted. */ hdr = pPage->hdrOffset; iPtr = hdr + 1; - iLast = pPage->pBt->usableSize - 4; - assert( iStart<=iLast ); - while( (iFreeBlk = get2byte(&data[iPtr]))0 ){ - if( iFreeBlk0 && iFreeBlkiLast ){ - return SQLITE_CORRUPT_BKPT; - } + if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT; assert( iFreeBlk>iPtr || iFreeBlk==0 ); - put2byte(&data[iPtr], iStart); - put2byte(&data[iStart], iFreeBlk); - put2byte(&data[iStart+2], iSize); - pPage->nFree = pPage->nFree + (u16)iSize; - /* Coalesce adjacent free blocks */ - iPtr = hdr + 1; - while( (iFreeBlk = get2byte(&data[iPtr]))>0 ){ - int iNextBlk; /* Next freeblock after iFreeBlk */ - int szFreeBlk; /* Size of iFreeBlk */ - assert( iFreeBlk>iPtr ); - assert( iFreeBlk <= (int)pPage->pBt->usableSize-4 ); - iNextBlk = get2byte(&data[iFreeBlk]); - szFreeBlk = get2byte(&data[iFreeBlk+2]); - if( iFreeBlk + szFreeBlk + 3 >= iNextBlk && iNextBlk>0 ){ - int nFrag; /* Fragment bytes in between iFreeBlk and iNextBlk */ - int x; /* Temp value */ - nFrag = iNextBlk - (iFreeBlk+szFreeBlk); - if( (nFrag<0) || (nFrag>(int)data[hdr+7]) ){ - return SQLITE_CORRUPT_BKPT; - } - data[hdr+7] -= (u8)nFrag; - x = get2byte(&data[iNextBlk]); - put2byte(&data[iFreeBlk], x); - x = iNextBlk + get2byte(&data[iNextBlk+2]) - iFreeBlk; - put2byte(&data[iFreeBlk+2], x); - }else{ - iPtr = iFreeBlk; + /* At this point: + ** iFreeBlk: First freeblock after iStart, or zero if none + ** iPtr: The address of a pointer iFreeBlk + ** + ** Check to see if iFreeBlk should be coalesced onto the end of iStart. + */ + if( iFreeBlk && iEnd+3>=iFreeBlk ){ + nFrag = iFreeBlk - iEnd; + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT; + iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); + iSize = iEnd - iStart; + iFreeBlk = get2byte(&data[iFreeBlk]); + } + + /* If iPtr is another freeblock (that is, if iPtr is not the freelist pointer + ** in the page header) then check to see if iStart should be coalesced + ** onto the end of iPtr. + */ + if( iPtr>hdr+1 ){ + int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); + if( iPtrEnd+3>=iStart ){ + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT; + nFrag += iStart - iPtrEnd; + iSize = iEnd - iPtr; + iStart = iPtr; } } + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT; - /* If the cell content area begins with a freeblock, remove it. */ - if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ - int top; - iFreeBlk = get2byte(&data[hdr+1]); - memcpy(&data[hdr+1], &data[iFreeBlk], 2); - top = get2byte(&data[hdr+5]) + get2byte(&data[iFreeBlk+2]); - put2byte(&data[hdr+5], top); + data[hdr+7] -= nFrag; + if( iPtr==hdr+1 && iStart==get2byte(&data[hdr+5]) ){ + /* The new freeblock is at the beginning of the cell content area, + ** so just extend the cell content area rather than create another + ** freelist entry */ + put2byte(&data[hdr+1], iFreeBlk); + put2byte(&data[hdr+5], iEnd); + }else{ + /* Insert the new freeblock into the freelist */ + put2byte(&data[iPtr], iStart); + put2byte(&data[iStart], iFreeBlk); + put2byte(&data[iStart+2], iSize); } - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + pPage->nFree += iOrigSize; return SQLITE_OK; } From 7bc4c454dab1568702db8ef230c624edc35ed815 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 18:43:44 +0000 Subject: [PATCH 15/42] A small performance improvement in freeSpace() by special-casing the relatively common case of an empty freelist. FossilOrigin-Name: 49f44d355ff70744e4951baca2481c7c2b6c02b3 --- manifest | 12 ++++---- manifest.uuid | 2 +- src/btree.c | 76 +++++++++++++++++++++++++++------------------------ 3 files changed, 47 insertions(+), 43 deletions(-) diff --git a/manifest b/manifest index 4fe8e5ec20..0e55755198 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reimplement\sthe\sfreeSpace()\sroutine\sin\sbtree.c\sso\sthat\sit\sruns\sfaster. -D 2014-08-20T17:56:27.585 +C A\ssmall\sperformance\simprovement\sin\sfreeSpace()\sby\sspecial-casing\sthe\nrelatively\scommon\scase\sof\san\sempty\sfreelist. +D 2014-08-20T18:43:44.510 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c fe2d11c8c0d99e324614141ad012b37d0601cf59 +F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b @@ -1186,7 +1186,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7e63089a191f29aefde05e89bb612f3036cfa034 -R cbff1ae81d05ca3b78b420deaaa6083f +P fe4fd014b42b7b158ca968f1535b5636c67769f6 +R 865eceb09aea170bb70d44b771b85e6e U drh -Z d684bbbc1bfe7cdee532398c2232ddf8 +Z 0631afdcc5729e41fc50a75336710200 diff --git a/manifest.uuid b/manifest.uuid index 238682a66d..2bb2527d30 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fe4fd014b42b7b158ca968f1535b5636c67769f6 \ No newline at end of file +49f44d355ff70744e4951baca2481c7c2b6c02b3 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index c10e2f1c32..56718b69d6 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1330,47 +1330,51 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ */ hdr = pPage->hdrOffset; iPtr = hdr + 1; - while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlkiLast ) return SQLITE_CORRUPT_BKPT; - assert( iFreeBlk>iPtr || iFreeBlk==0 ); - - /* At this point: - ** iFreeBlk: First freeblock after iStart, or zero if none - ** iPtr: The address of a pointer iFreeBlk - ** - ** Check to see if iFreeBlk should be coalesced onto the end of iStart. - */ - if( iFreeBlk && iEnd+3>=iFreeBlk ){ - nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT; - iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); - iSize = iEnd - iStart; - iFreeBlk = get2byte(&data[iFreeBlk]); - } - - /* If iPtr is another freeblock (that is, if iPtr is not the freelist pointer - ** in the page header) then check to see if iStart should be coalesced - ** onto the end of iPtr. - */ - if( iPtr>hdr+1 ){ - int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); - if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT; - nFrag += iStart - iPtrEnd; - iSize = iEnd - iPtr; - iStart = iPtr; + if( data[iPtr+1]==0 && data[iPtr]==0 ){ + iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ + }else{ + while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlkiLast ) return SQLITE_CORRUPT_BKPT; + assert( iFreeBlk>iPtr || iFreeBlk==0 ); + + /* At this point: + ** iFreeBlk: First freeblock after iStart, or zero if none + ** iPtr: The address of a pointer iFreeBlk + ** + ** Check to see if iFreeBlk should be coalesced onto the end of iStart. + */ + if( iFreeBlk && iEnd+3>=iFreeBlk ){ + nFrag = iFreeBlk - iEnd; + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT; + iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); + iSize = iEnd - iStart; + iFreeBlk = get2byte(&data[iFreeBlk]); + } + + /* If iPtr is another freeblock (that is, if iPtr is not the freelist pointer + ** in the page header) then check to see if iStart should be coalesced + ** onto the end of iPtr. + */ + if( iPtr>hdr+1 ){ + int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); + if( iPtrEnd+3>=iStart ){ + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT; + nFrag += iStart - iPtrEnd; + iSize = iEnd - iPtr; + iStart = iPtr; + } + } + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT; + data[hdr+7] -= nFrag; } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT; - - data[hdr+7] -= nFrag; - if( iPtr==hdr+1 && iStart==get2byte(&data[hdr+5]) ){ + if( iStart==get2byte(&data[hdr+5]) ){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ + if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT; put2byte(&data[hdr+1], iFreeBlk); put2byte(&data[hdr+5], iEnd); }else{ From f3f69ac942f6cbe0f143659399281c162ad1e743 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 23:38:07 +0000 Subject: [PATCH 16/42] Enhancements to skip-scan such that it is operable when a middle column of an index is skipped while the left-most column is constrained in the WHERE clause. FossilOrigin-Name: bc985caa7816f1f873ad8e4467c5278399f315ce --- manifest | 13 ++++---- manifest.uuid | 2 +- src/where.c | 21 +++++++++---- test/skipscan3.test | 73 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 test/skipscan3.test diff --git a/manifest b/manifest index 0e55755198..928130ab8a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C A\ssmall\sperformance\simprovement\sin\sfreeSpace()\sby\sspecial-casing\sthe\nrelatively\scommon\scase\sof\san\sempty\sfreelist. -D 2014-08-20T18:43:44.510 +C Enhancements\sto\sskip-scan\ssuch\sthat\sit\sis\soperable\swhen\sa\smiddle\scolumn\sof\nan\sindex\sis\sskipped\swhile\sthe\sleft-most\scolumn\sis\sconstrained\sin\sthe\sWHERE\nclause. +D 2014-08-20T23:38:07.310 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -296,7 +296,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c ab20f9c24a422ee8900831b343c3d1e5e7aca87b +F src/where.c 4c499d185827a492643cf017ae5e3aa0523f9f18 F src/whereInt.h 923820bee9726033a501a08d2fc69b9c1ee4feb3 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -832,6 +832,7 @@ F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868 F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329 F test/skipscan1.test 28c7faa41a0d7265040ecb0a0abd90c0904270b2 F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a +F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan5.test d8b9692b702745a0e41c23f9da6beac81df01196 F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24 @@ -1186,7 +1187,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fe4fd014b42b7b158ca968f1535b5636c67769f6 -R 865eceb09aea170bb70d44b771b85e6e +P 49f44d355ff70744e4951baca2481c7c2b6c02b3 +R 96923099996337b045b25027695cfca6 U drh -Z 0631afdcc5729e41fc50a75336710200 +Z 1b9938878e462b798940573e6153541a diff --git a/manifest.uuid b/manifest.uuid index 2bb2527d30..c25a80761d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -49f44d355ff70744e4951baca2481c7c2b6c02b3 \ No newline at end of file +bc985caa7816f1f873ad8e4467c5278399f315ce \ No newline at end of file diff --git a/src/where.c b/src/where.c index 9c30136e87..6a4299cc9a 100644 --- a/src/where.c +++ b/src/where.c @@ -3781,8 +3781,8 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ sqlite3DebugPrintf(" %12s", pItem->zAlias ? pItem->zAlias : pTab->zName); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - const char *zName; - if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ + const char *zName; + if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ int i = sqlite3Strlen30(zName) - 1; while( zName[i]!='_' ) i--; @@ -3803,7 +3803,11 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ sqlite3DebugPrintf(" %-19s", z); sqlite3_free(z); } - sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); + if( p->wsFlags & WHERE_SKIPSCAN ){ + sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->u.btree.nSkip); + }else{ + sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); + } sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); #ifdef SQLITE_ENABLE_TREE_EXPLAIN /* If the 0x100 bit of wheretracing is set, then show all of the constraint @@ -4316,8 +4320,7 @@ static int whereLoopAddBtreeIndex( ** On the other hand, the extra seeks could end up being significantly ** more expensive. */ assert( 42==sqlite3LogEst(18) ); - if( pTerm==0 - && saved_nEq==saved_nSkip + if( saved_nEq==saved_nSkip && saved_nEq+1nKeyCol && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK @@ -4328,9 +4331,17 @@ static int whereLoopAddBtreeIndex( pNew->aLTerm[pNew->nLTerm++] = 0; pNew->wsFlags |= WHERE_SKIPSCAN; nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1]; + if( pTerm ){ + /* TUNING: When estimating skip-scan for a term that is also indexable, + ** increase the cost of the skip-scan by 2x, to make it a little less + ** desirable than the regular index lookup. */ + nIter += 10; assert( 10==sqlite3LogEst(2) ); + } pNew->nOut -= nIter; whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); pNew->nOut = saved_nOut; + pNew->u.btree.nEq = saved_nEq; + pNew->u.btree.nSkip = saved_nSkip; } for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */ diff --git a/test/skipscan3.test b/test/skipscan3.test new file mode 100644 index 0000000000..260d11cac9 --- /dev/null +++ b/test/skipscan3.test @@ -0,0 +1,73 @@ +# 2014-08-20 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file implements tests of the "skip-scan" query strategy. +# In particular, this file looks at skipping intermediate terms +# in an index. For example, if (a,b,c) are indexed, and we have +# "WHERE a=?1 AND c=?2" - verify that skip-scan can still be used. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_execsql_test skipscan3-1.1 { + CREATE TABLE t1(a,b,c,d,PRIMARY KEY(a,b,c)); + WITH RECURSIVE + c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000) + INSERT INTO t1(a,b,c,d) + SELECT 1, 1, x, printf('x%04d',x) FROM c; + ANALYZE; +} {} + +# This version has long used skip-scan because of the "+a" +# +do_execsql_test skipscan3-1.2eqp { + EXPLAIN QUERY PLAN SELECT d FROM t1 WHERE +a=1 AND c=32; +} {/*ANY(a) AND ANY(b)*/} +do_execsql_test skipscan3-1.2 { + SELECT d FROM t1 WHERE +a=1 AND c=32; +} {x0032} + +# This version (with "a" instead of "+a") should use skip-scan but +# did not prior to changes implemented on 2014-08-20 +# +do_execsql_test skipscan3-1.3eqp { + EXPLAIN QUERY PLAN SELECT d FROM t1 WHERE a=1 AND c=32; +} {/*ANY(a) AND ANY(b)*/} +do_execsql_test skipscan3-1.3 { + SELECT d FROM t1 WHERE a=1 AND c=32; +} {x0032} + +# Repeat the test on a WITHOUT ROWID table +# +do_execsql_test skipscan3-2.1 { + CREATE TABLE t2(a,b,c,d,PRIMARY KEY(a,b,c)) WITHOUT ROWID; + WITH RECURSIVE + c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000) + INSERT INTO t2(a,b,c,d) + SELECT 1, 1, x, printf('x%04d',x) FROM c; + ANALYZE; +} {} +do_execsql_test skipscan3-2.2eqp { + EXPLAIN QUERY PLAN SELECT d FROM t2 WHERE +a=1 AND c=32; +} {/*ANY(a) AND ANY(b)*/} +do_execsql_test skipscan3-2.2 { + SELECT d FROM t2 WHERE +a=1 AND c=32; +} {x0032} +do_execsql_test skipscan3-2.3eqp { + EXPLAIN QUERY PLAN SELECT d FROM t2 WHERE a=1 AND c=32; +} {/*ANY(a) AND ANY(b)*/} +do_execsql_test skipscan3-2.3 { + SELECT d FROM t2 WHERE a=1 AND c=32; +} {x0032} + + +finish_test From b614eab3d2da06fea1c23eb3dbc08816ed178b5e Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 20 Aug 2014 23:42:50 +0000 Subject: [PATCH 17/42] Increase the version number to 3.8.7 FossilOrigin-Name: 91594aae0725388765070c80039dfe1bf126392d --- VERSION | 2 +- configure | 18 +++++++++--------- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/VERSION b/VERSION index 2e14a9557d..4351a7e3a3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.8.6 +3.8.7 diff --git a/configure b/configure index 8748a98406..9b8266d812 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.62 for sqlite 3.8.6. +# Generated by GNU Autoconf 2.62 for sqlite 3.8.7. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.8.6' -PACKAGE_STRING='sqlite 3.8.6' +PACKAGE_VERSION='3.8.7' +PACKAGE_STRING='sqlite 3.8.7' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. @@ -1483,7 +1483,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.8.6 to adapt to many kinds of systems. +\`configure' configures sqlite 3.8.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1548,7 +1548,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.8.6:";; + short | recursive ) echo "Configuration of sqlite 3.8.7:";; esac cat <<\_ACEOF @@ -1664,7 +1664,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.8.6 +sqlite configure 3.8.7 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1678,7 +1678,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.8.6, which was +It was created by sqlite $as_me 3.8.7, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ @@ -14021,7 +14021,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.8.6, which was +This file was extended by sqlite $as_me 3.8.7, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14074,7 +14074,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -sqlite config.status 3.8.6 +sqlite config.status 3.8.7 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/manifest b/manifest index 928130ab8a..292e662207 100644 --- a/manifest +++ b/manifest @@ -1,12 +1,12 @@ -C Enhancements\sto\sskip-scan\ssuch\sthat\sit\sis\soperable\swhen\sa\smiddle\scolumn\sof\nan\sindex\sis\sskipped\swhile\sthe\sleft-most\scolumn\sis\sconstrained\sin\sthe\sWHERE\nclause. -D 2014-08-20T23:38:07.310 +C Increase\sthe\sversion\snumber\sto\s3.8.7 +D 2014-08-20T23:42:50.860 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.msc 5b04e657cf08a9ac7fc47d876c5c8be962c47d6b F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0 F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8 -F VERSION 1c877615a9db323e3cd301e3d57d853f9d5c4a07 +F VERSION 53a0b870e7f16d3b06623c31d233a304c163a6af F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 @@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure 513f1e2464c3673bcdb5471b13d98e7eeb6f5ca2 x +F configure ad59a5f48b3c59a92b5506040a22fbe3f733a9d8 x F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 @@ -1187,7 +1187,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 49f44d355ff70744e4951baca2481c7c2b6c02b3 -R 96923099996337b045b25027695cfca6 +P bc985caa7816f1f873ad8e4467c5278399f315ce +R 69e5d59c0ae1acccebd6955e02833316 U drh -Z 1b9938878e462b798940573e6153541a +Z 5338496858d2cbdf1a890a2630150d12 diff --git a/manifest.uuid b/manifest.uuid index c25a80761d..d619efb0e7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bc985caa7816f1f873ad8e4467c5278399f315ce \ No newline at end of file +91594aae0725388765070c80039dfe1bf126392d \ No newline at end of file From b6b4b79f344096791542265763467fc90f139c2e Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 21 Aug 2014 14:10:23 +0000 Subject: [PATCH 18/42] Fix a faulty assert() statement. Add comments to clarify the behavior of the sqlite3OpenTableAndIndices() routine in insert.c. Add test cases to verify that the assert() statement is not firing inappropriately. Ticket [369d57fb8e5ccdff06f1]. FossilOrigin-Name: 7029b3404d3f5f698a496934f3a3f2972051b257 --- ext/rtree/rtreeF.test | 81 +++++++++++++++++++++++++++++++++++++++++++ manifest | 15 ++++---- manifest.uuid | 2 +- src/delete.c | 8 +++-- src/insert.c | 9 +++-- 5 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 ext/rtree/rtreeF.test diff --git a/ext/rtree/rtreeF.test b/ext/rtree/rtreeF.test new file mode 100644 index 0000000000..c9620d34f7 --- /dev/null +++ b/ext/rtree/rtreeF.test @@ -0,0 +1,81 @@ +# 2014-08-21 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file contains tests for the r-tree module. +# +# This file contains test cases for the ticket +# [369d57fb8e5ccdff06f197a37147a88f9de95cda] (2014-08-21) +# +# The following SQL causes an assertion fault while running +# sqlite3_prepare() on the DELETE statement: +# +# CREATE TABLE t1(x); +# CREATE TABLE t2(y); +# CREATE VIRTUAL TABLE t3 USING rtree(a,b,c); +# CREATE TRIGGER t2del AFTER DELETE ON t2 WHEN (SELECT 1 from t1) BEGIN +# DELETE FROM t3 WHERE a=old.y; +# END; +# DELETE FROM t2 WHERE y=1; +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source $testdir/tester.tcl +ifcapable !rtree { finish_test ; return } + +do_execsql_test rtreeF-1.1 { + CREATE TABLE t1(x); + CREATE TABLE t2(y); + CREATE VIRTUAL TABLE t3 USING rtree(a,b,c); + CREATE TRIGGER t2dwl AFTER DELETE ON t2 WHEN (SELECT 1 from t1) BEGIN + DELETE FROM t3 WHERE a=old.y; + END; + + INSERT INTO t1(x) VALUES(999); + INSERT INTO t2(y) VALUES(1),(2),(3),(4),(5); + INSERT INTO t3(a,b,c) VALUES(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7); + + SELECT a FROM t3 ORDER BY a; + SELECT '|'; + SELECT y FROM t2 ORDER BY y; +} {1 2 3 4 5 | 1 2 3 4 5} +do_execsql_test rtreeF-1.2 { + DELETE FROM t2 WHERE y=3; + + SELECT a FROM t3 ORDER BY a; + SELECT '|'; + SELECT y FROM t2 ORDER BY y; +} {1 2 4 5 | 1 2 4 5} +do_execsql_test rtreeF-1.3 { + DELETE FROM t1; + DELETE FROM t2 WHERE y=5; + + SELECT a FROM t3 ORDER BY a; + SELECT '|'; + SELECT y FROM t2 ORDER BY y; +} {1 2 4 5 | 1 2 4} +do_execsql_test rtreeF-1.4 { + INSERT INTO t1 DEFAULT VALUES; + DELETE FROM t2 WHERE y=5; + + SELECT a FROM t3 ORDER BY a; + SELECT '|'; + SELECT y FROM t2 ORDER BY y; +} {1 2 4 5 | 1 2 4} +do_execsql_test rtreeF-1.5 { + DELETE FROM t2 WHERE y=2; + + SELECT a FROM t3 ORDER BY a; + SELECT '|'; + SELECT y FROM t2 ORDER BY y; +} {1 4 5 | 1 4} + +finish_test diff --git a/manifest b/manifest index 292e662207..1e5132fbcf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.8.7 -D 2014-08-20T23:42:50.860 +C Fix\sa\sfaulty\sassert()\sstatement.\s\sAdd\scomments\sto\sclarify\sthe\sbehavior\sof\nthe\ssqlite3OpenTableAndIndices()\sroutine\sin\sinsert.c.\s\sAdd\stest\scases\sto\nverify\sthat\sthe\sassert()\sstatement\sis\snot\sfiring\sinappropriately.\nTicket\s[369d57fb8e5ccdff06f1]. +D 2014-08-21T14:10:23.770 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -138,6 +138,7 @@ F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06 F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca F ext/rtree/rtreeE.test 388c1c8602c3ce55c15f03b509e9cf545fb7c41f +F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd @@ -175,7 +176,7 @@ F src/callback.c fcff28cf0df2403dd2f313bb8d1b8f31f6f3cd64 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf +F src/delete.c 5adcd322c6b08fc25d215d780ca62cebce66304d F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 8545f3b36da47473e10800ea4fb0810fd4062514 @@ -184,7 +185,7 @@ F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 991e4964e9295da3993e2c0f81c7faf642371848 +F src/insert.c d1a104e67b33314d4cc5c1356147446086ab9fc8 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c febc2a9e7ad6c1a6191c7b5b9170b325d263f343 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -1187,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bc985caa7816f1f873ad8e4467c5278399f315ce -R 69e5d59c0ae1acccebd6955e02833316 +P 91594aae0725388765070c80039dfe1bf126392d +R 25e887863ed8cfd2c8a241fac46385f1 U drh -Z 5338496858d2cbdf1a890a2630150d12 +Z ed55b6e966354470a11e6c95fe10b90c diff --git a/manifest.uuid b/manifest.uuid index d619efb0e7..944f894bbc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -91594aae0725388765070c80039dfe1bf126392d \ No newline at end of file +7029b3404d3f5f698a496934f3a3f2972051b257 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index c74d8eab7d..af83903c42 100644 --- a/src/delete.c +++ b/src/delete.c @@ -466,10 +466,11 @@ void sqlite3DeleteFrom( ** triggers. */ if( !isView ){ + testcase( IsVirtual(pTab) ); sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen, &iDataCur, &iIdxCur); - assert( pPk || iDataCur==iTabCur ); - assert( pPk || iIdxCur==iDataCur+1 ); + assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); + assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); } /* Set up a loop over the rowids/primary-keys that were found in the @@ -477,7 +478,8 @@ void sqlite3DeleteFrom( */ if( okOnePass ){ /* Just one row. Hence the top-of-loop is a no-op */ - assert( nKey==nPk ); /* OP_Found will use an unpacked key */ + assert( nKey==nPk ); /* OP_Found will use an unpacked key */ + assert( !IsVirtual(pTab) ); if( aToOpen[iDataCur-iTabCur] ){ assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); diff --git a/src/insert.c b/src/insert.c index 5964b91ca4..3e6982d836 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1612,6 +1612,9 @@ void sqlite3CompleteInsertion( ** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range ** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the ** pTab->pIndex list. +** +** If pTab is a virtual table, then this routine is a no-op and the +** *piDataCur and *piIdxCur values are left uninitialized. */ int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ @@ -1630,9 +1633,9 @@ int sqlite3OpenTableAndIndices( assert( op==OP_OpenRead || op==OP_OpenWrite ); if( IsVirtual(pTab) ){ - assert( aToOpen==0 ); - *piDataCur = 0; - *piIdxCur = 1; + /* This routine is a no-op for virtual tables. Leave the output + ** variables *piDataCur and *piIdxCur uninitialized so that valgrind + ** can detect if they are used by mistake in the caller. */ return 0; } iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); From acbcb7e013b0c2d54f8b0977a464badc260d7048 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 21 Aug 2014 20:26:37 +0000 Subject: [PATCH 19/42] Simplify the interface to the symbol table, saving 600 bytes of code space. FossilOrigin-Name: 14b0f561fe15622b61c6676c9c455dca6b9ba5f0 --- manifest | 26 ++++++++++---------- manifest.uuid | 2 +- src/build.c | 24 ++++++------------ src/callback.c | 8 +++--- src/fkey.c | 5 ++-- src/hash.c | 66 ++++++++++++++++++++------------------------------ src/hash.h | 6 ++--- src/main.c | 3 +-- src/trigger.c | 17 +++++-------- src/vtab.c | 11 ++++----- 10 files changed, 69 insertions(+), 99 deletions(-) diff --git a/manifest b/manifest index 1e5132fbcf..bcba60c6c2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sfaulty\sassert()\sstatement.\s\sAdd\scomments\sto\sclarify\sthe\sbehavior\sof\nthe\ssqlite3OpenTableAndIndices()\sroutine\sin\sinsert.c.\s\sAdd\stest\scases\sto\nverify\sthat\sthe\sassert()\sstatement\sis\snot\sfiring\sinappropriately.\nTicket\s[369d57fb8e5ccdff06f1]. -D 2014-08-21T14:10:23.770 +C Simplify\sthe\sinterface\sto\sthe\ssymbol\stable,\ssaving\s600\sbytes\sof\scode\sspace. +D 2014-08-21T20:26:37.728 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -171,26 +171,26 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 -F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b -F src/callback.c fcff28cf0df2403dd2f313bb8d1b8f31f6f3cd64 +F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb +F src/callback.c b97d0695ffcf6a8710ee445ffe56ee387d4d8a6f F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c 5adcd322c6b08fc25d215d780ca62cebce66304d F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 8545f3b36da47473e10800ea4fb0810fd4062514 +F src/fkey.c 8d81a780ad78d16ec9082585758a8f1d6bf02ca3 F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7 F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4 -F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd -F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 +F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 +F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c d1a104e67b33314d4cc5c1356147446086ab9fc8 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c febc2a9e7ad6c1a6191c7b5b9170b325d263f343 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c 1cf92c5c6468f2b6ed99b638706781ccc9c60b42 +F src/main.c 1e5d34fb6dee85019b4bcc44e8576457b5075174 F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b @@ -279,7 +279,7 @@ F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec -F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb +F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e @@ -293,7 +293,7 @@ F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 -F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd +F src/vtab.c 180bfc5e69c92f2014c094bc49a66e8c37c188ac F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 91594aae0725388765070c80039dfe1bf126392d -R 25e887863ed8cfd2c8a241fac46385f1 +P 7029b3404d3f5f698a496934f3a3f2972051b257 +R 818f77c3be876451b2dad41de8a59565 U drh -Z ed55b6e966354470a11e6c95fe10b90c +Z cb34ea9e2178e12926edef43b644d982 diff --git a/manifest.uuid b/manifest.uuid index 944f894bbc..98b1fd2ac2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7029b3404d3f5f698a496934f3a3f2972051b257 \ No newline at end of file +14b0f561fe15622b61c6676c9c455dca6b9ba5f0 \ No newline at end of file diff --git a/src/build.c b/src/build.c index a9a8f21793..af776cb3d8 100644 --- a/src/build.c +++ b/src/build.c @@ -286,16 +286,14 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; - int nName; assert( zName!=0 ); - nName = sqlite3Strlen30(zName); /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); if( p ) break; } return p; @@ -378,7 +376,6 @@ Table *sqlite3LocateTableItem( Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; - int nName = sqlite3Strlen30(zName); /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ @@ -387,7 +384,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ assert( pSchema ); if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&pSchema->idxHash, zName, nName); + p = sqlite3HashFind(&pSchema->idxHash, zName); if( p ) break; } return p; @@ -415,13 +412,11 @@ static void freeIndex(sqlite3 *db, Index *p){ */ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; - int len; Hash *pHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pHash = &db->aDb[iDb].pSchema->idxHash; - len = sqlite3Strlen30(zIdxName); - pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0); + pIndex = sqlite3HashInsert(pHash, zIdxName, 0); if( ALWAYS(pIndex) ){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; @@ -581,7 +576,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ if( !db || db->pnBytesFreed==0 ){ char *zName = pIndex->zName; TESTONLY ( Index *pOld = ) sqlite3HashInsert( - &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 + &pIndex->pSchema->idxHash, zName, 0 ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); @@ -624,8 +619,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ pDb = &db->aDb[iDb]; - p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, - sqlite3Strlen30(zTabName),0); + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); sqlite3DeleteTable(db, p); db->flags |= SQLITE_InternChanges; } @@ -1947,8 +1941,7 @@ void sqlite3EndTable( Table *pOld; Schema *pSchema = p->pSchema; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, - sqlite3Strlen30(p->zName),p); + pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ db->mallocFailed = 1; @@ -2598,7 +2591,7 @@ void sqlite3CreateForeignKey( assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, - pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey + pFKey->zTo, (void *)pFKey ); if( pNextTo==pFKey ){ db->mallocFailed = 1; @@ -3146,8 +3139,7 @@ Index *sqlite3CreateIndex( Index *p; assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); p = sqlite3HashInsert(&pIndex->pSchema->idxHash, - pIndex->zName, sqlite3Strlen30(pIndex->zName), - pIndex); + pIndex->zName, pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ db->mallocFailed = 1; diff --git a/src/callback.c b/src/callback.c index 46fbe2c21a..63090899fb 100644 --- a/src/callback.c +++ b/src/callback.c @@ -154,11 +154,11 @@ static CollSeq *findCollSeqEntry( int create /* Create a new entry if true */ ){ CollSeq *pColl; - int nName = sqlite3Strlen30(zName); - pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); + pColl = sqlite3HashFind(&db->aCollSeq, zName); if( 0==pColl && create ){ - pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); + int nName = sqlite3Strlen30(zName); + pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1); if( pColl ){ CollSeq *pDel = 0; pColl[0].zName = (char*)&pColl[3]; @@ -169,7 +169,7 @@ static CollSeq *findCollSeqEntry( pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); pColl[0].zName[nName] = 0; - pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); + pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl); /* If a malloc() failure occurred in sqlite3HashInsert(), it will ** return the pColl pointer to be deleted (because it wasn't added diff --git a/src/fkey.c b/src/fkey.c index 50c10da822..415f35d2f8 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -659,8 +659,7 @@ static void fkScanChildren( ** table). */ FKey *sqlite3FkReferences(Table *pTab){ - int nName = sqlite3Strlen30(pTab->zName); - return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); + return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName); } /* @@ -1338,7 +1337,7 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){ }else{ void *p = (void *)pFKey->pNextTo; const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p); + sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; diff --git a/src/hash.c b/src/hash.c index f9901fee8f..b5886e0641 100644 --- a/src/hash.c +++ b/src/hash.c @@ -52,12 +52,11 @@ void sqlite3HashClear(Hash *pH){ /* ** The hashing function. */ -static unsigned int strHash(const char *z, int nKey){ +static unsigned int strHash(const char *z){ unsigned int h = 0; - assert( nKey>=0 ); - while( nKey > 0 ){ - h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++]; - nKey--; + unsigned char c; + while( (c = (unsigned char)*z++)!=0 ){ + h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; } return h; } @@ -129,7 +128,7 @@ static int rehash(Hash *pH, unsigned int new_size){ pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht); memset(new_ht, 0, new_size*sizeof(struct _ht)); for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - unsigned int h = strHash(elem->pKey, elem->nKey) % new_size; + unsigned int h = strHash(elem->pKey) % new_size; next_elem = elem->next; insertElement(pH, &new_ht[h], elem); } @@ -137,28 +136,33 @@ static int rehash(Hash *pH, unsigned int new_size){ } /* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key has -** already been computed and is passed as the 4th parameter. +** hash table that matches the given key. The hash for this key is +** also computed and returned in the *pH parameter. */ -static HashElem *findElementGivenHash( +static HashElem *findElementWithHash( const Hash *pH, /* The pH to be searched */ const char *pKey, /* The key we are searching for */ - int nKey, /* Bytes in key (not counting zero terminator) */ - unsigned int h /* The hash for this key. */ + unsigned int *pHash /* Write the hash value here */ ){ HashElem *elem; /* Used to loop thru the element list */ int count; /* Number of elements left to test */ + unsigned int h; /* The computed hash */ if( pH->ht ){ - struct _ht *pEntry = &pH->ht[h]; + struct _ht *pEntry; + h = strHash(pKey) % pH->htsize; + pEntry = &pH->ht[h]; elem = pEntry->chain; count = pEntry->count; }else{ + h = 0; elem = pH->first; count = pH->count; } - while( count-- && ALWAYS(elem) ){ - if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ + *pHash = h; + while( count-- ){ + assert( elem!=0 ); + if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ return elem; } elem = elem->next; @@ -201,26 +205,20 @@ static void removeElementGivenHash( } /* Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return the data for this element if it is +** that matches pKey. Return the data for this element if it is ** found, or NULL if there is no match. */ -void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){ +void *sqlite3HashFind(const Hash *pH, const char *pKey){ HashElem *elem; /* The element that matches key */ unsigned int h; /* A hash on key */ assert( pH!=0 ); assert( pKey!=0 ); - assert( nKey>=0 ); - if( pH->ht ){ - h = strHash(pKey, nKey) % pH->htsize; - }else{ - h = 0; - } - elem = findElementGivenHash(pH, pKey, nKey, h); + elem = findElementWithHash(pH, pKey, &h); return elem ? elem->data : 0; } -/* Insert an element into the hash table pH. The key is pKey,nKey +/* Insert an element into the hash table pH. The key is pKey ** and the data is "data". ** ** If no element exists with a matching key, then a new @@ -234,20 +232,14 @@ void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){ ** If the "data" parameter to this function is NULL, then the ** element corresponding to "key" is removed from the hash table. */ -void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){ +void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ unsigned int h; /* the hash of the key modulo hash table size */ HashElem *elem; /* Used to loop thru the element list */ HashElem *new_elem; /* New element added to the pH */ assert( pH!=0 ); assert( pKey!=0 ); - assert( nKey>=0 ); - if( pH->htsize ){ - h = strHash(pKey, nKey) % pH->htsize; - }else{ - h = 0; - } - elem = findElementGivenHash(pH,pKey,nKey,h); + elem = findElementWithHash(pH,pKey,&h); if( elem ){ void *old_data = elem->data; if( data==0 ){ @@ -255,7 +247,6 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){ }else{ elem->data = data; elem->pKey = pKey; - assert(nKey==elem->nKey); } return old_data; } @@ -263,19 +254,14 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){ new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); if( new_elem==0 ) return data; new_elem->pKey = pKey; - new_elem->nKey = nKey; new_elem->data = data; pH->count++; if( pH->count>=10 && pH->count > 2*pH->htsize ){ if( rehash(pH, pH->count*2) ){ assert( pH->htsize>0 ); - h = strHash(pKey, nKey) % pH->htsize; + h = strHash(pKey) % pH->htsize; } } - if( pH->ht ){ - insertElement(pH, &pH->ht[h], new_elem); - }else{ - insertElement(pH, 0, new_elem); - } + insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem); return 0; } diff --git a/src/hash.h b/src/hash.h index 82b7c58c71..6dfa4e035c 100644 --- a/src/hash.h +++ b/src/hash.h @@ -59,15 +59,15 @@ struct Hash { struct HashElem { HashElem *next, *prev; /* Next and previous elements in the table */ void *data; /* Data associated with this element */ - const char *pKey; int nKey; /* Key associated with this element */ + const char *pKey; /* Key associated with this element */ }; /* ** Access routines. To delete, insert a NULL pointer. */ void sqlite3HashInit(Hash*); -void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData); -void *sqlite3HashFind(const Hash*, const char *pKey, int nKey); +void *sqlite3HashInsert(Hash*, const char *pKey, void *pData); +void *sqlite3HashFind(const Hash*, const char *pKey); void sqlite3HashClear(Hash*); /* diff --git a/src/main.c b/src/main.c index cea72829df..2472321759 100644 --- a/src/main.c +++ b/src/main.c @@ -1998,7 +1998,6 @@ static int createCollation( ){ CollSeq *pColl; int enc2; - int nName = sqlite3Strlen30(zName); assert( sqlite3_mutex_held(db->mutex) ); @@ -2037,7 +2036,7 @@ static int createCollation( ** to be called. */ if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ - CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName); + CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName); int j; for(j=0; j<3; j++){ CollSeq *p = &aColl[j]; diff --git a/src/trigger.c b/src/trigger.c index 01f7b21f74..fc32a663bf 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -180,8 +180,7 @@ void sqlite3BeginTrigger( goto trigger_cleanup; } assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), - zName, sqlite3Strlen30(zName)) ){ + if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); }else{ @@ -324,13 +323,12 @@ void sqlite3FinishTrigger( Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig); + pTrig = sqlite3HashInsert(pHash, zName, pTrig); if( pTrig ){ db->mallocFailed = 1; }else if( pLink->pSchema==pLink->pTabSchema ){ Table *pTab; - int n = sqlite3Strlen30(pLink->table); - pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n); + pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); assert( pTab!=0 ); pLink->pNext = pTab->pTrigger; pTab->pTrigger = pLink; @@ -489,7 +487,6 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ int i; const char *zDb; const char *zName; - int nName; sqlite3 *db = pParse->db; if( db->mallocFailed ) goto drop_trigger_cleanup; @@ -500,13 +497,12 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ assert( pName->nSrc==1 ); zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; - nName = sqlite3Strlen30(zName); assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); + pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); if( pTrigger ) break; } if( !pTrigger ){ @@ -529,8 +525,7 @@ drop_trigger_cleanup: ** is set on. */ static Table *tableOfTrigger(Trigger *pTrigger){ - int n = sqlite3Strlen30(pTrigger->table); - return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); + return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table); } @@ -602,7 +597,7 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pHash = &(db->aDb[iDb].pSchema->trigHash); - pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0); + pTrigger = sqlite3HashInsert(pHash, zName, 0); if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); diff --git a/src/vtab.c b/src/vtab.c index ca0db214cc..ad18af48a4 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -43,7 +43,7 @@ static int createModule( sqlite3_mutex_enter(db->mutex); nName = sqlite3Strlen30(zName); - if( sqlite3HashFind(&db->aModule, zName, nName) ){ + if( sqlite3HashFind(&db->aModule, zName) ){ rc = SQLITE_MISUSE_BKPT; }else{ Module *pMod; @@ -56,7 +56,7 @@ static int createModule( pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod); + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); assert( pDel==0 || pDel==pMod ); if( pDel ){ db->mallocFailed = 1; @@ -425,9 +425,8 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Table *pOld; Schema *pSchema = pTab->pSchema; const char *zName = pTab->zName; - int nName = sqlite3Strlen30(zName); assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); + pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); if( pOld ){ db->mallocFailed = 1; assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ @@ -593,7 +592,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); if( !pMod ){ const char *zModule = pTab->azModuleArg[0]; @@ -661,7 +660,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); /* If the module has been registered and includes a Create method, ** invoke it now. If the module has not been registered, return an From 5ab567078a924d9eeff3616433532dd2905a21c7 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 11:11:30 +0000 Subject: [PATCH 20/42] Enhance the spellfix extension with the ability to specify a rowid when inserting new rows. FossilOrigin-Name: 369c480cda6fa66394b995346bbf51f3298446e1 --- ext/misc/spellfix.c | 22 ++++++++++++++++------ manifest | 14 +++++++------- manifest.uuid | 2 +- test/spellfix.test | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index 2e6743e4f7..2a26e08391 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -2736,12 +2736,22 @@ static int spellfix1Update( return SQLITE_NOMEM; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - spellfix1DbExec(&rc, db, - "INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) " - "VALUES(%d,%d,%Q,%Q,%Q)", - p->zDbName, p->zTableName, - iRank, iLang, zWord, zK1, zK2 - ); + if( sqlite3_value_type(argv[1])==SQLITE_NULL ){ + spellfix1DbExec(&rc, db, + "INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) " + "VALUES(%d,%d,%Q,%Q,%Q)", + p->zDbName, p->zTableName, + iRank, iLang, zWord, zK1, zK2 + ); + }else{ + newRowid = sqlite3_value_int64(argv[1]); + spellfix1DbExec(&rc, db, + "INSERT INTO \"%w\".\"%w_vocab\"(id,rank,langid,word,k1,k2) " + "VALUES(%lld,%d,%d,%Q,%Q,%Q)", + p->zDbName, p->zTableName, + newRowid, iRank, iLang, zWord, zK1, zK2 + ); + } *pRowid = sqlite3_last_insert_rowid(db); }else{ rowid = sqlite3_value_int64(argv[0]); diff --git a/manifest b/manifest index bcba60c6c2..c3d516552f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\sinterface\sto\sthe\ssymbol\stable,\ssaving\s600\sbytes\sof\scode\sspace. -D 2014-08-21T20:26:37.728 +C Enhance\sthe\sspellfix\sextension\swith\sthe\sability\sto\sspecify\sa\srowid\swhen\ninserting\snew\srows. +D 2014-08-22T11:11:30.047 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -116,7 +116,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/spellfix.c cb016c2dab951ffd7b819a7bc8a750ebd6c26c0f +F ext/misc/spellfix.c 56739fab8c2ed6a9e2dac5592a88d281a999c43b F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@ -847,7 +847,7 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920 -F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe +F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49 F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298 F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7029b3404d3f5f698a496934f3a3f2972051b257 -R 818f77c3be876451b2dad41de8a59565 +P 14b0f561fe15622b61c6676c9c455dca6b9ba5f0 +R e9738e2157edd7ced31f8162753e2f5b U drh -Z cb34ea9e2178e12926edef43b644d982 +Z 9671128edfd421e5d7e75c6453894b1f diff --git a/manifest.uuid b/manifest.uuid index 98b1fd2ac2..85d3cf892f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -14b0f561fe15622b61c6676c9c455dca6b9ba5f0 \ No newline at end of file +369c480cda6fa66394b995346bbf51f3298446e1 \ No newline at end of file diff --git a/test/spellfix.test b/test/spellfix.test index 21383c2d33..954bdb21f1 100644 --- a/test/spellfix.test +++ b/test/spellfix.test @@ -124,6 +124,22 @@ do_execsql_test 1.23 { SELECT next_char('ab','vocab2','w',null,'binary'); } {c} +do_execsql_test 1.30 { + SELECT rowid FROM t1 WHERE word='rabbit'; +} {2} +do_execsql_test 1.31 { + UPDATE t1 SET rowid=2000 WHERE word='rabbit'; + SELECT rowid FROM t1 WHERE word='rabbit'; +} {2000} +do_execsql_test 1.32 { + INSERT INTO t1(rowid, word) VALUES(3000,'melody'); + SELECT rowid, word, matchlen FROM t1 WHERE word MATCH 'melotti' + ORDER BY score LIMIT 3; +} {3000 melody 6} +do_test 1.33 { + catchsql {INSERT INTO t1(rowid, word) VALUES(3000,'garden');} +} {1 {constraint failed}} + do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING spellfix1; INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul'); From 3f5b199eb596a6e8031647d93e00451ade43806e Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 13:22:32 +0000 Subject: [PATCH 21/42] Change a while-loop into a do-loop in sqlite3VdbeSerialPut() for a small size reduction and performance improvement. FossilOrigin-Name: 750bb0a0960606ab24037e0992e9f7a17524cc3e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 7 ++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index c3d516552f..0e059ae46c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sspellfix\sextension\swith\sthe\sability\sto\sspecify\sa\srowid\swhen\ninserting\snew\srows. -D 2014-08-22T11:11:30.047 +C Change\sa\swhile-loop\sinto\sa\sdo-loop\sin\ssqlite3VdbeSerialPut()\sfor\sa\ssmall\nsize\sreduction\sand\sperformance\simprovement. +D 2014-08-22T13:22:32.819 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c 25d62ef82cf1be2a1255eacac636fa0d943d8b3d +F src/vdbeaux.c 9c9571706aaf0e5debab5b01629ef569cde40920 F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 14b0f561fe15622b61c6676c9c455dca6b9ba5f0 -R e9738e2157edd7ced31f8162753e2f5b +P 369c480cda6fa66394b995346bbf51f3298446e1 +R 9c1a6f648ddd3ddf03093ccb99facf2b U drh -Z 9671128edfd421e5d7e75c6453894b1f +Z 453b7d6a328e84b291043b75c1b3327d diff --git a/manifest.uuid b/manifest.uuid index 85d3cf892f..6ea1746008 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -369c480cda6fa66394b995346bbf51f3298446e1 \ No newline at end of file +750bb0a0960606ab24037e0992e9f7a17524cc3e \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index fb3f7c3a8c..83c6e1f65a 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2933,10 +2933,11 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ v = pMem->u.i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); - while( i-- ){ - buf[i] = (u8)(v&0xFF); + assert( i>0 ); + do{ + buf[--i] = (u8)(v&0xFF); v >>= 8; - } + }while( i ); return len; } From 14a924a5cd77e353ebae67d3b4bc7e64b7bd715a Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 14:34:05 +0000 Subject: [PATCH 22/42] Get the sqlite3VdbeSerialGet() routine to run faster by avoiding the use of local variables. FossilOrigin-Name: 8267d82174099e548a4f78d06af0c6324c89b83d --- manifest | 17 ++++++---- manifest.uuid | 2 +- src/sqliteInt.h | 12 +++++++ src/vdbeaux.c | 89 +++++++++++++++++++++++++++---------------------- 4 files changed, 73 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index 0e059ae46c..66e4c0b1b6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sa\swhile-loop\sinto\sa\sdo-loop\sin\ssqlite3VdbeSerialPut()\sfor\sa\ssmall\nsize\sreduction\sand\sperformance\simprovement. -D 2014-08-22T13:22:32.819 +C Get\sthe\ssqlite3VdbeSerialGet()\sroutine\sto\srun\sfaster\sby\savoiding\sthe\suse\nof\slocal\svariables. +D 2014-08-22T14:34:05.936 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -228,7 +228,7 @@ F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 641f8fbb65ca2084c8df95b525f6f82c7a1e91ae +F src/sqliteInt.h 99bd20e5a12dce7ba290e938123d27e87b5eae27 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c 9c9571706aaf0e5debab5b01629ef569cde40920 +F src/vdbeaux.c f83d5c265aea19d2e49ba018beaf99acff934020 F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,7 +1188,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 369c480cda6fa66394b995346bbf51f3298446e1 -R 9c1a6f648ddd3ddf03093ccb99facf2b +P 750bb0a0960606ab24037e0992e9f7a17524cc3e +R 6bc6a7681a89a137c23142249db6cf86 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * U drh -Z 453b7d6a328e84b291043b75c1b3327d +Z 612ca7a9b67c6d8d8dbe2b7affb6d3eb diff --git a/manifest.uuid b/manifest.uuid index 6ea1746008..9538f73f10 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -750bb0a0960606ab24037e0992e9f7a17524cc3e \ No newline at end of file +8267d82174099e548a4f78d06af0c6324c89b83d \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ee52487d66..5202beff78 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -153,6 +153,18 @@ # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define SQLITE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +# define SQLITE_NOINLINE __declspec(noinline) +#else +# define SQLITE_NOINLINE +#endif + /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 83c6e1f65a..d338806962 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2965,14 +2965,55 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ /* ** Deserialize the data blob pointed to by buf as serial type serial_type ** and store the result in pMem. Return the number of bytes read. +** +** This function is implemented as two separate routines for performance. +** The few cases that require local variables are broken out into a separate +** routine so that in most cases the overhead of moving the stack pointer +** is avoided. */ -u32 sqlite3VdbeSerialGet( +static u32 SQLITE_NOINLINE serialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ u64 x; - u32 y; + u32 y = FOUR_BYTE_UINT(buf); + if( serial_type==4 ){ + pMem->u.i = (i64)*(int*)&y; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 4; + } + x = (((u64)y)<<32)|FOUR_BYTE_UINT(buf+4); + if( serial_type==6 ){ + pMem->u.i = *(i64*)&x; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + }else{ +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) + /* Verify that integers and floating point values use the same + ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is + ** defined that 64-bit floating point values really are mixed + ** endian. + */ + static const u64 t1 = ((u64)0x3ff00000)<<32; + static const double r1 = 1.0; + u64 t2 = t1; + swapMixedEndianFloat(t2); + assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); +#endif + assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); + swapMixedEndianFloat(x); + memcpy(&pMem->r, &x, sizeof(x)); + pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; + } + return 8; +} +u32 sqlite3VdbeSerialGet( + const unsigned char *buf, /* Buffer to deserialize from */ + u32 serial_type, /* Serial type to deserialize */ + Mem *pMem /* Memory cell to write value into */ +){ switch( serial_type ){ case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ @@ -2998,47 +3039,19 @@ u32 sqlite3VdbeSerialGet( testcase( pMem->u.i<0 ); return 3; } - case 4: { /* 4-byte signed integer */ - y = FOUR_BYTE_UINT(buf); - pMem->u.i = (i64)*(int*)&y; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return 4; - } case 5: { /* 6-byte signed integer */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 6; } + case 4: /* 4-byte signed integer */ case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ -#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) - /* Verify that integers and floating point values use the same - ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is - ** defined that 64-bit floating point values really are mixed - ** endian. - */ - static const u64 t1 = ((u64)0x3ff00000)<<32; - static const double r1 = 1.0; - u64 t2 = t1; - swapMixedEndianFloat(t2); - assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); -#endif - x = FOUR_BYTE_UINT(buf); - y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) | y; - if( serial_type==6 ){ - pMem->u.i = *(i64*)&x; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - }else{ - assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->r, &x, sizeof(x)); - pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; - } - return 8; + /* These three cases require local variables, so do them in a + ** separate routine to avoid having to move the frame pointer in + ** the common case */ + return serialGet(buf,serial_type,pMem); } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ @@ -3048,17 +3061,15 @@ u32 sqlite3VdbeSerialGet( } default: { static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem }; - u32 len = (serial_type-12)/2; pMem->z = (char *)buf; - pMem->n = len; + pMem->n = (serial_type-12)/2; pMem->xDel = 0; pMem->flags = aFlag[serial_type&1]; - return len; + return pMem->n; } } return 0; } - /* ** This routine is used to allocate sufficient space for an UnpackedRecord ** structure large enough to be used with sqlite3VdbeRecordUnpack() if From 8932becbef8458f91b9316249e2ac9a3d24ed816 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 14:56:13 +0000 Subject: [PATCH 23/42] Handle the 4-byte integer case in the stackless routine. FossilOrigin-Name: 3f55484e81000c75e231f5580632a68e782ded4f --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/vdbeaux.c | 25 ++++++++++++------------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 66e4c0b1b6..2e7b46977a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Get\sthe\ssqlite3VdbeSerialGet()\sroutine\sto\srun\sfaster\sby\savoiding\sthe\suse\nof\slocal\svariables. -D 2014-08-22T14:34:05.936 +C Handle\sthe\s4-byte\sinteger\scase\sin\sthe\sstackless\sroutine. +D 2014-08-22T14:56:13.720 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c f83d5c265aea19d2e49ba018beaf99acff934020 +F src/vdbeaux.c d0b20a85d1ab8c951e5c8b2400a45252d6d2750c F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,10 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 750bb0a0960606ab24037e0992e9f7a17524cc3e -R 6bc6a7681a89a137c23142249db6cf86 -T *branch * experimental -T *sym-experimental * -T -sym-trunk * +P 8267d82174099e548a4f78d06af0c6324c89b83d +R 3e2300d1a615c65baf7081c06688a5fd U drh -Z 612ca7a9b67c6d8d8dbe2b7affb6d3eb +Z 9f4fad73eafc2d2adf27281640f7d1a1 diff --git a/manifest.uuid b/manifest.uuid index 9538f73f10..301ab7c9f7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8267d82174099e548a4f78d06af0c6324c89b83d \ No newline at end of file +3f55484e81000c75e231f5580632a68e782ded4f \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d338806962..513481bf00 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2961,6 +2961,7 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ #define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1]) #define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2]) #define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) +#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) /* ** Deserialize the data blob pointed to by buf as serial type serial_type @@ -2976,15 +2977,9 @@ static u32 SQLITE_NOINLINE serialGet( u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ - u64 x; - u32 y = FOUR_BYTE_UINT(buf); - if( serial_type==4 ){ - pMem->u.i = (i64)*(int*)&y; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return 4; - } - x = (((u64)y)<<32)|FOUR_BYTE_UINT(buf+4); + u64 x = FOUR_BYTE_UINT(buf); + u32 y = FOUR_BYTE_UINT(buf+4); + x = (x<<32) + y; if( serial_type==6 ){ pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; @@ -3039,18 +3034,22 @@ u32 sqlite3VdbeSerialGet( testcase( pMem->u.i<0 ); return 3; } + case 4: { /* 4-byte signed integer */ + pMem->u.i = FOUR_BYTE_INT(buf); + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 4; + } case 5: { /* 6-byte signed integer */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 6; } - case 4: /* 4-byte signed integer */ case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ - /* These three cases require local variables, so do them in a - ** separate routine to avoid having to move the frame pointer in - ** the common case */ + /* These use local variables, so do them in a separate routine + ** to avoid having to move the frame pointer in the common case */ return serialGet(buf,serial_type,pMem); } case 8: /* Integer 0 */ From 172087fb733f54d025fe6a112898cdcabada7e47 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 15:40:20 +0000 Subject: [PATCH 24/42] Performance improvement in the printf() logic by avoiding unnecessary stack pointer movement. FossilOrigin-Name: f7f2160db014f0ae11ad13c8ad70ad3444124e3e --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/printf.c | 10 +++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index ceff9d8346..5d853a3262 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sthe\sperformance\sand\sreduce\sthe\ssize\sof\sthe\ssqlite3VdbeSerialGet()\nroutine\sby\savoiding\sthe\suse\sof\sstack. -D 2014-08-22T15:19:59.113 +C Performance\simprovement\sin\sthe\sprintf()\slogic\sby\savoiding\sunnecessary\sstack\npointer\smovement. +D 2014-08-22T15:40:20.728 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -219,7 +219,7 @@ F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 -F src/printf.c af06f66927919730f03479fed6ae9854f73419f4 +F src/printf.c 00986c86ddfffefc2fd3c73667ff51b3b9709c74 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be @@ -1188,8 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 750bb0a0960606ab24037e0992e9f7a17524cc3e 3f55484e81000c75e231f5580632a68e782ded4f -R 3e2300d1a615c65baf7081c06688a5fd -T +closed 3f55484e81000c75e231f5580632a68e782ded4f +P ebc10e46c15017d7cd232b5f4f3ef67ef740d87f +R 200d7eb44581fc5fc17c5cd337adb810 U drh -Z 0797c3bb55e4f93e4c54043857e85ca3 +Z f2b0948089d8fe6b11165afcc09478da diff --git a/manifest.uuid b/manifest.uuid index 3b49bd178d..a75c3b426e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ebc10e46c15017d7cd232b5f4f3ef67ef740d87f \ No newline at end of file +f7f2160db014f0ae11ad13c8ad70ad3444124e3e \ No newline at end of file diff --git a/src/printf.c b/src/printf.c index 37910804d2..72ace932ba 100644 --- a/src/printf.c +++ b/src/printf.c @@ -784,7 +784,7 @@ void sqlite3AppendSpace(StrAccum *p, int N){ ** work (enlarging the buffer) using tail recursion, so that the ** sqlite3StrAccumAppend() routine can use fast calling semantics. */ -static void enlargeAndAppend(StrAccum *p, const char *z, int N){ +static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ N = sqlite3StrAccumEnlarge(p, N); if( N>0 ){ memcpy(&p->zText[p->nChar], z, N); @@ -803,11 +803,11 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ enlargeAndAppend(p,z,N); - return; + }else{ + assert( p->zText ); + p->nChar += N; + memcpy(&p->zText[p->nChar-N], z, N); } - assert( p->zText ); - memcpy(&p->zText[p->nChar], z, N); - p->nChar += N; } /* From 13f40da31d9692a96dcab00f85afee9fd68bae12 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 18:00:11 +0000 Subject: [PATCH 25/42] Split the sqlite3Error() routine into sqlite3Error() and sqlite3ErrorWithMsg(), for a slight size reduction and performance increase. FossilOrigin-Name: cf561d1f0bb60b3d638632d20bd686dda4fa4a04 --- manifest | 36 ++++++++++++++++++------------------ manifest.uuid | 2 +- src/backup.c | 12 ++++++------ src/legacy.c | 6 +++--- src/loadext.c | 2 +- src/main.c | 26 +++++++++++++------------- src/malloc.c | 2 +- src/notify.c | 2 +- src/prepare.c | 8 ++++---- src/sqliteInt.h | 3 ++- src/util.c | 23 ++++++++++++++++------- src/vdbeapi.c | 10 +++++----- src/vdbeaux.c | 4 ++-- src/vdbeblob.c | 6 +++--- src/vtab.c | 6 +++--- 15 files changed, 79 insertions(+), 69 deletions(-) diff --git a/manifest b/manifest index 5d853a3262..2ec516f887 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\simprovement\sin\sthe\sprintf()\slogic\sby\savoiding\sunnecessary\sstack\npointer\smovement. -D 2014-08-22T15:40:20.728 +C Split\sthe\ssqlite3Error()\sroutine\sinto\ssqlite3Error()\sand\nsqlite3ErrorWithMsg(),\sfor\sa\sslight\ssize\sreduction\sand\sperformance\sincrease. +D 2014-08-22T18:00:11.621 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -165,7 +165,7 @@ F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1 F src/analyze.c f98a351908da29f7b44741cfeb9eb20dda648ba0 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 -F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 +F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d @@ -187,11 +187,11 @@ F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c d1a104e67b33314d4cc5c1356147446086ab9fc8 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d -F src/legacy.c febc2a9e7ad6c1a6191c7b5b9170b325d263f343 +F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b -F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c 1e5d34fb6dee85019b4bcc44e8576457b5075174 -F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be +F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab +F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 +F src/malloc.c 0a88a97fc5ae621ca9659d38b080e0b9ddbb80ad F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -203,7 +203,7 @@ F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea F src/mutex_noop.c f3f09fd7a2eb4287cfc799753ffc30380e7b71a1 F src/mutex_unix.c 1b10d5413dfc794364a8adf3eb3a192926b43fa3 F src/mutex_w32.c 06bfff9a3a83b53389a51a967643db3967032e1e -F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 +F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 @@ -218,7 +218,7 @@ F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e -F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 +F src/prepare.c 3842c1dfc0b053458e3adcf9f6efc48e03e3fe3d F src/printf.c 00986c86ddfffefc2fd3c73667ff51b3b9709c74 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 @@ -228,7 +228,7 @@ F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 99bd20e5a12dce7ba290e938123d27e87b5eae27 +F src/sqliteInt.h 937869c407c61026443c879e8c90a9dff05d2d27 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -282,18 +282,18 @@ F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 -F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e +F src/util.c 524127b3c330b9f490a505ff6eb7f80dfc873a3a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df -F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c d0b20a85d1ab8c951e5c8b2400a45252d6d2750c -F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac +F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d +F src/vdbeaux.c f7fdc59e2eefa6fc4ba7324b03ea6f8f66e98d62 +F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 -F src/vtab.c 180bfc5e69c92f2014c094bc49a66e8c37c188ac +F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ebc10e46c15017d7cd232b5f4f3ef67ef740d87f -R 200d7eb44581fc5fc17c5cd337adb810 +P f7f2160db014f0ae11ad13c8ad70ad3444124e3e +R 668369bbbf2d81407f36345226c5d2a9 U drh -Z f2b0948089d8fe6b11165afcc09478da +Z bddb035a8072a327798c78fbe23bcf26 diff --git a/manifest.uuid b/manifest.uuid index a75c3b426e..5842d66545 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f7f2160db014f0ae11ad13c8ad70ad3444124e3e \ No newline at end of file +cf561d1f0bb60b3d638632d20bd686dda4fa4a04 \ No newline at end of file diff --git a/src/backup.c b/src/backup.c index 4a6bc7493c..92c6334bde 100644 --- a/src/backup.c +++ b/src/backup.c @@ -87,12 +87,12 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int rc = 0; pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); if( pParse==0 ){ - sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); + sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); rc = SQLITE_NOMEM; }else{ pParse->db = pDb; if( sqlite3OpenTempDatabase(pParse) ){ - sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); + sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); rc = SQLITE_ERROR; } sqlite3DbFree(pErrorDb, pParse->zErrMsg); @@ -105,7 +105,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ } if( i<0 ){ - sqlite3Error(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); + sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); return 0; } @@ -150,7 +150,7 @@ sqlite3_backup *sqlite3_backup_init( sqlite3_mutex_enter(pDestDb->mutex); if( pSrcDb==pDestDb ){ - sqlite3Error( + sqlite3ErrorWithMsg( pDestDb, SQLITE_ERROR, "source and destination must be distinct" ); p = 0; @@ -161,7 +161,7 @@ sqlite3_backup *sqlite3_backup_init( ** sqlite3_backup_finish(). */ p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); if( !p ){ - sqlite3Error(pDestDb, SQLITE_NOMEM, 0); + sqlite3Error(pDestDb, SQLITE_NOMEM); } } @@ -602,7 +602,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){ /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; if( p->pDestDb ){ - sqlite3Error(p->pDestDb, rc, 0); + sqlite3Error(p->pDestDb, rc); /* Exit the mutexes and free the backup context structure. */ sqlite3LeaveMutexAndCloseZombie(p->pDestDb); diff --git a/src/legacy.c b/src/legacy.c index 1913f0b5af..b8cb90d707 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -44,7 +44,7 @@ int sqlite3_exec( if( zSql==0 ) zSql = ""; sqlite3_mutex_enter(db->mutex); - sqlite3Error(db, SQLITE_OK, 0); + sqlite3Error(db, SQLITE_OK); while( rc==SQLITE_OK && zSql[0] ){ int nCol; char **azVals = 0; @@ -102,7 +102,7 @@ int sqlite3_exec( rc = SQLITE_ABORT; sqlite3VdbeFinalize((Vdbe *)pStmt); pStmt = 0; - sqlite3Error(db, SQLITE_ABORT, 0); + sqlite3Error(db, SQLITE_ABORT); goto exec_out; } } @@ -132,7 +132,7 @@ exec_out: memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); }else{ rc = SQLITE_NOMEM; - sqlite3Error(db, SQLITE_NOMEM, 0); + sqlite3Error(db, SQLITE_NOMEM); } }else if( pzErrMsg ){ *pzErrMsg = 0; diff --git a/src/loadext.c b/src/loadext.c index 828e865b61..05045dedb3 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -749,7 +749,7 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){ sqlite3_mutex_leave(mutex); zErrmsg = 0; if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ - sqlite3Error(db, rc, + sqlite3ErrorWithMsg(db, rc, "automatic extension loading failed: %s", zErrmsg); go = 0; } diff --git a/src/main.c b/src/main.c index 2472321759..219a8bec92 100644 --- a/src/main.c +++ b/src/main.c @@ -852,7 +852,7 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ ** SQLITE_BUSY if the connection can not be closed immediately. */ if( !forceZombie && connectionIsBusy(db) ){ - sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; @@ -982,7 +982,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ sqlite3HashClear(&db->aModule); #endif - sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ + sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */ sqlite3ValueFree(db->pErr); sqlite3CloseExtensions(db); @@ -1415,7 +1415,7 @@ int sqlite3CreateFunc( p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ if( db->nVdbeActive ){ - sqlite3Error(db, SQLITE_BUSY, + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to delete/modify user-function due to active statements"); assert( !db->mallocFailed ); return SQLITE_BUSY; @@ -1753,10 +1753,10 @@ int sqlite3_wal_checkpoint_v2( } if( iDb<0 ){ rc = SQLITE_ERROR; - sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb); + sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb); }else{ rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); @@ -1911,7 +1911,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ }else{ z = sqlite3_value_text16(db->pErr); if( z==0 ){ - sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode)); + sqlite3ErrorWithMsg(db, db->errCode, sqlite3ErrStr(db->errCode)); z = sqlite3_value_text16(db->pErr); } /* A malloc() may have failed within the call to sqlite3_value_text16() @@ -2022,7 +2022,7 @@ static int createCollation( pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); if( pColl && pColl->xCmp ){ if( db->nVdbeActive ){ - sqlite3Error(db, SQLITE_BUSY, + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } @@ -2056,7 +2056,7 @@ static int createCollation( pColl->pUser = pCtx; pColl->xDel = xDel; pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); - sqlite3Error(db, SQLITE_OK, 0); + sqlite3Error(db, SQLITE_OK); return SQLITE_OK; } @@ -2541,7 +2541,7 @@ static int openDatabase( rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; - sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg); + sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); sqlite3_free(zErrMsg); goto opendb_out; } @@ -2553,7 +2553,7 @@ static int openDatabase( if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM; } - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); goto opendb_out; } db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); @@ -2577,7 +2577,7 @@ static int openDatabase( ** database schema yet. This is delayed until the first time the database ** is accessed. */ - sqlite3Error(db, SQLITE_OK, 0); + sqlite3Error(db, SQLITE_OK); sqlite3RegisterBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered @@ -2634,7 +2634,7 @@ static int openDatabase( SQLITE_DEFAULT_LOCKING_MODE); #endif - if( rc ) sqlite3Error(db, rc, 0); + if( rc ) sqlite3Error(db, rc); /* Enable the lookaside-malloc subsystem */ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, @@ -2996,7 +2996,7 @@ error_out: zColumnName); rc = SQLITE_ERROR; } - sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqlite3ErrorWithMsg(db, rc, (zErrMsg?"%s":0), zErrMsg); sqlite3DbFree(db, zErrMsg); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); diff --git a/src/malloc.c b/src/malloc.c index 9c11d07767..9fb4303979 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -776,7 +776,7 @@ int sqlite3ApiExit(sqlite3* db, int rc){ */ assert( !db || sqlite3_mutex_held(db->mutex) ); if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){ - sqlite3Error(db, SQLITE_NOMEM, 0); + sqlite3Error(db, SQLITE_NOMEM); db->mallocFailed = 0; rc = SQLITE_NOMEM; } diff --git a/src/notify.c b/src/notify.c index fcab5bfaf0..8137226f35 100644 --- a/src/notify.c +++ b/src/notify.c @@ -184,7 +184,7 @@ int sqlite3_unlock_notify( leaveMutex(); assert( !db->mallocFailed ); - sqlite3Error(db, rc, (rc?"database is deadlocked":0)); + sqlite3ErrorWithMsg(db, rc, (rc?"database is deadlocked":0)); sqlite3_mutex_leave(db->mutex); return rc; } diff --git a/src/prepare.c b/src/prepare.c index c7ba53a1f5..5b92e88513 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -593,7 +593,7 @@ static int sqlite3Prepare( rc = sqlite3BtreeSchemaLocked(pBt); if( rc ){ const char *zDb = db->aDb[i].zName; - sqlite3Error(db, rc, "database schema is locked: %s", zDb); + sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); testcase( db->flags & SQLITE_ReadUncommitted ); goto end_prepare; } @@ -610,7 +610,7 @@ static int sqlite3Prepare( testcase( nBytes==mxLen ); testcase( nBytes==mxLen+1 ); if( nBytes>mxLen ){ - sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); + sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long"); rc = sqlite3ApiExit(db, SQLITE_TOOBIG); goto end_prepare; } @@ -677,10 +677,10 @@ static int sqlite3Prepare( } if( zErrMsg ){ - sqlite3Error(db, rc, "%s", zErrMsg); + sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); sqlite3DbFree(db, zErrMsg); }else{ - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); } /* Delete any TriggerPrg structures allocated while parsing this statement. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5202beff78..65dd7a9279 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3350,7 +3350,8 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); char sqlite3ExprAffinity(Expr *pExpr); int sqlite3Atoi64(const char*, i64*, int, u8); int sqlite3DecOrHexToI64(const char*, i64*); -void sqlite3Error(sqlite3*, int, const char*,...); +void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); +void sqlite3Error(sqlite3*,int); void *sqlite3HexToBlob(sqlite3*, const char *z, int n); u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); diff --git a/src/util.c b/src/util.c index 619af7f758..1c75e4cfbe 100644 --- a/src/util.c +++ b/src/util.c @@ -111,6 +111,15 @@ int sqlite3Strlen30(const char *z){ return 0x3fffffff & (int)(z2 - z); } +/* +** Set the current error code to err_code and clear any prior error message. +*/ +void sqlite3Error(sqlite3 *db, int err_code){ + assert( db!=0 ); + db->errCode = err_code; + if( db->pErr ) sqlite3ValueSetNull(db->pErr); +} + /* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". @@ -132,18 +141,18 @@ int sqlite3Strlen30(const char *z){ ** should be called with err_code set to SQLITE_OK and zFormat set ** to NULL. */ -void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ +void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ assert( db!=0 ); db->errCode = err_code; - if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ + if( zFormat==0 ){ + sqlite3Error(db, err_code); + }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){ char *z; va_list ap; va_start(ap, zFormat); z = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); - }else if( db->pErr ){ - sqlite3ValueSetNull(db->pErr); } } @@ -157,12 +166,12 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ ** %T Insert a token ** %S Insert the first element of a SrcList ** -** This function should be used to report any error that occurs whilst +** This function should be used to report any error that occurs while ** compiling an SQL statement (i.e. within sqlite3_prepare()). The ** last thing the sqlite3_prepare() function does is copy the error ** stored by this function into the database handle using sqlite3Error(). -** Function sqlite3Error() should be used during statement execution -** (sqlite3_step() etc.). +** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used +** during statement execution (sqlite3_step() etc.). */ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index f6cc2d8c05..675361013a 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -770,7 +770,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ }else{ if( pVm && ALWAYS(pVm->db) ){ sqlite3_mutex_enter(pVm->db->mutex); - sqlite3Error(pVm->db, SQLITE_RANGE, 0); + sqlite3Error(pVm->db, SQLITE_RANGE); } pOut = (Mem*)columnNullValue(); } @@ -1035,14 +1035,14 @@ static int vdbeUnbind(Vdbe *p, int i){ } sqlite3_mutex_enter(p->db->mutex); if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ - sqlite3Error(p->db, SQLITE_MISUSE, 0); + sqlite3Error(p->db, SQLITE_MISUSE); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); return SQLITE_MISUSE_BKPT; } if( i<1 || i>p->nVar ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); + sqlite3Error(p->db, SQLITE_RANGE); sqlite3_mutex_leave(p->db->mutex); return SQLITE_RANGE; } @@ -1050,7 +1050,7 @@ static int vdbeUnbind(Vdbe *p, int i){ pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; - sqlite3Error(p->db, SQLITE_OK, 0); + sqlite3Error(p->db, SQLITE_OK); /* If the bit corresponding to this variable in Vdbe.expmask is set, then ** binding a new value to this variable invalidates the current query plan. @@ -1092,7 +1092,7 @@ static int bindText( if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } - sqlite3Error(p->db, rc, 0); + sqlite3Error(p->db, rc); rc = sqlite3ApiExit(p->db, rc); } sqlite3_mutex_leave(p->db->mutex); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 513481bf00..58f39a48a8 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2497,7 +2497,7 @@ int sqlite3VdbeTransferError(Vdbe *p){ db->mallocFailed = mallocFailed; db->errCode = rc; }else{ - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); } return rc; } @@ -2560,7 +2560,7 @@ int sqlite3VdbeReset(Vdbe *p){ ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ - sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); + sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 083f3f413c..71bd8816d5 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -318,7 +318,7 @@ blob_open_out: if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } - sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); sqlite3ParserReset(pParse); sqlite3StackFree(db, pParse); @@ -371,7 +371,7 @@ static int blobReadWrite( if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; - sqlite3Error(db, SQLITE_ERROR, 0); + sqlite3Error(db, SQLITE_ERROR); }else if( v==0 ){ /* If there is no statement handle, then the blob-handle has ** already been invalidated. Return SQLITE_ABORT in this case. @@ -451,7 +451,7 @@ int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ char *zErr; rc = blobSeekToRow(p, iRow, &zErr); if( rc!=SQLITE_OK ){ - sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); } assert( rc!=SQLITE_SCHEMA ); diff --git a/src/vtab.c b/src/vtab.c index ad18af48a4..c7a8a5a33f 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -699,7 +699,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ sqlite3_mutex_enter(db->mutex); if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ - sqlite3Error(db, SQLITE_MISUSE, 0); + sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } @@ -727,7 +727,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ } db->pVtabCtx->pTab = 0; }else{ - sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } @@ -1088,7 +1088,7 @@ int sqlite3_vtab_config(sqlite3 *db, int op, ...){ } va_end(ap); - if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0); + if( rc!=SQLITE_OK ) sqlite3Error(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } From 2f2b2b85800866c9cebde588d09706feed6462eb Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 18:48:25 +0000 Subject: [PATCH 26/42] Performance enhancement in sqlite3PutVarint(). FossilOrigin-Name: a929be551924144c9bc7aab608404d59e479abb5 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqliteInt.h | 25 +++++-------------------- src/util.c | 27 ++++++++------------------- src/vdbemem.c | 2 +- 5 files changed, 23 insertions(+), 49 deletions(-) diff --git a/manifest b/manifest index 2ec516f887..4718b15953 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Split\sthe\ssqlite3Error()\sroutine\sinto\ssqlite3Error()\sand\nsqlite3ErrorWithMsg(),\sfor\sa\sslight\ssize\sreduction\sand\sperformance\sincrease. -D 2014-08-22T18:00:11.621 +C Performance\senhancement\sin\ssqlite3PutVarint(). +D 2014-08-22T18:48:25.634 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -228,7 +228,7 @@ F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 937869c407c61026443c879e8c90a9dff05d2d27 +F src/sqliteInt.h d8a9be2aa123a78c90ad4aba09b23e7dd3f8cc9f F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -282,7 +282,7 @@ F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 -F src/util.c 524127b3c330b9f490a505ff6eb7f80dfc873a3a +F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 @@ -290,7 +290,7 @@ F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d F src/vdbeaux.c f7fdc59e2eefa6fc4ba7324b03ea6f8f66e98d62 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 +F src/vdbemem.c 4a64659ed8e4c3b18a9238e038145ab1bdcd146f F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f7f2160db014f0ae11ad13c8ad70ad3444124e3e -R 668369bbbf2d81407f36345226c5d2a9 +P cf561d1f0bb60b3d638632d20bd686dda4fa4a04 +R 892fbe852e37f91de1b9f5afa35c0502 U drh -Z bddb035a8072a327798c78fbe23bcf26 +Z c70614e9322ab39ef4e9fbe07eb13b05 diff --git a/manifest.uuid b/manifest.uuid index 5842d66545..12c08a2c09 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cf561d1f0bb60b3d638632d20bd686dda4fa4a04 \ No newline at end of file +a929be551924144c9bc7aab608404d59e479abb5 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 65dd7a9279..a534c5cebc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3307,38 +3307,23 @@ u64 sqlite3LogEstToInt(LogEst); /* ** Routines to read and write variable-length integers. These used to ** be defined locally, but now we use the varint routines in the util.c -** file. Code should use the MACRO forms below, as the Varint32 versions -** are coded to assume the single byte case is already handled (which -** the MACRO form does). +** file. */ int sqlite3PutVarint(unsigned char*, u64); -int sqlite3PutVarint32(unsigned char*, u32); u8 sqlite3GetVarint(const unsigned char *, u64 *); u8 sqlite3GetVarint32(const unsigned char *, u32 *); int sqlite3VarintLen(u64 v); /* -** The header of a record consists of a sequence variable-length integers. -** These integers are almost always small and are encoded as a single byte. -** The following macros take advantage this fact to provide a fast encode -** and decode of the integers in a record header. It is faster for the common -** case where the integer is a single byte. It is a little slower when the -** integer is two or more bytes. But overall it is faster. -** -** The following expressions are equivalent: -** -** x = sqlite3GetVarint32( A, &B ); -** x = sqlite3PutVarint32( A, B ); -** -** x = getVarint32( A, B ); -** x = putVarint32( A, B ); -** +** The common case is for a varint to be a single byte. They following +** macros handle the common case without a procedure call, but then call +** the procedure for larger varints. */ #define getVarint32(A,B) \ (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B))) #define putVarint32(A,B) \ (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\ - sqlite3PutVarint32((A),(B))) + sqlite3PutVarint((A),(B))) #define getVarint sqlite3GetVarint #define putVarint sqlite3PutVarint diff --git a/src/util.c b/src/util.c index 1c75e4cfbe..839a4a4636 100644 --- a/src/util.c +++ b/src/util.c @@ -708,7 +708,7 @@ int sqlite3Atoi(const char *z){ ** bit clear. Except, if we get to the 9th byte, it stores the full ** 8 bits and is the last byte. */ -int sqlite3PutVarint(unsigned char *p, u64 v){ +static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){ int i, j, n; u8 buf[10]; if( v & (((u64)0xff000000)<<32) ){ @@ -732,28 +732,17 @@ int sqlite3PutVarint(unsigned char *p, u64 v){ } return n; } - -/* -** This routine is a faster version of sqlite3PutVarint() that only -** works for 32-bit positive integers and which is optimized for -** the common case of small integers. A MACRO version, putVarint32, -** is provided which inlines the single-byte case. All code should use -** the MACRO version as this function assumes the single-byte case has -** already been handled. -*/ -int sqlite3PutVarint32(unsigned char *p, u32 v){ -#ifndef putVarint32 - if( (v & ~0x7f)==0 ){ - p[0] = v; +int sqlite3PutVarint(unsigned char *p, u64 v){ + if( v<=0x7f ){ + p[0] = v&0x7f; return 1; } -#endif - if( (v & ~0x3fff)==0 ){ - p[0] = (u8)((v>>7) | 0x80); - p[1] = (u8)(v & 0x7f); + if( v<=0x3fff ){ + p[0] = ((v>>7)&0x7f)|0x80; + p[1] = v&0x7f; return 2; } - return sqlite3PutVarint(p, v); + return putVarint64(p,v); } /* diff --git a/src/vdbemem.c b/src/vdbemem.c index cf44aa7e2d..08cf40eaa8 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1130,7 +1130,7 @@ static void recordFunc( sqlite3_result_error_nomem(context); }else{ aRet[0] = nSerial+1; - sqlite3PutVarint(&aRet[1], iSerial); + putVarint32(&aRet[1], iSerial); sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); sqlite3DbFree(db, aRet); From a8dcba9199cef12aa979e6be7c98c50d5a777c9e Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 20:35:29 +0000 Subject: [PATCH 27/42] Combine the pcacheAddToDirtyList() and pcacheRemoveFromDirtyList() routines into a single pcacheManageDirtyList() routine. The resulting binary code is slightly faster and a few bytes smaller. FossilOrigin-Name: 6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 --- manifest | 12 ++-- manifest.uuid | 2 +- src/pcache.c | 150 ++++++++++++++++++++++++-------------------------- 3 files changed, 80 insertions(+), 84 deletions(-) diff --git a/manifest b/manifest index 4718b15953..63a01156f0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\senhancement\sin\ssqlite3PutVarint(). -D 2014-08-22T18:48:25.634 +C Combine\sthe\spcacheAddToDirtyList()\sand\spcacheRemoveFromDirtyList()\sroutines\ninto\sa\ssingle\spcacheManageDirtyList()\sroutine.\s\sThe\sresulting\sbinary\scode\sis\nslightly\sfaster\sand\sa\sfew\sbytes\ssmaller. +D 2014-08-22T20:35:29.948 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -214,7 +214,7 @@ F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 -F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 +F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P cf561d1f0bb60b3d638632d20bd686dda4fa4a04 -R 892fbe852e37f91de1b9f5afa35c0502 +P a929be551924144c9bc7aab608404d59e479abb5 +R 2ac5f67b7ba10391163889b9ff4c4145 U drh -Z c70614e9322ab39ef4e9fbe07eb13b05 +Z 6bffc4c72a94895b60e52defb6944efd diff --git a/manifest.uuid b/manifest.uuid index 12c08a2c09..da73897dba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a929be551924144c9bc7aab608404d59e479abb5 \ No newline at end of file +6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 \ No newline at end of file diff --git a/src/pcache.c b/src/pcache.c index e18bf93be0..2e4b5d78b2 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -62,71 +62,73 @@ static int pcacheCheckSynced(PCache *pCache){ } #endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */ -/* -** Remove page pPage from the list of dirty pages. -*/ -static void pcacheRemoveFromDirtyList(PgHdr *pPage){ - PCache *p = pPage->pCache; - - assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); - assert( pPage->pDirtyPrev || pPage==p->pDirty ); - - /* Update the PCache1.pSynced variable if necessary. */ - if( p->pSynced==pPage ){ - PgHdr *pSynced = pPage->pDirtyPrev; - while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ - pSynced = pSynced->pDirtyPrev; - } - p->pSynced = pSynced; - } - - if( pPage->pDirtyNext ){ - pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; - }else{ - assert( pPage==p->pDirtyTail ); - p->pDirtyTail = pPage->pDirtyPrev; - } - if( pPage->pDirtyPrev ){ - pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; - }else{ - assert( pPage==p->pDirty ); - p->pDirty = pPage->pDirtyNext; - if( p->pDirty==0 && p->bPurgeable ){ - assert( p->eCreate==1 ); - p->eCreate = 2; - } - } - pPage->pDirtyNext = 0; - pPage->pDirtyPrev = 0; - - expensive_assert( pcacheCheckSynced(p) ); -} +/* Allowed values for second argument to pcacheManageDirtyList() */ +#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */ +#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */ +#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */ /* -** Add page pPage to the head of the dirty list (PCache1.pDirty is set to -** pPage). +** Manage pPage's participation on the dirty list. Bits of the addRemove +** argument determines what operation to do. The 0x01 bit means first +** remove pPage from the dirty list. The 0x02 means add pPage back to +** the dirty list. Doing both moves pPage to the front of the dirty list. */ -static void pcacheAddToDirtyList(PgHdr *pPage){ +static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ PCache *p = pPage->pCache; - assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); - - pPage->pDirtyNext = p->pDirty; - if( pPage->pDirtyNext ){ - assert( pPage->pDirtyNext->pDirtyPrev==0 ); - pPage->pDirtyNext->pDirtyPrev = pPage; - }else if( p->bPurgeable ){ - assert( p->eCreate==2 ); - p->eCreate = 1; + if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ + assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); + assert( pPage->pDirtyPrev || pPage==p->pDirty ); + + /* Update the PCache1.pSynced variable if necessary. */ + if( p->pSynced==pPage ){ + PgHdr *pSynced = pPage->pDirtyPrev; + while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ + pSynced = pSynced->pDirtyPrev; + } + p->pSynced = pSynced; + } + + if( pPage->pDirtyNext ){ + pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; + }else{ + assert( pPage==p->pDirtyTail ); + p->pDirtyTail = pPage->pDirtyPrev; + } + if( pPage->pDirtyPrev ){ + pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; + }else{ + assert( pPage==p->pDirty ); + p->pDirty = pPage->pDirtyNext; + if( p->pDirty==0 && p->bPurgeable ){ + assert( p->eCreate==1 ); + p->eCreate = 2; + } + } + pPage->pDirtyNext = 0; + pPage->pDirtyPrev = 0; + expensive_assert( pcacheCheckSynced(p) ); } - p->pDirty = pPage; - if( !p->pDirtyTail ){ - p->pDirtyTail = pPage; + if( addRemove & PCACHE_DIRTYLIST_ADD ){ + assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); + + pPage->pDirtyNext = p->pDirty; + if( pPage->pDirtyNext ){ + assert( pPage->pDirtyNext->pDirtyPrev==0 ); + pPage->pDirtyNext->pDirtyPrev = pPage; + }else if( p->bPurgeable ){ + assert( p->eCreate==2 ); + p->eCreate = 1; + } + p->pDirty = pPage; + if( !p->pDirtyTail ){ + p->pDirtyTail = pPage; + } + if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ + p->pSynced = pPage; + } + expensive_assert( pcacheCheckSynced(p) ); } - if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ - p->pSynced = pPage; - } - expensive_assert( pcacheCheckSynced(p) ); } /* @@ -134,12 +136,11 @@ static void pcacheAddToDirtyList(PgHdr *pPage){ ** being used for an in-memory database, this function is a no-op. */ static void pcacheUnpin(PgHdr *p){ - PCache *pCache = p->pCache; - if( pCache->bPurgeable ){ + if( p->pCache->bPurgeable ){ if( p->pgno==1 ){ - pCache->pPage1 = 0; + p->pCache->pPage1 = 0; } - sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0); + sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0); } } @@ -332,18 +333,16 @@ int sqlite3PcacheFetch( ** Decrement the reference count on a page. If the page is clean and the ** reference count drops to 0, then it is made elible for recycling. */ -void sqlite3PcacheRelease(PgHdr *p){ +void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ assert( p->nRef>0 ); p->nRef--; if( p->nRef==0 ){ - PCache *pCache = p->pCache; - pCache->nRef--; + p->pCache->nRef--; if( (p->flags&PGHDR_DIRTY)==0 ){ pcacheUnpin(p); }else{ /* Move the page to the head of the dirty list. */ - pcacheRemoveFromDirtyList(p); - pcacheAddToDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); } } } @@ -362,17 +361,15 @@ void sqlite3PcacheRef(PgHdr *p){ ** page pointed to by p is invalid. */ void sqlite3PcacheDrop(PgHdr *p){ - PCache *pCache; assert( p->nRef==1 ); if( p->flags&PGHDR_DIRTY ){ - pcacheRemoveFromDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); } - pCache = p->pCache; - pCache->nRef--; + p->pCache->nRef--; if( p->pgno==1 ){ - pCache->pPage1 = 0; + p->pCache->pPage1 = 0; } - sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1); + sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1); } /* @@ -384,7 +381,7 @@ void sqlite3PcacheMakeDirty(PgHdr *p){ assert( p->nRef>0 ); if( 0==(p->flags & PGHDR_DIRTY) ){ p->flags |= PGHDR_DIRTY; - pcacheAddToDirtyList( p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); } } @@ -394,7 +391,7 @@ void sqlite3PcacheMakeDirty(PgHdr *p){ */ void sqlite3PcacheMakeClean(PgHdr *p){ if( (p->flags & PGHDR_DIRTY) ){ - pcacheRemoveFromDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC); if( p->nRef==0 ){ pcacheUnpin(p); @@ -433,8 +430,7 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ - pcacheRemoveFromDirtyList(p); - pcacheAddToDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); } } From 75e2a2d362175e222873a90d1d356bac92b31037 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 21:58:10 +0000 Subject: [PATCH 28/42] Performance enhancements in the b-tree mutex logic. FossilOrigin-Name: 8914530644f938a7a98e25ea1fb0bca1f9d79101 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btmutex.c | 19 ++++++++++++++++--- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 63a01156f0..812c653a73 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Combine\sthe\spcacheAddToDirtyList()\sand\spcacheRemoveFromDirtyList()\sroutines\ninto\sa\ssingle\spcacheManageDirtyList()\sroutine.\s\sThe\sresulting\sbinary\scode\sis\nslightly\sfaster\sand\sa\sfew\sbytes\ssmaller. -D 2014-08-22T20:35:29.948 +C Performance\senhancements\sin\sthe\sb-tree\smutex\slogic. +D 2014-08-22T21:58:10.354 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb -F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 +F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a929be551924144c9bc7aab608404d59e479abb5 -R 2ac5f67b7ba10391163889b9ff4c4145 +P 6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 +R 24d5ffe2f1d9679a613707454c70f45a U drh -Z 6bffc4c72a94895b60e52defb6944efd +Z 6801ae93f83fb9ed7a247305de8bd03a diff --git a/manifest.uuid b/manifest.uuid index da73897dba..5367fb5584 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 \ No newline at end of file +8914530644f938a7a98e25ea1fb0bca1f9d79101 \ No newline at end of file diff --git a/src/btmutex.c b/src/btmutex.c index d87d4d5fee..9672687fe0 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -38,7 +38,7 @@ static void lockBtreeMutex(Btree *p){ ** Release the BtShared mutex associated with B-Tree handle p and ** clear the p->locked boolean. */ -static void unlockBtreeMutex(Btree *p){ +static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){ BtShared *pBt = p->pBt; assert( p->locked==1 ); assert( sqlite3_mutex_held(pBt->mutex) ); @@ -49,6 +49,9 @@ static void unlockBtreeMutex(Btree *p){ p->locked = 0; } +/* Forward reference */ +static void SQLITE_NOINLINE btreeLockCarefully(Btree *p); + /* ** Enter a mutex on the given BTree object. ** @@ -66,8 +69,6 @@ static void unlockBtreeMutex(Btree *p){ ** subsequent Btrees that desire a lock. */ void sqlite3BtreeEnter(Btree *p){ - Btree *pLater; - /* Some basic sanity checking on the Btree. The list of Btrees ** connected by pNext and pPrev should be in sorted order by ** Btree.pBt value. All elements of the list should belong to @@ -92,6 +93,17 @@ void sqlite3BtreeEnter(Btree *p){ if( !p->sharable ) return; p->wantToLock++; if( p->locked ) return; + btreeLockCarefully(p); +} + +/* This is a helper function for sqlite3BtreeLock(). By moving +** complex, but seldom used logic, out of sqlite3BtreeLock() and +** into this routine, we avoid unnecessary stack pointer changes +** and thus help the sqlite3BtreeLock() routine to run much faster +** in the common case. +*/ +static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ + Btree *pLater; /* In most cases, we should be able to acquire the lock we ** want without having to go throught the ascending lock @@ -124,6 +136,7 @@ void sqlite3BtreeEnter(Btree *p){ } } + /* ** Exit the recursive mutex on a Btree. */ From 637f3d83b9455eeb87bce698877f9d8c03ec912b Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 22:26:07 +0000 Subject: [PATCH 29/42] Factor the saveAllCursors() routine of btree.c into two separate routines, for a noticable performance improvement. FossilOrigin-Name: 3eb084390382c108e9b0ff0b29dede58ebb149bc --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 35 +++++++++++++++++++++++++++++++---- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 812c653a73..a0fd1d8b2e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\senhancements\sin\sthe\sb-tree\smutex\slogic. -D 2014-08-22T21:58:10.354 +C Factor\sthe\ssaveAllCursors()\sroutine\sof\sbtree.c\sinto\stwo\sseparate\sroutines,\nfor\sa\snoticable\sperformance\simprovement. +D 2014-08-22T22:26:07.834 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 -F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d +F src/btree.c 776885dfef3033af7e8eabbf004481f219870a1d F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 -R 24d5ffe2f1d9679a613707454c70f45a +P 8914530644f938a7a98e25ea1fb0bca1f9d79101 +R 036983fb95199f1ba06f1397f389a453 U drh -Z 6801ae93f83fb9ed7a247305de8bd03a +Z 9ea20fed62648c22294e9e322338cabb diff --git a/manifest.uuid b/manifest.uuid index 5367fb5584..334a3ae4c0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8914530644f938a7a98e25ea1fb0bca1f9d79101 \ No newline at end of file +3eb084390382c108e9b0ff0b29dede58ebb149bc \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 56718b69d6..6da3715e30 100644 --- a/src/btree.c +++ b/src/btree.c @@ -629,16 +629,42 @@ static int saveCursorPosition(BtCursor *pCur){ return rc; } +/* Forward reference */ +static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); + /* ** Save the positions of all cursors (except pExcept) that are open on -** the table with root-page iRoot. Usually, this is called just before cursor -** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). +** the table with root-page iRoot. "Saving the cursor position" means that +** the location in the btree is remembered in such a way that it can be +** moved back to the same spot after the btree has been modified. This +** routine is called just before cursor pExcept is used to modify the +** table, for example in BtreeDelete() or BtreeInsert(). +** +** Implementation note: This routine merely checks to see if any cursors +** need to be saved. It calls out to saveCursorsOnList() in the (unusual) +** event that cursors are in need to being saved. */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ - BtCursor *p; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); + BtCursor *p; for(p=pBt->pCursor; p; p=p->pNext){ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; + } + return p ? saveCursorsOnList(p, iRoot, pExcept) : SQLITE_OK; +} + +/* This helper routine to saveAllCursors does the actual work of saving +** the cursors if and when a cursor is found that actually requires saving. +** The common case is that no cursors need to be saved, so this routine is +** broken out from its caller to avoid unnecessary stack pointer movement. +*/ +static int SQLITE_NOINLINE saveCursorsOnList( + BtCursor *p, /* The first cursor that needs saving */ + Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */ + BtCursor *pExcept /* Do not save this cursor */ +){ + do{ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ if( p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); @@ -650,7 +676,8 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ btreeReleaseAllCursorPages(p); } } - } + p = p->pNext; + }while( p ); return SQLITE_OK; } From 6848dad89477be4146d535e7a2646300c472f429 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 23:33:03 +0000 Subject: [PATCH 30/42] Another performance tweak: Split the sqlite3BtreeCursorHasMoved() routine into two with the second routine named sqlite3BtreeCursorRestore(). The first now only reports whether or not the cursor has moved and the second tries to restore the cursor. This allows the sqlite3VdbeCursorMoveto() routine to be refactored to avoid stack pointer movements, for a noticable performance gain. FossilOrigin-Name: ce123b5c592556a8cd38b01fcc91ba76231d3098 --- manifest | 16 ++++++------ manifest.uuid | 2 +- src/btree.c | 51 ++++++++++++++++++++++--------------- src/btree.h | 3 ++- src/vdbeaux.c | 69 ++++++++++++++++++++++++++++++++++----------------- 5 files changed, 88 insertions(+), 53 deletions(-) diff --git a/manifest b/manifest index a0fd1d8b2e..98cd57119e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Factor\sthe\ssaveAllCursors()\sroutine\sof\sbtree.c\sinto\stwo\sseparate\sroutines,\nfor\sa\snoticable\sperformance\simprovement. -D 2014-08-22T22:26:07.834 +C Another\sperformance\stweak:\sSplit\sthe\ssqlite3BtreeCursorHasMoved()\sroutine\s\ninto\stwo\swith\sthe\ssecond\sroutine\snamed\ssqlite3BtreeCursorRestore().\s\sThe\sfirst\nnow\sonly\sreports\swhether\sor\snot\sthe\scursor\shas\smoved\sand\sthe\ssecond\stries\sto\nrestore\sthe\scursor.\s\sThis\sallows\sthe\ssqlite3VdbeCursorMoveto()\sroutine\sto\sbe\nrefactored\sto\savoid\sstack\spointer\smovements,\sfor\sa\snoticable\sperformance\sgain. +D 2014-08-22T23:33:03.189 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,8 +168,8 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 -F src/btree.c 776885dfef3033af7e8eabbf004481f219870a1d -F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a +F src/btree.c c4b4e1c9524ba7b7dab840e6f8b29e2379a3bdd2 +F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb F src/callback.c b97d0695ffcf6a8710ee445ffe56ee387d4d8a6f @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d -F src/vdbeaux.c f7fdc59e2eefa6fc4ba7324b03ea6f8f66e98d62 +F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 F src/vdbemem.c 4a64659ed8e4c3b18a9238e038145ab1bdcd146f F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8914530644f938a7a98e25ea1fb0bca1f9d79101 -R 036983fb95199f1ba06f1397f389a453 +P 3eb084390382c108e9b0ff0b29dede58ebb149bc +R 356d2e894dc7576ad768e53fab77ee5b U drh -Z 9ea20fed62648c22294e9e322338cabb +Z 78a9bc2b7c59c5e05ea01f499ba8646b diff --git a/manifest.uuid b/manifest.uuid index 334a3ae4c0..af6d676ce0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3eb084390382c108e9b0ff0b29dede58ebb149bc \ No newline at end of file +ce123b5c592556a8cd38b01fcc91ba76231d3098 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 6da3715e30..23de31db07 100644 --- a/src/btree.c +++ b/src/btree.c @@ -762,37 +762,48 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){ SQLITE_OK) /* -** Determine whether or not a cursor has moved from the position it -** was last placed at. Cursors can move when the row they are pointing -** at is deleted out from under them. +** Determine whether or not a cursor has moved from the position where +** it was last placed, or has been invalidated for any other reason. +** Cursors can move when the row they are pointing at is deleted out +** from under them, for example. Cursor might also move if a btree +** is rebalanced. ** -** This routine returns an error code if something goes wrong. The -** integer *pHasMoved is set as follows: +** Calling this routine with a NULL cursor pointer returns false. ** -** 0: The cursor is unchanged -** 1: The cursor is still pointing at the same row, but the pointers -** returned by sqlite3BtreeKeyFetch() or sqlite3BtreeDataFetch() -** might now be invalid because of a balance() or other change to the -** b-tree. -** 2: The cursor is no longer pointing to the row. The row might have -** been deleted out from under the cursor. +** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor +** back to where it ought to be if this routine returns true. */ -int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){ +int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ + return pCur && pCur->eState!=CURSOR_VALID; +} + +/* +** This routine restores a cursor back to its original position after it +** has been moved by some outside activity (such as a btree rebalance or +** a row having been deleted out from under the cursor). +** +** On success, the *pDifferentRow parameter is false if the cursor is left +** pointing at exactly the same row. *pDifferntRow is the row the cursor +** was pointing to has been deleted, forcing the cursor to point to some +** nearby row. +** +** This routine should only be called for a cursor that just returned +** TRUE from sqlite3BtreeCursorHasMoved(). +*/ +int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){ int rc; - if( pCur->eState==CURSOR_VALID ){ - *pHasMoved = 0; - return SQLITE_OK; - } + assert( pCur!=0 ); + assert( pCur->eState!=CURSOR_VALID ); rc = restoreCursorPosition(pCur); if( rc ){ - *pHasMoved = 2; + *pDifferentRow = 1; return rc; } if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){ - *pHasMoved = 2; + *pDifferentRow = 1; }else{ - *pHasMoved = 1; + *pDifferentRow = 0; } return SQLITE_OK; } diff --git a/src/btree.h b/src/btree.h index 7118534f93..38abdca1a2 100644 --- a/src/btree.h +++ b/src/btree.h @@ -169,7 +169,8 @@ int sqlite3BtreeMovetoUnpacked( int bias, int *pRes ); -int sqlite3BtreeCursorHasMoved(BtCursor*, int*); +int sqlite3BtreeCursorHasMoved(BtCursor*); +int sqlite3BtreeCursorRestore(BtCursor*, int*); int sqlite3BtreeDelete(BtCursor*); int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 58f39a48a8..2037121ddc 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2713,6 +2713,48 @@ void sqlite3VdbeDelete(Vdbe *p){ sqlite3DbFree(db, p); } +/* +** The cursor "p" has a pending seek operation that has not yet been +** carried out. Seek the cursor now. If an error occurs, return +** the appropriate error code. +*/ +static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){ + int res, rc; +#ifdef SQLITE_TEST + extern int sqlite3_search_count; +#endif + assert( p->deferredMoveto ); + assert( p->isTable ); + rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); + if( rc ) return rc; + p->lastRowid = p->movetoTarget; + if( res!=0 ) return SQLITE_CORRUPT_BKPT; + p->rowidIsValid = 1; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + p->deferredMoveto = 0; + p->cacheStatus = CACHE_STALE; + return SQLITE_OK; +} + +/* +** Something has moved cursor "p" out of place. Maybe the row it was +** pointed to was deleted out from under it. Or maybe the btree was +** rebalanced. Whatever the cause, try to restore "p" to the place it +** is suppose to be pointing. If the row was deleted out from under the +** cursor, set the cursor to point to a NULL row. +*/ +static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){ + int isDifferentRow, rc; + assert( p->pCursor!=0 ); + assert( sqlite3BtreeCursorHasMoved(p->pCursor) ); + rc = sqlite3BtreeCursorRestore(p->pCursor, &isDifferentRow); + p->cacheStatus = CACHE_STALE; + if( isDifferentRow ) p->nullRow = 1; + return rc; +} + /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error @@ -2728,29 +2770,10 @@ void sqlite3VdbeDelete(Vdbe *p){ */ int sqlite3VdbeCursorMoveto(VdbeCursor *p){ if( p->deferredMoveto ){ - int res, rc; -#ifdef SQLITE_TEST - extern int sqlite3_search_count; -#endif - assert( p->isTable ); - rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); - if( rc ) return rc; - p->lastRowid = p->movetoTarget; - if( res!=0 ) return SQLITE_CORRUPT_BKPT; - p->rowidIsValid = 1; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - p->deferredMoveto = 0; - p->cacheStatus = CACHE_STALE; - }else if( p->pCursor ){ - int hasMoved; - int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved); - if( rc ) return rc; - if( hasMoved ){ - p->cacheStatus = CACHE_STALE; - if( hasMoved==2 ) p->nullRow = 1; - } + return handleDeferredMoveto(p); + } + if( sqlite3BtreeCursorHasMoved(p->pCursor) ){ + return handleMovedCursor(p); } return SQLITE_OK; } From bd9507c8daa292989b382628cb7fedba18dc2fb3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 17:21:37 +0000 Subject: [PATCH 31/42] Performance optimization in the applyAffinity() logic inside the VDBE. FossilOrigin-Name: 25f2246be404f38b4f8dd70397cd1454d46358c4 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 34 +++++++++++++++++++++++----------- src/vdbeInt.h | 2 +- src/vdbemem.c | 13 +++++++------ 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 98cd57119e..8450ec16e4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\sperformance\stweak:\sSplit\sthe\ssqlite3BtreeCursorHasMoved()\sroutine\s\ninto\stwo\swith\sthe\ssecond\sroutine\snamed\ssqlite3BtreeCursorRestore().\s\sThe\sfirst\nnow\sonly\sreports\swhether\sor\snot\sthe\scursor\shas\smoved\sand\sthe\ssecond\stries\sto\nrestore\sthe\scursor.\s\sThis\sallows\sthe\ssqlite3VdbeCursorMoveto()\sroutine\sto\sbe\nrefactored\sto\savoid\sstack\spointer\smovements,\sfor\sa\snoticable\sperformance\sgain. -D 2014-08-22T23:33:03.189 +C Performance\soptimization\sin\sthe\sapplyAffinity()\slogic\sinside\sthe\sVDBE. +D 2014-08-23T17:21:37.343 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -284,13 +284,13 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 +F src/vdbe.c 76f9fc30dc28751900e85f615e29cdf89c069a77 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 -F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df +F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c 4a64659ed8e4c3b18a9238e038145ab1bdcd146f +F src/vdbemem.c f2e162888521a9af35d608ac4c13db4991dfb417 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3eb084390382c108e9b0ff0b29dede58ebb149bc -R 356d2e894dc7576ad768e53fab77ee5b +P ce123b5c592556a8cd38b01fcc91ba76231d3098 +R f59cf04b4ec2e84886c139f6982d2702 U drh -Z 78a9bc2b7c59c5e05ea01f499ba8646b +Z 3f5bd9d4c135b090a54f8be497682e06 diff --git a/manifest.uuid b/manifest.uuid index af6d676ce0..4ee0b9c481 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ce123b5c592556a8cd38b01fcc91ba76231d3098 \ No newline at end of file +25f2246be404f38b4f8dd70397cd1454d46358c4 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 61adb9cccd..13a076cacb 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -146,7 +146,7 @@ int sqlite3_found_count = 0; ** already. Return non-zero if a malloc() fails. */ #define Stringify(P, enc) \ - if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \ { goto no_mem; } /* @@ -228,8 +228,17 @@ static VdbeCursor *allocateCursor( ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. +** +** If the bTryForInt flag is true, then extra effort is made to give +** an integer representation. Strings that look like floating point +** values but which have no fractional component (example: '48.00') +** will have a MEM_Int representation when bTryForInt is true. +** +** If bTryForInt is false, then if the input string contains a decimal +** point or exponential notation, the result is only MEM_Real, even +** if there is an exact integer representation of the quantity. */ -static void applyNumericAffinity(Mem *pRec){ +static void applyNumericAffinity(Mem *pRec, int bTryForInt){ double rValue; i64 iValue; u8 enc = pRec->enc; @@ -241,10 +250,9 @@ static void applyNumericAffinity(Mem *pRec){ }else{ pRec->r = rValue; pRec->flags |= MEM_Real; + if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); } } -#define ApplyNumericAffinity(X) \ - if(((X)->flags&(MEM_Real|MEM_Int))==0){applyNumericAffinity(X);} /* ** Processing is determine by the affinity parameter: @@ -275,15 +283,17 @@ static void applyAffinity( ** representation. */ if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ - sqlite3VdbeMemStringify(pRec, enc); + sqlite3VdbeMemStringify(pRec, enc, 1); } - pRec->flags &= ~(MEM_Real|MEM_Int); }else if( affinity!=SQLITE_AFF_NONE ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL || affinity==SQLITE_AFF_NUMERIC ); - ApplyNumericAffinity(pRec); - if( pRec->flags & MEM_Real ){ - sqlite3VdbeIntegerAffinity(pRec); + if( (pRec->flags & MEM_Int)==0 ){ + if( (pRec->flags & MEM_Real)==0 ){ + applyNumericAffinity(pRec,1); + }else{ + sqlite3VdbeIntegerAffinity(pRec); + } } } } @@ -298,7 +308,7 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; - applyNumericAffinity(pMem); + applyNumericAffinity(pMem, 0); eType = sqlite3_value_type(pVal); } return eType; @@ -3603,7 +3613,9 @@ case OP_SeekGT: { /* jump, in3 */ ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so covert it. */ pIn3 = &aMem[pOp->p3]; - ApplyNumericAffinity(pIn3); + if( (pIn3->flags & (MEM_Int|MEM_Real))==0 ){ + applyNumericAffinity(pIn3, 0); + } iKey = sqlite3VdbeIntValue(pIn3); pC->rowidIsValid = 0; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 141573eef4..ba44b61e91 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -418,7 +418,7 @@ void sqlite3VdbeMemSetNull(Mem*); void sqlite3VdbeMemSetZeroBlob(Mem*,int); void sqlite3VdbeMemSetRowSet(Mem*); int sqlite3VdbeMemMakeWriteable(Mem*); -int sqlite3VdbeMemStringify(Mem*, int); +int sqlite3VdbeMemStringify(Mem*, u8, u8); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); diff --git a/src/vdbemem.c b/src/vdbemem.c index 08cf40eaa8..572d486fc4 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -223,7 +223,8 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ ** are converted using sqlite3_snprintf(). Converting a BLOB to a string ** is a no-op. ** -** Existing representations MEM_Int and MEM_Real are *not* invalidated. +** Existing representations MEM_Int and MEM_Real are invalidated if +** bForce is true but are retained if bForce is false. ** ** A MEM_Null value will never be passed to this function. This function is ** used for converting values to text for returning to the user (i.e. via @@ -231,8 +232,7 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ ** keys are strings. In the former case a NULL pointer is returned the ** user and the later is an internal programming error. */ -int sqlite3VdbeMemStringify(Mem *pMem, int enc){ - int rc = SQLITE_OK; +int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ int fg = pMem->flags; const int nByte = 32; @@ -248,7 +248,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ return SQLITE_NOMEM; } - /* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 + /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 ** string representation of the value. Then, if the required encoding ** is UTF-16le or UTF-16be do a translation. ** @@ -263,8 +263,9 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ pMem->n = sqlite3Strlen30(pMem->z); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); sqlite3VdbeChangeEncoding(pMem, enc); - return rc; + return SQLITE_OK; } /* @@ -877,7 +878,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ }else{ assert( (pVal->flags&MEM_Blob)==0 ); - sqlite3VdbeMemStringify(pVal, enc); + sqlite3VdbeMemStringify(pVal, enc, 0); assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); } assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 From f1a89ede4a392fec648f6a51f8aa0a3f5216cd4e Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 17:41:15 +0000 Subject: [PATCH 32/42] Improved performance in the type handling of arithmetic operators in the VDBE. FossilOrigin-Name: 0c0a603950c97837442d82886f947aab0acbd805 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 26 +++++++++++++++++++------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 8450ec16e4..a5fad99ba9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\soptimization\sin\sthe\sapplyAffinity()\slogic\sinside\sthe\sVDBE. -D 2014-08-23T17:21:37.343 +C Improved\sperformance\sin\sthe\stype\shandling\sof\sarithmetic\soperators\sin\sthe\sVDBE. +D 2014-08-23T17:41:15.456 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -284,7 +284,7 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 76f9fc30dc28751900e85f615e29cdf89c069a77 +F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ce123b5c592556a8cd38b01fcc91ba76231d3098 -R f59cf04b4ec2e84886c139f6982d2702 +P 25f2246be404f38b4f8dd70397cd1454d46358c4 +R 2a69d28bf2271ac25d420aa80c42027b U drh -Z 3f5bd9d4c135b090a54f8be497682e06 +Z c64b6b94b93d1da5e9e0a75cc412b115 diff --git a/manifest.uuid b/manifest.uuid index 4ee0b9c481..53a34bdd8d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -25f2246be404f38b4f8dd70397cd1454d46358c4 \ No newline at end of file +0c0a603950c97837442d82886f947aab0acbd805 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 13a076cacb..2e797eeaf5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -326,6 +326,24 @@ void sqlite3ValueApplyAffinity( applyAffinity((Mem *)pVal, affinity, enc); } +/* +** pMem currently only holds a string type (or maybe a BLOB that we can +** interpret as a string if we want to). Compute its corresponding +** numeric type, if has one. Set the pMem->r and pMem->u.i fields +** accordingly. +*/ +static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ + assert( (pMem->flags & (MEM_Int|MEM_Real))==0 ); + assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); + if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ + return 0; + } + if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ + return MEM_Int; + } + return MEM_Real; +} + /* ** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or ** none. @@ -338,13 +356,7 @@ static u16 numericType(Mem *pMem){ return pMem->flags & (MEM_Int|MEM_Real); } if( pMem->flags & (MEM_Str|MEM_Blob) ){ - if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ - return 0; - } - if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ - return MEM_Int; - } - return MEM_Real; + return computeNumericType(pMem); } return 0; } From 9de4a17185a18927a72a7278fc70b600e46c653e Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 18:17:19 +0000 Subject: [PATCH 33/42] Make the implementation of the sqlite3_aggregate_context() interface faster for second an subsequent invocations. This helps all aggregate functions to perform better. FossilOrigin-Name: 802148f3110462eac939d53ce08eb9a2f6aac739 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeapi.c | 42 ++++++++++++++++++++++++++---------------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index a5fad99ba9..aa0c254b02 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sperformance\sin\sthe\stype\shandling\sof\sarithmetic\soperators\sin\sthe\sVDBE. -D 2014-08-23T17:41:15.456 +C Make\sthe\simplementation\sof\sthe\ssqlite3_aggregate_context()\sinterface\sfaster\nfor\ssecond\san\ssubsequent\sinvocations.\s\sThis\shelps\sall\saggregate\sfunctions\sto\nperform\sbetter. +D 2014-08-23T18:17:19.059 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -287,7 +287,7 @@ F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 -F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d +F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 F src/vdbemem.c f2e162888521a9af35d608ac4c13db4991dfb417 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 25f2246be404f38b4f8dd70397cd1454d46358c4 -R 2a69d28bf2271ac25d420aa80c42027b +P 0c0a603950c97837442d82886f947aab0acbd805 +R d4bdc3de1168bf2d862dde32e02d949b U drh -Z c64b6b94b93d1da5e9e0a75cc412b115 +Z 5d66d6e81701eb9b183824f31680ac42 diff --git a/manifest.uuid b/manifest.uuid index 53a34bdd8d..5b8e019c7e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c0a603950c97837442d82886f947aab0acbd805 \ No newline at end of file +802148f3110462eac939d53ce08eb9a2f6aac739 \ No newline at end of file diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 675361013a..b2d8059153 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -606,32 +606,42 @@ void sqlite3InvalidFunction( sqlite3_free(zErr); } +/* +** Create a new aggregate context for p and return a pointer to +** its pMem->z element. +*/ +static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ + Mem *pMem = p->pMem; + assert( (pMem->flags & MEM_Agg)==0 ); + if( nByte<=0 ){ + sqlite3VdbeMemReleaseExternal(pMem); + pMem->flags = MEM_Null; + pMem->z = 0; + }else{ + sqlite3VdbeMemGrow(pMem, nByte, 0); + pMem->flags = MEM_Agg; + pMem->u.pDef = p->pFunc; + if( pMem->z ){ + memset(pMem->z, 0, nByte); + } + } + return (void*)pMem->z; +} + /* ** Allocate or return the aggregate context for a user function. A new ** context is allocated on the first call. Subsequent calls return the ** same context that was returned on prior calls. */ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ - Mem *pMem; assert( p && p->pFunc && p->pFunc->xStep ); assert( sqlite3_mutex_held(p->s.db->mutex) ); - pMem = p->pMem; testcase( nByte<0 ); - if( (pMem->flags & MEM_Agg)==0 ){ - if( nByte<=0 ){ - sqlite3VdbeMemReleaseExternal(pMem); - pMem->flags = MEM_Null; - pMem->z = 0; - }else{ - sqlite3VdbeMemGrow(pMem, nByte, 0); - pMem->flags = MEM_Agg; - pMem->u.pDef = p->pFunc; - if( pMem->z ){ - memset(pMem->z, 0, nByte); - } - } + if( (p->pMem->flags & MEM_Agg)==0 ){ + return createAggContext(p, nByte); + }else{ + return (void*)p->pMem->z; } - return (void*)pMem->z; } /* From 3ccd5bf89e57d67b1ee89e7cf9ad3bc5989b0339 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 19:04:55 +0000 Subject: [PATCH 34/42] Changes to sqlite3ScratchMalloc() that make the entire memory allocation interface a little faster and about 100 bytes smaller. FossilOrigin-Name: f83daa16f65ef35062412e88c214852a4aeb3da2 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/malloc.c | 14 ++++++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index aa0c254b02..91d323beb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\sthe\simplementation\sof\sthe\ssqlite3_aggregate_context()\sinterface\sfaster\nfor\ssecond\san\ssubsequent\sinvocations.\s\sThis\shelps\sall\saggregate\sfunctions\sto\nperform\sbetter. -D 2014-08-23T18:17:19.059 +C Changes\sto\ssqlite3ScratchMalloc()\sthat\smake\sthe\sentire\smemory\sallocation\ninterface\sa\slittle\sfaster\sand\sabout\s100\sbytes\ssmaller. +D 2014-08-23T19:04:55.170 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -191,7 +191,7 @@ F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 -F src/malloc.c 0a88a97fc5ae621ca9659d38b080e0b9ddbb80ad +F src/malloc.c 7f26fcedc42b93bb49c4c12a77aa0d891182392e F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0c0a603950c97837442d82886f947aab0acbd805 -R d4bdc3de1168bf2d862dde32e02d949b +P 802148f3110462eac939d53ce08eb9a2f6aac739 +R f2effcc85284cd0fae163c222d4987e9 U drh -Z 5d66d6e81701eb9b183824f31680ac42 +Z d2f180c60ae7591aa14ffa4ab8835b4a diff --git a/manifest.uuid b/manifest.uuid index 5b8e019c7e..233ca94126 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -802148f3110462eac939d53ce08eb9a2f6aac739 \ No newline at end of file +f83daa16f65ef35062412e88c214852a4aeb3da2 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 9fb4303979..f3b317da5f 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -352,22 +352,20 @@ void *sqlite3ScratchMalloc(int n){ assert( n>0 ); sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ p = mem0.pScratchFree; mem0.pScratchFree = mem0.pScratchFree->pNext; mem0.nScratchFree--; sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); - sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); sqlite3_mutex_leave(mem0.mutex); }else{ - if( sqlite3GlobalConfig.bMemstat ){ - sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); - n = mallocWithAlarm(n, &p); - if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); + sqlite3_mutex_leave(mem0.mutex); + p = sqlite3Malloc(n); + if( sqlite3GlobalConfig.bMemstat && p ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); sqlite3_mutex_leave(mem0.mutex); - }else{ - sqlite3_mutex_leave(mem0.mutex); - p = sqlite3GlobalConfig.m.xMalloc(n); } sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); } From 3bdffddc418b3b202d48eff685780eba2af24465 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 19:08:09 +0000 Subject: [PATCH 35/42] Fix a variable-declaration after code problem in btree.c. Harmless in GCC and CLANG but unacceptable for MSVC. FossilOrigin-Name: 45abd5c0bad2847861f3b26a7040490aa9bb1332 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 91d323beb8..f86063d01b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\ssqlite3ScratchMalloc()\sthat\smake\sthe\sentire\smemory\sallocation\ninterface\sa\slittle\sfaster\sand\sabout\s100\sbytes\ssmaller. -D 2014-08-23T19:04:55.170 +C Fix\sa\svariable-declaration\safter\scode\sproblem\sin\sbtree.c.\s\sHarmless\sin\nGCC\sand\sCLANG\sbut\sunacceptable\sfor\sMSVC. +D 2014-08-23T19:08:09.445 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 -F src/btree.c c4b4e1c9524ba7b7dab840e6f8b29e2379a3bdd2 +F src/btree.c 4737cb5bdb2eb8989cb292f6ff921f7ff45f0c46 F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 802148f3110462eac939d53ce08eb9a2f6aac739 -R f2effcc85284cd0fae163c222d4987e9 +P f83daa16f65ef35062412e88c214852a4aeb3da2 +R 964769625a1b08555f23e3f40e4e1b01 U drh -Z d2f180c60ae7591aa14ffa4ab8835b4a +Z 8bbf37cac5a7f4ae4955d0f942660ce9 diff --git a/manifest.uuid b/manifest.uuid index 233ca94126..948c00a194 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f83daa16f65ef35062412e88c214852a4aeb3da2 \ No newline at end of file +45abd5c0bad2847861f3b26a7040490aa9bb1332 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 23de31db07..384bab218c 100644 --- a/src/btree.c +++ b/src/btree.c @@ -645,9 +645,9 @@ static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); ** event that cursors are in need to being saved. */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ + BtCursor *p; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); - BtCursor *p; for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; } From b4586f1254df07a7eccba2101ae4a95dfe2ca34b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 19:42:06 +0000 Subject: [PATCH 36/42] Another memory allocator performance optimization. FossilOrigin-Name: 6da6f46d0c43e3b68c21f514ddf8ee663c20f249 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/malloc.c | 10 +++++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index f86063d01b..0f001ae399 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\svariable-declaration\safter\scode\sproblem\sin\sbtree.c.\s\sHarmless\sin\nGCC\sand\sCLANG\sbut\sunacceptable\sfor\sMSVC. -D 2014-08-23T19:08:09.445 +C Another\smemory\sallocator\sperformance\soptimization. +D 2014-08-23T19:42:06.737 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -191,7 +191,7 @@ F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 -F src/malloc.c 7f26fcedc42b93bb49c4c12a77aa0d891182392e +F src/malloc.c 06f8507831d04d2830237bf0c9f2fd04623f9868 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f83daa16f65ef35062412e88c214852a4aeb3da2 -R 964769625a1b08555f23e3f40e4e1b01 +P 45abd5c0bad2847861f3b26a7040490aa9bb1332 +R 863f9a5c456ee79d86d610ec7db424be U drh -Z 8bbf37cac5a7f4ae4955d0f942660ce9 +Z 2076d0986bc3817907a655695f4a8b4e diff --git a/manifest.uuid b/manifest.uuid index 948c00a194..7e569bfcb7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45abd5c0bad2847861f3b26a7040490aa9bb1332 \ No newline at end of file +6da6f46d0c43e3b68c21f514ddf8ee663c20f249 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index f3b317da5f..1b219604bc 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -477,6 +477,14 @@ void sqlite3_free(void *p){ } } +/* +** Add the size of memory allocation "p" to the count in +** *db->pnBytesFreed. +*/ +static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){ + *db->pnBytesFreed += sqlite3DbMallocSize(db,p); +} + /* ** Free memory that might be associated with a particular database ** connection. @@ -486,7 +494,7 @@ void sqlite3DbFree(sqlite3 *db, void *p){ if( p==0 ) return; if( db ){ if( db->pnBytesFreed ){ - *db->pnBytesFreed += sqlite3DbMallocSize(db, p); + measureAllocationSize(db, p); return; } if( isLookaside(db, p) ){ From b50c65d561532c689a894112459be6e48f9ae366 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 20:25:53 +0000 Subject: [PATCH 37/42] Faster implementation of the sqlite3ApiExit() routine. FossilOrigin-Name: bd41d394d48516eb7d8ddc46abdcb427aa80173e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/malloc.c | 17 ++++++++++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 0f001ae399..1044726bb0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\smemory\sallocator\sperformance\soptimization. -D 2014-08-23T19:42:06.737 +C Faster\simplementation\sof\sthe\ssqlite3ApiExit()\sroutine. +D 2014-08-23T20:25:53.209 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -191,7 +191,7 @@ F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 -F src/malloc.c 06f8507831d04d2830237bf0c9f2fd04623f9868 +F src/malloc.c 954de5f998c23237e04474a3f2159bf483bba65a F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 45abd5c0bad2847861f3b26a7040490aa9bb1332 -R 863f9a5c456ee79d86d610ec7db424be +P 6da6f46d0c43e3b68c21f514ddf8ee663c20f249 +R cfcb5b6ff857caed22b759c12472ea06 U drh -Z 2076d0986bc3817907a655695f4a8b4e +Z c1d7ee14996f329ac13456e7bf7bb3df diff --git a/manifest.uuid b/manifest.uuid index 7e569bfcb7..215297c16b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6da6f46d0c43e3b68c21f514ddf8ee663c20f249 \ No newline at end of file +bd41d394d48516eb7d8ddc46abdcb427aa80173e \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 1b219604bc..b4b70350f4 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -761,6 +761,14 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){ *pz = z; } +/* +** Take actions at the end of an API call to indicate an OOM error +*/ +static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ + db->mallocFailed = 0; + sqlite3Error(db, SQLITE_NOMEM); + return SQLITE_NOMEM; +} /* ** This function must be called before exiting any API function (i.e. @@ -781,10 +789,9 @@ int sqlite3ApiExit(sqlite3* db, int rc){ ** is unsafe, as is the call to sqlite3Error(). */ assert( !db || sqlite3_mutex_held(db->mutex) ); - if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){ - sqlite3Error(db, SQLITE_NOMEM); - db->mallocFailed = 0; - rc = SQLITE_NOMEM; + if( db==0 ) return rc & 0xff; + if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ + return apiOomError(db); } - return rc & (db ? db->errMask : 0xff); + return rc & db->errMask; } From efbf04458341672c9200d51b1fd7d485ddd09ce3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 23:15:31 +0000 Subject: [PATCH 38/42] Faster implementation of pcache1Fetch() FossilOrigin-Name: 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d --- manifest | 12 +-- manifest.uuid | 2 +- src/pcache1.c | 210 ++++++++++++++++++++++++++------------------------ 3 files changed, 116 insertions(+), 108 deletions(-) diff --git a/manifest b/manifest index 1044726bb0..6e1bca5a72 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Faster\simplementation\sof\sthe\ssqlite3ApiExit()\sroutine. -D 2014-08-23T20:25:53.209 +C Faster\simplementation\sof\spcache1Fetch() +D 2014-08-23T23:15:31.233 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -216,7 +216,7 @@ F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 -F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c +F src/pcache1.c c5af6403a55178c9d1c09e4f77b0f9c88822762c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e F src/prepare.c 3842c1dfc0b053458e3adcf9f6efc48e03e3fe3d F src/printf.c 00986c86ddfffefc2fd3c73667ff51b3b9709c74 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6da6f46d0c43e3b68c21f514ddf8ee663c20f249 -R cfcb5b6ff857caed22b759c12472ea06 +P bd41d394d48516eb7d8ddc46abdcb427aa80173e +R d2491d65f44f8709d1d156c840c25703 U drh -Z c1d7ee14996f329ac13456e7bf7bb3df +Z 15bb2365f5f8da3e5de34ee820ad0674 diff --git a/manifest.uuid b/manifest.uuid index 215297c16b..bd2aebab20 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd41d394d48516eb7d8ddc46abdcb427aa80173e \ No newline at end of file +0371cc3bb07448bcd64fd671f3e71bb7f30deb4d \ No newline at end of file diff --git a/src/pcache1.c b/src/pcache1.c index 1644b0693c..82015befce 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -383,7 +383,7 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){ ** ** The PCache mutex must be held when this function is called. */ -static int pcache1ResizeHash(PCache1 *p){ +static void pcache1ResizeHash(PCache1 *p){ PgHdr1 **apNew; unsigned int nNew; unsigned int i; @@ -415,8 +415,6 @@ static int pcache1ResizeHash(PCache1 *p){ p->apHash = apNew; p->nHash = nNew; } - - return (p->apHash ? SQLITE_OK : SQLITE_NOMEM); } /* @@ -551,6 +549,9 @@ static void pcache1Shutdown(void *NotUsed){ memset(&pcache1, 0, sizeof(pcache1)); } +/* forward declaration */ +static void pcache1Destroy(sqlite3_pcache *p); + /* ** Implementation of the sqlite3_pcache.xCreate method. ** @@ -595,12 +596,17 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ pCache->szPage = szPage; pCache->szExtra = szExtra; pCache->bPurgeable = (bPurgeable ? 1 : 0); + pcache1EnterMutex(pGroup); + pcache1ResizeHash(pCache); if( bPurgeable ){ pCache->nMin = 10; - pcache1EnterMutex(pGroup); pGroup->nMinPage += pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pcache1LeaveMutex(pGroup); + } + pcache1LeaveMutex(pGroup); + if( pCache->nHash==0 ){ + pcache1Destroy((sqlite3_pcache*)pCache); + pCache = 0; } } return (sqlite3_pcache *)pCache; @@ -656,6 +662,95 @@ static int pcache1Pagecount(sqlite3_pcache *p){ return n; } + +/* +** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described +** in the header of the pcache1Fetch() procedure. +** +** This steps are broken out into a separate procedure because they are +** usually not needed, and by avoiding the stack initialization required +** for these steps, the main pcache1Fetch() procedure can run faster. +*/ +static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( + PCache1 *pCache, + unsigned int iKey, + int createFlag +){ + unsigned int nPinned; + PGroup *pGroup = pCache->pGroup; + PgHdr1 *pPage = 0; + + /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ + assert( pCache->nPage >= pCache->nRecyclable ); + nPinned = pCache->nPage - pCache->nRecyclable; + assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); + assert( pCache->n90pct == pCache->nMax*9/10 ); + if( createFlag==1 && ( + nPinned>=pGroup->mxPinned + || nPinned>=pCache->n90pct + || pcache1UnderMemoryPressure(pCache) + )){ + return 0; + } + + if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache); + assert( pCache->nHash>0 && pCache->apHash ); + + /* Step 4. Try to recycle a page. */ + if( pCache->bPurgeable && pGroup->pLruTail && ( + (pCache->nPage+1>=pCache->nMax) + || pGroup->nCurrentPage>=pGroup->nMaxPage + || pcache1UnderMemoryPressure(pCache) + )){ + PCache1 *pOther; + pPage = pGroup->pLruTail; + assert( pPage->isPinned==0 ); + pcache1RemoveFromHash(pPage); + pcache1PinPage(pPage); + pOther = pPage->pCache; + + /* We want to verify that szPage and szExtra are the same for pOther + ** and pCache. Assert that we can verify this by comparing sums. */ + assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 ); + assert( pCache->szExtra<512 ); + assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 ); + assert( pOther->szExtra<512 ); + + if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){ + pcache1FreePage(pPage); + pPage = 0; + }else{ + pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); + } + } + + /* Step 5. If a usable page buffer has still not been found, + ** attempt to allocate a new one. + */ + if( !pPage ){ + if( createFlag==1 ) sqlite3BeginBenignMalloc(); + pPage = pcache1AllocPage(pCache); + if( createFlag==1 ) sqlite3EndBenignMalloc(); + } + + if( pPage ){ + unsigned int h = iKey % pCache->nHash; + pCache->nPage++; + pPage->iKey = iKey; + pPage->pNext = pCache->apHash[h]; + pPage->pCache = pCache; + pPage->pLruPrev = 0; + pPage->pLruNext = 0; + pPage->isPinned = 1; + *(void **)pPage->page.pExtra = 0; + pCache->apHash[h] = pPage; + if( iKey>pCache->iMaxKey ){ + pCache->iMaxKey = iKey; + } + } + return pPage; +} + /* ** Implementation of the sqlite3_pcache.xFetch method. ** @@ -715,9 +810,7 @@ static sqlite3_pcache_page *pcache1Fetch( unsigned int iKey, int createFlag ){ - unsigned int nPinned; PCache1 *pCache = (PCache1 *)p; - PGroup *pGroup; PgHdr1 *pPage = 0; assert( offsetof(PgHdr1,page)==0 ); @@ -725,107 +818,22 @@ static sqlite3_pcache_page *pcache1Fetch( assert( pCache->bPurgeable || pCache->nMin==0 ); assert( pCache->bPurgeable==0 || pCache->nMin==10 ); assert( pCache->nMin==0 || pCache->bPurgeable ); - pcache1EnterMutex(pGroup = pCache->pGroup); + assert( pCache->nHash>0 ); + pcache1EnterMutex(pCache->pGroup); /* Step 1: Search the hash table for an existing entry. */ - if( pCache->nHash>0 ){ - unsigned int h = iKey % pCache->nHash; - for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext); - } + pPage = pCache->apHash[iKey % pCache->nHash]; + while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; } /* Step 2: Abort if no existing page is found and createFlag is 0 */ if( pPage ){ if( !pPage->isPinned ) pcache1PinPage(pPage); - goto fetch_out; + }else if( createFlag ){ + /* Steps 3, 4, and 5 implemented by this subroutine */ + pPage = pcache1FetchStage2(pCache, iKey, createFlag); } - if( createFlag==0 ){ - goto fetch_out; - } - - /* The pGroup local variable will normally be initialized by the - ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined, - ** then pcache1EnterMutex() is a no-op, so we have to initialize the - ** local variable here. Delaying the initialization of pGroup is an - ** optimization: The common case is to exit the module before reaching - ** this point. - */ -#ifdef SQLITE_MUTEX_OMIT - pGroup = pCache->pGroup; -#endif - - /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ - assert( pCache->nPage >= pCache->nRecyclable ); - nPinned = pCache->nPage - pCache->nRecyclable; - assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); - assert( pCache->n90pct == pCache->nMax*9/10 ); - if( createFlag==1 && ( - nPinned>=pGroup->mxPinned - || nPinned>=pCache->n90pct - || pcache1UnderMemoryPressure(pCache) - )){ - goto fetch_out; - } - - if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){ - goto fetch_out; - } - assert( pCache->nHash>0 && pCache->apHash ); - - /* Step 4. Try to recycle a page. */ - if( pCache->bPurgeable && pGroup->pLruTail && ( - (pCache->nPage+1>=pCache->nMax) - || pGroup->nCurrentPage>=pGroup->nMaxPage - || pcache1UnderMemoryPressure(pCache) - )){ - PCache1 *pOther; - pPage = pGroup->pLruTail; - assert( pPage->isPinned==0 ); - pcache1RemoveFromHash(pPage); - pcache1PinPage(pPage); - pOther = pPage->pCache; - - /* We want to verify that szPage and szExtra are the same for pOther - ** and pCache. Assert that we can verify this by comparing sums. */ - assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 ); - assert( pCache->szExtra<512 ); - assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 ); - assert( pOther->szExtra<512 ); - - if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){ - pcache1FreePage(pPage); - pPage = 0; - }else{ - pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); - } - } - - /* Step 5. If a usable page buffer has still not been found, - ** attempt to allocate a new one. - */ - if( !pPage ){ - if( createFlag==1 ) sqlite3BeginBenignMalloc(); - pPage = pcache1AllocPage(pCache); - if( createFlag==1 ) sqlite3EndBenignMalloc(); - } - - if( pPage ){ - unsigned int h = iKey % pCache->nHash; - pCache->nPage++; - pPage->iKey = iKey; - pPage->pNext = pCache->apHash[h]; - pPage->pCache = pCache; - pPage->pLruPrev = 0; - pPage->pLruNext = 0; - pPage->isPinned = 1; - *(void **)pPage->page.pExtra = 0; - pCache->apHash[h] = pPage; - } - -fetch_out: - if( pPage && iKey>pCache->iMaxKey ){ - pCache->iMaxKey = iKey; - } - pcache1LeaveMutex(pGroup); + assert( pPage==0 || pCache->iMaxKey>=iKey ); + pcache1LeaveMutex(pCache->pGroup); return (sqlite3_pcache_page*)pPage; } From f063e08fd93c4f00cb44c03bad01e811d76ddb6e Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Aug 2014 01:32:43 +0000 Subject: [PATCH 39/42] Patch the sqlite3PagerWrite() method in the Pager to run a bit faster. FossilOrigin-Name: c63311e2f3344363a5ed99838fb5850004eaee30 --- manifest | 12 ++-- manifest.uuid | 2 +- src/pager.c | 185 ++++++++++++++++++++++++++------------------------ 3 files changed, 105 insertions(+), 94 deletions(-) diff --git a/manifest b/manifest index 6e1bca5a72..a21c0da13e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Faster\simplementation\sof\spcache1Fetch() -D 2014-08-23T23:15:31.233 +C Patch\sthe\ssqlite3PagerWrite()\smethod\sin\sthe\sPager\sto\srun\sa\sbit\sfaster. +D 2014-08-24T01:32:43.379 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -211,7 +211,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542 F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 -F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8 +F src/pager.c c831b0df879114915c08dc5a0188f9f22c48403b F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bd41d394d48516eb7d8ddc46abdcb427aa80173e -R d2491d65f44f8709d1d156c840c25703 +P 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d +R 2fe545d9c9446b3adf94c91625adc119 U drh -Z 15bb2365f5f8da3e5de34ee820ad0674 +Z 79e99766e8b4bdebd57118e507ef67dc diff --git a/manifest.uuid b/manifest.uuid index bd2aebab20..308d8ad8ef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0371cc3bb07448bcd64fd671f3e71bb7f30deb4d \ No newline at end of file +c63311e2f3344363a5ed99838fb5850004eaee30 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index a77dcecc4c..4a178a2985 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5772,6 +5772,97 @@ static int pager_write(PgHdr *pPg){ return rc; } +/* +** This is a variant of sqlite3PagerWrite() that runs when the sector size +** is larger than the page size. SQLite makes the (reasonable) assumption that +** all bytes of a sector are written together by hardware. Hence, all bytes of +** a sector need to be journalled in case of a power loss in the middle of +** a write. +** +** Usually, the sector size is less than or equal to the page size, in which +** case pages can be individually written. This routine only runs in the exceptional +** case where the page size is smaller than the sector size. +*/ +static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ + int rc = SQLITE_OK; /* Return code */ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage = 0; /* Number of pages starting at pg1 to journal */ + int ii; /* Loop counter */ + int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ + Pager *pPager = pPg->pPager; /* The pager that owns pPg */ + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow + ** a journal header to be written between the pages journaled by + ** this function. + */ + assert( !MEMDB ); + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); + pPager->doNotSpill |= SPILLFLAG_NOSYNC; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + nPageCount = pPager->dbSize; + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ + if( pg!=PAGER_MJ_PGNO(pPager) ){ + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + + /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages + ** starting at pg1, then it needs to be set for all of them. Because + ** writing to any of these nPage pages may damage the others, the + ** journal file must contain sync()ed copies of all of them + ** before any of them can be written out to the database file. + */ + if( rc==SQLITE_OK && needSync ){ + assert( !MEMDB ); + for(ii=0; iiflags |= PGHDR_NEED_SYNC; + sqlite3PagerUnrefNotNull(pPage); + } + } + } + + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); + pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; + return rc; +} + /* ** Mark a data page as writeable. This routine must be called before ** making changes to a page. The caller must check the return value @@ -5786,96 +5877,16 @@ static int pager_write(PgHdr *pPg){ ** If an error occurs, SQLITE_NOMEM or an IO error code is returned ** as appropriate. Otherwise, SQLITE_OK. */ -int sqlite3PagerWrite(DbPage *pDbPage){ - int rc = SQLITE_OK; - - PgHdr *pPg = pDbPage; - Pager *pPager = pPg->pPager; - +int sqlite3PagerWrite(PgHdr *pPg){ assert( (pPg->flags & PGHDR_MMAP)==0 ); - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( pPager->eState!=PAGER_ERROR ); - assert( assert_pager_state(pPager) ); - - if( pPager->sectorSize > (u32)pPager->pageSize ){ - Pgno nPageCount; /* Total number of pages in database file */ - Pgno pg1; /* First page of the sector pPg is located on. */ - int nPage = 0; /* Number of pages starting at pg1 to journal */ - int ii; /* Loop counter */ - int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ - Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); - - /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow - ** a journal header to be written between the pages journaled by - ** this function. - */ - assert( !MEMDB ); - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); - pPager->doNotSpill |= SPILLFLAG_NOSYNC; - - /* This trick assumes that both the page-size and sector-size are - ** an integer power of 2. It sets variable pg1 to the identifier - ** of the first page of the sector pPg is located on. - */ - pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; - - nPageCount = pPager->dbSize; - if( pPg->pgno>nPageCount ){ - nPage = (pPg->pgno - pg1)+1; - }else if( (pg1+nPagePerSector-1)>nPageCount ){ - nPage = nPageCount+1-pg1; - }else{ - nPage = nPagePerSector; - } - assert(nPage>0); - assert(pg1<=pPg->pgno); - assert((pg1+nPage)>pPg->pgno); - - for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ - if( pg!=PAGER_MJ_PGNO(pPager) ){ - rc = sqlite3PagerGet(pPager, pg, &pPage); - if( rc==SQLITE_OK ){ - rc = pager_write(pPage); - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - - /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages - ** starting at pg1, then it needs to be set for all of them. Because - ** writing to any of these nPage pages may damage the others, the - ** journal file must contain sync()ed copies of all of them - ** before any of them can be written out to the database file. - */ - if( rc==SQLITE_OK && needSync ){ - assert( !MEMDB ); - for(ii=0; iiflags |= PGHDR_NEED_SYNC; - sqlite3PagerUnrefNotNull(pPage); - } - } - } - - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); - pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; + assert( pPg->pPager->eState>=PAGER_WRITER_LOCKED ); + assert( pPg->pPager->eState!=PAGER_ERROR ); + assert( assert_pager_state(pPg->pPager) ); + if( pPg->pPager->sectorSize > (u32)pPg->pPager->pageSize ){ + return pagerWriteLargeSector(pPg); }else{ - rc = pager_write(pDbPage); + return pager_write(pPg); } - return rc; } /* From 4274dae9e9971ce49bda44989be0e3aff4e1b865 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Aug 2014 02:53:23 +0000 Subject: [PATCH 40/42] The sqlite3VdbeChangeEncoding() routine goes about 3x faster if the sqlite3VdbeMemTranslate() subroutine is not inlined. FossilOrigin-Name: 0c7e1b875a14ff9d71af7bb125a0272a23d57353 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/utf.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index a21c0da13e..bb740b999a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Patch\sthe\ssqlite3PagerWrite()\smethod\sin\sthe\sPager\sto\srun\sa\sbit\sfaster. -D 2014-08-24T01:32:43.379 +C The\ssqlite3VdbeChangeEncoding()\sroutine\sgoes\sabout\s3x\sfaster\sif\sthe\nsqlite3VdbeMemTranslate()\ssubroutine\sis\snot\sinlined. +D 2014-08-24T02:53:23.646 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 -F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 +F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d -R 2fe545d9c9446b3adf94c91625adc119 +P c63311e2f3344363a5ed99838fb5850004eaee30 +R 195c0a9c31ce9f43b0d460b5ca896167 U drh -Z 79e99766e8b4bdebd57118e507ef67dc +Z 7685d4da1bf506f63008f6a3d5e2d0bd diff --git a/manifest.uuid b/manifest.uuid index 308d8ad8ef..de00fe8cee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c63311e2f3344363a5ed99838fb5850004eaee30 \ No newline at end of file +0c7e1b875a14ff9d71af7bb125a0272a23d57353 \ No newline at end of file diff --git a/src/utf.c b/src/utf.c index 97898746a2..557f3a95e4 100644 --- a/src/utf.c +++ b/src/utf.c @@ -199,7 +199,7 @@ u32 sqlite3Utf8Read( ** desiredEnc. It is an error if the string is already of the desired ** encoding, or if *pMem does not contain a string value. */ -int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ +SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ int len; /* Maximum length of output string in bytes */ unsigned char *zOut; /* Output buffer */ unsigned char *zIn; /* Input iterator */ From 12b7c7d8c397ff07626d720d9c2b68701b53fe0b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Aug 2014 11:20:27 +0000 Subject: [PATCH 41/42] Change the name of the VdbeMemRelease() macro to VdbeMemReleaseExtern() to more accurately reflect what it does. Performance enhancement to the sqlite3VdbeMemRelease() function. FossilOrigin-Name: 3ca5846da7da5e08192a4c96288197be3b7ab6f7 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 8 ++++---- src/vdbeInt.h | 2 +- src/vdbemem.c | 39 ++++++++++++++++++++++++++++++--------- 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index bb740b999a..bfef72eb6a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3VdbeChangeEncoding()\sroutine\sgoes\sabout\s3x\sfaster\sif\sthe\nsqlite3VdbeMemTranslate()\ssubroutine\sis\snot\sinlined. -D 2014-08-24T02:53:23.646 +C Change\sthe\sname\sof\sthe\sVdbeMemRelease()\smacro\sto\sVdbeMemReleaseExtern()\sto\nmore\saccurately\sreflect\swhat\sit\sdoes.\s\sPerformance\senhancement\sto\sthe\nsqlite3VdbeMemRelease()\sfunction. +D 2014-08-25T11:20:27.189 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -284,13 +284,13 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 +F src/vdbe.c 0fe4b47668b36a50bd9f7fd7b15cbeeb69d54b37 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 -F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 +F src/vdbeInt.h 20056cd59ff93ef9eb91009ece726d65dd7ed322 F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c f2e162888521a9af35d608ac4c13db4991dfb417 +F src/vdbemem.c 4c9d686da474957d2e78834f13cc5f141fe6b87f F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c63311e2f3344363a5ed99838fb5850004eaee30 -R 195c0a9c31ce9f43b0d460b5ca896167 +P 0c7e1b875a14ff9d71af7bb125a0272a23d57353 +R 3449942ddb4a22bfe8e7f1684bd27e8b U drh -Z 7685d4da1bf506f63008f6a3d5e2d0bd +Z c7041d8c52f909d88b499b4a5f3227aa diff --git a/manifest.uuid b/manifest.uuid index de00fe8cee..725161693a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c7e1b875a14ff9d71af7bb125a0272a23d57353 \ No newline at end of file +3ca5846da7da5e08192a4c96288197be3b7ab6f7 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 2e797eeaf5..72a1552ce1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -640,7 +640,7 @@ int sqlite3VdbeExec( assert( pOp->p2<=(p->nMem-p->nCursor) ); pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); - VdbeMemRelease(pOut); + VdbeMemReleaseExtern(pOut); pOut->flags = MEM_Int; } @@ -1079,7 +1079,7 @@ case OP_Null: { /* out2-prerelease */ while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); - VdbeMemRelease(pOut); + VdbeMemReleaseExtern(pOut); pOut->flags = nullFlag; cnt--; } @@ -1165,7 +1165,7 @@ case OP_Move: { assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); - VdbeMemRelease(pOut); + VdbeMemReleaseExtern(pOut); zMalloc = pOut->zMalloc; memcpy(pOut, pIn1, sizeof(Mem)); #ifdef SQLITE_DEBUG @@ -2538,7 +2538,7 @@ case OP_Column: { if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ - VdbeMemRelease(pDest); + VdbeMemReleaseExtern(pDest); sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); }else{ /* This branch happens only when content is on overflow pages */ diff --git a/src/vdbeInt.h b/src/vdbeInt.h index ba44b61e91..384c5eb37b 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -430,7 +430,7 @@ void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemReleaseExternal(Mem *p); #define VdbeMemDynamic(X) \ (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) -#define VdbeMemRelease(X) \ +#define VdbeMemReleaseExtern(X) \ if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); diff --git a/src/vdbemem.c b/src/vdbemem.c index 572d486fc4..55e212d8ca 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -121,7 +121,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } if( pMem->zMalloc==0 ){ - VdbeMemRelease(pMem); + VdbeMemReleaseExtern(pMem); pMem->z = 0; pMem->flags = MEM_Null; return SQLITE_NOMEM; @@ -300,6 +300,9 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ ** If the memory cell contains a string value that must be freed by ** invoking an external callback, free it now. Calling this function ** does not free any Mem.zMalloc buffer. +** +** The VdbeMemReleaseExtern() macro invokes this routine if only if there +** is work for this routine to do. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); @@ -319,6 +322,25 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ } } +/* +** Release memory held by the Mem p, both external memory cleared +** by p->xDel and memory in p->zMalloc. +** +** This is a helper routine invoked by sqlite3VdbeMemRelease() in +** the uncommon case when there really is memory in p that is +** need of freeing. +*/ +static SQLITE_NOINLINE void vdbeMemRelease(Mem *p){ + if( VdbeMemDynamic(p) ){ + sqlite3VdbeMemReleaseExternal(p); + } + if( p->zMalloc ){ + sqlite3DbFree(p->db, p->zMalloc); + p->zMalloc = 0; + } + p->z = 0; +} + /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and @@ -326,13 +348,12 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ */ void sqlite3VdbeMemRelease(Mem *p){ assert( sqlite3VdbeCheckMemInvariants(p) ); - VdbeMemRelease(p); - if( p->zMalloc ){ - sqlite3DbFree(p->db, p->zMalloc); - p->zMalloc = 0; + if( VdbeMemDynamic(p) || p->zMalloc ){ + vdbeMemRelease(p); + }else{ + p->z = 0; } - p->z = 0; - assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */ + assert( p->xDel==0 ); } /* @@ -638,7 +659,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ */ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ assert( (pFrom->flags & MEM_RowSet)==0 ); - VdbeMemRelease(pTo); + VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->xDel = 0; if( (pFrom->flags&MEM_Static)==0 ){ @@ -656,7 +677,7 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; assert( (pFrom->flags & MEM_RowSet)==0 ); - VdbeMemRelease(pTo); + VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; pTo->xDel = 0; From c137807a87d4754885c83dc7660026ca6c0bb8af Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Aug 2014 11:33:41 +0000 Subject: [PATCH 42/42] Remove the pager_lookup() function since it is redundant with sqlite3PagerLookup(). FossilOrigin-Name: 54164ce47cfc3ad5dd8797114e4ba78811f23bef --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 26 +++++--------------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index bfef72eb6a..3c6bec475e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\sVdbeMemRelease()\smacro\sto\sVdbeMemReleaseExtern()\sto\nmore\saccurately\sreflect\swhat\sit\sdoes.\s\sPerformance\senhancement\sto\sthe\nsqlite3VdbeMemRelease()\sfunction. -D 2014-08-25T11:20:27.189 +C Remove\sthe\spager_lookup()\sfunction\ssince\sit\sis\sredundant\swith\s\nsqlite3PagerLookup(). +D 2014-08-25T11:33:41.726 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -211,7 +211,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542 F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 -F src/pager.c c831b0df879114915c08dc5a0188f9f22c48403b +F src/pager.c 53cc5e9d73afb74add79f49755c8ee240fbdbef7 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0c7e1b875a14ff9d71af7bb125a0272a23d57353 -R 3449942ddb4a22bfe8e7f1684bd27e8b +P 3ca5846da7da5e08192a4c96288197be3b7ab6f7 +R e183e353a27fb2d0c63a06eeb0b66e97 U drh -Z c7041d8c52f909d88b499b4a5f3227aa +Z 12acde8fd951a315f106f1112e06c5c6 diff --git a/manifest.uuid b/manifest.uuid index 725161693a..698dca573d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ca5846da7da5e08192a4c96288197be3b7ab6f7 \ No newline at end of file +54164ce47cfc3ad5dd8797114e4ba78811f23bef \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 4a178a2985..8930ce862c 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1677,21 +1677,6 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ return rc; } -/* -** Find a page in the hash table given its page number. Return -** a pointer to the page or NULL if the requested page is not -** already in memory. -*/ -static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ - PgHdr *p = 0; /* Return value */ - - /* It is not possible for a call to PcacheFetch() with createFlag==0 to - ** fail, since no attempt to allocate dynamic memory will be made. - */ - (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p); - return p; -} - /* ** Discard the entire contents of the in-memory page-cache. */ @@ -1984,7 +1969,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ #ifdef SQLITE_CHECK_PAGES sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ - PgHdr *p = pager_lookup(pPager, 1); + PgHdr *p = sqlite3PagerLookup(pPager, 1); if( p ){ p->pageHash = 0; sqlite3PagerUnrefNotNull(p); @@ -2263,7 +2248,7 @@ static int pager_playback_one_page( if( pagerUseWal(pPager) ){ pPg = 0; }else{ - pPg = pager_lookup(pPager, pgno); + pPg = sqlite3PagerLookup(pPager, pgno); } assert( pPg || !MEMDB ); assert( pPager->eState!=PAGER_OPEN || pPg==0 ); @@ -5434,7 +5419,6 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ assert( pPager!=0 ); assert( pgno!=0 ); assert( pPager->pPCache!=0 ); - assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR ); sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); return pPg; } @@ -5833,7 +5817,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ sqlite3PagerUnrefNotNull(pPage); } } - }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ + }else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){ if( pPage->flags&PGHDR_NEED_SYNC ){ needSync = 1; } @@ -5850,7 +5834,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ if( rc==SQLITE_OK && needSync ){ assert( !MEMDB ); for(ii=0; iiflags |= PGHDR_NEED_SYNC; sqlite3PagerUnrefNotNull(pPage); @@ -6782,7 +6766,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ ** for the page moved there. */ pPg->flags &= ~PGHDR_NEED_SYNC; - pPgOld = pager_lookup(pPager, pgno); + pPgOld = sqlite3PagerLookup(pPager, pgno); assert( !pPgOld || pPgOld->nRef==1 ); if( pPgOld ){ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);