SHA1 Hash: | 7a2c37063a65a141cc925976444c01508dba1d17 |
---|---|
Date: | 2009-09-22 07:49:39 |
User: | bob |
Comment: | merge trunk into creole branch |
Timelines: | ancestors | descendants | both | creole |
Other Links: | files | ZIP archive | manifest |
- bgcolor=#c0ffc0 inherited from [ecd1f09632]
- branch=creole propagates to descendants
- sym-creole propagates to descendants
Modified BUILD.txt from [e7fed9d5b6] to [334b80c575].
@@ -13,11 +13,11 @@ -------------------------------------------------------------------------- Here are some notes on what is happening behind the scenes: -* The Makefile just set up a few macros and then invokes the +* The Makefile just sets up a few macros and then invokes the real makefile in src/main.mk. The src/main.mk makefile is automatically generated by a TCL script found at src/makemake.tcl. Do not edit src/main.mk directly. Update src/makemake.tcl and then rerun it.
Modified Makefile.w32 from [c6249fceb5] to [8092d93409].
@@ -2,11 +2,11 @@ # #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # -SRCDIR = ../src +SRCDIR = ./src #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. This is used # to compile code-generator programs as part of the build process. # See TCC below for the C compiler for building the finished binary.
Deleted ideas.txt version [b3e2a29039]
Deleted src/VERSION version [24bbb3aad6]
Modified src/add.c from [c6fe5d6e20] to [c094792c50].
@@ -27,10 +27,15 @@ #include "config.h" #include "add.h" #include <assert.h> #include <dirent.h> +/* +** Set to true if files whose names begin with "." should be +** included when processing a recursive "add" command. +*/ +static int includeDotFiles = 0; /* ** Add a single file */ static void add_one_file(const char *zName, int vid, Blob *pOmit){ @@ -75,11 +80,15 @@ origSize = blob_size(&path); d = opendir(zDir); if( d ){ while( (pEntry=readdir(d))!=0 ){ char *zPath; - if( pEntry->d_name[0]=='.' ) continue; + if( pEntry->d_name[0]=='.' ){ + if( !includeDotFiles ) continue; + if( pEntry->d_name[1]==0 ) continue; + if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue; + } blob_appendf(&path, "/%s", pEntry->d_name); zPath = blob_str(&path); if( file_isdir(zPath)==1 ){ add_directory_content(zPath); }else if( file_isfile(zPath) ){ @@ -112,16 +121,21 @@ ** ** Usage: %fossil add FILE... ** ** Make arrangements to add one or more files to the current checkout ** at the next commit. +** +** When adding files recursively, filenames that begin with "." are +** excluded by default. To include such files, add the "--dotfiles" +** option to the command-line. */ void add_cmd(void){ int i; int vid; Blob repo; + includeDotFiles = find_option("dotfiles",0,0)!=0; db_must_be_within_tree(); vid = db_lget_int("checkout",0); if( vid==0 ){ fossil_panic("no checkout to add to"); }
Deleted src/admin.c version [bf62e8d4f5]
Modified src/allrepo.c from [cc52a38ad8] to [22228def76].
@@ -55,18 +55,20 @@ /* ** COMMAND: all ** -** Usage: %fossil all (list|pull|push|rebuild|sync) +** Usage: %fossil all (list|ls|pull|push|rebuild|sync) ** ** The ~/.fossil file records the location of all repositories for a ** user. This command performs certain operations on all repositories ** that can be useful before or after a period of disconnection operation. ** Available operations are: ** ** list Display the location of all repositories +** +** ls An alias for "list" ** ** pull Run a "pull" operation on all repositories ** ** push Run a "push" on all repositories ** @@ -86,16 +88,18 @@ char *zFossil; char *zQFilename; int nMissing; if( g.argc<3 ){ - usage("list|pull|push|rebuild|sync"); + usage("list|ls|pull|push|rebuild|sync"); } n = strlen(g.argv[2]); - db_open_config(); + db_open_config(1); zCmd = g.argv[2]; if( strncmp(zCmd, "list", n)==0 ){ + zCmd = "list"; + }else if( strncmp(zCmd, "ls", n)==0 ){ /* alias for "list" above */ zCmd = "list"; }else if( strncmp(zCmd, "push", n)==0 ){ zCmd = "push -autourl -R"; }else if( strncmp(zCmd, "pull", n)==0 ){ zCmd = "pull -autourl -R"; @@ -103,11 +107,11 @@ zCmd = "rebuild"; }else if( strncmp(zCmd, "sync", n)==0 ){ zCmd = "sync -autourl -R"; }else{ fossil_fatal("\"all\" subcommand should be one of: " - "list push pull rebuild sync"); + "list ls push pull rebuild sync"); } zFossil = quoteFilename(g.argv[0]); nMissing = 0; db_prepare(&q, "SELECT substr(name, 6) FROM global_config" " WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"); @@ -123,11 +127,11 @@ } zQFilename = quoteFilename(zFilename); zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename); printf("%s\n", zSyscmd); fflush(stdout); - system(zSyscmd); + portable_system(zSyscmd); free(zSyscmd); free(zQFilename); } /* If any repositories hows names appear in the ~/.fossil file could not
Modified src/bag.c from [c1c41296e0] to [91c2be456c].
@@ -32,10 +32,25 @@ #if INTERFACE /* ** An integer can appear in the bag at most once. ** Integers must be positive. +** +** On a hash collision, search continues to the next slot in the array, +** looping back to the beginning of the array when we reach the end. +** The search stops when a match is found or upon encountering a 0 entry. +** +** When an entry is deleted, its value is changed to -1. +** +** Bag.cnt is the number of live entries in the table. Bag.used is +** the number of live entries plus the number of deleted entries. So +** Bag.used>=Bag.cnt. We want to keep Bag.used-Bag.cnt as small as +** possible. +** +** The length of a search increases as the hash table fills up. So +** the table is enlarged whenever Bag.used reaches half of Bag.sz. That +** way, the expected collision length never exceeds 2. */ struct Bag { int cnt; /* Number of integers in the bag */ int sz; /* Number of slots in a[] */ int used; /* Number of used slots in a[] */ @@ -64,14 +79,20 @@ #define bag_hash(i) (i*101) /* ** Change the size of the hash table on a bag so that ** it contains N slots +** +** Completely reconstruct the hash table from scratch. Deleted +** entries (indicated by a -1) are removed. When finished, it +** should be the case that p->cnt==p->used. */ static void bag_resize(Bag *p, int newSize){ int i; Bag old; + int nDel = 0; /* Number of deleted entries */ + int nLive = 0; /* Number of live entries */ old = *p; assert( newSize>old.cnt ); p->a = malloc( sizeof(p->a[0])*newSize ); p->sz = newSize; @@ -83,12 +104,17 @@ while( p->a[h] ){ h++; if( h==newSize ) h = 0; } p->a[h] = e; + nLive++; + }else if( e<0 ){ + nDel++; } } + assert( p->cnt == nLive ); + assert( p->used == nLive+nDel ); p->used = p->cnt; bag_clear(&old); } /* @@ -99,20 +125,21 @@ int bag_insert(Bag *p, int e){ unsigned h; int rc = 0; assert( e>0 ); if( p->used+1 >= p->sz/2 ){ - bag_resize(p, p->cnt*2 + 20 ); + int n = p->sz*2; + bag_resize(p, n + 20 ); } h = bag_hash(e)%p->sz; - while( p->a[h] && p->a[h]!=e ){ + while( p->a[h]>0 && p->a[h]!=e ){ h++; if( h>=p->sz ) h = 0; } - if( p->a[h]==0 ){ - p->a[h] = e; - p->used++; + if( p->a[h]<=0 ){ + if( p->a[h]==0 ) p->used++; + p->a[h] = e; p->cnt++; rc = 1; } return rc; } @@ -146,13 +173,23 @@ while( p->a[h] && p->a[h]!=e ){ h++; if( h>=p->sz ) h = 0; } if( p->a[h] ){ - p->a[h] = -1; + int nx = h+1; + if( nx>=p->sz ) nx = 0; + if( p->a[nx]==0 ){ + p->a[h] = 0; + p->used--; + }else{ + p->a[h] = -1; + } p->cnt--; - if( p->sz>20 && p->cnt<p->sz/8 ){ + if( p->cnt==0 ){ + memset(p->a, 0, p->sz*sizeof(p->a[0])); + p->used = 0; + }else if( p->sz>40 && p->cnt<p->sz/8 ){ bag_resize(p, p->sz/2); } } }
Modified src/blob.c from [1998856256] to [80cddafe2a].
@@ -79,12 +79,27 @@ /* ** We find that the built-in isspace() function does not work for ** some international character sets. So here is a substitute. */ static int blob_isspace(char c){ - return c==' ' || c=='\n' || c=='\t' || - c=='\r' || c=='\f' || c=='\v'; + return c==' ' || (c<='\r' && c>='\t'); +} + +/* +** COMMAND: test-isspace +*/ +void isspace_cmd(void){ + int i; + for(i=0; i<=255; i++){ + if( i==' ' || i=='\n' || i=='\t' || i=='\v' + || i=='\f' || i=='\r' ){ + assert( blob_isspace((char)i) ); + }else{ + assert( !blob_isspace((char)i) ); + } + } + printf("All 256 characters OK\n"); } /* ** This routine is called if a blob operation fails because we ** have run out of memory.
Added src/captcha.c version [d47d9e7153]
@@ -1,1 +1,446 @@ +/* +** Copyright (c) 2009 D. Richard Hipp +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public +** License version 2 as published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** You should have received a copy of the GNU General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@hwaci.com +** http://www.hwaci.com/drh/ +** +******************************************************************************* +** +** This file contains code to a simple text-based CAPTCHA. Though eaily +** defeated by a sophisticated attacker, this CAPTCHA does at least make +** scripting attacks more difficult. +*/ +#include <assert.h> +#include "config.h" +#include "captcha.h" + +#if INTERFACE +#define CAPTCHA 3 /* Which captcha rendering to use */ +#endif + +/* +** Convert a hex digit into a value between 0 and 15 +*/ +static int hexValue(char c){ + if( c>='0' && c<='9' ){ + return c - '0'; + }else if( c>='a' && c<='f' ){ + return c - 'a' + 10; + }else if( c>='A' && c<='F' ){ + return c - 'A' + 10; + }else{ + return 0; + } +} + +#if CAPTCHA==1 +/* +** A 4x6 pixel bitmap font for hexadecimal digits +*/ +static const unsigned int aFont1[] = { + 0x699996, + 0x262227, + 0x69124f, + 0xf16196, + 0x26af22, + 0xf8e196, + 0x68e996, + 0xf12244, + 0x696996, + 0x699716, + 0x699f99, + 0xe9e99e, + 0x698896, + 0xe9999e, + 0xf8e88f, + 0xf8e888, +}; + +/* +** Render an 8-character hexadecimal string as ascii art. +** Space to hold the result is obtained from malloc() and should be freed +** by the caller. +*/ +char *captcha_render(const char *zPw){ + char *z = malloc( 500 ); + int i, j, k, m; + + k = 0; + for(i=0; i<6; i++){ + for(j=0; j<8; j++){ + unsigned char v = hexValue(zPw[j]); + v = (aFont1[v] >> ((5-i)*4)) & 0xf; + for(m=8; m>=1; m = m>>1){ + if( v & m ){ + z[k++] = 'X'; + z[k++] = 'X'; + }else{ + z[k++] = ' '; + z[k++] = ' '; + } + } + z[k++] = ' '; + z[k++] = ' '; + } + z[k++] = '\n'; + } + z[k] = 0; + return z; +} +#endif /* CAPTCHA==1 */ + + +#if CAPTCHA==2 +static const char *azFont2[] = { + /* 0 */ + " __ ", + " / \\ ", + "| () |", + " \\__/ ", + + /* 1 */ + " _ ", + "/ |", + "| |", + "|_|", + + /* 2 */ + " ___ ", + "|_ )", + " / / ", + "/___|", + + /* 3 */ + " ____", + "|__ /", + " |_ \\", + "|___/", + + /* 4 */ + " _ _ ", + "| | | ", + "|_ _|", + " |_| ", + + /* 5 */ + " ___ ", + "| __|", + "|__ \\", + "|___/", + + /* 6 */ + " __ ", + " / / ", + "/ _ \\", + "\\___/", + + /* 7 */ + " ____ ", + "|__ |", + " / / ", + " /_/ ", + + /* 8 */ + " ___ ", + "( _ )", + "/ _ \\", + "\\___/", + + /* 9 */ + " ___ ", + "/ _ \\", + "\\_, /", + " /_/ ", + + /* A */ + " ", + " /\\ ", + " / \\ ", + "/_/\\_\\", + + /* B */ + " ___ ", + "| _ )", + "| _ \\", + "|___/", + + /* C */ + " ___ ", + " / __|", + "| (__ ", + " \\___|", + + /* D */ + " ___ ", + "| \\ ", + "| |) |", + "|___/ ", + + /* E */ + " ___ ", + "| __|", + "| _| ", + "|___|", + + /* F */ + " ___ ", + "| __|", + "| _| ", + "|_| ", +}; + +/* +** Render an 8-digit hexadecimal string as ascii arg. +** Space to hold the result is obtained from malloc() and should be freed +** by the caller. +*/ +char *captcha_render(const char *zPw){ + char *z = malloc( 300 ); + int i, j, k, m; + const char *zChar; + + k = 0; + for(i=0; i<4; i++){ + for(j=0; j<8; j++){ + unsigned char v = hexValue(zPw[j]); + zChar = azFont2[4*v + i]; + for(m=0; zChar[m]; m++){ + z[k++] = zChar[m]; + } + } + z[k++] = '\n'; + } + z[k] = 0; + return z; +} +#endif /* CAPTCHA==2 */ + +#if CAPTCHA==3 +static const char *azFont3[] = { + /* 0 */ + " ___ ", + " / _ \\ ", + "| | | |", + "| | | |", + "| |_| |", + " \\___/ ", + + /* 1 */ + " __ ", + "/_ |", + " | |", + " | |", + " | |", + " |_|", + + /* 2 */ + " ___ ", + "|__ \\ ", + " ) |", + " / / ", + " / /_ ", + "|____|", + + /* 3 */ + " ____ ", + "|___ \\ ", + " __) |", + " |__ < ", + " ___) |", + "|____/ ", + + /* 4 */ + " _ _ ", + "| || | ", + "| || |_ ", + "|__ _|", + " | | ", + " |_| ", + + /* 5 */ + " _____ ", + "| ____|", + "| |__ ", + "|___ \\ ", + " ___) |", + "|____/ ", + + /* 6 */ + " __ ", + " / / ", + " / /_ ", + "| '_ \\ ", + "| (_) |", + " \\___/ ", + + /* 7 */ + " ______ ", + "|____ |", + " / / ", + " / / ", + " / / ", + " /_/ ", + + /* 8 */ + " ___ ", + " / _ \\ ", + "| (_) |", + " > _ < ", + "| (_) |", + " \\___/ ", + + /* 9 */ + " ___ ", + " / _ \\ ", + "| (_) |", + " \\__, |", + " / / ", + " /_/ ", + + /* A */ + " ", + " /\\ ", + " / \\ ", + " / /\\ \\ ", + " / ____ \\ ", + "/_/ \\_\\", + + /* B */ + " ____ ", + "| _ \\ ", + "| |_) |", + "| _ < ", + "| |_) |", + "|____/ ", + + /* C */ + " _____ ", + " / ____|", + "| | ", + "| | ", + "| |____ ", + " \\_____|", + + /* D */ + " _____ ", + "| __ \\ ", + "| | | |", + "| | | |", + "| |__| |", + "|_____/ ", + + /* E */ + " ______ ", + "| ____|", + "| |__ ", + "| __| ", + "| |____ ", + "|______|", + + /* F */ + " ______ ", + "| ____|", + "| |__ ", + "| __| ", + "| | ", + "|_| ", +}; + +/* +** Render an 8-digit hexadecimal string as ascii arg. +** Space to hold the result is obtained from malloc() and should be freed +** by the caller. +*/ +char *captcha_render(const char *zPw){ + char *z = malloc( 600 ); + int i, j, k, m; + const char *zChar; + + k = 0; + for(i=0; i<6; i++){ + for(j=0; j<8; j++){ + unsigned char v = hexValue(zPw[j]); + zChar = azFont3[6*v + i]; + for(m=0; zChar[m]; m++){ + z[k++] = zChar[m]; + } + } + z[k++] = '\n'; + } + z[k] = 0; + return z; +} +#endif /* CAPTCHA==3 */ + +/* +** COMMAND: test-captcha +*/ +void test_captcha(void){ + int i; + unsigned int v; + char *z; + + for(i=2; i<g.argc; i++){ + char zHex[30]; + v = (unsigned int)atoi(g.argv[i]); + sprintf(zHex, "%x", v); + z = captcha_render(zHex); + printf("%s:\n%s", zHex, z); + free(z); + } +} + +/* +** Compute a seed value for a captcha. The seed is public and is sent +** has a hidden parameter with the page that contains the captcha. Knowledge +** of the seed is insufficient for determining the captcha without additional +** information held only on the server and never revealed. +*/ +unsigned int captcha_seed(void){ + unsigned int x; + sqlite3_randomness(sizeof(x), &x); + x &= 0x7fffffff; + return x; +} + +/* +** Translate a captcha seed value into the captcha password string. +*/ +char *captcha_decode(unsigned int seed){ + const char *zSecret; + const char *z; + Blob b; + static char zRes[20]; + zSecret = db_get("captcha-secret", 0); + if( zSecret==0 ){ + db_multi_exec( + "REPLACE INTO config(name,value)" + " VALUES('captcha-secret', lower(hex(randomblob(20))));" + ); + zSecret = db_get("captcha-secret", 0); + assert( zSecret!=0 ); + } + blob_init(&b, 0, 0); + blob_appendf(&b, "%s-%x", zSecret, seed); + sha1sum_blob(&b, &b); + z = blob_buffer(&b); + memcpy(zRes, z, 8); + zRes[8] = 0; + return zRes; +}
Modified src/cgi.c from [8c16621a50] to [0a66f5aa4a].
@@ -40,10 +40,13 @@ # include <sys/times.h> # include <sys/time.h> # include <sys/wait.h> # include <sys/select.h> #endif +#ifdef __EMX__ + typedef int socklen_t; +#endif #include <time.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "cgi.h" @@ -65,17 +68,10 @@ */ #define CGI_HEADER 0 #define CGI_BODY 1 #endif /* INTERFACE */ - -/* -** Provide a reliable implementation of a caseless string comparison -** function. -*/ -#define stricmp sqlite3StrICmp -extern int sqlite3StrICmp(const char*, const char*); /* ** The HTTP reply is generated in two pieces: the header and the body. ** These pieces are generated separately because they are not necessary ** produced in order. Parts of the header might be built after all or @@ -641,21 +637,22 @@ showBytes = 0; }else{ nArg = tokenize_line(zLine, sizeof(azArg)/sizeof(azArg[0]), azArg); for(i=0; i<nArg; i++){ int c = tolower(azArg[i][0]); - if( c=='c' && stricmp(azArg[i],"content-disposition:")==0 ){ + int n = strlen(azArg[i]); + if( c=='c' && sqlite3_strnicmp(azArg[i],"content-disposition:",n)==0 ){ i++; - }else if( c=='n' && stricmp(azArg[i],"name=")==0 ){ + }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){ zName = azArg[++i]; - }else if( c=='f' && stricmp(azArg[i],"filename=")==0 ){ + }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){ char *z = azArg[++i]; if( zName && z && islower(zName[0]) ){ cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z); } showBytes = 1; - }else if( c=='c' && stricmp(azArg[i],"content-type:")==0 ){ + }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){ char *z = azArg[++i]; if( zName && z && islower(zName[0]) ){ cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z); } } @@ -677,10 +674,13 @@ z = (char*)P("QUERY_STRING"); if( z ){ z = mprintf("%s",z); add_param_list(z, '&'); } + + z = (char*)P("REMOTE_ADDR"); + if( z ) g.zIpAddr = mprintf("%s", z); len = atoi(PD("CONTENT_LENGTH", "0")); g.zContentType = zType = P("CONTENT_TYPE"); if( len>0 && zType ){ blob_zero(&g.cgiIn);
Modified src/checkin.c from [54d694aac3] to [2e4a6e1c0f].
@@ -163,26 +163,30 @@ } db_finalize(&q); } /* -** COMMAND: extra -** Usage: %fossil extra +** COMMAND: extras +** Usage: %fossil extras ?--dotfiles? ** ** Print a list of all files in the source tree that are not part of ** the current checkout. See also the "clean" command. +** +** Files and subdirectories whose names begin with "." are normally +** ignored but can be included by adding the --dotfiles option. */ void extra_cmd(void){ Blob path; Blob repo; Stmt q; int n; + int allFlag = find_option("dotfiles",0,0)!=0; db_must_be_within_tree(); db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); n = strlen(g.zLocalRoot); blob_init(&path, g.zLocalRoot, n-1); - vfile_scan(0, &path, blob_size(&path)); + vfile_scan(0, &path, blob_size(&path), allFlag); db_prepare(&q, "SELECT x FROM sfile" " WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_')" " ORDER BY 1"); if( file_tree_name(g.zRepositoryName, &repo, 0) ){ @@ -194,31 +198,37 @@ db_finalize(&q); } /* ** COMMAND: clean -** Usage: %fossil clean ?-all? +** Usage: %fossil clean ?--force? ?--dotfiles? ** ** Delete all "extra" files in the source tree. "Extra" files are ** files that are not officially part of the checkout. See also ** the "extra" command. This operation cannot be undone. ** ** You will be prompted before removing each file. If you are ** sure you wish to remove all "extra" files you can specify the -** optional -all flag. +** optional --force flag and no prmpts will be issued. +** +** Files and subdirectories whose names begin with "." are +** normally ignored. They are included if the "--dotfiles" option +** is used. */ void clean_cmd(void){ int allFlag; + int dotfilesFlag; Blob path, repo; Stmt q; int n; allFlag = find_option("all","a",0)!=0; + dotfilesFlag = find_option("dotfiles",0,0)!=0; db_must_be_within_tree(); db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); n = strlen(g.zLocalRoot); blob_init(&path, g.zLocalRoot, n-1); - vfile_scan(0, &path, blob_size(&path)); + vfile_scan(0, &path, blob_size(&path), dotfilesFlag); db_prepare(&q, "SELECT %Q || x FROM sfile" " WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_')" " ORDER BY 1", g.zLocalRoot); if( file_tree_name(g.zRepositoryName, &repo, 0) ){ @@ -260,10 +270,17 @@ "\n" "# Enter comments on this check-in. Lines beginning with # are ignored.\n" "# The check-in comment follows wiki formatting rules.\n" "#\n" ); + if( g.markPrivate ){ + blob_append(&text, + "# PRIVATE BRANCH: This check-in will be private and will not sync to\n" + "# repositories.\n" + "#\n", -1 + ); + } status_report(&text, "# "); zEditor = db_get("editor", 0); if( zEditor==0 ){ zEditor = getenv("VISUAL"); } @@ -283,11 +300,11 @@ blob_add_cr(&text); #endif blob_write_to_file(&text, zFile); zCmd = mprintf("%s \"%s\"", zEditor, zFile); printf("%s\n", zCmd); - if( system(zCmd) ){ + if( portable_system(zCmd) ){ fossil_panic("editor aborted"); } blob_reset(&text); blob_read_from_file(&text, zFile); blob_remove_cr(&text); @@ -385,17 +402,21 @@ ** entries in the new branch when shown in the web timeline interface. ** ** A check-in is not permitted to fork unless the --force or -f ** option appears. A check-in is not allowed against a closed check-in. ** +** The --private option creates a private check-in that is never synced. +** Children of private check-ins are automatically private. +** ** Options: ** ** --comment|-m COMMENT-TEXT ** --branch NEW-BRANCH-NAME ** --bgcolor COLOR ** --nosign ** --force|-f +** --private ** */ void commit_cmd(void){ int rc; int vid, nrid, nvid; @@ -410,10 +431,11 @@ char *zManifestFile; /* Name of the manifest file */ int nBasename; /* Length of "g.zLocalRoot/" */ const char *zBranch; /* Create a new branch with this name */ const char *zBgColor; /* Set background color when branching */ const char *zDateOvrd; /* Override date string */ + const char *zUserOvrd; /* Override user name */ Blob filename; /* complete filename */ Blob manifest; Blob muuid; /* Manifest uuid */ Blob mcksum; /* Self-checksum on the manifest */ Blob cksum1, cksum2; /* Before and after commit checksums */ @@ -423,20 +445,34 @@ noSign = find_option("nosign",0,0)!=0; zComment = find_option("comment","m",1); forceFlag = find_option("force", "f", 0)!=0; zBranch = find_option("branch","b",1); zBgColor = find_option("bgcolor",0,1); + if( find_option("private",0,0) ){ + g.markPrivate = 1; + if( zBranch==0 ) zBranch = "private"; + if( zBgColor==0 ) zBgColor = "#fec084"; /* Orange */ + } zDateOvrd = find_option("date-override",0,1); + zUserOvrd = find_option("user-override",0,1); db_must_be_within_tree(); noSign = db_get_boolean("omitsign", 0)|noSign; if( db_get_boolean("clearsign", 1)==0 ){ noSign = 1; } verify_all_options(); - /* - ** Autosync if requested. - */ - autosync(AUTOSYNC_PULL); + /* Get the ID of the parent manifest artifact */ + vid = db_lget_int("checkout", 0); + if( content_is_private(vid) ){ + g.markPrivate = 1; + } + + /* + ** Autosync if autosync is enabled and this is not a private check-in. + */ + if( !g.markPrivate ){ + autosync(AUTOSYNC_PULL); + } /* There are two ways this command may be executed. If there are ** no arguments following the word "commit", then all modified files ** in the checked out directory are committed. If one or more arguments ** follows "commit", then only those files are committed. @@ -480,17 +516,15 @@ if( strlen(blob_str(&unmodified)) ){ fossil_panic("file %s has not changed", blob_str(&unmodified)); } } - vid = db_lget_int("checkout", 0); - /* ** Do not allow a commit that will cause a fork unless the --force flag - ** is used. - */ - if( zBranch==0 && forceFlag==0 && !is_a_leaf(vid) ){ + ** is used or unless this is a private check-in. + */ + if( zBranch==0 && forceFlag==0 && g.markPrivate==0 && !is_a_leaf(vid) ){ fossil_fatal("would fork. \"update\" first or use -f or --force."); } /* ** Do not allow a commit against a closed leaf @@ -556,21 +590,22 @@ blob_appendf(&manifest, "C %F\n", blob_str(&comment)); zDate = db_text(0, "SELECT datetime('%q')", zDateOvrd ? zDateOvrd : "now"); zDate[10] = 'T'; blob_appendf(&manifest, "D %s\n", zDate); db_prepare(&q, - "SELECT pathname, uuid, origname" + "SELECT pathname, uuid, origname, blob.rid" " FROM vfile JOIN blob ON vfile.mrid=blob.rid" " WHERE NOT deleted AND vfile.vid=%d" " ORDER BY 1", vid); blob_zero(&filename); - blob_appendf(&filename, "%s/", g.zLocalRoot); + blob_appendf(&filename, "%s", g.zLocalRoot); nBasename = blob_size(&filename); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); const char *zUuid = db_column_text(&q, 1); const char *zOrig = db_column_text(&q, 2); + int frid = db_column_int(&q, 3); const char *zPerm; blob_append(&filename, zName, -1); if( file_isexe(blob_str(&filename)) ){ zPerm = " x"; }else{ @@ -581,10 +616,11 @@ blob_appendf(&manifest, "F %F %s%s\n", zName, zUuid, zPerm); }else{ if( zPerm[0]==0 ){ zPerm = " w"; } blob_appendf(&manifest, "F %F %s%s %F\n", zName, zUuid, zPerm, zOrig); } + if( !g.markPrivate ) content_make_public(frid); } blob_reset(&filename); db_finalize(&q); zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); blob_appendf(&manifest, "P %s", zUuid); @@ -591,10 +627,11 @@ db_prepare(&q2, "SELECT merge FROM vmerge WHERE id=:id"); db_bind_int(&q2, ":id", 0); while( db_step(&q2)==SQLITE_ROW ){ int mid = db_column_int(&q2, 0); + if( !g.markPrivate && content_is_private(mid) ) continue; zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid); if( zUuid ){ blob_appendf(&manifest, " %s", zUuid); free(zUuid); } @@ -623,15 +660,15 @@ const char *zTag = db_column_text(&q, 0); blob_appendf(&manifest, "T -%F *\n", zTag); } db_finalize(&q); } - blob_appendf(&manifest, "U %F\n", g.zLogin); + blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); md5sum_blob(&manifest, &mcksum); blob_appendf(&manifest, "Z %b\n", &mcksum); zManifestFile = mprintf("%smanifest", g.zLocalRoot); - if( !noSign && clearsign(&manifest, &manifest) ){ + if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){ Blob ans; blob_zero(&ans); prompt_user("unable to sign manifest. continue [y/N]? ", &ans); if( blob_str(&ans)[0]!='y' ){ db_end_transaction(1); @@ -700,11 +737,13 @@ undo_reset(); /* Commit */ db_end_transaction(0); - autosync(AUTOSYNC_PUSH); + if( !g.markPrivate ){ + autosync(AUTOSYNC_PUSH); + } if( count_nonbranch_children(vid)>1 ){ printf("**** warning: a fork has occurred *****\n"); } }
Modified src/checkout.c from [24593c59e3] to [975bc66779].
@@ -71,11 +71,14 @@ if( name_to_uuid(&uuid, 1) ){ fossil_panic(g.zErrMsg); } vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid); if( vid==0 ){ - fossil_panic("no such version: %s", g.argv[2]); + fossil_fatal("no such check-in: %s", g.argv[2]); + } + if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", vid) ){ + fossil_fatal("object [%.10s] is not a check-in", blob_str(&uuid)); } load_vfile_from_rid(vid); return vid; } @@ -135,62 +138,103 @@ /* ** COMMAND: checkout ** COMMAND: co ** -** Usage: %fossil checkout VERSION ?-f|--force? +** Usage: %fossil checkout VERSION ?-f|--force? ?--keep? ** ** Check out a version specified on the command-line. This command -** will not overwrite edited files in the current checkout unless -** the --force option appears on the command-line. +** will abort if there are edited files in the current checkout unless +** the --force option appears on the command-line. The --keep option +** leaves files on disk unchanged, except the manifest and manifest.uuid +** files. +** +** The --latest flag can be used in place of VERSION to checkout the +** latest version in the repository. ** ** See also the "update" command. */ void checkout_cmd(void){ - int forceFlag; - int noWrite; + int forceFlag; /* Force checkout even if edits exist */ + int keepFlag; /* Do not change any files on disk */ + int latestFlag; /* Checkout the latest version */ + char *zVers; /* Version to checkout */ int vid, prior; Blob cksum1, cksum1b, cksum2; db_must_be_within_tree(); db_begin_transaction(); forceFlag = find_option("force","f",0)!=0; - noWrite = find_option("dontwrite",0,0)!=0; - if( g.argc!=3 ) usage("?--force? VERSION"); + keepFlag = find_option("keep",0,0)!=0; + latestFlag = find_option("latest",0,0)!=0; + if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){ + usage("VERSION|--latest ?--force? ?--keep?"); + } if( !forceFlag && unsaved_changes()==1 ){ fossil_fatal("there are unsaved changes in the current checkout"); } if( forceFlag ){ db_multi_exec("DELETE FROM vfile"); prior = 0; }else{ prior = db_lget_int("checkout",0); } - vid = load_vfile(g.argv[2]); + if( latestFlag ){ + compute_leaves(db_lget_int("checkout",0), 1); + zVers = db_text(0, "SELECT uuid FROM leaves, event, blob" + " WHERE event.objid=leaves.rid AND blob.rid=leaves.rid" + " ORDER BY event.mtime DESC"); + if( zVers==0 ){ + fossil_fatal("cannot locate \"latest\" checkout"); + } + }else{ + zVers = g.argv[2]; + } + vid = load_vfile(zVers); if( prior==vid ){ return; } - if( !noWrite ){ + if( !keepFlag ){ uncheckout(prior); } db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid); - if( !noWrite ){ + if( !keepFlag ){ vfile_to_disk(vid, 0, 1); - manifest_to_disk(vid); - db_lset_int("checkout", vid); - undo_reset(); } + manifest_to_disk(vid); + db_lset_int("checkout", vid); + undo_reset(); db_multi_exec("DELETE FROM vmerge"); - vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b); - vfile_aggregate_checksum_disk(vid, &cksum2); - if( blob_compare(&cksum1, &cksum2) ){ - printf("WARNING: manifest checksum does not agree with disk\n"); - } - if( blob_compare(&cksum1, &cksum1b) ){ - printf("WARNING: manifest checksum does not agree with manifest\n"); + if( !keepFlag ){ + vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b); + vfile_aggregate_checksum_disk(vid, &cksum2); + if( blob_compare(&cksum1, &cksum2) ){ + printf("WARNING: manifest checksum does not agree with disk\n"); + } + if( blob_compare(&cksum1, &cksum1b) ){ + printf("WARNING: manifest checksum does not agree with manifest\n"); + } } db_end_transaction(0); +} + +/* +** Unlink the local database file +*/ +void unlink_local_database(void){ + static const char *azFile[] = { + "%s_FOSSIL_", + "%s_FOSSIL_-journal", + "%s.fos", + "%s.fos-journal", + }; + int i; + for(i=0; i<sizeof(azFile)/sizeof(azFile[0]); i++){ + char *z = mprintf(azFile[i], g.zLocalRoot); + unlink(z); + free(z); + } } /* ** COMMAND: close ** @@ -205,8 +249,7 @@ db_must_be_within_tree(); if( !forceFlag && unsaved_changes()==1 ){ fossil_fatal("there are unsaved changes in the current checkout"); } db_close(); - unlink(mprintf("%s_FOSSIL_", g.zLocalRoot)); - unlink(mprintf("%s_FOSSIL_-journal", g.zLocalRoot)); + unlink_local_database(); }
Modified src/clearsign.c from [3e61358e2b] to [4431c80a36].
@@ -45,11 +45,11 @@ zRand = db_text(0, "SELECT hex(randomblob(10))"); zOut = mprintf("out-%s", zRand); zIn = mprintf("in-%z", zRand); blob_write_to_file(pIn, zOut); zCmd = mprintf("%s %s %s", zBase, zIn, zOut); - rc = system(zCmd); + rc = portable_system(zCmd); free(zCmd); if( rc==0 ){ if( pOut==pIn ){ blob_reset(pIn); }
Modified src/clone.c from [f5925839e5] to [70ab216ac2].
@@ -41,28 +41,33 @@ char *zPassword; url_proxy_options(); if( g.argc!=4 ){ usage("FILE-OR-URL NEW-REPOSITORY"); } - db_open_config(); + db_open_config(0); if( file_size(g.argv[3])>0 ){ fossil_panic("file already exists: %s", g.argv[3]); } url_parse(g.argv[2]); if( g.urlIsFile ){ file_copy(g.urlName, g.argv[3]); db_close(); db_open_repository(g.argv[3]); - db_open_config(); db_record_repository_filename(g.argv[3]); db_multi_exec( "REPLACE INTO config(name,value)" " VALUES('server-code', lower(hex(randomblob(20))));" "REPLACE INTO config(name,value)" - " VALUES('last-sync-url', 'file://%q');", - g.urlName + " VALUES('last-sync-url', '%q');", + g.urlCanonical + ); + db_multi_exec( + "DELETE FROM blob WHERE rid IN private;" + "DELETE FROM delta wHERE rid IN private;" + "DELETE FROM private;" ); + shun_artifacts(); g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'"); if( g.zLogin==0 ){ db_create_default_users(1); } printf("Repository cloned into %s\n", g.argv[3]); @@ -73,11 +78,11 @@ db_record_repository_filename(g.argv[3]); db_initial_setup(0, 0); user_select(); db_set("content-schema", CONTENT_SCHEMA, 0); db_set("aux-schema", AUX_SCHEMA, 0); - db_set("last-sync-url", g.argv[2], 0); + db_set("last-sync-url", g.urlCanonical, 0); db_multi_exec( "REPLACE INTO config(name,value)" " VALUES('server-code', lower(hex(randomblob(20))));" ); url_enable_proxy(0);
Modified src/construct.c from [bf4879b005] to [763e35ebbe].
@@ -137,11 +137,11 @@ } /* Create the foundation */ db_create_repository(zRepository); db_open_repository(zRepository); - db_open_config(); + db_open_config(0); db_begin_transaction(); db_initial_setup(0, 1); printf("project-id: %s\n", db_get("project-code", 0));
Modified src/content.c from [6508de1118] to [79f280c4e2].
@@ -151,16 +151,34 @@ } bag_clear(&pending); } /* +** Get the blob.content value for blob.rid=rid. Return 1 on success or +** 0 on failure. +*/ +static int content_of_blob(int rid, Blob *pBlob){ + static Stmt q; + int rc = 0; + db_static_prepare(&q, "SELECT content FROM blob WHERE rid=:rid AND size>=0"); + db_bind_int(&q, ":rid", rid); + if( db_step(&q)==SQLITE_ROW ){ + db_ephemeral_blob(&q, 0, pBlob); + blob_uncompress(pBlob, pBlob); + rc = 1; + } + db_reset(&q); + return rc; +} + + +/* ** Extract the content for ID rid and put it into the ** uninitialized blob. Return 1 on success. If the record ** is a phantom, zero pBlob and return 0. */ int content_get(int rid, Blob *pBlob){ - Stmt q; Blob src; int srcid; int rc = 0; int i; static Bag inProcess; @@ -183,11 +201,11 @@ blob_zero(&contentCache.a[i].content); contentCache.n--; if( i<contentCache.n ){ contentCache.a[i] = contentCache.a[contentCache.n]; } - CONTENT_TRACE(("%*shit cache: %d\n", + CONTENT_TRACE(("%*scache: %d\n", bag_count(&inProcess), "", rid)) return 1; } } @@ -210,21 +228,17 @@ return 0; } bag_insert(&inProcess, srcid); if( content_get(srcid, &src) ){ - db_prepare(&q, "SELECT content FROM blob WHERE rid=%d AND size>=0", rid); - if( db_step(&q)==SQLITE_ROW ){ - Blob delta; - db_ephemeral_blob(&q, 0, &delta); - blob_uncompress(&delta, &delta); + Blob delta; + if( content_of_blob(rid, &delta) ){ blob_init(pBlob,0,0); blob_delta_apply(&src, &delta, pBlob); blob_reset(&delta); rc = 1; } - db_finalize(&q); /* Save the srcid artifact in the cache */ if( contentCache.n<MX_CACHE_CNT ){ i = contentCache.n++; }else if( ((contentCache.skipCnt++)%EXPELL_INTERVAL)!=0 ){ @@ -254,17 +268,13 @@ } } bag_remove(&inProcess, srcid); }else{ /* No delta required. Read content directly from the database */ - db_prepare(&q, "SELECT content FROM blob WHERE rid=%d AND size>=0", rid); - if( db_step(&q)==SQLITE_ROW ){ - db_ephemeral_blob(&q, 0, pBlob); - blob_uncompress(pBlob, pBlob); + if( content_of_blob(rid, pBlob) ){ rc = 1; } - db_finalize(&q); } if( rc==0 ){ bag_insert(&contentCache.missing, rid); }else{ bag_insert(&contentCache.available, rid); @@ -450,10 +460,14 @@ db_exec(&s1); rid = db_last_insert_rowid(); if( !pBlob ){ db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); } + if( g.markPrivate ){ + db_multi_exec("INSERT INTO private VALUES(%d)", rid); + markAsUnclustered = 0; + } } blob_reset(&cmpr); /* If the srcId is specified, then the data we just added is ** really a delta. Record this fact in the delta table. @@ -510,15 +524,19 @@ db_static_prepare(&s2, "INSERT INTO phantom VALUES(:rid)" ); db_bind_int(&s2, ":rid", rid); db_exec(&s2); - db_static_prepare(&s3, - "INSERT INTO unclustered VALUES(:rid)" - ); - db_bind_int(&s3, ":rid", rid); - db_exec(&s3); + if( g.markPrivate ){ + db_multi_exec("INSERT INTO private VALUES(%d)", rid); + }else{ + db_static_prepare(&s3, + "INSERT INTO unclustered VALUES(:rid)" + ); + db_bind_int(&s3, ":rid", rid); + db_exec(&s3); + } bag_insert(&contentCache.missing, rid); db_end_transaction(0); return rid; } @@ -572,45 +590,84 @@ rid = atoi(g.argv[2]); content_undelta(rid); } /* +** Return true if the given RID is marked as PRIVATE. +*/ +int content_is_private(int rid){ + static Stmt s1; + int rc; + db_static_prepare(&s1, + "SELECT 1 FROM private WHERE rid=:rid" + ); + db_bind_int(&s1, ":rid", rid); + rc = db_step(&s1); + db_reset(&s1); + return rc==SQLITE_ROW; +} + +/* +** Make sure an artifact is public. +*/ +void content_make_public(int rid){ + static Stmt s1; + db_static_prepare(&s1, + "DELETE FROM private WHERE rid=:rid" + ); + db_bind_int(&s1, ":rid", rid); + db_exec(&s1); +} + +/* ** Change the storage of rid so that it is a delta of srcid. ** ** If rid is already a delta from some other place then no ** conversion occurs and this is a no-op unless force==1. +** +** Never generate a delta that carries a private artifact into a public +** artifact. Otherwise, when we go to send the public artifact on a +** sync operation, the other end of the sync will never be able to receive +** the source of the delta. It is OK to delta private->private and +** public->private and public->public. Just no private->public delta. ** ** If srcid is a delta that depends on rid, then srcid is ** converted to undeltaed text. ** ** If either rid or srcid contain less than 50 bytes, or if the ** resulting delta does not achieve a compression of at least 25% on ** its own the rid is left untouched. -** -** NOTE: IMHO the creation of the delta should be defered until after -** the blob sizes have been checked. Doing it before the check as is -** done now the code will generate a delta just to immediately throw -** it away, wasting space and time. */ void content_deltify(int rid, int srcid, int force){ int s; Blob data, src, delta; Stmt s1, s2; if( srcid==rid ) return; if( !force && findSrcid(rid)>0 ) return; + if( content_is_private(srcid) && !content_is_private(rid) ){ + return; + } s = srcid; while( (s = findSrcid(s))>0 ){ if( s==rid ){ content_undelta(srcid); break; } } content_get(srcid, &src); + if( blob_size(&src)<50 ){ + blob_reset(&src); + return; + } content_get(rid, &data); + if( blob_size(&data)<50 ){ + blob_reset(&src); + blob_reset(&data); + return; + } blob_delta_create(&src, &data, &delta); - if( blob_size(&src)>=50 && blob_size(&data)>=50 && - blob_size(&delta) < blob_size(&data)*0.75 ){ + if( blob_size(&delta) < blob_size(&data)*0.75 ){ blob_compress(&delta, &delta); db_prepare(&s1, "UPDATE blob SET content=:data WHERE rid=%d", rid); db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, srcid); db_bind_blob(&s1, ":data", &delta); db_begin_transaction();
Modified src/db.c from [6f78bab6b5] to [16bc22dd3c].
@@ -620,35 +620,65 @@ sqlite3_exec(db, "COMMIT", 0, 0, 0); sqlite3_close(db); } /* +** Open a database file. Return a pointer to the new database +** connection. An error results in process abort. +*/ +static sqlite3 *openDatabase(const char *zDbName){ + int rc; + const char *zVfs; + sqlite3 *db; + + zVfs = getenv("FOSSIL_VFS"); +#ifdef __MINGW32__ + zDbName = mbcsToUtf8(zDbName); +#endif + rc = sqlite3_open_v2( + zDbName, &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + zVfs + ); + if( rc!=SQLITE_OK ){ + db_err(sqlite3_errmsg(db)); + } + sqlite3_busy_timeout(db, 5000); + return db; +} + + +/* ** zDbName is the name of a database file. If no other database ** file is open, then open this one. If another database file is ** already open, then attach zDbName using the name zLabel. */ void db_open_or_attach(const char *zDbName, const char *zLabel){ -#ifdef __MINGW32__ - zDbName = mbcsToUtf8(zDbName); -#endif if( !g.db ){ - int rc = sqlite3_open(zDbName, &g.db); - if( rc!=SQLITE_OK ){ - db_err(sqlite3_errmsg(g.db)); - } - sqlite3_busy_timeout(g.db, 5000); + g.db = openDatabase(zDbName); db_connection_init(); }else{ +#ifdef __MINGW32__ + zDbName = mbcsToUtf8(zDbName); +#endif db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel); } } /* ** Open the user database in "~/.fossil". Create the database anew if ** it does not already exist. -*/ -void db_open_config(void){ +** +** If the useAttach flag is 0 (the usual case) then the user database is +** opened on a separate database connection g.dbConfig. This prevents +** the ~/.fossil database from becoming locked on long check-in or sync +** operations which hold an exclusive transaction. In a few cases, though, +** it is convenient for the ~/.fossil to be attached to the main database +** connection so that we can join between the various databases. In that +** case, invoke this routine with useAttach as 1. +*/ +void db_open_config(int useAttach){ char *zDbName; const char *zHome; if( g.configOpen ) return; #ifdef __MINGW32__ zHome = getenv("LOCALAPPDATA"); @@ -656,26 +686,37 @@ zHome = getenv("APPDATA"); if( zHome==0 ){ zHome = getenv("HOMEPATH"); } } + if( zHome==0 ){ + db_err("cannot locate home directory - " + "please set the HOMEPATH environment variable"); + } #else zHome = getenv("HOME"); -#endif if( zHome==0 ){ - db_err("cannot local home directory"); - } + db_err("cannot locate home directory - " + "please set the HOME environment variable"); + } +#endif #ifdef __MINGW32__ /* . filenames give some window systems problems and many apps problems */ zDbName = mprintf("%//_fossil", zHome); #else zDbName = mprintf("%s/.fossil", zHome); #endif if( file_size(zDbName)<1024*3 ){ db_init_database(zDbName, zConfigSchema, (char*)0); } - db_open_or_attach(zDbName, "configdb"); + g.useAttach = useAttach; + if( useAttach ){ + db_open_or_attach(zDbName, "configdb"); + g.dbConfig = 0; + }else{ + g.dbConfig = openDatabase(zDbName); + } g.configOpen = 1; } /* ** If zDbName is a valid local database file, open it and return @@ -689,11 +730,11 @@ if( access(zDbName, F_OK) ) return 0; lsize = file_size(zDbName); if( lsize%1024!=0 || lsize<4096 ) return 0; db_open_or_attach(zDbName, "localdb"); g.localOpen = 1; - db_open_config(); + db_open_config(0); db_open_repository(0); /* If the "mtime" column is missing from the vfile table, then ** add it now. This code added on 2008-12-06. After all users have ** upgraded, this code can be safely deleted. @@ -784,11 +825,11 @@ db_err("unable to find the name of a repository database"); } } if( access(zDbName, R_OK) || file_size(zDbName)<1024 ){ if( access(zDbName, 0) ){ - fossil_panic("repository does not exists or" + fossil_panic("repository does not exist or" " is in an unreadable directory: %s", zDbName); }else if( access(zDbName, R_OK) ){ fossil_panic("read permission denied for repository %s", zDbName); }else{ fossil_panic("not a valid repository: %s", zDbName); @@ -891,15 +932,17 @@ "VALUES(%Q,lower(hex(randomblob(3))),'s','')", zUser ); if( !setupUserOnly ){ db_multi_exec( "INSERT INTO user(login,pw,cap,info)" - " VALUES('anonymous','anonymous','ghknw','Anon');" + " VALUES('anonymous',hex(randomblob(8)),'ghmncz','Anon');" "INSERT INTO user(login,pw,cap,info)" " VALUES('nobody','','jor','Nobody');" "INSERT INTO user(login,pw,cap,info)" - " VALUES('developer','','deipt','Dev');" + " VALUES('developer','','dei','Dev');" + "INSERT INTO user(login,pw,cap,info)" + " VALUES('reader','','kptw','Reader');" ); } } /* @@ -906,15 +949,16 @@ ** Fill an empty repository database with the basic information for a ** repository. This function is shared between 'create_repository_cmd' ** ('new') and 'reconstruct_cmd' ('reconstruct'), both of which create ** new repositories. ** -** The makeInitialVersion flag determines whether or not an initial -** manifest is created. The makeServerCodes flag determines whether or +** The zInitialDate parameter determines the date of the initial check-in +** that is automatically created. If zInitialDate is 0 then no initial +** check-in is created. The makeServerCodes flag determines whether or ** not server and project codes are invented for this repository. */ -void db_initial_setup (int makeInitialVersion, int makeServerCodes){ +void db_initial_setup (const char *zInitialDate, int makeServerCodes){ char *zDate; Blob hash; Blob manifest; db_set("content-schema", CONTENT_SCHEMA, 0); @@ -930,15 +974,15 @@ if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0); if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0); db_create_default_users(0); user_select(); - if (makeInitialVersion){ + if( zInitialDate ){ int rid; blob_zero(&manifest); blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n"); - zDate = db_text(0, "SELECT datetime('now')"); + zDate = db_text(0, "SELECT datetime(%Q)", zInitialDate); zDate[10]='T'; blob_appendf(&manifest, "D %s\n", zDate); blob_appendf(&manifest, "P\n"); md5sum_init(); blob_appendf(&manifest, "R %s\n", md5sum_finish(0)); @@ -962,18 +1006,22 @@ ** This command is distinct from "clone". The "clone" command makes ** a copy of an existing project. This command starts a new project. */ void create_repository_cmd(void){ char *zPassword; + const char *zDate; /* Date of the initial check-in */ + + zDate = find_option("date-override",0,1); + if( zDate==0 ) zDate = "now"; if( g.argc!=3 ){ usage("REPOSITORY-NAME"); } db_create_repository(g.argv[2]); db_open_repository(g.argv[2]); - db_open_config(); + db_open_config(0); db_begin_transaction(); - db_initial_setup(1, 1); + db_initial_setup(zDate, 1); db_end_transaction(0); printf("project-id: %s\n", db_get("project-code", 0)); printf("server-id: %s\n", db_get("server-code", 0)); zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); printf("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword); @@ -1095,10 +1143,11 @@ ** database connection is first established. */ LOCAL void db_connection_init(void){ static int once = 1; if( once ){ + sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0); sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); sqlite3_create_function( g.db, "file_is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0 ); if( g.fSqlTrace ){ @@ -1127,50 +1176,83 @@ } return 0; } /* +** Swap the g.db and g.dbConfig connections so that the various db_* routines +** work on the ~/.fossil database instead of on the repository database. +** Be sure to swap them back after doing the operation. +** +** If g.useAttach that means the ~/.fossil database was opened with +** the useAttach flag set to 1. In that case no connection swap is required +** so this routine is a no-op. +*/ +void db_swap_connections(void){ + if( !g.useAttach ){ + sqlite3 *dbTemp = g.db; + g.db = g.dbConfig; + g.dbConfig = dbTemp; + } +} + +/* ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the ** repository and local databases. */ char *db_get(const char *zName, char *zDefault){ char *z = 0; if( g.repositoryOpen ){ z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName); } if( z==0 && g.configOpen ){ + db_swap_connections(); z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName); + db_swap_connections(); } if( z==0 ){ z = zDefault; } return z; } void db_set(const char *zName, const char *zValue, int globalFlag){ db_begin_transaction(); - db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%Q)", - globalFlag ? "global_" : "", zName, zValue); + if( globalFlag ){ + db_swap_connections(); + db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)", + zName, zValue); + db_swap_connections(); + }else{ + db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%Q)", + zName, zValue); + } if( globalFlag && g.repositoryOpen ){ db_multi_exec("DELETE FROM config WHERE name=%Q", zName); } db_end_transaction(0); } void db_unset(const char *zName, int globalFlag){ db_begin_transaction(); - db_multi_exec("DELETE FROM %sconfig WHERE name=%Q", - globalFlag ? "global_" : "", zName); + if( globalFlag ){ + db_swap_connections(); + db_multi_exec("DELETE FROM global_config WHERE name=%Q", zName); + db_swap_connections(); + }else{ + db_multi_exec("DELETE FROM config WHERE name=%Q", zName); + } if( globalFlag && g.repositoryOpen ){ db_multi_exec("DELETE FROM config WHERE name=%Q", zName); } db_end_transaction(0); } int db_is_global(const char *zName){ + int rc = 0; if( g.configOpen ){ - return db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName); - }else{ - return 0; - } + db_swap_connections(); + rc = db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName); + db_swap_connections(); + } + return rc; } int db_get_int(const char *zName, int dflt){ int v = dflt; int rc; if( g.repositoryOpen ){ @@ -1183,22 +1265,29 @@ db_finalize(&q); }else{ rc = SQLITE_DONE; } if( rc==SQLITE_DONE && g.configOpen ){ + db_swap_connections(); v = db_int(dflt, "SELECT value FROM global_config WHERE name=%Q", zName); + db_swap_connections(); } return v; } void db_set_int(const char *zName, int value, int globalFlag){ - db_begin_transaction(); - db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%d)", - globalFlag ? "global_" : "", zName, value); + if( globalFlag ){ + db_swap_connections(); + db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)", + zName, value); + db_swap_connections(); + }else{ + db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%d)", + zName, value); + } if( globalFlag && g.repositoryOpen ){ db_multi_exec("DELETE FROM config WHERE name=%Q", zName); } - db_end_transaction(0); } int db_get_boolean(const char *zName, int dflt){ char *zVal = db_get(zName, dflt ? "on" : "off"); if( is_truth(zVal) ) return 1; if( is_false(zVal) ) return 0; @@ -1232,34 +1321,42 @@ if( zName==0 ){ if( !g.localOpen ) return; zName = db_lget("repository", 0); } file_canonical_name(zName, &full); + db_swap_connections(); db_multi_exec( "INSERT OR IGNORE INTO global_config(name,value)" "VALUES('repo:%q',1)", blob_str(&full) ); + db_swap_connections(); blob_reset(&full); } /* ** COMMAND: open ** -** Usage: %fossil open FILENAME +** Usage: %fossil open FILENAME ?VERSION? ?--keep? ** ** Open a connection to the local repository in FILENAME. A checkout ** for the repository is created with its root at the working directory. +** If VERSION is specified then that version is checked out. Otherwise +** the latest version is checked out. No files other than "manifest" +** and "manifest.uuid" are modified if the --keep option is present. +** ** See also the "close" command. */ void cmd_open(void){ Blob path; int vid; - static char *azNewArgv[] = { 0, "update", "--latest", 0 }; + int keepFlag; + static char *azNewArgv[] = { 0, "checkout", "--latest", 0, 0, 0 }; url_proxy_options(); - if( g.argc!=3 ){ - usage("REPOSITORY-FILENAME"); + keepFlag = find_option("keep",0,0)!=0; + if( g.argc!=3 && g.argc!=4 ){ + usage("REPOSITORY-FILENAME ?VERSION?"); } if( db_open_local() ){ fossil_panic("already within an open tree rooted at %s", g.zLocalRoot); } file_canonical_name(g.argv[2], &path); @@ -1271,14 +1368,23 @@ vid = db_int(0, "SELECT pid FROM plink y" " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)"); if( vid==0 ){ db_lset_int("checkout", 1); }else{ + char **oldArgv = g.argv; + int oldArgc = g.argc; db_lset_int("checkout", vid); + azNewArgv[0] = g.argv[0]; g.argv = azNewArgv; g.argc = 3; - update_cmd(); + if( oldArgc==4 ){ + azNewArgv[g.argc-1] = oldArgv[3]; + } + if( keepFlag ){ + azNewArgv[g.argc++] = "--keep"; + } + checkout_cmd(); g.argc = 2; info_cmd(); } } @@ -1327,10 +1433,13 @@ ** after commit or tag or branch creation. ** ** diff-command External command to run when performing a diff. ** If undefined, the internal text diff will be used. ** +** dont-push Prevent this repository from pushing from client to +** server. Useful when setting up a private branch. +** ** editor Text editor command used for check-in comments. ** ** http-port The TCP/IP port number to use by the "server" ** and "ui" commands. Default: 8080 ** @@ -1364,10 +1473,11 @@ */ void setting_cmd(void){ static const char *azName[] = { "autosync", "diff-command", + "dont-push", "editor", "gdiff-command", "http-port", "localauth", "clearsign", @@ -1377,15 +1487,15 @@ "web-browser", }; int i; int globalFlag = find_option("global","g",0)!=0; int unsetFlag = g.argv[1][0]=='u'; + db_open_config(1); db_find_and_open_repository(0); if( !g.repositoryOpen ){ globalFlag = 1; } - db_open_config(); if( unsetFlag && g.argc!=3 ){ usage("PROPERTY ?-global?"); } if( g.argc==2 ){ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ @@ -1408,169 +1518,6 @@ print_setting(azName[i]); } }else{ usage("?PROPERTY? ?VALUE?"); } -} - -/* -** SQL function to render a UUID as a hyperlink to a page describing -** that UUID. -*/ -static void hyperlinkUuidFunc( - sqlite3_context *pCxt, /* function context */ - int argc, /* number of arguments to the function */ - sqlite3_value **argv /* values of all function arguments */ -){ - const char *zUuid; /* The UUID to render */ - char *z; /* Rendered HTML text */ - - zUuid = (const char*)sqlite3_value_text(argv[0]); - if( g.okHistory && zUuid && strlen(zUuid)>=10 ){ - z = mprintf("<tt><a href='%s/info/%t'><span style='font-size:1.5em'>" - "%#h</span>%h</a></tt>", - g.zBaseURL, zUuid, 10, zUuid, &zUuid[10]); - sqlite3_result_text(pCxt, z, -1, free); - }else{ - sqlite3_result_text(pCxt, zUuid, -1, SQLITE_TRANSIENT); - } -} - -/* -** SQL function to render a TAGID as a hyperlink to a page describing -** that tag. -*/ -static void hyperlinkTagidFunc( - sqlite3_context *pCxt, /* function context */ - int argc, /* number of arguments to the function */ - sqlite3_value **argv /* values of all function arguments */ -){ - int tagid; /* The tagid to render */ - char *z; /* rendered html text */ - - tagid = sqlite3_value_int(argv[0]); - if( g.okHistory ){ - z = mprintf("<a href='%s/tagview?tagid=%d'>%d</a>", - g.zBaseURL, tagid, tagid); - }else{ - z = mprintf("%d", tagid); - } - sqlite3_result_text(pCxt, z, -1, free); -} - -/* -** SQL function to render a TAGNAME as a hyperlink to a page describing -** that tag. -*/ -static void hyperlinkTagnameFunc( - sqlite3_context *pCxt, /* function context */ - int argc, /* number of arguments to the function */ - sqlite3_value **argv /* values of all function arguments */ -){ - const char *zTag; /* The tag to render */ - char *z; /* rendered html text */ - - zTag = (const char*)sqlite3_value_text(argv[0]); - if( g.okHistory ){ - z = mprintf("<a href='%s/tagview?name=%T&raw=y'>%h</a>", - g.zBaseURL, zTag, zTag); - }else{ - z = mprintf("%h", zTag); - } - sqlite3_result_text(pCxt, z, -1, free); -} - -/* -** SQL function to escape all characters in a string that have special -** meaning to HTML. -*/ -static void htmlizeFunc( - sqlite3_context *pCxt, /* function context */ - int argc, /* number of arguments to the function */ - sqlite3_value **argv /* values of all function arguments */ -){ - const char *zText; /* Text to be htmlized */ - char *z; /* rendered html text */ - - zText = (const char*)sqlite3_value_text(argv[0]); - z = htmlize(zText, -1); - sqlite3_result_text(pCxt, z, -1, free); -} - -/* -** This routine is a helper to run an SQL query and table-ize the -** results. -** -** The zSql parameter should be a single, complete SQL statement. -** Tableized output of the SQL statement is rendered back to the client. -** -** The isSafe flag is true if all query results have been processed -** by routines such as -** -** linkuuid() -** linktagid() -** linktagname() -** htmlize() -** -** and are therefore safe for direct rendering. If isSafe is false, -** then all characters in the query result that have special meaning -** to HTML are escaped. -** -** Returns SQLITE_OK on success and any other value on error. -*/ -int db_generic_query_view(const char *zSql, int isSafe){ - sqlite3_stmt *pStmt; - int rc; - int nCol, i; - int nRow; - const char *zRow; - static int once = 1; - - /* Install the special functions on the first call to this routine */ - if( once ){ - once = 0; - sqlite3_create_function(g.db, "linkuuid", 1, SQLITE_UTF8, 0, - hyperlinkUuidFunc, 0, 0); - sqlite3_create_function(g.db, "linktagid", 1, SQLITE_UTF8, 0, - hyperlinkTagidFunc, 0, 0); - sqlite3_create_function(g.db, "linktagname", 1, SQLITE_UTF8, 0, - hyperlinkTagnameFunc, 0, 0); - sqlite3_create_function(g.db, "htmlize", 1, SQLITE_UTF8, 0, - htmlizeFunc, 0, 0); - } - - /* - ** Use sqlite3_stmt directly rather than going through db_prepare(), - ** so that we can treat errors a non-fatal. - */ - rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0); - if( SQLITE_OK != rc ){ - @ <span style='color:red'>db_generic_query_view() SQL error: - @ %h(sqlite3_errmsg(g.db))</span> - return rc; - } - nCol = sqlite3_column_count(pStmt); - @ <table class='fossil_db_generic_query_view'><tbody> - @ <tr class='header'> - for(i=0; i<nCol; ++i){ - @ <td>%h(sqlite3_column_name(pStmt,i))</td> - } - @ </tr> - - nRow = 0; - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *azClass[] = { "even", "odd" }; - @ <tr class='%s(azClass[(nRow++)&1])'> - for(i=0; i<nCol; i++){ - zRow = (char const*)sqlite3_column_text(pStmt,i); - if( isSafe ){ - @ <td>%s(zRow)</td> - }else{ - @ <td>%h(zRow)</td> - } - } - @ </tr> - } - @ </tbody></table> - sqlite3_finalize(pStmt); - return SQLITE_OK; }
Modified src/descendants.c from [fabaf35b08] to [21679d5ff4].
@@ -31,11 +31,12 @@ /* ** Create a temporary table named "leaves" if it does not ** already exist. Load this table with the RID of all ** check-ins that are leaves which are decended from -** check-in iBase. +** check-in iBase. If iBase==0, find all leaves within the +** entire check-in hierarchy. ** ** A "leaf" is a check-in that has no children in the same branch. ** ** The closeMode flag determines behavior associated with the "closed" ** tag: @@ -49,15 +50,10 @@ ** The default behavior is to ignore closed leaves (closeMode==0). To ** Show all leaves, use closeMode==1. To show only closed leaves, use ** closeMode==2. */ void compute_leaves(int iBase, int closeMode){ - Bag seen; /* Descendants seen */ - Bag pending; /* Unpropagated descendants */ - Stmt q1; /* Query to find children of a check-in */ - Stmt isBr; /* Query to check to see if a check-in starts a new branch */ - Stmt ins; /* INSERT statement for a new record */ /* Create the LEAVES table if it does not already exist. Make sure ** it is empty. */ db_multi_exec( @@ -66,71 +62,98 @@ ");" "DELETE FROM leaves;" ); /* We are checking all descendants of iBase. If iBase==0, then - ** change iBase to be the root of the entire check-in hierarchy. + ** use a short-cut to find all leaves anywhere in the hierarchy. */ if( iBase<=0 ){ - iBase = db_int(0, "SELECT objid FROM event WHERE type='ci'" - " ORDER BY mtime LIMIT 1"); - if( iBase==0 ) return; - } - - /* Initialize the bags. */ - bag_init(&seen); - bag_init(&pending); - bag_insert(&pending, iBase); - - /* This query returns all non-merge children of check-in :rid */ - db_prepare(&q1, "SELECT cid FROM plink WHERE pid=:rid AND isprim"); - - /* This query returns a single row if check-in :rid is the first - ** check-in of a new branch. - */ - db_prepare(&isBr, - "SELECT 1 FROM tagxref" - " WHERE rid=:rid AND tagid=%d AND tagtype=2" - " AND srcid>0", - TAG_BRANCH - ); + db_multi_exec( + "INSERT OR IGNORE INTO leaves" + " SELECT cid FROM plink" + " EXCEPT" + " SELECT pid FROM plink" + " WHERE coalesce((SELECT value FROM tagxref" + " WHERE tagid=%d AND rid=plink.pid),'trunk')" + " == coalesce((SELECT value FROM tagxref" + " WHERE tagid=%d AND rid=plink.cid),'trunk');", + TAG_BRANCH, TAG_BRANCH + ); + }else{ + Bag seen; /* Descendants seen */ + Bag pending; /* Unpropagated descendants */ + Stmt q1; /* Query to find children of a check-in */ + Stmt isBr; /* Query to check to see if a check-in starts a new branch */ + Stmt ins; /* INSERT statement for a new record */ + + /* Initialize the bags. */ + bag_init(&seen); + bag_init(&pending); + bag_insert(&pending, iBase); + + /* This query returns all non-branch-merge children of check-in :rid. + ** + ** If a a child is a merge of a fork within the same branch, it is + ** returned. Only merge children in different branches are excluded. + */ + db_prepare(&q1, + "SELECT cid FROM plink" + " WHERE pid=:rid" + " AND (isprim" + " OR coalesce((SELECT value FROM tagxref" + " WHERE tagid=%d AND rid=plink.pid), 'trunk')" + "=coalesce((SELECT value FROM tagxref" + " WHERE tagid=%d AND rid=plink.cid), 'trunk'))", + TAG_BRANCH, TAG_BRANCH + ); + + /* This query returns a single row if check-in :rid is the first + ** check-in of a new branch. + */ + db_prepare(&isBr, + "SELECT 1 FROM tagxref" + " WHERE rid=:rid AND tagid=%d AND tagtype=2" + " AND srcid>0", + TAG_BRANCH + ); + + /* This statement inserts check-in :rid into the LEAVES table. + */ + db_prepare(&ins, "INSERT OR IGNORE INTO leaves VALUES(:rid)"); - /* This statement inserts check-in :rid into the LEAVES table. - */ - db_prepare(&ins, "INSERT OR IGNORE INTO leaves VALUES(:rid)"); - - while( bag_count(&pending) ){ - int rid = bag_first(&pending); - int cnt = 0; - bag_remove(&pending, rid); - db_bind_int(&q1, ":rid", rid); - while( db_step(&q1)==SQLITE_ROW ){ - int cid = db_column_int(&q1, 0); - if( bag_insert(&seen, cid) ){ - bag_insert(&pending, cid); + while( bag_count(&pending) ){ + int rid = bag_first(&pending); + int cnt = 0; + bag_remove(&pending, rid); + db_bind_int(&q1, ":rid", rid); + while( db_step(&q1)==SQLITE_ROW ){ + int cid = db_column_int(&q1, 0); + if( bag_insert(&seen, cid) ){ + bag_insert(&pending, cid); + } + db_bind_int(&isBr, ":rid", cid); + if( db_step(&isBr)==SQLITE_DONE ){ + cnt++; + } + db_reset(&isBr); } - db_bind_int(&isBr, ":rid", cid); - if( db_step(&isBr)==SQLITE_DONE ){ + db_reset(&q1); + if( cnt==0 && !is_a_leaf(rid) ){ cnt++; } - db_reset(&isBr); - } - db_reset(&q1); - if( cnt==0 && !is_a_leaf(rid) ){ - cnt++; + if( cnt==0 ){ + db_bind_int(&ins, ":rid", rid); + db_step(&ins); + db_reset(&ins); + } } - if( cnt==0 ){ - db_bind_int(&ins, ":rid", rid); - db_step(&ins); - db_reset(&ins); - } - } - db_finalize(&ins); - db_finalize(&isBr); - db_finalize(&q1); - bag_clear(&pending); - bag_clear(&seen); + db_finalize(&ins); + db_finalize(&isBr); + db_finalize(&q1); + bag_clear(&pending); + bag_clear(&seen); + } if( closeMode==1 ){ db_multi_exec( "DELETE FROM leaves WHERE rid IN" " (SELECT leaves.rid FROM leaves, tagxref" " WHERE tagxref.rid=leaves.rid "
Modified src/diff.c from [cebb8ba99c] to [423e7bd7db].
@@ -76,19 +76,19 @@ ** Trailing whitespace is removed from each line. ** ** Return 0 if the file is binary or contains a line that is ** too long. */ -static DLine *break_into_lines(const char *z, int *pnLine){ +static DLine *break_into_lines(const char *z, int n, int *pnLine){ int nLine, i, j, k, x; unsigned int h, h2; DLine *a; /* Count the number of lines. Allocate space to hold ** the returned array. */ - for(i=j=0, nLine=1; z[i]; i++, j++){ + for(i=j=0, nLine=1; i<n; i++, j++){ int c = z[i]; if( c==0 ){ return 0; } if( c=='\n' && z[i+1]!=0 ){ @@ -484,12 +484,12 @@ ){ DContext c; /* Prepare the input files */ memset(&c, 0, sizeof(c)); - c.aFrom = break_into_lines(blob_str(pA_Blob), &c.nFrom); - c.aTo = break_into_lines(blob_str(pB_Blob), &c.nTo); + c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), &c.nFrom); + c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob), &c.nTo); if( c.aFrom==0 || c.aTo==0 ){ free(c.aFrom); free(c.aTo); if( pOut ){ blob_appendf(pOut, "cannot compute difference between binary files\n"); @@ -580,11 +580,11 @@ */ static int annotation_start(Annotator *p, Blob *pInput){ int i; memset(p, 0, sizeof(*p)); - p->c.aTo = break_into_lines(blob_str(pInput), &p->c.nTo); + p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput), &p->c.nTo); if( p->c.aTo==0 ){ return 1; } p->aOrig = malloc( sizeof(p->aOrig[0])*p->c.nTo ); if( p->aOrig==0 ) fossil_panic("out of memory"); @@ -607,11 +607,12 @@ static int annotation_step(Annotator *p, Blob *pParent, char *zPName){ int i, j; int lnTo; /* Prepare the parent file to be diffed */ - p->c.aFrom = break_into_lines(blob_str(pParent), &p->c.nFrom); + p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), + &p->c.nFrom); if( p->c.aFrom==0 ){ return 1; } /* Compute the differences going from pParent to the file being
Modified src/diffcmd.c from [38b20f8775] to [4832395b8a].
@@ -100,11 +100,11 @@ zPathname ); shell_escape(&cmd, zFullName); printf("%s\n", blob_str(&cmd)); fflush(stdout); - system(blob_str(&cmd)); + portable_system(blob_str(&cmd)); } free(zFullName); } db_finalize(&q); } @@ -169,13 +169,15 @@ }else{ zExternalCommand = db_get("gdiff-command", 0); } if( zExternalCommand==0 ){ internalDiff=1; - } - blob_zero(&cmd); - blob_appendf(&cmd, "%s ", zExternalCommand); + }else{ + blob_zero(&cmd); + shell_escape(&cmd, zExternalCommand); + blob_append(&cmd, " ", 1); + } } zFile = g.argv[g.argc-1]; file_tree_name(zFile, &fname, 1); blob_zero(&vname); @@ -208,12 +210,32 @@ blob_write_to_file(&record, blob_str(&vname)); blob_reset(&record); shell_escape(&cmd, blob_str(&vname)); blob_appendf(&cmd, " "); shell_escape(&cmd, zFile); - system(blob_str(&cmd)); + portable_system(blob_str(&cmd)); unlink(blob_str(&vname)); blob_reset(&vname); blob_reset(&cmd); } blob_reset(&fname); +} + +/* +** This function implements a cross-platform "system()" interface. +*/ +int portable_system(char *zOrigCmd){ + int rc; +#ifdef __MINGW32__ + /* On windows, we have to put double-quotes around the entire command. + ** Who knows why - this is just the way windows works. + */ + char *zNewCmd = mprintf("\"%s\"", zOrigCmd); + rc = system(zNewCmd); + free(zNewCmd); +#else + /* On unix, evaluate the command directly. + */ + rc = system(zOrigCmd); +#endif + return rc; }
Modified src/doc.c from [b634a7084a] to [a9193f6c29].
@@ -349,10 +349,13 @@ zName += i; while( zName[0]=='/' ){ zName++; } if( !file_is_simple_pathname(zName) ){ goto doc_not_found; } + if( strcmp(zBaseline,"ckout")==0 && db_open_local()==0 ){ + strcpy(zBaseline,"tip"); + } if( strcmp(zBaseline,"ckout")==0 ){ /* Read from the local checkout */ char *zFullpath; db_must_be_within_tree(); zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); @@ -437,12 +440,18 @@ /* The file is now contained in the filebody blob. Deliver the ** file to the user */ zMime = mimetype_from_name(zName); if( strcmp(zMime, "application/x-fossil-wiki")==0 ){ - style_header("Documentation"); - wiki_convert(&filebody, 0, 0); + Blob title, tail; + if( wiki_find_title(&filebody, &title, &tail) ){ + style_header(blob_str(&title)); + wiki_convert(&tail, 0, 0); + }else{ + style_header("Documentation"); + wiki_convert(&filebody, 0, 0); + } style_footer(); }else if( strcmp(zMime, "text/plain")==0 ){ style_header("Documentation"); @ <blockquote><pre> @ %h(blob_str(&filebody))
Modified src/encode.c from [1fff362c9d] to [ffe3dddccb].
@@ -299,11 +299,11 @@ /* ** The characters used for HTTP base64 encoding. */ static unsigned char zBase[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* ** Encode a string using a base-64 encoding. ** The encoding can be reversed using the <b>decode64</b> function. ** @@ -314,11 +314,11 @@ int i, n; if( nData<=0 ){ nData = strlen(zData); } - z64 = malloc( (nData*4)/3 + 6 ); + z64 = malloc( (nData*4)/3 + 8 ); for(i=n=0; i+2<nData; i+=3){ z64[n++] = zBase[ (zData[i]>>2) & 0x3f ]; z64[n++] = zBase[ ((zData[i]<<4) & 0x30) | ((zData[i+1]>>4) & 0x0f) ]; z64[n++] = zBase[ ((zData[i+1]<<2) & 0x3c) | ((zData[i+2]>>6) & 0x03) ]; z64[n++] = zBase[ zData[i+2] & 0x3f ]; @@ -325,17 +325,35 @@ } if( i+1<nData ){ z64[n++] = zBase[ (zData[i]>>2) & 0x3f ]; z64[n++] = zBase[ ((zData[i]<<4) & 0x30) | ((zData[i+1]>>4) & 0x0f) ]; z64[n++] = zBase[ ((zData[i+1]<<2) & 0x3c) ]; + z64[n++] = '='; }else if( i<nData ){ z64[n++] = zBase[ (zData[i]>>2) & 0x3f ]; z64[n++] = zBase[ ((zData[i]<<4) & 0x30) ]; + z64[n++] = '='; + z64[n++] = '='; } z64[n] = 0; return z64; } + +/* +** COMMAND: test-encode64 +** Usage: %fossil test-encode64 STRING +*/ +void test_encode64_cmd(void){ + char *z; + int i; + for(i=2; i<g.argc; i++){ + z = encode64(g.argv[i], -1); + printf("%s\n", z); + free(z); + } +} + /* ** This function treats its input as a base-64 string and returns the ** decoded value of that string. Characters of input that are not ** valid base-64 characters (such as spaces and newlines) are ignored. @@ -384,10 +402,24 @@ *pnByte = j; return zData; } /* +** COMMAND: test-decode64 +** Usage: %fossil test-decode64 STRING +*/ +void test_decode64_cmd(void){ + char *z; + int i, n; + for(i=2; i<g.argc; i++){ + z = decode64(g.argv[i], &n); + printf("%d: %s\n", n, z); + free(z); + } +} + +/* ** The base-16 encoding using the following characters: ** ** 0123456789abcdef ** */ @@ -423,10 +455,18 @@ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 64, 64, 64, 64, 64, 64, 64, 10, 11, 12, 13, 14, 15, 64, 64, 1, 64, 64, 1, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 10, 11, 12, 13, 14, 15, 64, 64, 1, 64, 64, 1, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, }; /* ** Decode a N-character base-16 number into base-256. N must be a ** multiple of 2. The output buffer must be at least N/2 characters @@ -450,14 +490,15 @@ /* ** Return true if the input string contains only valid base-16 digits. ** If any invalid characters appear in the string, return false. */ int validate16(const char *zIn, int nIn){ - int c, i; - for(i=0; i<nIn && (c = zIn[i])!=0; i++){ - if( c & ~0x7f ) return 0; - if( zDecode[c]>63 ) return 0; + int i; + for(i=0; i<nIn; i++, zIn++){ + if( zDecode[zIn[0]&0xff]>63 ){ + return zIn[0]==0; + } } return 1; } /*
Modified src/file.c from [7217527055] to [146394c81a].
@@ -244,10 +244,11 @@ ** Convert /A/../ to just / */ void file_canonical_name(const char *zOrigName, Blob *pOut){ if( zOrigName[0]=='/' #ifdef __MINGW32__ + || zOrigName[0]=='\\' || (strlen(zOrigName)>3 && zOrigName[1]==':' && (zOrigName[2]=='\\' || zOrigName[2]=='/')) #endif ){ blob_set(pOut, zOrigName);
Modified src/http.c from [15b4647138] to [2787a16cdc].
@@ -51,11 +51,11 @@ blob_zero(pLogin); if( g.urlUser==0 ){ user_select(); db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid); sha1sum_blob(&pw, &sig); - blob_appendf(pLogin, "login %s %b %b\n", g.zLogin, &nonce, &sig); + blob_appendf(pLogin, "login %F %b %b\n", g.zLogin, &nonce, &sig); }else{ if( g.urlPasswd==0 ){ if( strcmp(g.urlUser,"anonymous")!=0 ){ char *zPrompt = mprintf("password for %s: ", g.urlUser); Blob x; @@ -66,11 +66,11 @@ g.urlPasswd = ""; } } blob_append(&pw, g.urlPasswd, -1); sha1sum_blob(&pw, &sig); - blob_appendf(pLogin, "login %s %b %b\n", g.urlUser, &nonce, &sig); + blob_appendf(pLogin, "login %F %b %b\n", g.urlUser, &nonce, &sig); } blob_reset(&nonce); blob_reset(&pw); blob_reset(&sig); } @@ -90,10 +90,13 @@ zSep = ""; }else{ zSep = "/"; } blob_appendf(pHdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep); + if( g.urlProxyAuth ){ + blob_appendf(pHdr, "Proxy-Authorization: %s\n", g.urlProxyAuth); + } blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n"); if( g.fHttpTrace ){ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); }else{
Modified src/http_transport.c from [cbbda92e40] to [a410394220].
@@ -36,22 +36,37 @@ int isOpen; /* True when the transport layer is open */ char *pBuf; /* Buffer used to hold the reply */ int nAlloc; /* Space allocated for transportBuf[] */ int nUsed ; /* Space of transportBuf[] used */ int iCursor; /* Next unread by in transportBuf[] */ + int nSent; /* Number of bytes sent */ + int nRcvd; /* Number of bytes received */ FILE *pFile; /* File I/O for FILE: */ char *zOutFile; /* Name of outbound file for FILE: */ char *zInFile; /* Name of inbound file for FILE: */ } transport = { - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }; /* ** Return the current transport error message. */ const char *transport_errmsg(void){ return socket_errmsg(); +} + +/* +** Retrieve send/receive counts from the transport layer. If "resetFlag" +** is true, then reset the counts. +*/ +void transport_stats(int *pnSent, int *pnRcvd, int resetFlag){ + if( pnSent ) *pnSent = transport.nSent; + if( pnRcvd ) *pnRcvd = transport.nRcvd; + if( resetFlag ){ + transport.nSent = 0; + transport.nRcvd = 0; + } } /* ** Open a connection to the server. The server is defined by the following ** global variables: @@ -120,10 +135,11 @@ ** Send content over the wire. */ void transport_send(Blob *toSend){ char *z = blob_buffer(toSend); int n = blob_size(toSend); + transport.nSent += n; if( g.urlIsHttps ){ /* TBD */ }else if( g.urlIsFile ){ fwrite(z, 1, n, transport.pFile); }else{ @@ -146,11 +162,11 @@ char *zCmd; fclose(transport.pFile); zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1", g.argv[0], g.urlName, transport.zOutFile, transport.zInFile ); - system(zCmd); + portable_system(zCmd); free(zCmd); transport.pFile = fopen(transport.zInFile, "rb"); } } @@ -198,10 +214,11 @@ got = socket_receive(0, zBuf, N); /* printf("received %d of %d bytes\n", got, N); fflush(stdout); */ } if( got>0 ){ nByte += got; + transport.nRcvd += got; } } return nByte; }
Modified src/info.c from [012036faaa] to [bdf1a77d15].
@@ -21,11 +21,11 @@ ** ******************************************************************************* ** ** This file contains code to implement the "info" command. The ** "info" command gives command-line access to information about -** the current tree, or a particular artifact or baseline. +** the current tree, or a particular artifact or check-in. */ #include "config.h" #include "info.h" #include <assert.h> @@ -40,31 +40,45 @@ */ void show_common_info(int rid, const char *zUuidName, int showComment){ Stmt q; char *zComment = 0; char *zTags; - db_prepare(&q, - "SELECT uuid" - " FROM blob WHERE rid=%d", rid - ); - if( db_step(&q)==SQLITE_ROW ){ + char *zDate; + char *zUuid; + zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); + if( zUuid ){ + zDate = db_text("", + "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", + rid + ); /* 01234567890123 */ - printf("%-13s %s\n", zUuidName, db_column_text(&q, 0)); - } - db_finalize(&q); - db_prepare(&q, "SELECT uuid FROM plink JOIN blob ON pid=rid " + printf("%-13s %s %s\n", zUuidName, zUuid, zDate); + free(zUuid); + free(zDate); + } + db_prepare(&q, "SELECT uuid, pid FROM plink JOIN blob ON pid=rid " " WHERE cid=%d", rid); while( db_step(&q)==SQLITE_ROW ){ const char *zUuid = db_column_text(&q, 0); - printf("parent: %s\n", zUuid); - } - db_finalize(&q); - db_prepare(&q, "SELECT uuid FROM plink JOIN blob ON cid=rid " + zDate = db_text("", + "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", + db_column_int(&q, 1) + ); + printf("parent: %s %s\n", zUuid, zDate); + free(zDate); + } + db_finalize(&q); + db_prepare(&q, "SELECT uuid, cid FROM plink JOIN blob ON cid=rid " " WHERE pid=%d", rid); while( db_step(&q)==SQLITE_ROW ){ const char *zUuid = db_column_text(&q, 0); - printf("child: %s\n", zUuid); + zDate = db_text("", + "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", + db_column_int(&q, 1) + ); + printf("child: %s %s\n", zUuid, zDate); + free(zDate); } db_finalize(&q); zTags = db_text(0, "SELECT group_concat(substr(tagname, 5), ', ')" " FROM tagxref, tag" " WHERE tagxref.rid=%d AND tagxref.tagtype>0" @@ -97,23 +111,24 @@ i64 fsize; if( g.argc!=2 && g.argc!=3 ){ usage("?FILENAME|ARTIFACT-ID?"); } if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){ - db_open_config(); + db_open_config(0); db_record_repository_filename(g.argv[2]); db_open_repository(g.argv[2]); - printf("project-code: %s\n", db_get("project-code", "<none>")); printf("project-name: %s\n", db_get("project-name", "<unnamed>")); + printf("project-code: %s\n", db_get("project-code", "<none>")); printf("server-code: %s\n", db_get("server-code", "<none>")); return; } db_must_be_within_tree(); if( g.argc==2 ){ int vid; /* 012345678901234 */ db_record_repository_filename(0); + printf("project-name: %s\n", db_get("project-name", "<unnamed>")); printf("repository: %s\n", db_lget("repository", "")); printf("local-root: %s\n", g.zLocalRoot); printf("project-code: %s\n", db_get("project-code", "")); printf("server-code: %s\n", db_get("server-code", "")); vid = db_lget_int("checkout", 0); @@ -127,143 +142,10 @@ rid = name_to_rid(g.argv[2]); if( rid==0 ){ fossil_panic("no such object: %s\n", g.argv[2]); } show_common_info(rid, "uuid:", 1); - } -} - -/* -** Show information about descendants of a baseline. Do this recursively -** to a depth of N. Return true if descendants are shown and false if not. -*/ -static int showDescendants(int pid, int depth, const char *zTitle){ - Stmt q; - int cnt = 0; - db_prepare(&q, - "SELECT plink.cid, blob.uuid, datetime(plink.mtime, 'localtime')," - " coalesce(event.euser,event.user)," - " coalesce(event.ecomment,event.comment)" - " FROM plink, blob, event" - " WHERE plink.pid=%d" - " AND blob.rid=plink.cid" - " AND event.objid=plink.cid" - " ORDER BY plink.mtime ASC", - pid - ); - while( db_step(&q)==SQLITE_ROW ){ - int n; - int cid = db_column_int(&q, 0); - const char *zUuid = db_column_text(&q, 1); - const char *zDate = db_column_text(&q, 2); - const char *zUser = db_column_text(&q, 3); - const char *zCom = db_column_text(&q, 4); - cnt++; - if( cnt==1 ){ - if( zTitle ){ - @ <div class="section">%s(zTitle)</div> - } - @ <ul> - } - @ <li> - hyperlink_to_uuid(zUuid); - @ %w(zCom) (by %s(zUser) on %s(zDate)) - if( depth ){ - n = showDescendants(cid, depth-1, 0); - }else{ - n = db_int(0, "SELECT 1 FROM plink WHERE pid=%d", cid); - } - if( n==0 ){ - db_multi_exec("DELETE FROM leaves WHERE rid=%d", cid); - @ <b>leaf</b> - } - } - db_finalize(&q); - if( cnt ){ - @ </ul> - } - return cnt; -} - -/* -** Show information about ancestors of a baseline. Do this recursively -** to a depth of N. Return true if ancestors are shown and false if not. -*/ -static void showAncestors(int pid, int depth, const char *zTitle){ - Stmt q; - int cnt = 0; - db_prepare(&q, - "SELECT plink.pid, blob.uuid, datetime(event.mtime, 'localtime')," - " coalesce(event.euser,event.user)," - " coalesce(event.ecomment,event.comment)" - " FROM plink, blob, event" - " WHERE plink.cid=%d" - " AND blob.rid=plink.pid" - " AND event.objid=plink.pid" - " ORDER BY event.mtime DESC", - pid - ); - while( db_step(&q)==SQLITE_ROW ){ - int cid = db_column_int(&q, 0); - const char *zUuid = db_column_text(&q, 1); - const char *zDate = db_column_text(&q, 2); - const char *zUser = db_column_text(&q, 3); - const char *zCom = db_column_text(&q, 4); - cnt++; - if( cnt==1 ){ - if( zTitle ){ - @ <div class="section">%s(zTitle)</div> - } - @ <ul> - } - @ <li> - hyperlink_to_uuid(zUuid); - @ %w(zCom) (by %s(zUser) on %s(zDate)) - if( depth ){ - showAncestors(cid, depth-1, 0); - } - } - db_finalize(&q); - if( cnt ){ - @ </ul> - } -} - - -/* -** Show information about baselines mentioned in the "leaves" table. -*/ -static void showLeaves(int rid){ - Stmt q; - int cnt = 0; - db_prepare(&q, - "SELECT blob.uuid, datetime(event.mtime, 'localtime')," - " coalesce(event.euser, event.user)," - " coalesce(event.ecomment,event.comment)" - " FROM leaves, blob, event" - " WHERE blob.rid=leaves.rid AND blob.rid!=%d" - " AND event.objid=leaves.rid" - " ORDER BY event.mtime DESC", - rid - ); - while( db_step(&q)==SQLITE_ROW ){ - const char *zUuid = db_column_text(&q, 0); - const char *zDate = db_column_text(&q, 1); - const char *zUser = db_column_text(&q, 2); - const char *zCom = db_column_text(&q, 3); - cnt++; - if( cnt==1 ){ - @ <div class="section">Leaves</div> - @ <ul> - } - @ <li> - hyperlink_to_uuid(zUuid); - @ %w(zCom) (by %s(zUser) on %s(zDate)) - } - db_finalize(&q); - if( cnt ){ - @ </ul> } } /* ** Show information about all tags on a given node. @@ -313,11 +195,12 @@ @ by }else{ @ added by } hyperlink_to_uuid(zSrcUuid); - @ on %s(zDate) + @ on + hyperlink_to_date(zDate,0); } } db_finalize(&q); if( cnt ){ @ </ul> @@ -324,15 +207,31 @@ } } /* +** Append the difference between two RIDs to the output +*/ +static void append_diff(int fromid, int toid){ + Blob from, to, out; + content_get(fromid, &from); + content_get(toid, &to); + blob_zero(&out); + text_diff(&from, &to, &out, 5); + @ %h(blob_str(&out)) + blob_reset(&from); + blob_reset(&to); + blob_reset(&out); +} + + +/* ** WEBPAGE: vinfo ** WEBPAGE: ci ** URL: /ci?name=RID|ARTIFACTID ** -** Return information about a baseline +** Display information about a particular check-in. */ void ci_page(void){ Stmt q; int rid; int isLeaf; @@ -358,10 +257,11 @@ const char *zUuid = db_column_text(&q, 0); char *zTitle = mprintf("Check-in [%.10s]", zUuid); char *zEUser, *zEComment; const char *zUser; const char *zComment; + const char *zDate; style_header(zTitle); login_anonymous_available(); free(zTitle); zEUser = db_text(0, "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", @@ -369,22 +269,28 @@ zEComment = db_text(0, "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", TAG_COMMENT, rid); zUser = db_column_text(&q, 2); zComment = db_column_text(&q, 3); + zDate = db_column_text(&q,1); @ <div class="section">Overview</div> @ <p><table class="label-value"> - @ <tr><th>SHA1 Hash:</th><td>%s(zUuid)</td></tr> - @ <tr><th>Date:</th><td>%s(db_column_text(&q, 1))</td></tr> + @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) if( g.okSetup ){ - @ <tr><th>Record ID:</th><td>%d(rid)</td></tr> - } + @ (Record ID: %d(rid)) + } + @ </td></tr> + @ <tr><th>Date:</th><td> + hyperlink_to_date(zDate, "</td></tr>"); if( zEUser ){ - @ <tr><th>Edited User:</td><td>%h(zEUser)</td></tr> - @ <tr><th>Original User:</th><td>%h(zUser)</td></tr> - }else{ - @ <tr><th>User:</td><td>%h(zUser)</td></tr> + @ <tr><th>Edited User:</td><td> + hyperlink_to_user(zEUser,zDate,"</td></tr>"); + @ <tr><th>Original User:</th><td> + hyperlink_to_user(zUser,zDate,"</td></tr>"); + }else{ + @ <tr><th>User:</td><td> + hyperlink_to_user(zUser,zDate,"</td></tr>"); } if( zEComment ){ @ <tr><th>Edited Comment:</th><td>%w(zEComment)</td></tr> @ <tr><th>Original Comment:</th><td>%w(zComment)</td></tr> }else{ @@ -423,14 +329,13 @@ const char *zTagName = db_column_text(&q, 0); @ | <a href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">%h(zTagName)</a> } db_finalize(&q); @ </td></tr> - @ <tr><th>Commands:</th> + @ <tr><th>Other Links:</th> @ <td> - @ <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a> - @ | <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a> + @ <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a> @ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)"> @ ZIP archive</a> @ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a> if( g.okWrite ){ @ | <a href="%s(g.zBaseURL)/ci_edit?r=%d(rid)">edit</a> @@ -444,62 +349,50 @@ style_header("Check-in Information"); login_anonymous_available(); } db_finalize(&q); showTags(rid, ""); - @ <div class="section">File Changes</div> - @ <ul> + @ <div class="section">Changes</div> db_prepare(&q, - "SELECT a.name, b.name" - " FROM mlink, filename AS a, filename AS b" - " WHERE mid=%d" - " AND a.fnid=mlink.fnid" - " AND b.fnid=mlink.pfnid", + "SELECT pid, fid, name, substr(a.uuid,1,10), substr(b.uuid,1,10)" + " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" + " LEFT JOIN blob a ON a.rid=pid" + " LEFT JOIN blob b ON b.rid=fid" + " WHERE mlink.mid=%d" + " ORDER BY name", rid ); while( db_step(&q)==SQLITE_ROW ){ - const char *zName = db_column_text(&q, 0); - const char *zPrior = db_column_text(&q, 1); - @ <li><b>Renamed:</b> - if( g.okHistory ){ - @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zPrior)</a> to - @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></li> - }else{ - @ %h(zPrior) to %h(zName)</li> - } - } - db_finalize(&q); - db_prepare(&q, - "SELECT name, pid, fid " - " FROM mlink, filename" - " WHERE mid=%d" - " AND fid!=pid" - " AND filename.fnid=mlink.fnid", - rid - ); - while( db_step(&q)==SQLITE_ROW ){ - const char *zName = db_column_text(&q, 0); - int pid = db_column_int(&q, 1); - int fid = db_column_int(&q, 2); - if( pid && fid ){ - @ <li><b>Modified:</b> - }else if( fid ){ - @ <li><b>Added:</b> - }else if( pid ){ - @ <li><b>Deleted:</b> - } - if( g.okHistory ){ - @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></li> - }else{ - @ %h(zName)</li> - } - } - @ </ul> - compute_leaves(rid, 0); - showDescendants(rid, 2, "Descendants"); - showLeaves(rid); - showAncestors(rid, 2, "Ancestors"); + int pid = db_column_int(&q,0); + int fid = db_column_int(&q,1); + const char *zName = db_column_text(&q,2); + const char *zOld = db_column_text(&q,3); + const char *zNew = db_column_text(&q,4); + if( !g.okHistory ){ + if( zNew==0 ){ + @ <p>Deleted %h(zName)</p> + continue; + }else{ + @ <p>Changes to %h(zName)</p> + } + }else if( zOld && zNew ){ + @ <p>Modified <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> + @ from <a href="%s(g.zBaseURL)/artifact/%s(zOld)">[%s(zOld)]</a> + @ to <a href="%s(g.zBaseURL)/artifact/%s(zNew)">[%s(zNew)]</a></p> + }else if( zOld ){ + @ <p>Deleted <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> + @ version <a href="%s(g.zBaseURL)/artifact/%s(zOld)">[%s(zOld)]</a></p> + continue; + }else{ + @ <p>Added <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> + @ version <a href="%s(g.zBaseURL)/artifact/%s(zNew)">[%s(zNew)]</a></p> + } + @ <blockquote><pre> + append_diff(pid, fid); + @ </pre></blockquote> + } + db_finalize(&q); style_footer(); } /* ** WEBPAGE: winfo @@ -533,21 +426,25 @@ ); if( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); const char *zUuid = db_column_text(&q, 1); char *zTitle = mprintf("Wiki Page %s", zName); + const char *zDate = db_column_text(&q,2); + const char *zUser = db_column_text(&q,3); style_header(zTitle); free(zTitle); login_anonymous_available(); @ <div class="section">Overview</div> @ <p><table class="label-value"> @ <tr><th>Version:</th><td>%s(zUuid)</td></tr> - @ <tr><th>Date:</th><td>%s(db_column_text(&q, 2))</td></tr> + @ <tr><th>Date:</th><td> + hyperlink_to_date(zDate, "</td></tr>"); if( g.okSetup ){ @ <tr><th>Record ID:</th><td>%d(rid)</td></tr> } - @ <tr><th>Original User:</th><td>%s(db_column_text(&q, 3))</td></tr> + @ <tr><th>Original User:</th><td> + hyperlink_to_user(zUser, zDate, "</td></tr>"); if( g.okHistory ){ @ <tr><th>Commands:</th> @ <td> /* @ <a href="%s(g.zBaseURL)/wdiff/%d(rid)">diff</a> | */ @ <a href="%s(g.zBaseURL)/whistory?name=%t(zName)">history</a> @@ -602,15 +499,16 @@ zFilename = PD("name",""); db_prepare(&q, "SELECT substr(b.uuid,1,10), datetime(event.mtime,'localtime')," " coalesce(event.ecomment, event.comment)," " coalesce(event.euser, event.user)," - " mlink.pid, mlink.fid, mlink.mid, mlink.fnid" - " FROM mlink, blob b, event" + " mlink.pid, mlink.fid, mlink.mid, mlink.fnid, ci.uuid" + " FROM mlink, blob b, event, blob ci" " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" " AND b.rid=mlink.fid" " AND event.objid=mlink.mid" + " AND event.objid=ci.rid" " ORDER BY event.mtime DESC", zFilename ); blob_zero(&title); blob_appendf(&title, "History of "); @@ -625,32 +523,34 @@ const char *zUser = db_column_text(&q, 3); int fpid = db_column_int(&q, 4); int frid = db_column_int(&q, 5); int mid = db_column_int(&q, 6); int fnid = db_column_int(&q, 7); + const char *zCkin = db_column_text(&q,8); char zShort[20]; + char zShortCkin[20]; if( memcmp(zDate, zPrevDate, 10) ){ sprintf(zPrevDate, "%.10s", zDate); @ <tr><td colspan=3> - @ <table cellpadding=2 border=0> - @ <tr><td bgcolor="#a0b5f4" class="border1"> - @ <table cellpadding=2 cellspacing=0 border=0><tr> - @ <td bgcolor="#d0d9f4" class="bkgnd1">%s(zPrevDate)</td> - @ </tr></table> - @ </td></tr></table> + @ <div class="divider">%s(zPrevDate)</div> @ </td></tr> } @ <tr><td valign="top">%s(&zDate[11])</td> @ <td width="20"></td> @ <td valign="top" align="left"> sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); + sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); if( g.okHistory ){ @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%s(zShort)]</a> }else{ @ [%s(zShort)] } - @ %h(zCom) (By: %h(zUser)) + @ part of check-in + hyperlink_to_uuid(zShortCkin); + @ %h(zCom) (By: + hyperlink_to_user(zUser, zDate, " on"); + hyperlink_to_date(zDate, ")"); if( g.okHistory ){ if( fpid ){ @ <a href="%s(g.zBaseURL)/fdiff?v1=%d(fpid)&v2=%d(frid)">[diff]</a> } @ <a href="%s(g.zBaseURL)/annotate?mid=%d(mid)&fnid=%d(fnid)"> @@ -663,25 +563,10 @@ style_footer(); } /* -** Append the difference between two RIDs to the output -*/ -static void append_diff(int fromid, int toid){ - Blob from, to, out; - content_get(fromid, &from); - content_get(toid, &to); - blob_zero(&out); - text_diff(&from, &to, &out, 5); - @ %h(blob_str(&out)) - blob_reset(&from); - blob_reset(&to); - blob_reset(&out); -} - -/* ** WEBPAGE: vdiff ** URL: /vdiff?name=RID ** ** Show all differences for a particular check-in. */ @@ -690,51 +575,73 @@ Stmt q; char *zUuid; login_check_credentials(); if( !g.okRead ){ login_needed(); return; } - style_header("Check-in Changes"); login_anonymous_available(); rid = name_to_rid(PD("name","")); if( rid==0 ){ fossil_redirect_home(); } + zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); + style_header("Check-in [%.10s]", zUuid); + db_prepare(&q, + "SELECT datetime(mtime), " + " coalesce(event.ecomment,event.comment)," + " coalesce(event.euser,event.user)" + " FROM event WHERE type='ci' AND objid=%d", + rid + ); + while( db_step(&q)==SQLITE_ROW ){ + const char *zDate = db_column_text(&q, 0); + const char *zUser = db_column_text(&q, 2); + const char *zComment = db_column_text(&q, 1); + @ <h2>Check-in %s(zUuid)</h2> + @ <p>Made by + hyperlink_to_user(zUser,zDate," on"); + hyperlink_to_date(zDate, ":"); + @ %w(zComment). + if( g.okHistory ){ + @ <a href="%s(g.zBaseURL)/ci/%s(zUuid)">[details]</a> + } + @ </p><hr> + } + db_finalize(&q); db_prepare(&q, "SELECT pid, fid, name" " FROM mlink, filename" " WHERE mlink.mid=%d" " AND filename.fnid=mlink.fnid" " ORDER BY name", rid ); - zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); - @ <h2>All Changes In Check-in - hyperlink_to_uuid(zUuid); - @ </h2> while( db_step(&q)==SQLITE_ROW ){ int pid = db_column_int(&q,0); int fid = db_column_int(&q,1); const char *zName = db_column_text(&q,2); - @ <p><a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></p> + if( g.okHistory ){ + @ <p><a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></p> + }else{ + @ <p>%h(zName)</p> + } @ <blockquote><pre> append_diff(pid, fid); @ </pre></blockquote> } db_finalize(&q); style_footer(); } - /* ** Write a description of an object to the www reply. ** ** If the object is a file then mention: ** ** * It's artifact ID ** * All its filenames -** * The baselines it was checked-in on, with times and users +** * The check-in it was part of, with times and users ** ** If the object is a manifest, then mention: ** ** * It's artifact ID ** * date of check-in @@ -747,11 +654,11 @@ ){ Stmt q; int cnt = 0; int nWiki = 0; db_prepare(&q, - "SELECT filename.name, datetime(event.mtime), substr(a.uuid,1,10)," + "SELECT filename.name, datetime(event.mtime)," " coalesce(event.ecomment,event.comment)," " coalesce(event.euser,event.user)," " b.uuid" " FROM mlink, filename, event, blob a, blob b" " WHERE filename.fnid=mlink.fnid" @@ -762,104 +669,116 @@ rid ); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); const char *zDate = db_column_text(&q, 1); - const char *zFuuid = db_column_text(&q, 2); - const char *zCom = db_column_text(&q, 3); - const char *zUser = db_column_text(&q, 4); - const char *zVers = db_column_text(&q, 5); + const char *zCom = db_column_text(&q, 2); + const char *zUser = db_column_text(&q, 3); + const char *zVers = db_column_text(&q, 4); if( cnt>0 ){ @ Also file }else{ @ File } - @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> - @ artifact %s(zFuuid) part of check-in + if( g.okHistory ){ + @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> + }else{ + @ %h(zName) + } + @ part of check-in hyperlink_to_uuid(zVers); - @ - %w(zCom) by %h(zUser) on %s(zDate). + @ - %w(zCom) by + hyperlink_to_user(zUser,zDate," on"); + hyperlink_to_date(zDate,"."); cnt++; if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_append(pDownloadName, zName, -1); } } db_finalize(&q); db_prepare(&q, "SELECT substr(tagname, 6, 10000), datetime(event.mtime)," - " coalesce(event.euser, event.user), uuid" - " FROM tagxref, tag, event, blob" + " coalesce(event.euser, event.user)" + " FROM tagxref, tag, event" " WHERE tagxref.rid=%d" " AND tag.tagid=tagxref.tagid" " AND tag.tagname LIKE 'wiki-%%'" - " AND event.objid=tagxref.rid" - " AND blob.rid=tagxref.rid", + " AND event.objid=tagxref.rid", rid ); while( db_step(&q)==SQLITE_ROW ){ const char *zPagename = db_column_text(&q, 0); const char *zDate = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); - const char *zUuid = db_column_text(&q, 3); if( cnt>0 ){ @ Also wiki page }else{ @ Wiki page } - @ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>] - @ artifact %s(zUuid) by %h(zUser) on %s(zDate). + if( g.okHistory ){ + @ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>] + }else{ + @ [%h(zPagename)] + } + @ by + hyperlink_to_user(zUser,zDate," on"); + hyperlink_to_date(zDate,"."); nWiki++; cnt++; if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_append(pDownloadName, zPagename, -1); } } db_finalize(&q); if( nWiki==0 ){ db_prepare(&q, - "SELECT datetime(mtime), user, comment, uuid, type" + "SELECT datetime(mtime), user, comment, type, uuid" " FROM event, blob" " WHERE event.objid=%d" " AND blob.rid=%d", rid, rid ); while( db_step(&q)==SQLITE_ROW ){ const char *zDate = db_column_text(&q, 0); - const char *zUuid = db_column_text(&q, 3); const char *zUser = db_column_text(&q, 1); const char *zCom = db_column_text(&q, 2); - const char *zType = db_column_text(&q, 4); + const char *zType = db_column_text(&q, 3); + const char *zUuid = db_column_text(&q, 4); if( cnt>0 ){ @ Also } if( zType[0]=='w' ){ @ Wiki edit }else if( zType[0]=='t' ){ @ Ticket change }else if( zType[0]=='c' ){ - @ Manifest of baseline + @ Manifest of check-in }else{ @ Control file referencing } hyperlink_to_uuid(zUuid); - @ - %w(zCom) by %h(zUser) on %s(zDate). + @ - %w(zCom) by + hyperlink_to_user(zUser,zDate," on"); + hyperlink_to_date(zDate, "."); if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_append(pDownloadName, zUuid, -1); } cnt++; } db_finalize(&q); } if( cnt==0 ){ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); - @ Control file %s(zUuid). + @ Control artifact. if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_append(pDownloadName, zUuid, -1); } - }else if( linkToView ){ + }else if( linkToView && g.okHistory ){ @ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a> } } + /* ** WEBPAGE: fdiff ** ** Two arguments, v1 and v2, are integers. Show the difference between @@ -977,10 +896,11 @@ */ void hexdump_page(void){ int rid; Blob content; Blob downloadName; + char *zUuid; rid = name_to_rid(PD("name","0")); login_check_credentials(); if( !g.okRead ){ login_needed(); return; } if( rid==0 ){ cgi_redirect("/home"); } @@ -993,11 +913,12 @@ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } style_header("Hex Artifact Content"); - @ <h2>Hexadecimal Content Of:</h2> + zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); + @ <h2>Artifact %s(zUuid):</h2> @ <blockquote> blob_zero(&downloadName); object_description(rid, 0, &downloadName); style_submenu_element("Download", "Download", "%s/raw/%T?name=%d", g.zBaseURL, blob_str(&downloadName), rid); @@ -1022,10 +943,11 @@ Blob content; const char *zMime; Blob downloadName; int renderAsWiki = 0; int renderAsHtml = 0; + const char *zUuid; rid = name_to_rid(PD("name","0")); login_check_credentials(); if( !g.okRead ){ login_needed(); return; } if( rid==0 ){ cgi_redirect("/home"); } @@ -1038,11 +960,12 @@ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } style_header("Artifact Content"); - @ <h2>Content Of:</h2> + zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); + @ <h2>Artifact %s(zUuid)</h2> @ <blockquote> blob_zero(&downloadName); object_description(rid, 0, &downloadName); style_submenu_element("Download", "Download", "%s/raw/%T?name=%d", g.zTop, blob_str(&downloadName), rid); @@ -1135,16 +1058,23 @@ } style_header("Ticket Change Details"); zDate = db_text(0, "SELECT datetime(%.12f)", m.rDate); memcpy(zTktName, m.zTicketUuid, 10); zTktName[10] = 0; - @ <h2>Changes to ticket <a href="%s(m.zTicketUuid)">%s(zTktName)</a></h2> - @ - @ <p>By %h(m.zUser) on %s(zDate). See also: - @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and - @ <a href="%s(g.zTop)/tkthistory/%s(m.zTicketUuid)">ticket history</a> - @ </p> + if( g.okHistory ){ + @ <h2>Changes to ticket <a href="%s(m.zTicketUuid)">%s(zTktName)</a></h2> + @ + @ <p>By %h(m.zUser) on %s(zDate). See also: + @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and + @ <a href="%s(g.zTop)/tkthistory/%s(m.zTicketUuid)">ticket history</a> + @ </p> + }else{ + @ <h2>Changes to ticket %s(zTktName)</h2> + @ + @ <p>By %h(m.zUser) on %s(zDate). + @ </p> + } @ @ <ol> free(zDate); ticket_output_change_artifact(&m); manifest_clear(&m); @@ -1230,14 +1160,16 @@ ** * The check-in comment ** * The background color. */ void ci_edit_page(void){ int rid; - const char *zComment; - const char *zNewComment; - const char *zUser; - const char *zNewUser; + const char *zComment; /* Current comment on the check-in */ + const char *zNewComment; /* Revised check-in comment */ + const char *zUser; /* Current user for the check-in */ + const char *zNewUser; /* Revised user */ + const char *zDate; /* Current date of the check-in */ + const char *zNewDate; /* Revised check-in date */ const char *zColor; const char *zNewColor; const char *zNewTagFlag; const char *zNewTag; const char *zNewBrFlag; @@ -1280,10 +1212,14 @@ zNewComment = PD("c",zComment); zUser = db_text(0, "SELECT coalesce(euser,user)" " FROM event WHERE objid=%d", rid); if( zUser==0 ) fossil_redirect_home(); zNewUser = PD("u",zUser); + zDate = db_text(0, "SELECT datetime(mtime)" + " FROM event WHERE objid=%d", rid); + if( zDate==0 ) fossil_redirect_home(); + zNewDate = PD("dt",zDate); zColor = db_text("", "SELECT bgcolor" " FROM event WHERE objid=%d", rid); zNewColor = PD("clr",zColor); fPropagateColor = P("pclr")!=0; zNewTagFlag = P("newtag") ? " checked" : ""; @@ -1314,10 +1250,14 @@ db_multi_exec("REPLACE INTO newtags VALUES('bgcolor','-',NULL)"); } if( strcmp(zComment,zNewComment)!=0 ){ db_multi_exec("REPLACE INTO newtags VALUES('comment','+',%Q)", zNewComment); + } + if( strcmp(zDate,zNewDate)!=0 ){ + db_multi_exec("REPLACE INTO newtags VALUES('date','+',%Q)", + zNewDate); } if( strcmp(zUser,zNewUser)!=0 ){ db_multi_exec("REPLACE INTO newtags VALUES('user','+',%Q)", zNewUser); } db_prepare(&q, @@ -1373,10 +1313,11 @@ Blob cksum; blob_appendf(&ctrl, "U %F\n", g.zLogin); md5sum_blob(&ctrl, &cksum); blob_appendf(&ctrl, "Z %b\n", &cksum); db_begin_transaction(); + g.markPrivate = content_is_private(rid); nrid = content_put(&ctrl, 0, 0); manifest_crosslink(nrid, &ctrl); db_end_transaction(0); } cgi_redirectf("ci?name=%d", rid); @@ -1433,10 +1374,15 @@ @ </td></tr> @ <tr><td align="right" valign="top"><b>Comment:</b></td> @ <td valign="top"> @ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea> + @ </td></tr> + + @ <tr><td align="right" valign="top"><b>Check-in Time:</b></td> + @ <td valign="top"> + @ <input type="text" name="dt" size="20" value="%h(zNewDate)"> @ </td></tr> @ <tr><td align="right" valign="top"><b>Background Color:</b></td> @ <td valign="top"> @ <table border=0 cellpadding=0 cellspacing=1>
Modified src/login.c from [f3badebb6b] to [24e3ed3b13].
@@ -79,21 +79,52 @@ fossil_redirect_home(); } } /* -** WEBPAGE: /login -** WEBPAGE: /logout +** Check to see if the anonymous login is valid. If it is valid, return +** the userid of the anonymous user. +*/ +static int isValidAnonymousLogin( + const char *zUsername, /* The username. Must be "anonymous" */ + const char *zPassword /* The supplied password */ +){ + const char *zCS; /* The captcha seed value */ + const char *zPw; /* The correct password shown in the captcha */ + int uid; /* The user ID of anonymous */ + + if( zUsername==0 ) return 0; + if( zPassword==0 ) return 0; + if( strcmp(zUsername,"anonymous")!=0 ) return 0; + zCS = P("cs"); /* The "cs" parameter is the "captcha seed" */ + if( zCS==0 ) return 0; + zPw = captcha_decode((unsigned int)atoi(zCS)); + if( strcasecmp(zPw, zPassword)!=0 ) return 0; + uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'" + " AND length(pw)>0 AND length(cap)>0"); + return uid; +} + +/* +** WEBPAGE: login +** WEBPAGE: logout +** WEBPAGE: my +** +** Generate the login page. ** -** Generate the login page +** There used to be a page named "my" that was designed to show information +** about a specific user. The "my" page was linked from the "Logged in as USER" +** line on the title bar. The "my" page was never completed so it is now +** removed. Use this page as a placeholder in older installations. */ void login_page(void){ const char *zUsername, *zPasswd; const char *zNew1, *zNew2; const char *zAnonPw = 0; int anonFlag; char *zErrMsg = ""; + int uid; /* User id loged in user */ login_check_credentials(); zUsername = P("u"); zPasswd = P("p"); anonFlag = P("anon")!=0; @@ -125,15 +156,39 @@ ); redirect_to_g(); return; } } + uid = isValidAnonymousLogin(zUsername, zPasswd); + if( uid>0 ){ + char *zNow; /* Current time (julian day number) */ + const char *zIpAddr; /* IP address of requestor */ + char *zCookie; /* The login cookie */ + const char *zCookieName; /* Name of the login cookie */ + Blob b; /* Blob used during cookie construction */ + + zIpAddr = PD("REMOTE_ADDR","nil"); + zCookieName = login_cookie_name(); + zNow = db_text("0", "SELECT julianday('now')"); + blob_init(&b, zNow, -1); + blob_appendf(&b, "/%s/%s", zIpAddr, db_get("captcha-secret","")); + sha1sum_blob(&b, &b); + zCookie = sqlite3_mprintf("anon/%s/%s", zNow, blob_buffer(&b)); + blob_reset(&b); + free(zNow); + cgi_set_cookie(zCookieName, zCookie, 0, 6*3600); + redirect_to_g(); + } if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ - int uid = db_int(0, + uid = db_int(0, "SELECT uid FROM user" - " WHERE login=%Q AND pw=%Q", zUsername, zPasswd); - if( uid<=0 || strcmp(zUsername,"nobody")==0 ){ + " WHERE login=%Q" + " AND login NOT IN ('anonymous','nobody','developer','reader')" + " AND pw=%Q", + zUsername, zPasswd + ); + if( uid<=0 ){ sleep(1); zErrMsg = @ <p><font color="red"> @ You entered an unknown user or an incorrect password. @ </font></p> @@ -143,21 +198,17 @@ const char *zCookieName = login_cookie_name(); const char *zExpire = db_get("cookie-expire","8766"); int expires = atoi(zExpire)*3600; const char *zIpAddr = PD("REMOTE_ADDR","nil"); - if( strcmp(zUsername, "anonymous")==0 ){ - cgi_set_cookie(zCookieName, "anonymous", 0, expires); - }else{ - zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); - cgi_set_cookie(zCookieName, zCookie, 0, expires); - db_multi_exec( - "UPDATE user SET cookie=%Q, ipaddr=%Q, " - " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", - zCookie, zIpAddr, expires, uid - ); - } + zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); + cgi_set_cookie(zCookieName, zCookie, 0, expires); + db_multi_exec( + "UPDATE user SET cookie=%Q, ipaddr=%Q, " + " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", + zCookie, zIpAddr, expires, uid + ); redirect_to_g(); } } style_header("Login/Logout"); @ %s(zErrMsg) @@ -180,38 +231,37 @@ @ </tr> if( g.zLogin==0 ){ zAnonPw = db_text(0, "SELECT pw FROM user" " WHERE login='anonymous'" " AND cap!=''"); - if( zAnonPw && anonFlag ){ - @ <tr><td></td> - @ <td>The anonymous password is "<b>%h(zAnonPw)</b>".</td> - @ </tr> - } } @ <tr> @ <td></td> @ <td><input type="submit" name="in" value="Login"></td> @ </tr> @ </table> if( g.zLogin==0 ){ - @ <p>To login + @ <p>Enter }else{ @ <p>You are currently logged in as <b>%h(g.zLogin)</b></p> - @ <p>To change your login to a different user - } - @ enter the user-id and password at the left and press the + @ <p>To change your login to a different user, enter + } + @ your user-id and password at the left and press the @ "Login" button. Your user name will be stored in a browser cookie. @ You must configure your web browser to accept cookies in order for @ the login to take.</p> - if( g.zLogin==0 ){ - if( zAnonPw && !anonFlag ){ - @ <p>The password for user "anonymous" is "<b>%h(zAnonPw)</b>".</p> - @ <p> </p> - }else{ - @ <p> </p><p> </p> - } + if( zAnonPw ){ + unsigned int uSeed = captcha_seed(); + char *zCaptcha = captcha_render(captcha_decode(uSeed)); + + @ <input type="hidden" name="cs" value="%u(uSeed)"> + @ <p>Visitors may enter <b>anonymous</b> as the user-ID with + @ the 8-character hexadecimal password shown below:</p> + @ <center><table border="1" cellpadding="10"><tr><td><pre> + @ %s(zCaptcha) + @ </pre></td></tr></table></center> + free(zCaptcha); } if( g.zLogin ){ @ <br clear="both"><hr> @ <p>To log off the system (and delete your login cookie) @ press the following button:<br> @@ -250,12 +300,10 @@ void login_check_credentials(void){ int uid = 0; /* User id */ const char *zCookie; /* Text of the login cookie */ const char *zRemoteAddr; /* IP address of the requestor */ const char *zCap = 0; /* Capability string */ - const char *zNcap; /* Capabilities of user "nobody" */ - const char *zAcap; /* Capabllities of user "anonymous" */ /* Only run this check once. */ if( g.userUid!=0 ) return; @@ -278,61 +326,107 @@ /* Check the login cookie to see if it matches a known valid user. */ if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){ if( isdigit(zCookie[0]) ){ + /* Cookies of the form "uid/randomness". There must be a + ** corresponding entry in the user table. */ uid = db_int(0, "SELECT uid FROM user" " WHERE uid=%d" " AND cookie=%Q" " AND ipaddr=%Q" " AND cexpire>julianday('now')", atoi(zCookie), zCookie, zRemoteAddr ); - }else if( zCookie[0]=='a' ){ - uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'"); + }else if( memcmp(zCookie,"anon/",5)==0 ){ + /* Cookies of the form "anon/TIME/HASH". The TIME must not be + ** too old and the sha1 hash of TIME+IPADDR+SECRET must match HASH. + ** SECRET is the "captcha-secret" value in the repository. + */ + double rTime; + int i; + Blob b; + rTime = atof(&zCookie[5]); + for(i=5; zCookie[i] && zCookie[i]!='/'; i++){} + blob_init(&b, &zCookie[5], i-5); + if( zCookie[i]=='/' ){ i++; } + blob_append(&b, "/", 1); + blob_appendf(&b, "%s/%s", zRemoteAddr, db_get("captcha-secret","")); + sha1sum_blob(&b, &b); + uid = db_int(0, + "SELECT uid FROM user WHERE login='anonymous'" + " AND length(cap)>0" + " AND length(pw)>0" + " AND %f+0.25>julianday('now')" + " AND %Q=%Q", + rTime, &zCookie[i], blob_buffer(&b) + ); + blob_reset(&b); } sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zCookie); } + /* If no user found yet, try to log in as "nobody" */ if( uid==0 ){ uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); if( uid==0 ){ + /* If there is no user "nobody", then make one up - with no privileges */ uid = -1; zCap = ""; } strcpy(g.zCsrfToken, "none"); } + + /* At this point, we know that uid!=0. Find the privileges associated + ** with user uid. + */ + assert( uid!=0 ); if( zCap==0 ){ - if( uid ){ - Stmt s; - db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid); - if( db_step(&s)==SQLITE_ROW ){ - g.zLogin = db_column_malloc(&s, 0); - zCap = db_column_malloc(&s, 1); - } - db_finalize(&s); + Stmt s; + db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid); + if( db_step(&s)==SQLITE_ROW ){ + g.zLogin = db_column_malloc(&s, 0); + zCap = db_column_malloc(&s, 1); } + db_finalize(&s); if( zCap==0 ){ zCap = ""; } } + + /* Set the global variables recording the userid and login. The + ** "nobody" user is a special case in that g.zLogin==0. + */ g.userUid = uid; if( g.zLogin && strcmp(g.zLogin,"nobody")==0 ){ g.zLogin = 0; } - if( uid && g.zLogin ){ + + /* Set the capabilities */ + login_set_capabilities(zCap); + login_set_anon_nobody_capabilities(); +} + +/* +** Add the default privileges of users "nobody" and "anonymous" as appropriate +** for the user g.zLogin. +*/ +void login_set_anon_nobody_capabilities(void){ + static int once = 1; + if( g.zLogin && once ){ + const char *zCap; /* All logged-in users inherit privileges from "nobody" */ - zNcap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'"); - login_set_capabilities(zNcap); + zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'"); + login_set_capabilities(zCap); if( strcmp(g.zLogin, "anonymous")!=0 ){ /* All logged-in users inherit privileges from "anonymous" */ - zAcap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'"); - login_set_capabilities(zAcap); + zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'"); + login_set_capabilities(zCap); } - } - login_set_capabilities(zCap); + once = 0; + } } /* ** Set the global capability flags based on a capability string. */ @@ -474,12 +568,12 @@ } /* ** Before using the results of a form, first call this routine to verify ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token -** is missing or is incorrect, then this emits and error message and never -** returns. +** is missing or is incorrect, that indicates a cross-site scripting attach +** so emits an error message and abort. */ void login_verify_csrf_secret(void){ const char *zCsrf; /* The CSRF secret */ if( g.okCsrf ) return; if( (zCsrf = P("csrf"))!=0 && strcmp(zCsrf, g.zCsrfToken)==0 ){
Modified src/main.c from [828c799fea] to [e990b4f28d].
@@ -27,10 +27,13 @@ #include "config.h" #include "main.h" #include <string.h> #include <time.h> #include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + #if INTERFACE /* ** Number of elements in an array @@ -52,10 +55,12 @@ */ struct Global { int argc; char **argv; /* Command-line arguments to the program */ int isConst; /* True if the output is unchanging */ sqlite3 *db; /* The connection to the databases */ + sqlite3 *dbConfig; /* Separate connection for global_config table */ + int useAttach; /* True if global_config is attached to repository */ int configOpen; /* True if the config database is open */ long long int now; /* Seconds since 1970 */ int repositoryOpen; /* True if the main repository database is open */ char *zRepositoryName; /* Name of the repository database */ int localOpen; /* True if the local database is open */ @@ -79,12 +84,12 @@ Th_Interp *interp; /* The TH1 interpreter */ FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ - int *aCommitFile; /* Array of files to be committed */ + int markPrivate; /* All new artifacts are private if true */ int urlIsFile; /* True if a "file:" url */ int urlIsHttps; /* True if a "https:" url */ char *urlName; /* Hostname for http: or filename for file: */ char *urlHostname; /* The HOST: parameter on http headers */ @@ -93,10 +98,11 @@ int urlDfltPort; /* The default port for the given protocol */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ + char *urlProxyAuth; /* Proxy-Authorizer: string */ const char *zLogin; /* Login name. "" if not logged in. */ int noPswd; /* Logged in without password (on 127.0.0.1) */ int userUid; /* Integer user id */ @@ -623,10 +629,15 @@ /* Set binary mode on windows to avoid undesired translations ** between \n and \r\n. */ setmode(_fileno(g.httpOut), _O_BINARY); setmode(_fileno(g.httpIn), _O_BINARY); #endif +#ifdef __EMX__ + /* Similar hack for OS/2 */ + setmode(fileno(g.httpOut), O_BINARY); + setmode(fileno(g.httpIn), O_BINARY); +#endif g.cgiPanic = 1; blob_read_from_file(&config, zFile); while( blob_line(&config, &line) ){ if( !blob_token(&line, &key) ) continue; if( blob_buffer(&key)[0]=='#' ) continue; @@ -673,10 +684,29 @@ void cmd_http(void){ const char *zIpAddr; if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){ cgi_panic("no repository specified"); } +#if !defined(__MINGW32__) + if( g.argc==3 && getuid()==0 ){ + int i; + char *zRepo = g.argv[2]; + struct stat sStat; + for(i=strlen(zRepo)-1; i>0 && zRepo[i]!='/'; i--){} + if( zRepo[i]=='/' ){ + zRepo[i] = 0; + chdir(g.argv[2]); + chroot(g.argv[2]); + g.argv[2] = &zRepo[i+1]; + } + if( stat(g.argv[2], &sStat)!=0 ){ + fossil_fatal("cannot stat() repository: %s", g.argv[2]); + } + setgid(sStat.st_gid); + setuid(sStat.st_uid); + } +#endif g.cgiPanic = 1; g.fullHttpReply = 1; if( g.argc==6 ){ g.httpIn = fopen(g.argv[3], "rb"); g.httpOut = fopen(g.argv[4], "wb"); @@ -701,10 +731,34 @@ */ void cmd_test_http(void){ login_set_capabilities("s"); cmd_http(); } + + +#if !defined(__DARWIN__) && !defined(__APPLE__) +/* +** Search for an executable on the PATH environment variable. +** Return true (1) if found and false (0) if not found. +*/ +static int binaryOnPath(const char *zBinary){ + const char *zPath = getenv("PATH"); + char *zFull; + int i; + int bExists; + while( zPath && zPath[0] ){ + while( zPath[0]==':' ) zPath++; + for(i=0; zPath[i] && zPath[i]!=':'; i++){} + zFull = mprintf("%.*s/%s", i, zPath, zBinary); + bExists = access(zFull, X_OK); + free(zFull); + if( bExists==0 ) return 1; + zPath += i; + } + return 0; +} +#endif /* ** COMMAND: server ** COMMAND: ui ** @@ -745,11 +799,22 @@ } #ifndef __MINGW32__ /* Unix implementation */ if( g.argv[1][0]=='u' ){ #if !defined(__DARWIN__) && !defined(__APPLE__) - zBrowser = db_get("web-browser", "firefox"); + zBrowser = db_get("web-browser", 0); + if( zBrowser==0 ){ + static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" }; + int i; + zBrowser = "echo"; + for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){ + if( binaryOnPath(azBrowserProg[i]) ){ + zBrowser = azBrowserProg[i]; + break; + } + } + } #else zBrowser = db_get("web-browser", "open"); #endif zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser); }
Modified src/main.mk from [6c3a053810] to [e1989b9164].
@@ -12,16 +12,16 @@ XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR) SRC = \ $(SRCDIR)/add.c \ - $(SRCDIR)/admin.c \ $(SRCDIR)/allrepo.c \ $(SRCDIR)/bag.c \ $(SRCDIR)/blob.c \ $(SRCDIR)/branch.c \ $(SRCDIR)/browse.c \ + $(SRCDIR)/captcha.c \ $(SRCDIR)/cgi.c \ $(SRCDIR)/checkin.c \ $(SRCDIR)/checkout.c \ $(SRCDIR)/clearsign.c \ $(SRCDIR)/clone.c \ @@ -47,11 +47,10 @@ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ - $(SRCDIR)/my_page.c \ $(SRCDIR)/name.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/rebuild.c \ @@ -64,11 +63,10 @@ $(SRCDIR)/shun.c \ $(SRCDIR)/stat.c \ $(SRCDIR)/style.c \ $(SRCDIR)/sync.c \ $(SRCDIR)/tag.c \ - $(SRCDIR)/tagview.c \ $(SRCDIR)/th_main.c \ $(SRCDIR)/timeline.c \ $(SRCDIR)/tkt.c \ $(SRCDIR)/tktsetup.c \ $(SRCDIR)/undo.c \ @@ -83,16 +81,16 @@ $(SRCDIR)/xfer.c \ $(SRCDIR)/zip.c TRANS_SRC = \ add_.c \ - admin_.c \ allrepo_.c \ bag_.c \ blob_.c \ branch_.c \ browse_.c \ + captcha_.c \ cgi_.c \ checkin_.c \ checkout_.c \ clearsign_.c \ clone_.c \ @@ -118,11 +116,10 @@ main_.c \ manifest_.c \ md5_.c \ merge_.c \ merge3_.c \ - my_page_.c \ name_.c \ pivot_.c \ pqueue_.c \ printf_.c \ rebuild_.c \ @@ -135,11 +132,10 @@ shun_.c \ stat_.c \ style_.c \ sync_.c \ tag_.c \ - tagview_.c \ th_main_.c \ timeline_.c \ tkt_.c \ tktsetup_.c \ undo_.c \ @@ -154,16 +150,16 @@ xfer_.c \ zip_.c OBJ = \ add.o \ - admin.o \ allrepo.o \ bag.o \ blob.o \ branch.o \ browse.o \ + captcha.o \ cgi.o \ checkin.o \ checkout.o \ clearsign.o \ clone.o \ @@ -189,11 +185,10 @@ main.o \ manifest.o \ md5.o \ merge.o \ merge3.o \ - my_page.o \ name.o \ pivot.o \ pqueue.o \ printf.o \ rebuild.o \ @@ -206,11 +201,10 @@ shun.o \ stat.o \ style.o \ sync.o \ tag.o \ - tagview.o \ th_main.o \ timeline.o \ tkt.o \ tktsetup.o \ undo.o \ @@ -264,506 +258,492 @@ # noop clean: rm -f *.o *_.c $(APPNAME) VERSION.h rm -f translate makeheaders mkindex page_index.h headers - rm -f add.h admin.h allrepo.h bag.h blob.h branch.h browse.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h creoleparser.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h my_page.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h tagview.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h + rm -f add.h allrepo.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h creoleparser.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h page_index.h: $(TRANS_SRC) mkindex ./mkindex $(TRANS_SRC) >$@ headers: page_index.h makeheaders VERSION.h - ./makeheaders add_.c:add.h admin_.c:admin.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h creoleparser_.c:creoleparser.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h my_page_.c:my_page.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tagview_.c:tagview.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h + ./makeheaders add_.c:add.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h creoleparser_.c:creoleparser.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h touch headers headers: Makefile Makefile: -add_.c: $(SRCDIR)/add.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/add.c | sed -f $(SRCDIR)/VERSION >add_.c +add_.c: $(SRCDIR)/add.c translate + ./translate $(SRCDIR)/add.c >add_.c add.o: add_.c add.h $(SRCDIR)/config.h $(XTCC) -o add.o -c add_.c add.h: headers -admin_.c: $(SRCDIR)/admin.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/admin.c | sed -f $(SRCDIR)/VERSION >admin_.c - -admin.o: admin_.c admin.h $(SRCDIR)/config.h - $(XTCC) -o admin.o -c admin_.c - -admin.h: headers -allrepo_.c: $(SRCDIR)/allrepo.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/allrepo.c | sed -f $(SRCDIR)/VERSION >allrepo_.c +allrepo_.c: $(SRCDIR)/allrepo.c translate + ./translate $(SRCDIR)/allrepo.c >allrepo_.c allrepo.o: allrepo_.c allrepo.h $(SRCDIR)/config.h $(XTCC) -o allrepo.o -c allrepo_.c allrepo.h: headers -bag_.c: $(SRCDIR)/bag.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/bag.c | sed -f $(SRCDIR)/VERSION >bag_.c +bag_.c: $(SRCDIR)/bag.c translate + ./translate $(SRCDIR)/bag.c >bag_.c bag.o: bag_.c bag.h $(SRCDIR)/config.h $(XTCC) -o bag.o -c bag_.c bag.h: headers -blob_.c: $(SRCDIR)/blob.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/blob.c | sed -f $(SRCDIR)/VERSION >blob_.c +blob_.c: $(SRCDIR)/blob.c translate + ./translate $(SRCDIR)/blob.c >blob_.c blob.o: blob_.c blob.h $(SRCDIR)/config.h $(XTCC) -o blob.o -c blob_.c blob.h: headers -branch_.c: $(SRCDIR)/branch.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/branch.c | sed -f $(SRCDIR)/VERSION >branch_.c +branch_.c: $(SRCDIR)/branch.c translate + ./translate $(SRCDIR)/branch.c >branch_.c branch.o: branch_.c branch.h $(SRCDIR)/config.h $(XTCC) -o branch.o -c branch_.c branch.h: headers -browse_.c: $(SRCDIR)/browse.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/browse.c | sed -f $(SRCDIR)/VERSION >browse_.c +browse_.c: $(SRCDIR)/browse.c translate + ./translate $(SRCDIR)/browse.c >browse_.c browse.o: browse_.c browse.h $(SRCDIR)/config.h $(XTCC) -o browse.o -c browse_.c browse.h: headers -cgi_.c: $(SRCDIR)/cgi.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/cgi.c | sed -f $(SRCDIR)/VERSION >cgi_.c +captcha_.c: $(SRCDIR)/captcha.c translate + ./translate $(SRCDIR)/captcha.c >captcha_.c + +captcha.o: captcha_.c captcha.h $(SRCDIR)/config.h + $(XTCC) -o captcha.o -c captcha_.c + +captcha.h: headers +cgi_.c: $(SRCDIR)/cgi.c translate + ./translate $(SRCDIR)/cgi.c >cgi_.c cgi.o: cgi_.c cgi.h $(SRCDIR)/config.h $(XTCC) -o cgi.o -c cgi_.c cgi.h: headers -checkin_.c: $(SRCDIR)/checkin.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/checkin.c | sed -f $(SRCDIR)/VERSION >checkin_.c +checkin_.c: $(SRCDIR)/checkin.c translate + ./translate $(SRCDIR)/checkin.c >checkin_.c checkin.o: checkin_.c checkin.h $(SRCDIR)/config.h $(XTCC) -o checkin.o -c checkin_.c checkin.h: headers -checkout_.c: $(SRCDIR)/checkout.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/checkout.c | sed -f $(SRCDIR)/VERSION >checkout_.c +checkout_.c: $(SRCDIR)/checkout.c translate + ./translate $(SRCDIR)/checkout.c >checkout_.c checkout.o: checkout_.c checkout.h $(SRCDIR)/config.h $(XTCC) -o checkout.o -c checkout_.c checkout.h: headers -clearsign_.c: $(SRCDIR)/clearsign.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/clearsign.c | sed -f $(SRCDIR)/VERSION >clearsign_.c +clearsign_.c: $(SRCDIR)/clearsign.c translate + ./translate $(SRCDIR)/clearsign.c >clearsign_.c clearsign.o: clearsign_.c clearsign.h $(SRCDIR)/config.h $(XTCC) -o clearsign.o -c clearsign_.c clearsign.h: headers -clone_.c: $(SRCDIR)/clone.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/clone.c | sed -f $(SRCDIR)/VERSION >clone_.c +clone_.c: $(SRCDIR)/clone.c translate + ./translate $(SRCDIR)/clone.c >clone_.c clone.o: clone_.c clone.h $(SRCDIR)/config.h $(XTCC) -o clone.o -c clone_.c clone.h: headers -comformat_.c: $(SRCDIR)/comformat.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/comformat.c | sed -f $(SRCDIR)/VERSION >comformat_.c +comformat_.c: $(SRCDIR)/comformat.c translate + ./translate $(SRCDIR)/comformat.c >comformat_.c comformat.o: comformat_.c comformat.h $(SRCDIR)/config.h $(XTCC) -o comformat.o -c comformat_.c comformat.h: headers -configure_.c: $(SRCDIR)/configure.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/configure.c | sed -f $(SRCDIR)/VERSION >configure_.c +configure_.c: $(SRCDIR)/configure.c translate + ./translate $(SRCDIR)/configure.c >configure_.c configure.o: configure_.c configure.h $(SRCDIR)/config.h $(XTCC) -o configure.o -c configure_.c configure.h: headers -construct_.c: $(SRCDIR)/construct.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/construct.c | sed -f $(SRCDIR)/VERSION >construct_.c +construct_.c: $(SRCDIR)/construct.c translate + ./translate $(SRCDIR)/construct.c >construct_.c construct.o: construct_.c construct.h $(SRCDIR)/config.h $(XTCC) -o construct.o -c construct_.c construct.h: headers -content_.c: $(SRCDIR)/content.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/content.c | sed -f $(SRCDIR)/VERSION >content_.c +content_.c: $(SRCDIR)/content.c translate + ./translate $(SRCDIR)/content.c >content_.c content.o: content_.c content.h $(SRCDIR)/config.h $(XTCC) -o content.o -c content_.c content.h: headers -creoleparser_.c: $(SRCDIR)/creoleparser.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/creoleparser.c | sed -f $(SRCDIR)/VERSION >creoleparser_.c +creoleparser_.c: $(SRCDIR)/creoleparser.c translate + ./translate $(SRCDIR)/creoleparser.c >creoleparser_.c creoleparser.o: creoleparser_.c creoleparser.h $(SRCDIR)/config.h $(XTCC) -o creoleparser.o -c creoleparser_.c creoleparser.h: headers -db_.c: $(SRCDIR)/db.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/db.c | sed -f $(SRCDIR)/VERSION >db_.c +db_.c: $(SRCDIR)/db.c translate + ./translate $(SRCDIR)/db.c >db_.c db.o: db_.c db.h $(SRCDIR)/config.h $(XTCC) -o db.o -c db_.c db.h: headers -delta_.c: $(SRCDIR)/delta.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/delta.c | sed -f $(SRCDIR)/VERSION >delta_.c +delta_.c: $(SRCDIR)/delta.c translate + ./translate $(SRCDIR)/delta.c >delta_.c delta.o: delta_.c delta.h $(SRCDIR)/config.h $(XTCC) -o delta.o -c delta_.c delta.h: headers -deltacmd_.c: $(SRCDIR)/deltacmd.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/deltacmd.c | sed -f $(SRCDIR)/VERSION >deltacmd_.c +deltacmd_.c: $(SRCDIR)/deltacmd.c translate + ./translate $(SRCDIR)/deltacmd.c >deltacmd_.c deltacmd.o: deltacmd_.c deltacmd.h $(SRCDIR)/config.h $(XTCC) -o deltacmd.o -c deltacmd_.c deltacmd.h: headers -descendants_.c: $(SRCDIR)/descendants.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/descendants.c | sed -f $(SRCDIR)/VERSION >descendants_.c +descendants_.c: $(SRCDIR)/descendants.c translate + ./translate $(SRCDIR)/descendants.c >descendants_.c descendants.o: descendants_.c descendants.h $(SRCDIR)/config.h $(XTCC) -o descendants.o -c descendants_.c descendants.h: headers -diff_.c: $(SRCDIR)/diff.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/diff.c | sed -f $(SRCDIR)/VERSION >diff_.c +diff_.c: $(SRCDIR)/diff.c translate + ./translate $(SRCDIR)/diff.c >diff_.c diff.o: diff_.c diff.h $(SRCDIR)/config.h $(XTCC) -o diff.o -c diff_.c diff.h: headers -diffcmd_.c: $(SRCDIR)/diffcmd.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/diffcmd.c | sed -f $(SRCDIR)/VERSION >diffcmd_.c +diffcmd_.c: $(SRCDIR)/diffcmd.c translate + ./translate $(SRCDIR)/diffcmd.c >diffcmd_.c diffcmd.o: diffcmd_.c diffcmd.h $(SRCDIR)/config.h $(XTCC) -o diffcmd.o -c diffcmd_.c diffcmd.h: headers -doc_.c: $(SRCDIR)/doc.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/doc.c | sed -f $(SRCDIR)/VERSION >doc_.c +doc_.c: $(SRCDIR)/doc.c translate + ./translate $(SRCDIR)/doc.c >doc_.c doc.o: doc_.c doc.h $(SRCDIR)/config.h $(XTCC) -o doc.o -c doc_.c doc.h: headers -encode_.c: $(SRCDIR)/encode.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/encode.c | sed -f $(SRCDIR)/VERSION >encode_.c +encode_.c: $(SRCDIR)/encode.c translate + ./translate $(SRCDIR)/encode.c >encode_.c encode.o: encode_.c encode.h $(SRCDIR)/config.h $(XTCC) -o encode.o -c encode_.c encode.h: headers -file_.c: $(SRCDIR)/file.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/file.c | sed -f $(SRCDIR)/VERSION >file_.c +file_.c: $(SRCDIR)/file.c translate + ./translate $(SRCDIR)/file.c >file_.c file.o: file_.c file.h $(SRCDIR)/config.h $(XTCC) -o file.o -c file_.c file.h: headers -http_.c: $(SRCDIR)/http.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/http.c | sed -f $(SRCDIR)/VERSION >http_.c +http_.c: $(SRCDIR)/http.c translate + ./translate $(SRCDIR)/http.c >http_.c http.o: http_.c http.h $(SRCDIR)/config.h $(XTCC) -o http.o -c http_.c http.h: headers -http_socket_.c: $(SRCDIR)/http_socket.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/http_socket.c | sed -f $(SRCDIR)/VERSION >http_socket_.c +http_socket_.c: $(SRCDIR)/http_socket.c translate + ./translate $(SRCDIR)/http_socket.c >http_socket_.c http_socket.o: http_socket_.c http_socket.h $(SRCDIR)/config.h $(XTCC) -o http_socket.o -c http_socket_.c http_socket.h: headers -http_transport_.c: $(SRCDIR)/http_transport.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/http_transport.c | sed -f $(SRCDIR)/VERSION >http_transport_.c +http_transport_.c: $(SRCDIR)/http_transport.c translate + ./translate $(SRCDIR)/http_transport.c >http_transport_.c http_transport.o: http_transport_.c http_transport.h $(SRCDIR)/config.h $(XTCC) -o http_transport.o -c http_transport_.c http_transport.h: headers -info_.c: $(SRCDIR)/info.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/info.c | sed -f $(SRCDIR)/VERSION >info_.c +info_.c: $(SRCDIR)/info.c translate + ./translate $(SRCDIR)/info.c >info_.c info.o: info_.c info.h $(SRCDIR)/config.h $(XTCC) -o info.o -c info_.c info.h: headers -login_.c: $(SRCDIR)/login.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/login.c | sed -f $(SRCDIR)/VERSION >login_.c +login_.c: $(SRCDIR)/login.c translate + ./translate $(SRCDIR)/login.c >login_.c login.o: login_.c login.h $(SRCDIR)/config.h $(XTCC) -o login.o -c login_.c login.h: headers -main_.c: $(SRCDIR)/main.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/main.c | sed -f $(SRCDIR)/VERSION >main_.c +main_.c: $(SRCDIR)/main.c translate + ./translate $(SRCDIR)/main.c >main_.c main.o: main_.c main.h page_index.h $(SRCDIR)/config.h $(XTCC) -o main.o -c main_.c main.h: headers -manifest_.c: $(SRCDIR)/manifest.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/manifest.c | sed -f $(SRCDIR)/VERSION >manifest_.c +manifest_.c: $(SRCDIR)/manifest.c translate + ./translate $(SRCDIR)/manifest.c >manifest_.c manifest.o: manifest_.c manifest.h $(SRCDIR)/config.h $(XTCC) -o manifest.o -c manifest_.c manifest.h: headers -md5_.c: $(SRCDIR)/md5.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/md5.c | sed -f $(SRCDIR)/VERSION >md5_.c +md5_.c: $(SRCDIR)/md5.c translate + ./translate $(SRCDIR)/md5.c >md5_.c md5.o: md5_.c md5.h $(SRCDIR)/config.h $(XTCC) -o md5.o -c md5_.c md5.h: headers -merge_.c: $(SRCDIR)/merge.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/merge.c | sed -f $(SRCDIR)/VERSION >merge_.c +merge_.c: $(SRCDIR)/merge.c translate + ./translate $(SRCDIR)/merge.c >merge_.c merge.o: merge_.c merge.h $(SRCDIR)/config.h $(XTCC) -o merge.o -c merge_.c merge.h: headers -merge3_.c: $(SRCDIR)/merge3.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/merge3.c | sed -f $(SRCDIR)/VERSION >merge3_.c +merge3_.c: $(SRCDIR)/merge3.c translate + ./translate $(SRCDIR)/merge3.c >merge3_.c merge3.o: merge3_.c merge3.h $(SRCDIR)/config.h $(XTCC) -o merge3.o -c merge3_.c merge3.h: headers -my_page_.c: $(SRCDIR)/my_page.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/my_page.c | sed -f $(SRCDIR)/VERSION >my_page_.c - -my_page.o: my_page_.c my_page.h $(SRCDIR)/config.h - $(XTCC) -o my_page.o -c my_page_.c - -my_page.h: headers -name_.c: $(SRCDIR)/name.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/name.c | sed -f $(SRCDIR)/VERSION >name_.c +name_.c: $(SRCDIR)/name.c translate + ./translate $(SRCDIR)/name.c >name_.c name.o: name_.c name.h $(SRCDIR)/config.h $(XTCC) -o name.o -c name_.c name.h: headers -pivot_.c: $(SRCDIR)/pivot.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/pivot.c | sed -f $(SRCDIR)/VERSION >pivot_.c +pivot_.c: $(SRCDIR)/pivot.c translate + ./translate $(SRCDIR)/pivot.c >pivot_.c pivot.o: pivot_.c pivot.h $(SRCDIR)/config.h $(XTCC) -o pivot.o -c pivot_.c pivot.h: headers -pqueue_.c: $(SRCDIR)/pqueue.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/pqueue.c | sed -f $(SRCDIR)/VERSION >pqueue_.c +pqueue_.c: $(SRCDIR)/pqueue.c translate + ./translate $(SRCDIR)/pqueue.c >pqueue_.c pqueue.o: pqueue_.c pqueue.h $(SRCDIR)/config.h $(XTCC) -o pqueue.o -c pqueue_.c pqueue.h: headers -printf_.c: $(SRCDIR)/printf.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/printf.c | sed -f $(SRCDIR)/VERSION >printf_.c +printf_.c: $(SRCDIR)/printf.c translate + ./translate $(SRCDIR)/printf.c >printf_.c printf.o: printf_.c printf.h $(SRCDIR)/config.h $(XTCC) -o printf.o -c printf_.c printf.h: headers -rebuild_.c: $(SRCDIR)/rebuild.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/rebuild.c | sed -f $(SRCDIR)/VERSION >rebuild_.c +rebuild_.c: $(SRCDIR)/rebuild.c translate + ./translate $(SRCDIR)/rebuild.c >rebuild_.c rebuild.o: rebuild_.c rebuild.h $(SRCDIR)/config.h $(XTCC) -o rebuild.o -c rebuild_.c rebuild.h: headers -report_.c: $(SRCDIR)/report.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/report.c | sed -f $(SRCDIR)/VERSION >report_.c +report_.c: $(SRCDIR)/report.c translate + ./translate $(SRCDIR)/report.c >report_.c report.o: report_.c report.h $(SRCDIR)/config.h $(XTCC) -o report.o -c report_.c report.h: headers -rss_.c: $(SRCDIR)/rss.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/rss.c | sed -f $(SRCDIR)/VERSION >rss_.c +rss_.c: $(SRCDIR)/rss.c translate + ./translate $(SRCDIR)/rss.c >rss_.c rss.o: rss_.c rss.h $(SRCDIR)/config.h $(XTCC) -o rss.o -c rss_.c rss.h: headers -rstats_.c: $(SRCDIR)/rstats.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/rstats.c | sed -f $(SRCDIR)/VERSION >rstats_.c +rstats_.c: $(SRCDIR)/rstats.c translate + ./translate $(SRCDIR)/rstats.c >rstats_.c rstats.o: rstats_.c rstats.h $(SRCDIR)/config.h $(XTCC) -o rstats.o -c rstats_.c rstats.h: headers -schema_.c: $(SRCDIR)/schema.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/schema.c | sed -f $(SRCDIR)/VERSION >schema_.c +schema_.c: $(SRCDIR)/schema.c translate + ./translate $(SRCDIR)/schema.c >schema_.c schema.o: schema_.c schema.h $(SRCDIR)/config.h $(XTCC) -o schema.o -c schema_.c schema.h: headers -setup_.c: $(SRCDIR)/setup.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/setup.c | sed -f $(SRCDIR)/VERSION >setup_.c +setup_.c: $(SRCDIR)/setup.c translate + ./translate $(SRCDIR)/setup.c >setup_.c setup.o: setup_.c setup.h $(SRCDIR)/config.h $(XTCC) -o setup.o -c setup_.c setup.h: headers -sha1_.c: $(SRCDIR)/sha1.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/sha1.c | sed -f $(SRCDIR)/VERSION >sha1_.c +sha1_.c: $(SRCDIR)/sha1.c translate + ./translate $(SRCDIR)/sha1.c >sha1_.c sha1.o: sha1_.c sha1.h $(SRCDIR)/config.h $(XTCC) -o sha1.o -c sha1_.c sha1.h: headers -shun_.c: $(SRCDIR)/shun.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/shun.c | sed -f $(SRCDIR)/VERSION >shun_.c +shun_.c: $(SRCDIR)/shun.c translate + ./translate $(SRCDIR)/shun.c >shun_.c shun.o: shun_.c shun.h $(SRCDIR)/config.h $(XTCC) -o shun.o -c shun_.c shun.h: headers -stat_.c: $(SRCDIR)/stat.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/stat.c | sed -f $(SRCDIR)/VERSION >stat_.c +stat_.c: $(SRCDIR)/stat.c translate + ./translate $(SRCDIR)/stat.c >stat_.c stat.o: stat_.c stat.h $(SRCDIR)/config.h $(XTCC) -o stat.o -c stat_.c stat.h: headers -style_.c: $(SRCDIR)/style.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/style.c | sed -f $(SRCDIR)/VERSION >style_.c +style_.c: $(SRCDIR)/style.c translate + ./translate $(SRCDIR)/style.c >style_.c style.o: style_.c style.h $(SRCDIR)/config.h $(XTCC) -o style.o -c style_.c style.h: headers -sync_.c: $(SRCDIR)/sync.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/sync.c | sed -f $(SRCDIR)/VERSION >sync_.c +sync_.c: $(SRCDIR)/sync.c translate + ./translate $(SRCDIR)/sync.c >sync_.c sync.o: sync_.c sync.h $(SRCDIR)/config.h $(XTCC) -o sync.o -c sync_.c sync.h: headers -tag_.c: $(SRCDIR)/tag.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/tag.c | sed -f $(SRCDIR)/VERSION >tag_.c +tag_.c: $(SRCDIR)/tag.c translate + ./translate $(SRCDIR)/tag.c >tag_.c tag.o: tag_.c tag.h $(SRCDIR)/config.h $(XTCC) -o tag.o -c tag_.c tag.h: headers -tagview_.c: $(SRCDIR)/tagview.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/tagview.c | sed -f $(SRCDIR)/VERSION >tagview_.c - -tagview.o: tagview_.c tagview.h $(SRCDIR)/config.h - $(XTCC) -o tagview.o -c tagview_.c - -tagview.h: headers -th_main_.c: $(SRCDIR)/th_main.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/th_main.c | sed -f $(SRCDIR)/VERSION >th_main_.c +th_main_.c: $(SRCDIR)/th_main.c translate + ./translate $(SRCDIR)/th_main.c >th_main_.c th_main.o: th_main_.c th_main.h $(SRCDIR)/config.h $(XTCC) -o th_main.o -c th_main_.c th_main.h: headers -timeline_.c: $(SRCDIR)/timeline.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/timeline.c | sed -f $(SRCDIR)/VERSION >timeline_.c +timeline_.c: $(SRCDIR)/timeline.c translate + ./translate $(SRCDIR)/timeline.c >timeline_.c timeline.o: timeline_.c timeline.h $(SRCDIR)/config.h $(XTCC) -o timeline.o -c timeline_.c timeline.h: headers -tkt_.c: $(SRCDIR)/tkt.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/tkt.c | sed -f $(SRCDIR)/VERSION >tkt_.c +tkt_.c: $(SRCDIR)/tkt.c translate + ./translate $(SRCDIR)/tkt.c >tkt_.c tkt.o: tkt_.c tkt.h $(SRCDIR)/config.h $(XTCC) -o tkt.o -c tkt_.c tkt.h: headers -tktsetup_.c: $(SRCDIR)/tktsetup.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/tktsetup.c | sed -f $(SRCDIR)/VERSION >tktsetup_.c +tktsetup_.c: $(SRCDIR)/tktsetup.c translate + ./translate $(SRCDIR)/tktsetup.c >tktsetup_.c tktsetup.o: tktsetup_.c tktsetup.h $(SRCDIR)/config.h $(XTCC) -o tktsetup.o -c tktsetup_.c tktsetup.h: headers -undo_.c: $(SRCDIR)/undo.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/undo.c | sed -f $(SRCDIR)/VERSION >undo_.c +undo_.c: $(SRCDIR)/undo.c translate + ./translate $(SRCDIR)/undo.c >undo_.c undo.o: undo_.c undo.h $(SRCDIR)/config.h $(XTCC) -o undo.o -c undo_.c undo.h: headers -update_.c: $(SRCDIR)/update.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/update.c | sed -f $(SRCDIR)/VERSION >update_.c +update_.c: $(SRCDIR)/update.c translate + ./translate $(SRCDIR)/update.c >update_.c update.o: update_.c update.h $(SRCDIR)/config.h $(XTCC) -o update.o -c update_.c update.h: headers -url_.c: $(SRCDIR)/url.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/url.c | sed -f $(SRCDIR)/VERSION >url_.c +url_.c: $(SRCDIR)/url.c translate + ./translate $(SRCDIR)/url.c >url_.c url.o: url_.c url.h $(SRCDIR)/config.h $(XTCC) -o url.o -c url_.c url.h: headers -user_.c: $(SRCDIR)/user.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/user.c | sed -f $(SRCDIR)/VERSION >user_.c +user_.c: $(SRCDIR)/user.c translate + ./translate $(SRCDIR)/user.c >user_.c user.o: user_.c user.h $(SRCDIR)/config.h $(XTCC) -o user.o -c user_.c user.h: headers -verify_.c: $(SRCDIR)/verify.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/verify.c | sed -f $(SRCDIR)/VERSION >verify_.c +verify_.c: $(SRCDIR)/verify.c translate + ./translate $(SRCDIR)/verify.c >verify_.c verify.o: verify_.c verify.h $(SRCDIR)/config.h $(XTCC) -o verify.o -c verify_.c verify.h: headers -vfile_.c: $(SRCDIR)/vfile.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/vfile.c | sed -f $(SRCDIR)/VERSION >vfile_.c +vfile_.c: $(SRCDIR)/vfile.c translate + ./translate $(SRCDIR)/vfile.c >vfile_.c vfile.o: vfile_.c vfile.h $(SRCDIR)/config.h $(XTCC) -o vfile.o -c vfile_.c vfile.h: headers -wiki_.c: $(SRCDIR)/wiki.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/wiki.c | sed -f $(SRCDIR)/VERSION >wiki_.c +wiki_.c: $(SRCDIR)/wiki.c translate + ./translate $(SRCDIR)/wiki.c >wiki_.c wiki.o: wiki_.c wiki.h $(SRCDIR)/config.h $(XTCC) -o wiki.o -c wiki_.c wiki.h: headers -wikiformat_.c: $(SRCDIR)/wikiformat.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/wikiformat.c | sed -f $(SRCDIR)/VERSION >wikiformat_.c +wikiformat_.c: $(SRCDIR)/wikiformat.c translate + ./translate $(SRCDIR)/wikiformat.c >wikiformat_.c wikiformat.o: wikiformat_.c wikiformat.h $(SRCDIR)/config.h $(XTCC) -o wikiformat.o -c wikiformat_.c wikiformat.h: headers -winhttp_.c: $(SRCDIR)/winhttp.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/winhttp.c | sed -f $(SRCDIR)/VERSION >winhttp_.c +winhttp_.c: $(SRCDIR)/winhttp.c translate + ./translate $(SRCDIR)/winhttp.c >winhttp_.c winhttp.o: winhttp_.c winhttp.h $(SRCDIR)/config.h $(XTCC) -o winhttp.o -c winhttp_.c winhttp.h: headers -xfer_.c: $(SRCDIR)/xfer.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/xfer.c | sed -f $(SRCDIR)/VERSION >xfer_.c +xfer_.c: $(SRCDIR)/xfer.c translate + ./translate $(SRCDIR)/xfer.c >xfer_.c xfer.o: xfer_.c xfer.h $(SRCDIR)/config.h $(XTCC) -o xfer.o -c xfer_.c xfer.h: headers -zip_.c: $(SRCDIR)/zip.c $(SRCDIR)/VERSION translate - ./translate $(SRCDIR)/zip.c | sed -f $(SRCDIR)/VERSION >zip_.c +zip_.c: $(SRCDIR)/zip.c translate + ./translate $(SRCDIR)/zip.c >zip_.c zip.o: zip_.c zip.h $(SRCDIR)/config.h $(XTCC) -o zip.o -c zip_.c zip.h: headers sqlite3.o: $(SRCDIR)/sqlite3.c - $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_PRIVATE= -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_FTS3=1 -Dlocaltime=fossil_localtime -c $(SRCDIR)/sqlite3.c -o sqlite3.o + $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -c $(SRCDIR)/sqlite3.c -o sqlite3.o th.o: $(SRCDIR)/th.c $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o th.o th_lang.o: $(SRCDIR)/th_lang.c $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o th_lang.o
Modified src/makemake.tcl from [f6bd7d70e3] to [f6304e19c8].
@@ -6,16 +6,16 @@ # Basenames of all source files that get preprocessed using # "translate" and "makeheaders" # set src { add - admin allrepo bag blob branch browse + captcha cgi checkin checkout clearsign clone @@ -41,11 +41,10 @@ main manifest md5 merge merge3 - my_page name pivot pqueue printf rebuild @@ -58,11 +57,10 @@ shun stat style sync tag - tagview th_main timeline tkt tktsetup undo @@ -177,26 +175,27 @@ puts "headers: Makefile" puts "Makefile:" set extra_h(main) page_index.h foreach s [lsort $src] { - puts "${s}_.c:\t\$(SRCDIR)/$s.c \$(SRCDIR)/VERSION translate" - puts "\t./translate \$(SRCDIR)/$s.c | sed -f \$(SRCDIR)/VERSION >${s}_.c\n" + puts "${s}_.c:\t\$(SRCDIR)/$s.c translate" + puts "\t./translate \$(SRCDIR)/$s.c >${s}_.c\n" puts "$s.o:\t${s}_.c $s.h $extra_h($s) \$(SRCDIR)/config.h" puts "\t\$(XTCC) -o $s.o -c ${s}_.c\n" puts "$s.h:\theaders" # puts "\t./makeheaders $mhargs\n\ttouch headers\n" # puts "\t./makeheaders ${s}_.c:${s}.h\n" } puts "sqlite3.o:\t\$(SRCDIR)/sqlite3.c" -set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_PRIVATE=} +set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1} append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4" -append opt " -DSQLITE_ENABLE_FTS3=1 -Dlocaltime=fossil_localtime" +#append opt " -DSQLITE_ENABLE_FTS3=1" +append opt " -Dlocaltime=fossil_localtime" puts "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o sqlite3.o\n" puts "th.o:\t\$(SRCDIR)/th.c" puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o th.o\n" puts "th_lang.o:\t\$(SRCDIR)/th_lang.c" puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o th_lang.o\n"
Modified src/manifest.c from [a82cc38cad] to [5e32c12dce].
@@ -700,10 +700,33 @@ manifest_parse(&m, &b); manifest_clear(&m); } /* +** Translate a filename into a filename-id (fnid). Create a new fnid +** if no previously exists. +*/ +static int filename_to_fnid(const char *zFilename){ + static Stmt q1, s1; + int fnid; + db_static_prepare(&q1, "SELECT fnid FROM filename WHERE name=:fn"); + db_bind_text(&q1, ":fn", zFilename); + fnid = 0; + if( db_step(&q1)==SQLITE_ROW ){ + fnid = db_column_int(&q1, 0); + } + db_reset(&q1); + if( fnid==0 ){ + db_static_prepare(&s1, "INSERT INTO filename(name) VALUES(:fn)"); + db_bind_text(&s1, ":fn", zFilename); + db_exec(&s1); + fnid = db_last_insert_rowid(); + } + return fnid; +} + +/* ** Add a single entry to the mlink table. Also add the filename to ** the filename table if it is not there already. */ static void add_one_mlink( int mid, /* The record ID of the manifest */ @@ -711,24 +734,17 @@ const char *zToUuid, /* UUID for the mlink.fid field */ const char *zFilename, /* Filename */ const char *zPrior /* Previous filename. NULL if unchanged */ ){ int fnid, pfnid, pid, fid; - - fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); - if( fnid==0 ){ - db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zFilename); - fnid = db_last_insert_rowid(); - } + static Stmt s1; + + fnid = filename_to_fnid(zFilename); if( zPrior==0 ){ pfnid = 0; }else{ - pfnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zPrior); - if( pfnid==0 ){ - db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zPrior); - pfnid = db_last_insert_rowid(); - } + pfnid = filename_to_fnid(zPrior); } if( zFromUuid==0 ){ pid = 0; }else{ pid = uuid_to_rid(zFromUuid, 1); @@ -736,14 +752,20 @@ if( zToUuid==0 ){ fid = 0; }else{ fid = uuid_to_rid(zToUuid, 1); } - db_multi_exec( + db_static_prepare(&s1, "INSERT INTO mlink(mid,pid,fid,fnid,pfnid)" - "VALUES(%d,%d,%d,%d,%d)", mid, pid, fid, fnid, pfnid + "VALUES(:m,:p,:f,:n,:pfn)" ); + db_bind_int(&s1, ":m", mid); + db_bind_int(&s1, ":p", pid); + db_bind_int(&s1, ":f", fid); + db_bind_int(&s1, ":n", fnid); + db_bind_int(&s1, ":pfn", pfnid); + db_exec(&s1); if( pid && fid ){ content_deltify(pid, fid, 0); } } @@ -861,10 +883,122 @@ } manifest_clear(&other); } /* +** True if manifest_crosslink_begin() has been called but +** manifest_crosslink_end() is still pending. +*/ +static int manifest_crosslink_busy = 0; + +/* +** Setup to do multiple manifest_crosslink() calls. +** This is only required if processing ticket changes. +*/ +void manifest_crosslink_begin(void){ + assert( manifest_crosslink_busy==0 ); + manifest_crosslink_busy = 1; + db_begin_transaction(); + db_multi_exec("CREATE TEMP TABLE pending_tkt(uuid TEXT UNIQUE)"); +} + +/* +** Finish up a sequence of manifest_crosslink calls. +*/ +void manifest_crosslink_end(void){ + Stmt q; + assert( manifest_crosslink_busy==1 ); + db_prepare(&q, "SELECT uuid FROM pending_tkt"); + while( db_step(&q)==SQLITE_ROW ){ + const char *zUuid = db_column_text(&q, 0); + ticket_rebuild_entry(zUuid); + } + db_finalize(&q); + db_multi_exec("DROP TABLE pending_tkt"); + db_end_transaction(0); + manifest_crosslink_busy = 0; +} + +/* +** Make an entry in the event table for a ticket change artifact. +*/ +void manifest_ticket_event( + int rid, /* Artifact ID of the change ticket artifact */ + const Manifest *pManifest, /* Parsed content of the artifact */ + int isNew, /* True if this is the first event */ + int tktTagId /* Ticket tag ID */ +){ + int i; + char *zTitle; + Blob comment; + Blob brief; + char *zNewStatus = 0; + static char *zTitleExpr = 0; + static char *zStatusColumn = 0; + static int once = 1; + + blob_zero(&comment); + blob_zero(&brief); + if( once ){ + once = 0; + zTitleExpr = db_get("ticket-title-expr", "title"); + zStatusColumn = db_get("ticket-status-column", "status"); + } + zTitle = db_text("unknown", + "SELECT %s FROM ticket WHERE tkt_uuid='%s'", + zTitleExpr, pManifest->zTicketUuid + ); + if( !isNew ){ + for(i=0; i<pManifest->nField; i++){ + if( strcmp(pManifest->aField[i].zName, zStatusColumn)==0 ){ + zNewStatus = pManifest->aField[i].zValue; + } + } + if( zNewStatus ){ + blob_appendf(&comment, "%h ticket [%.10s]: <i>%h</i>", + zNewStatus, pManifest->zTicketUuid, zTitle + ); + if( pManifest->nField>1 ){ + blob_appendf(&comment, " plus %d other change%s", + pManifest->nField-1, pManifest->nField==2 ? "" : "s"); + } + blob_appendf(&brief, "%h ticket [%.10s].", + zNewStatus, pManifest->zTicketUuid); + }else{ + zNewStatus = db_text("unknown", + "SELECT %s FROM ticket WHERE tkt_uuid='%s'", + zStatusColumn, pManifest->zTicketUuid + ); + blob_appendf(&comment, "Ticket [%.10s] <i>%h</i> status still %h with " + "%d other change%s", + pManifest->zTicketUuid, zTitle, zNewStatus, pManifest->nField, + pManifest->nField==1 ? "" : "s" + ); + free(zNewStatus); + blob_appendf(&brief, "Ticket [%.10s]: %d change%s", + pManifest->zTicketUuid, pManifest->nField, + pManifest->nField==1 ? "" : "s" + ); + } + }else{ + blob_appendf(&comment, "New ticket [%.10s] <i>%h</i>.", + pManifest->zTicketUuid, zTitle + ); + blob_appendf(&brief, "New ticket [%.10s].", pManifest->zTicketUuid); + } + free(zTitle); + db_multi_exec( + "REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)" + "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)", + tktTagId, pManifest->rDate, rid, pManifest->zUser, + blob_str(&comment), blob_str(&brief) + ); + blob_reset(&comment); + blob_reset(&brief); +} + +/* ** Scan artifact rid/pContent to see if it is a control artifact of ** any key: ** ** * Manifest ** * Control @@ -915,16 +1049,22 @@ add_mlink(rid, &m, cid, 0); } db_finalize(&q); db_multi_exec( "REPLACE INTO event(type,mtime,objid,user,comment," - " bgcolor,euser,ecomment)" - "VALUES('ci',%.17g,%d,%Q,%Q," - " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>0)," + "bgcolor,euser,ecomment)" + "VALUES('ci'," + " coalesce(" + " (SELECT julianday(value) FROM tagxref WHERE tagid=%d AND rid=%d)," + " %.17g" + " )," + " %d,%Q,%Q," + " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>0)," " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d)," " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", - m.rDate, rid, m.zUser, m.zComment, + TAG_DATE, rid, m.rDate, + rid, m.zUser, m.zComment, TAG_BGCOLOR, rid, TAG_USER, rid, TAG_COMMENT, rid ); } @@ -996,72 +1136,18 @@ TAG_COMMENT, rid ); free(zComment); } if( m.type==CFTYPE_TICKET ){ - int i; - char *zTitle; char *zTag; - Blob comment; - char *zNewStatus = 0; - static char *zTitleExpr = 0; - static char *zStatusColumn = 0; - static int once = 1; - int isNew; - isNew = ticket_insert(&m, 1, 1); + assert( manifest_crosslink_busy==1 ); zTag = mprintf("tkt-%s", m.zTicketUuid); tag_insert(zTag, 1, 0, rid, m.rDate, rid); free(zTag); - blob_zero(&comment); - if( once ){ - once = 0; - zTitleExpr = db_get("ticket-title-expr", "title"); - zStatusColumn = db_get("ticket-status-column", "status"); - } - zTitle = db_text("unknown", - "SELECT %s FROM ticket WHERE tkt_uuid='%s'", - zTitleExpr, m.zTicketUuid - ); - if( !isNew ){ - for(i=0; i<m.nField; i++){ - if( strcmp(m.aField[i].zName, zStatusColumn)==0 ){ - zNewStatus = m.aField[i].zValue; - } - } - if( zNewStatus ){ - blob_appendf(&comment, "%h ticket [%.10s]: <i>%h</i>", - zNewStatus, m.zTicketUuid, zTitle - ); - if( m.nField>1 ){ - blob_appendf(&comment, " plus %d other change%s", - m.nField-1, m.nField==2 ? "" : "s"); - } - }else{ - zNewStatus = db_text("unknown", - "SELECT %s FROM ticket WHERE tkt_uuid='%s'", - zStatusColumn, m.zTicketUuid - ); - blob_appendf(&comment, "Ticket [%.10s] <i>%h</i> status still %h with " - "%d other change%s", - m.zTicketUuid, zTitle, zNewStatus, m.nField, - m.nField==1 ? "" : "s" - ); - free(zNewStatus); - } - }else{ - blob_appendf(&comment, "New ticket [%.10s] <i>%h</i>.", - m.zTicketUuid, zTitle - ); - } - free(zTitle); - db_multi_exec( - "REPLACE INTO event(type,mtime,objid,user,comment)" - "VALUES('t',%.17g,%d,%Q,%Q)", - m.rDate, rid, m.zUser, blob_str(&comment) - ); - blob_reset(&comment); + db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)", + m.zTicketUuid); } db_end_transaction(0); manifest_clear(&m); return 1; }
Deleted src/my_page.c version [57fa8e406f]
Modified src/name.c from [040558eaa3] to [1511a64c2c].
@@ -123,11 +123,11 @@ Stmt q; int count = 0; db_prepare(&q, "SELECT (SELECT uuid FROM blob WHERE rid=objid)" " FROM tagxref JOIN event ON rid=objid" - " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q||%Q)" + " WHERE tagxref.tagid=(SELECT tagid FROM tag WHERE tagname=%Q||%Q)" " AND tagtype>0" " AND value IS NULL" " ORDER BY event.mtime DESC", pPrefix, pName
Modified src/rebuild.c from [485e8e6098] to [fa901199b7].
@@ -206,10 +206,11 @@ char *zTable; bag_init(&bagDone); ttyOutput = doOut; processCnt = 0; + printf("0 (0%%)...\r"); fflush(stdout); db_multi_exec(zSchemaUpdates); for(;;){ zTable = db_text(0, "SELECT name FROM sqlite_master" " WHERE type='table'" @@ -240,10 +241,11 @@ db_prepare(&s, "SELECT rid, size FROM blob" " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)" ); + manifest_crosslink_begin(); while( db_step(&s)==SQLITE_ROW ){ int rid = db_column_int(&s, 0); int size = db_column_int(&s, 1); if( size>=0 ){ Blob content; @@ -269,10 +271,11 @@ db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); rebuild_step_done(rid); } } db_finalize(&s); + manifest_crosslink_end(); rebuild_tag_trunk(); if( ttyOutput ){ printf("\n"); } return errCnt; @@ -279,11 +282,11 @@ } /* ** COMMAND: rebuild ** -** Usage: %fossil rebuild REPOSITORY +** Usage: %fossil rebuild ?REPOSITORY? ** ** Reconstruct the named repository database from the core ** records. Run this command after updating the fossil ** executable in a way that changes the database schema. */ @@ -292,14 +295,20 @@ int randomizeFlag; int errCnt; forceFlag = find_option("force","f",0)!=0; randomizeFlag = find_option("randomize", 0, 0)!=0; - if( g.argc!=3 ){ - usage("REPOSITORY-FILENAME"); - } - db_open_repository(g.argv[2]); + if( g.argc==3 ){ + db_open_repository(g.argv[2]); + }else{ + db_find_and_open_repository(1); + if( g.argc!=2 ){ + usage("?REPOSITORY-FILENAME?"); + } + db_close(); + db_open_repository(g.zRepositoryName); + } db_begin_transaction(); ttyOutput = 1; errCnt = rebuild_db(randomizeFlag, 1); if( errCnt && !forceFlag ){ printf("%d errors. Rolling back changes. Use --force to force a commit.\n", @@ -327,6 +336,67 @@ " WHERE name='project-code';" "UPDATE config SET value='detached-' || value" " WHERE name='project-name' AND value NOT GLOB 'detached-*';" ); db_end_transaction(0); +} + +/* +** COMMAND: scrub +** %fossil scrub [--verily] [--force] [REPOSITORY] +** +** The command removes sensitive information (such as passwords) from a +** repository so that the respository can be sent to an untrusted reader. +** +** By default, only passwords are removed. However, if the --verily option +** is added, then private branches, concealed email addresses, IP +** addresses of correspondents, and similar privacy-sensitive fields +** are also purged. +** +** This command permanently deletes the scrubbed information. The effects +** of this command are irreversible. Use with caution. +** +** The user is prompted to confirm the scrub unless the --force option +** is used. +*/ +void scrub_cmd(void){ + int bVerily = find_option("verily",0,0)!=0; + int bForce = find_option("force", "f", 0)!=0; + int bNeedRebuild = 0; + if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); + if( g.argc==2 ){ + db_must_be_within_tree(); + }else{ + db_open_repository(g.argv[2]); + } + if( !bForce ){ + Blob ans; + blob_zero(&ans); + prompt_user("Scrubbing the repository will permanently remove user\n" + "passwords and other information. Changes cannot be undone.\n" + "Continue [y/N]? ", &ans); + if( blob_str(&ans)[0]!='y' ){ + exit(1); + } + } + db_begin_transaction(); + db_multi_exec( + "UPDATE user SET pw='';" + "DELETE FROM config WHERE name='last-sync-url';" + ); + if( bVerily ){ + bNeedRebuild = db_exists("SELECT 1 FROM private"); + db_multi_exec( + "DELETE FROM concealed;" + "UPDATE rcvfrom SET ipaddr='unknown';" + "UPDATE user SET photo=NULL, info='';" + "INSERT INTO shun SELECT uuid FROM blob WHERE rid IN private;" + ); + } + if( !bNeedRebuild ){ + db_end_transaction(0); + db_multi_exec("VACUUM;"); + }else{ + rebuild_db(0, 1); + db_end_transaction(0); + } }
Modified src/report.c from [79992110fa] to [911a1c587a].
@@ -45,10 +45,16 @@ if( g.okNewTkt ){ @ <p>Enter a new ticket:</p> @ <ol><li value="1"><a href="tktnew">New ticket</a></li></ol> @ cnt++; + }else if( db_exists( + "SELECT 1 FROM user" + " WHERE login='anonymous' AND cap GLOB '*n*'") + ){ + @ <p><a href="login?anon=1&g=tktnew">Login as "anonymous"</a> + @ to enter a new ticket.</p> } if( !g.okRdTkt ){ @ <p>You are not authorized to view existing tickets.</p> }else{ db_prepare(&q, "SELECT rn, title, owner FROM reportfmt ORDER BY title"); @@ -777,11 +783,15 @@ wiki_convert(&content, 0, 0); blob_reset(&content); } }else if( azName[i][0]=='#' ){ zTid = zData; - @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td> + if( g.okHistory ){ + @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td> + }else{ + @ <td valign="top">%h(zData)</td> + } }else if( zData[0]==0 ){ @ <td valign="top"> </td> }else{ @ <td valign="top"> @ %h(zData)
Modified src/schema.c from [216bff41ba] to [6fd1e2b445].
@@ -223,16 +223,18 @@ @ -- @ CREATE TABLE event( @ type TEXT, -- Type of event @ mtime DATETIME, -- Date and time when the event occurs @ objid INTEGER PRIMARY KEY, -- Associated record ID +@ tagid INTEGER, -- Associated ticket or wiki name tag @ uid INTEGER REFERENCES user, -- User who caused the event @ bgcolor TEXT, -- Color set by 'bgcolor' property @ euser TEXT, -- User set by 'user' property @ user TEXT, -- Name of the user @ ecomment TEXT, -- Comment set by 'comment' property -@ comment TEXT -- Comment describing the event +@ comment TEXT, -- Comment describing the event +@ brief TEXT -- Short comment when tagid already seen @ ); @ CREATE INDEX event_i1 ON event(mtime); @ @ -- A record of phantoms. A phantom is a record for which we know the @ -- UUID but we do not (yet) know the file content. @@ -276,15 +278,16 @@ @ tagname TEXT UNIQUE -- Tag name. @ ); @ INSERT INTO tag VALUES(1, 'bgcolor'); -- TAG_BGCOLOR @ INSERT INTO tag VALUES(2, 'comment'); -- TAG_COMMENT @ INSERT INTO tag VALUES(3, 'user'); -- TAG_USER -@ INSERT INTO tag VALUES(4, 'hidden'); -- TAG_HIDDEN -@ INSERT INTO tag VALUES(5, 'private'); -- TAG_PRIVATE -@ INSERT INTO tag VALUES(6, 'cluster'); -- TAG_CLUSTER -@ INSERT INTO tag VALUES(7, 'branch'); -- TAG_BRANCH -@ INSERT INTO tag VALUES(8, 'closed'); -- TAG_CLOSED +@ INSERT INTO tag VALUES(4, 'date'); -- TAG_DATE +@ INSERT INTO tag VALUES(5, 'hidden'); -- TAG_HIDDEN +@ INSERT INTO tag VALUES(6, 'private'); -- TAG_PRIVATE +@ INSERT INTO tag VALUES(7, 'cluster'); -- TAG_CLUSTER +@ INSERT INTO tag VALUES(8, 'branch'); -- TAG_BRANCH +@ INSERT INTO tag VALUES(9, 'closed'); -- TAG_CLOSED @ @ -- Assignments of tags to baselines. Note that we allow tags to @ -- have values assigned to them. So we are not really dealing with @ -- tags here. These are really properties. But we are going to @ -- keep calling them tags because in many cases the value is ignored. @@ -330,18 +333,19 @@ */ #if INTERFACE # define TAG_BGCOLOR 1 /* Set the background color for display */ # define TAG_COMMENT 2 /* The check-in comment */ # define TAG_USER 3 /* User who made a checking */ -# define TAG_HIDDEN 4 /* Do not display or sync */ -# define TAG_PRIVATE 5 /* Display but do not sync */ -# define TAG_CLUSTER 6 /* A cluster */ -# define TAG_BRANCH 7 /* Value is name of the current branch */ -# define TAG_CLOSED 8 /* Do not display this check-in as a leaf */ +# define TAG_DATE 4 /* The date of a check-in */ +# define TAG_HIDDEN 5 /* Do not display or sync */ +# define TAG_PRIVATE 6 /* Display but do not sync */ +# define TAG_CLUSTER 7 /* A cluster */ +# define TAG_BRANCH 8 /* Value is name of the current branch */ +# define TAG_CLOSED 9 /* Do not display this check-in as a leaf */ #endif #if EXPORT_INTERFACE -# define MAX_INT_TAG 8 /* The largest pre-assigned tag id */ +# define MAX_INT_TAG 9 /* The largest pre-assigned tag id */ #endif /* ** The schema for the locate FOSSIL database file found at the root ** of very check-out. This database contains the complete state of
Modified src/setup.c from [d905d90c04] to [ddfa4b243d].
@@ -64,10 +64,12 @@ "Grant privileges to individual users."); setup_menu_entry("Access", "setup_access", "Control access settings."); setup_menu_entry("Configuration", "setup_config", "Configure the WWW components of the repository"); + setup_menu_entry("Behavior", "setup_behavior", + "Configure the SCM behavior of the repository"); setup_menu_entry("Timeline", "setup_timeline", "Timeline display preferences"); setup_menu_entry("Tickets", "tktsetup", "Configure the trouble-ticketing system for this repository"); setup_menu_entry("CSS", "setup_editcss", @@ -173,11 +175,11 @@ @ <tr><td valign="top"><b>s</b></td> @ <td><i>Setup/Super-user:</i> Setup and configure this website</td></tr> @ <tr><td valign="top"><b>t</b></td> @ <td><i>Tkt-Report:</i> Create new bug summary reports</td></tr> @ <tr><td valign="top"><b>u</b></td> - @ <td><i>Developer:</i> Inherit privileges of + @ <td><i>Reader:</i> Inherit privileges of @ user <tt>reader</tt></td></tr> @ <tr><td valign="top"><b>v</b></td> @ <td><i>Developer:</i> Inherit privileges of @ user <tt>developer</tt></td></tr> @ <tr><td valign="top"><b>w</b></td> @@ -778,10 +780,91 @@ @ <hr> entry_attribute("Max timeline comment length", 6, "timeline-max-comment", "tmc", "0"); @ <p>The maximum length of a comment to be displayed in a timeline. @ "0" there is no length limit.</p> + + @ <hr> + @ <p><input type="submit" name="submit" value="Apply Changes"></p> + @ </form> + db_end_transaction(0); + style_footer(); +} + +/* +** WEBPAGE: setup_behavior +*/ +void setup_behavior(void){ + login_check_credentials(); + if( !g.okSetup ){ + login_needed(); + } + + style_header("Fossil SCM Behavior"); + db_begin_transaction(); + @ <form action="%s(g.zBaseURL)/setup_behavior" method="POST"> + login_insert_csrf_secret(); + + @ <hr> + onoff_attribute("Automatically synchronize with repository", + "autosync", "autosync", 0); + @ <p>Automatically keeps your work in sync with a centralized server.</p> + + @ <hr> + onoff_attribute("Sign all commits with gpg", + "clearsign", "clearsign", 0); + @ <p>When enabled (the default), fossil will attempt to + @ sign all commits with gpg. When disabled, commits will + @ be unsigned.</p> + + @ <hr> + onoff_attribute("Require local authentication", + "localauth", "localauth", 0); + @ <p>If enabled, require that HTTP connections from + @ 127.0.0.1 be authenticated by password. If + @ false, all HTTP requests from localhost have + @ unrestricted access to the repository.</p> + + @ <hr> + onoff_attribute("Modification times used to detect changes", + "mtime-changes", "mtime-changes", 0); + @ <p>Use file modification times (mtimes) to detect when files have been modified.</p> + + @ <hr> + entry_attribute("Diff Command", 16, + "diff-command", "diff-command", "diff"); + @ <p>External command used to generate a textual diff</p> + + @ <hr> + entry_attribute("Gdiff Command", 16, + "gdiff-command", "gdiff-command", "gdiff"); + @ <p>External command to run when performing a graphical diff. If undefined, text diff will be used.</p> + + @ <hr> + entry_attribute("Editor", 16, + "editor", "editor", ""); + @ <p>Text editor command used for check-in comments.</p> + + @ <hr> + entry_attribute("HTTP port", 16, + "http-port", "http-port", "8080"); + @ <p>The TCP/IP port number to use by the "server" and "ui" commands. Default: 8080</p> + + @ <hr> + entry_attribute("PGP Command", 32, + "pgp-command", "pgp-command", "gpg --clearsign -o "); + @ <p>Command used to clear-sign manifests at check-in.The default is "gpg --clearsign -o ".</p> + + @ <hr> + entry_attribute("Proxy", 32, + "proxy", "proxy", "off"); + @ <p>URL of the HTTP proxy.</p> + + @ <hr> + entry_attribute("Web browser", 32, + "web-browser", "web-browser", ""); + @ <p>Default web browser for "fossil ui".</p> @ <hr> @ <p><input type="submit" name="submit" value="Apply Changes"></p> @ </form> db_end_transaction(0);
Modified src/shun.c from [42fc2023fe] to [5eec8953fc].
@@ -95,33 +95,15 @@ @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> has been @ shunned. It will no longer be pushed. @ It will be removed from the repository the next time the respository @ is rebuilt using the <b>fossil rebuild</b> command-line</font></p> } - @ <p>The artifacts listed below have been shunned by this repository. - @ This means that the artifacts will not be transmitted on a push nor - @ recieved on a pull. These artifacts are banned from the respository.</p> - @ <blockquote> - db_prepare(&q, - "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)" - " FROM shun ORDER BY uuid"); - while( db_step(&q)==SQLITE_ROW ){ - const char *zUuid = db_column_text(&q, 0); - int stillExists = db_column_int(&q, 1); - cnt++; - if( stillExists ){ - @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br> - }else{ - @ <b>%s(zUuid)</b><br> - } - } - if( cnt==0 ){ - @ <i>no artifacts are shunned on this server</i> - } - db_finalize(&q); - @ </blockquote> - @ <hr> + @ <p>A shunned artifact will not be pushed nor accepted in a pull and the + @ artifact content will be purged from the repository the next time the + @ repository is rebuilt. A list of shunned artifacts can be seen at the + @ bottom of this page.</p> + @ @ <a name="addshun"></a> @ <p>To shun an artifact, enter its artifact ID (the 40-character SHA1 @ hash of the artifact) in the @ following box and press the "Shun" button. This will cause the artifact @ to be removed from the repository and will prevent the artifact from being @@ -157,21 +139,42 @@ @ <input type="text" name="uuid" size="50"> @ <input type="submit" name="sub" value="Accept"> @ </form> @ </blockquote> @ - @ <hr> - @ <p>Press the button below to rebuild the respository. The rebuild - @ may take several seconds, so be patient after pressing the button.</p> + @ <p>Press the Rebuild button below to rebuild the respository. The + @ content of newly shunned artifacts is not purged until the repository + @ is rebuilt. On larger repositories, the rebuild may take minute or + @ two, so be patient after pressing the button.</p> @ @ <blockquote> @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> login_insert_csrf_secret(); @ <input type="submit" name="rebuild" value="Rebuild"> @ </form> @ </blockquote> @ + @ <hr><p>Shunned Artifacts:</p> + @ <blockquote> + db_prepare(&q, + "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)" + " FROM shun ORDER BY uuid"); + while( db_step(&q)==SQLITE_ROW ){ + const char *zUuid = db_column_text(&q, 0); + int stillExists = db_column_int(&q, 1); + cnt++; + if( stillExists ){ + @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br> + }else{ + @ <b>%s(zUuid)</b><br> + } + } + if( cnt==0 ){ + @ <i>no artifacts are shunned on this server</i> + } + db_finalize(&q); + @ </blockquote> style_footer(); } /* ** Remove from the BLOB table all artifacts that are in the SHUN table. @@ -192,10 +195,12 @@ db_finalize(&q); db_multi_exec( "DELETE FROM delta WHERE rid IN toshun;" "DELETE FROM blob WHERE rid IN toshun;" "DROP TABLE toshun;" + "DELETE FROM private " + " WHERE NOT EXISTS (SELECT 1 FROM blob WHERE rid=private.rid);" ); } /* ** WEBPAGE: rcvfromlist
Modified src/sqlite3.c from [dfe6236892] to [6a71c71db8].
@@ -1,25 +1,25 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.6.13. By combining all the individual C code files into this +** version 3.6.18. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a one translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% are more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other ** programs, you need this file and the "sqlite3.h" header file that defines ** the programming interface to the SQLite library. (If you do not have -** the "sqlite3.h" header file at hand, you will find a copy in the first -** 5503 lines past this header comment.) Additional code files may be -** needed if you want a wrapper to interface SQLite with your choice of -** programming language. The code for the "sqlite3" command-line shell -** is also in a separate file. This file contains only code for the core -** SQLite library. -** -** This amalgamation was generated on 2009-04-13 09:47:15 UTC. +** the "sqlite3.h" header file at hand, you will find a copy embedded within +** the text of this file. Search for "Begin file sqlite3.h" to find the start +** of the embedded sqlite3.h header file.) Additional code files may be needed +** if you want a wrapper to interface SQLite with your choice of programming +** language. The code for the "sqlite3" command-line shell is also in a +** separate file. This file contains only code for the core SQLite library. +** +** This amalgamation was generated on 2009-09-11 14:16:13 UTC. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static @@ -39,14 +39,40 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.854 2009/04/08 13:51:51 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ + +/* +** These #defines should enable >2GB file support on POSIX if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: Red Hat 7.2) but you want your code to work +** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in Red Hat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ @@ -245,10 +271,21 @@ */ #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH # define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 #endif +/* +** Maximum depth of recursion for triggers. +*/ +#ifndef SQLITE_MAX_TRIGGER_DEPTH +#if defined(SQLITE_SMALL_STACK) +# define SQLITE_MAX_TRIGGER_DEPTH 10 +#else +# define SQLITE_MAX_TRIGGER_DEPTH 1000 +#endif +#endif + /************** End of sqliteLimit.h *****************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /* Disable nuisance warnings on Borland compilers */ #if defined(__BORLANDC__) @@ -272,52 +309,42 @@ #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif -/* - * This macro is used to "hide" some ugliness in casting an int - * value to a ptr value under the MSVC 64-bit compiler. Casting - * non 64-bit values to ptr types results in a "hard" error with - * the MSVC 64-bit compiler which this attempts to avoid. - * - * A simple compiler pragma or casting sequence could not be found - * to correct this in all situations, so this macro was introduced. - * - * It could be argued that the intptr_t type could be used in this - * case, but that type is not available on all compilers, or - * requires the #include of specific headers which differs between - * platforms. - */ -#define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) -#define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) - -/* -** These #defines should enable >2GB file support on POSIX if the -** underlying operating system supports it. If the OS lacks -** large file support, or if the OS is windows, these should be no-ops. -** -** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any -** system #includes. Hence, this block of code must be the very first -** code in all source files. -** -** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch -** on the compiler command line. This is necessary if you are compiling -** on a recent machine (ex: Red Hat 7.2) but you want your code to work -** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 -** without this option, LFS is enable. But LFS does not exist in the kernel -** in Red Hat 6.0, so the code won't work. Hence, for maximum binary -** portability you should omit LFS. -** -** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. -*/ -#ifndef SQLITE_DISABLE_LFS -# define _LARGE_FILE 1 -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# define _LARGEFILE_SOURCE 1 +#define SQLITE_INDEX_SAMPLES 10 + +/* +** This macro is used to "hide" some ugliness in casting an int +** value to a ptr value under the MSVC 64-bit compiler. Casting +** non 64-bit values to ptr types results in a "hard" error with +** the MSVC 64-bit compiler which this attempts to avoid. +** +** A simple compiler pragma or casting sequence could not be found +** to correct this in all situations, so this macro was introduced. +** +** It could be argued that the intptr_t type could be used in this +** case, but that type is not available on all compilers, or +** requires the #include of specific headers which differs between +** platforms. +** +** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on +** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). +** So we have to define the macros in different ways depending on the +** compiler. +*/ +#if defined(__GNUC__) +# if defined(HAVE_STDINT_H) +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) +# else +# define SQLITE_INT_TO_PTR(X) ((void*)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(X)) +# endif +#else +# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) +# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) #endif /* ** The SQLITE_THREADSAFE macro must be defined as either 0 or 1. @@ -367,14 +394,14 @@ defined(SQLITE_POW2_MEMORY_SIZE)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* -** If SQLITE_MALLOC_SOFT_LIMIT is defined, then try to keep the +** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ -#if defined(SQLITE_POW2_MEMORY_SIZE) && !defined(SQLITE_MALLOC_SOFT_LIMIT) +#if !defined(SQLITE_MALLOC_SOFT_LIMIT) # define SQLITE_MALLOC_SOFT_LIMIT 1024 #endif /* ** We need to define _XOPEN_SOURCE as follows in order to enable @@ -442,10 +469,24 @@ #else # define TESTONLY(X) #endif /* +** Sometimes we need a small amount of code such as a variable initialization +** to setup for a later assert() statement. We do not want this code to +** appear when assert() is disabled. The following macro is therefore +** used to contain that setup code. The "VVA" acronym stands for +** "Verification, Validation, and Accreditation". In other words, the +** code within VVA_ONLY() will only run during verification processes. +*/ +#ifndef NDEBUG +# define VVA_ONLY(X) X +#else +# define VVA_ONLY(X) +#endif + +/* ** The ALWAYS and NEVER macros surround boolean expressions which ** are intended to always be true or false, respectively. Such ** expressions could be omitted from the code completely. But they ** are included in a few cases in order to enhance the resilience ** of SQLite to unexpected behavior - to make the code "self-healing" @@ -460,13 +501,12 @@ */ #if defined(SQLITE_COVERAGE_TEST) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) -SQLITE_PRIVATE int sqlite3Assert(void); -# define ALWAYS(X) ((X)?1:sqlite3Assert()) -# define NEVER(X) ((X)?sqlite3Assert():0) +# define ALWAYS(X) ((X)?1:(assert(0),0)) +# define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif @@ -480,24 +520,10 @@ # define likely(X) __builtin_expect((X),1) # define unlikely(X) __builtin_expect((X),0) #else # define likely(X) !!(X) # define unlikely(X) !!(X) -#endif - -/* -** Sometimes we need a small amount of code such as a variable initialization -** to setup for a later assert() statement. We do not want this code to -** appear when assert() is disabled. The following macro is therefore -** used to contain that setup code. The "VVA" acronym stands for -** "Verification, Validation, and Accreditation". In other words, the -** code within VVA_ONLY() will only run during verification processes. -*/ -#ifndef NDEBUG -# define VVA_ONLY(X) X -#else -# define VVA_ONLY(X) #endif /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ /************** Begin file sqlite3.h *****************************************/ /* @@ -518,23 +544,21 @@ ** notice, and should not be referenced by programs that use SQLite. ** ** Some of the definitions that are in this file are marked as ** "experimental". Experimental interfaces are normally new ** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. +** to experimental interfaces but reserve the right to make minor changes +** if experience from use "in the wild" suggest such changes are prudent. ** ** The official C-language API documentation for SQLite is derived ** from comments in this file. This file is the authoritative source ** on how SQLite interfaces are suppose to operate. ** ** The name of this file under configuration management is "sqlite.h.in". ** The makefile makes some minor changes to this file (such as inserting ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. -** -** @(#) $Id: sqlite.h.in,v 1.440 2009/04/06 15:55:04 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include <stdarg.h> /* Needed for the definition of va_list */ @@ -551,14 +575,19 @@ */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif +#ifndef SQLITE_API +# define SQLITE_API +#endif + + /* ** These no-op macros are used in front of interfaces to mark those ** interfaces as either deprecated or experimental. New applications -** should not use deprecated intrfaces - they are support for backwards +** should not use deprecated interfaces - they are support for backwards ** compatibility only. Application writers should be aware that ** experimental interfaces are subject to change in point releases. ** ** These macros used to resolve to various kinds of compiler magic that ** would generate warning messages when they were used. But that @@ -584,55 +613,85 @@ ** ** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in ** the sqlite3.h file specify the version of SQLite with which ** that header file is associated. ** -** The "version" of SQLite is a string of the form "X.Y.Z". -** The phrase "alpha" or "beta" might be appended after the Z. -** The X value is major version number always 3 in SQLite3. -** The X value only changes when backwards compatibility is +** The "version" of SQLite is a string of the form "W.X.Y" or "W.X.Y.Z". +** The W value is major version number and is always 3 in SQLite3. +** The W value only changes when backwards compatibility is ** broken and we intend to never break backwards compatibility. -** The Y value is the minor version number and only changes when +** The X value is the minor version number and only changes when ** there are major feature enhancements that are forwards compatible ** but not backwards compatible. -** The Z value is the release number and is incremented with -** each release but resets back to 0 whenever Y is incremented. -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. +** The Y value is the release number and is incremented with +** each release but resets back to 0 whenever X is incremented. +** The Z value only appears on branch releases. +** +** The SQLITE_VERSION_NUMBER is an integer that is computed as +** follows: +** +** <blockquote><pre> +** SQLITE_VERSION_NUMBER = W*1000000 + X*1000 + Y +** </pre></blockquote> +** +** Since version 3.6.18, SQLite source code has been stored in the +** <a href="http://www.fossil-scm.org/">fossil configuration management +** system</a>. The SQLITE_SOURCE_ID +** macro is a string which identifies a particular check-in of SQLite +** within its configuration management system. The string contains the +** date and time of the check-in (UTC) and an SHA1 hash of the entire +** source tree. +** +** See also: [sqlite3_libversion()], +** [sqlite3_libversion_number()], [sqlite3_sourceid()], +** [sqlite_version()] and [sqlite_source_id()]. ** ** Requirements: [H10011] [H10014] */ -#define SQLITE_VERSION "3.6.13" -#define SQLITE_VERSION_NUMBER 3006013 +#define SQLITE_VERSION "3.6.18" +#define SQLITE_VERSION_NUMBER 3006018 +#define SQLITE_SOURCE_ID "2009-09-11 14:05:07 b084828a771ec40be85f07c590ca99de4f6c24ee" /* ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> ** KEYWORDS: sqlite3_version ** -** These features provide the same information as the [SQLITE_VERSION] -** and [SQLITE_VERSION_NUMBER] #defines in the header, but are associated -** with the library instead of the header file. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. +** These interfaces provide the same information as the [SQLITE_VERSION], +** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] #defines in the header, +** but are associated with the library instead of the header file. Cautious +** programmers might include assert() statements in their application to +** verify that values returned by these interfaces match the macros in +** the header, and thus insure that the application is +** compiled with matching library and header files. +** +** <blockquote><pre> +** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); +** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 ); +** assert( strcmp(sqlite3_libversion,SQLITE_VERSION)==0 ); +** </pre></blockquote> ** ** The sqlite3_libversion() function returns the same information as is ** in the sqlite3_version[] string constant. The function is provided ** for use in DLLs since DLL users usually do not have direct access to string -** constants within the DLL. +** constants within the DLL. Similarly, the sqlite3_sourceid() function +** returns the same information as is in the [SQLITE_SOURCE_ID] #define of +** the header file. +** +** See also: [sqlite_version()] and [sqlite_source_id()]. ** ** Requirements: [H10021] [H10022] [H10023] */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} <S60100> ** ** SQLite can be compiled with or without mutexes. When -** the [SQLITE_THREADSAFE] C preprocessor macro 1 or 2, mutexes +** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes ** are enabled and SQLite is threadsafe. When the ** [SQLITE_THREADSAFE] macro is 0, ** the mutexes are omitted. Without the mutexes, it is not safe ** to use SQLite concurrently from more than one thread. ** @@ -639,11 +698,11 @@ ** Enabling mutexes incurs a measurable performance penalty. ** So if speed is of utmost importance, it makes sense to disable ** the mutexes. But for maximum safety, mutexes should be enabled. ** The default behavior is for mutexes to be enabled. ** -** This interface can be used by a program to make sure that the +** This interface can be used by an application to make sure that the ** version of SQLite that it is linking against was compiled with ** the desired setting of the [SQLITE_THREADSAFE] macro. ** ** This interface only reports on the compile-time mutex setting ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with @@ -892,24 +951,26 @@ ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the xOpen method of the ** [sqlite3_vfs] object. */ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 -#define SQLITE_OPEN_NOMUTEX 0x00008000 -#define SQLITE_OPEN_FULLMUTEX 0x00010000 +#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ +#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ +#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ /* ** CAPI3REF: Device Characteristics {H10240} <H11120> ** ** The xDeviceCapabilities method of the [sqlite3_io_methods] @@ -973,12 +1034,13 @@ #define SQLITE_SYNC_DATAONLY 0x00010 /* ** CAPI3REF: OS Interface Open File Handle {H11110} <S20110> ** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will +** An [sqlite3_file] object represents an open file in the +** [sqlite3_vfs | OS interface layer]. Individual OS interface +** implementations will ** want to subclass this object by appending additional fields ** for their own use. The pMethods entry is a pointer to an ** [sqlite3_io_methods] object that defines methods for performing ** I/O operations on the open file. */ @@ -993,10 +1055,16 @@ ** Every file opened by the [sqlite3_vfs] xOpen method populates an ** [sqlite3_file] object (or, more commonly, a subclass of the ** [sqlite3_file] object) with a pointer to an instance of this object. ** This object defines the methods used to perform various operations ** against the open file represented by the [sqlite3_file] object. +** +** If the xOpen method sets the sqlite3_file.pMethods element +** to a non-NULL pointer, then the sqlite3_io_methods.xClose method +** may be invoked even if the xOpen reported that it failed. The +** only way to prevent a call to xClose following a failed xOpen +** is for the xOpen to set the sqlite3_file.pMethods element to NULL. ** ** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or ** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). ** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] ** flag may be ORed in to indicate that only the data of the file @@ -1154,15 +1222,15 @@ ** ** SQLite will guarantee that the zFilename parameter to xOpen ** is either a NULL pointer or string obtained ** from xFullPathname(). SQLite further guarantees that ** the string will be valid and unchanged until xClose() is -** called. Because of the previous sentense, +** called. Because of the previous sentence, ** the [sqlite3_file] can safely store a pointer to the ** filename if it needs to remember the filename for some reason. ** If the zFilename parameter is xOpen is a NULL pointer then xOpen -** must invite its own temporary name for the file. Whenever the +** must invent its own temporary name for the file. Whenever the ** xFilename parameter is NULL it will also be the case that the ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. ** ** The flags argument to xOpen() includes all bits set in ** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] @@ -1202,18 +1270,28 @@ ** ** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be ** deleted when it is closed. The [SQLITE_OPEN_DELETEONCLOSE] ** will be set for TEMP databases, journals and for subjournals. ** -** The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. +** The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction +** with the [SQLITE_OPEN_CREATE] flag, which are both directly +** analogous to the O_EXCL and O_CREAT flags of the POSIX open() +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** SQLITE_OPEN_CREATE, is used to indicate that file should always +** be created, and that it is an error if it already exists. +** It is <i>not</i> used to indicate the file should be opened +** for exclusive access. ** ** At least szOsFile bytes of memory are allocated by SQLite ** to hold the [sqlite3_file] structure passed as the third ** argument to xOpen. The xOpen method does not have to -** allocate the structure; it should just fill it in. +** allocate the structure; it should just fill it in. Note that +** the xOpen method must set the sqlite3_file.pMethods to either +** a valid [sqlite3_io_methods] object or to NULL. xOpen must do +** this even if the open fails. SQLite expects that the sqlite3_file.pMethods +** element will be valid after xOpen returns regardless of the success +** or failure of the xOpen call. ** ** The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] ** to test whether a file is at least readable. The file can be a @@ -1291,10 +1369,15 @@ ** the process, or if it is the first time sqlite3_initialize() is invoked ** following a call to sqlite3_shutdown(). Only an effective call ** of sqlite3_initialize() does any initialization. All other calls ** are harmless no-ops. ** +** A call to sqlite3_shutdown() is an "effective" call if it is the first +** call to sqlite3_shutdown() since the last sqlite3_initialize(). Only +** an effective call to sqlite3_shutdown() does any deinitialization. +** All other calls to sqlite3_shutdown() are harmless no-ops. +** ** Among other things, sqlite3_initialize() shall invoke ** sqlite3_os_init(). Similarly, sqlite3_shutdown() ** shall invoke sqlite3_os_end(). ** ** The sqlite3_initialize() routine returns [SQLITE_OK] on success. @@ -1329,12 +1412,13 @@ ** or sqlite3_os_end() directly. The application should only invoke ** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() ** interface is called automatically by sqlite3_initialize() and ** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate ** implementations for sqlite3_os_init() and sqlite3_os_end() -** are built into SQLite when it is compiled for unix, windows, or os/2. -** When built for other platforms (using the [SQLITE_OS_OTHER=1] compile-time +** are built into SQLite when it is compiled for Unix, Windows, or OS/2. +** When [custom builds | built for other platforms] +** (using the [SQLITE_OS_OTHER=1] compile-time ** option) the application must supply a suitable implementation for ** sqlite3_os_init() and sqlite3_os_end(). An application-supplied ** implementation of sqlite3_os_init() or sqlite3_os_end() ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. @@ -1411,42 +1495,69 @@ ** and low-level memory allocation routines. ** ** This object is used in only one place in the SQLite interface. ** A pointer to an instance of this object is the argument to ** [sqlite3_config()] when the configuration option is -** [SQLITE_CONFIG_MALLOC]. By creating an instance of this object -** and passing it to [sqlite3_config()] during configuration, an -** application can specify an alternative memory allocation subsystem -** for SQLite to use for all of its dynamic memory needs. -** -** Note that SQLite comes with a built-in memory allocator that is -** perfectly adequate for the overwhelming majority of applications +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** By creating an instance of this object +** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) +** during configuration, an application can specify an alternative +** memory allocation subsystem for SQLite to use for all of its +** dynamic memory needs. +** +** Note that SQLite comes with several [built-in memory allocators] +** that are perfectly adequate for the overwhelming majority of applications ** and that this object is only useful to a tiny minority of applications ** with specialized memory allocation requirements. This object is ** also used during testing of SQLite in order to specify an alternative ** memory allocator that simulates memory out-of-memory conditions in ** order to verify that SQLite recovers gracefully from such ** conditions. ** -** The xMalloc, xFree, and xRealloc methods must work like the -** malloc(), free(), and realloc() functions from the standard library. +** The xMalloc and xFree methods must work like the +** malloc() and free() functions from the standard C library. +** The xRealloc method must work like realloc() from the standard C library +** with the exception that if the second argument to xRealloc is zero, +** xRealloc must be a no-op - it must not perform any allocation or +** deallocation. SQLite guaranteeds that the second argument to +** xRealloc is always a value returned by a prior call to xRoundup. +** And so in cases where xRoundup always returns a positive number, +** xRealloc can perform exactly as the standard library realloc() and +** still be in compliance with this specification. ** ** xSize should return the allocated size of a memory allocation ** previously obtained from xMalloc or xRealloc. The allocated size ** is always at least as big as the requested size but may be larger. ** ** The xRoundup method returns what would be the allocated size of ** a memory allocation given a particular requested size. Most memory ** allocators round up memory allocations at least to the next multiple ** of 8. Some allocators round up to a larger multiple or to a power of 2. +** Every memory allocation request coming in through [sqlite3_malloc()] +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** that causes the corresponding memory allocation to fail. ** ** The xInit method initializes the memory allocator. (For example, ** it might allocate any require mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite3_shutdown()] and should deallocate any resources acquired ** by xInit. The pAppData pointer is used as the only parameter to ** xInit and xShutdown. +** +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. For all other methods, SQLite +** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the +** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which +** it is by default) and so the methods are automatically serialized. +** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other +** methods must be threadsafe or else make their own arrangements for +** serialization. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). */ typedef struct sqlite3_mem_methods sqlite3_mem_methods; struct sqlite3_mem_methods { void *(*xMalloc)(int); /* Memory allocation function */ void (*xFree)(void*); /* Free a prior allocation */ @@ -1526,16 +1637,18 @@ ** </ul> ** </dd> ** ** <dt>SQLITE_CONFIG_SCRATCH</dt> ** <dd>This option specifies a static memory buffer that SQLite can use for -** scratch memory. There are three arguments: A pointer to the memory, the -** size of each scratch buffer (sz), and the number of buffers (N). The sz +** scratch memory. There are three arguments: A pointer an 8-byte +** aligned memory buffer from which the scrach allocations will be +** drawn, the size of each scratch allocation (sz), +** and the maximum number of scratch allocations (N). The sz ** argument must be a multiple of 16. The sz parameter should be a few bytes -** larger than the actual scratch space required due internal overhead. -** The first -** argument should point to an allocation of at least sz*N bytes of memory. +** larger than the actual scratch space required due to internal overhead. +** The first argument should pointer to an 8-byte aligned buffer +** of at least sz*N bytes of memory. ** SQLite will use no more than one scratch buffer at once per thread, so ** N should be set to the expected maximum number of threads. The sz ** parameter should be 6 times the size of the largest database page size. ** Scratch buffers are used as part of the btree balance operation. If ** The btree balancer needs additional memory beyond what is provided by @@ -1545,33 +1658,41 @@ ** <dt>SQLITE_CONFIG_PAGECACHE</dt> ** <dd>This option specifies a static memory buffer that SQLite can use for ** the database page cache with the default page cache implemenation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option. -** There are three arguments to this option: A pointer to the +** There are three arguments to this option: A pointer to 8-byte aligned ** memory, the size of each page buffer (sz), and the number of pages (N). -** The sz argument must be a power of two between 512 and 32768. The first +** The sz argument should be the size of the largest database page +** (a power of two between 512 and 32768) plus a little extra for each +** page header. The page header size is 20 to 40 bytes depending on +** the host architecture. It is harmless, apart from the wasted memory, +** to make sz a little too large. The first ** argument should point to an allocation of at least sz*N bytes of memory. ** SQLite will use the memory provided by the first argument to satisfy its ** memory needs for the first N pages that it adds to cache. If additional ** page cache memory is needed beyond what is provided by this option, then ** SQLite goes to [sqlite3_malloc()] for the additional storage space. ** The implementation might use one or more of the N buffers to hold -** memory accounting information. </dd> +** memory accounting information. The pointer in the first argument must +** be aligned to an 8-byte boundary or subsequent behavior of SQLite +** will be undefined.</dd> ** ** <dt>SQLITE_CONFIG_HEAP</dt> ** <dd>This option specifies a static memory buffer that SQLite will use ** for all of its dynamic memory allocation needs beyond those provided ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. -** There are three arguments: A pointer to the memory, the number of -** bytes in the memory buffer, and the minimum allocation size. If -** the first pointer (the memory pointer) is NULL, then SQLite reverts +** There are three arguments: An 8-byte aligned pointer to the memory, +** the number of bytes in the memory buffer, and the minimum allocation size. +** If the first pointer (the memory pointer) is NULL, then SQLite reverts ** to using its default memory allocator (the system malloc() implementation), ** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. If the ** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or ** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory -** allocator is engaged to handle all of SQLites memory allocation needs.</dd> +** allocator is engaged to handle all of SQLites memory allocation needs. +** The first pointer (the memory pointer) must be aligned to an 8-byte +** boundary or subsequent behavior of SQLite will be undefined.</dd> ** ** <dt>SQLITE_CONFIG_MUTEX</dt> ** <dd>This option takes a single argument which is a pointer to an ** instance of the [sqlite3_mutex_methods] structure. The argument specifies ** alternative low-level mutex routines to be used in place @@ -1586,13 +1707,16 @@ ** routines with a wrapper used to track mutex usage for performance ** profiling or testing, for example.</dd> ** ** <dt>SQLITE_CONFIG_LOOKASIDE</dt> ** <dd>This option takes two arguments that determine the default -** memory allcation lookaside optimization. The first argument is the +** memory allocation lookaside optimization. The first argument is the ** size of each lookaside buffer slot and the second is the number of -** slots allocated to each database connection.</dd> +** slots allocated to each database connection. This option sets the +** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** verb to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.</dd> ** ** <dt>SQLITE_CONFIG_PCACHE</dt> ** <dd>This option takes a single argument which is a pointer to ** an [sqlite3_pcache_methods] object. This object specifies the interface ** to a custom page cache implementation. SQLite makes a copy of the @@ -1638,16 +1762,19 @@ ** <dl> ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dd>This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. ** The first argument (the third parameter to [sqlite3_db_config()] is a -** pointer to a memory buffer to use for lookaside memory. The first -** argument may be NULL in which case SQLite will allocate the lookaside -** buffer itself using [sqlite3_malloc()]. The second argument is the +** pointer to an memory buffer to use for lookaside memory. +** The first argument may be NULL in which case SQLite will allocate the +** lookaside buffer itself using [sqlite3_malloc()]. The second argument is the ** size of each lookaside buffer slot and the third argument is the number of ** slots. The size of the buffer in the first argument must be greater than -** or equal to the product of the second and third arguments.</dd> +** or equal to the product of the second and third arguments. The buffer +** must be aligned to an 8-byte boundary. If the second argument is not +** a multiple of 8, it is internally rounded down to the next smaller +** multiple of 8. See also: [SQLITE_CONFIG_LOOKASIDE]</dd> ** ** </dl> */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ @@ -1718,18 +1845,22 @@ ** Only changes that are directly specified by the [INSERT], [UPDATE], ** or [DELETE] statement are counted. Auxiliary changes caused by ** triggers are not counted. Use the [sqlite3_total_changes()] function ** to find the total number of changes including changes caused by triggers. ** +** Changes to a view that are simulated by an [INSTEAD OF trigger] +** are not counted. Only real table changes are counted. +** ** A "row change" is a change to a single row of a single table ** caused by an INSERT, DELETE, or UPDATE statement. Rows that -** are changed as side effects of REPLACE constraint resolution, -** rollback, ABORT processing, DROP TABLE, or by any other +** are changed as side effects of [REPLACE] constraint resolution, +** rollback, ABORT processing, [DROP TABLE], or by any other ** mechanisms do not count as direct row changes. ** ** A "trigger context" is a scope of execution that begins and -** ends with the script of a trigger. Most SQL statements are +** ends with the script of a [CREATE TRIGGER | trigger]. +** Most SQL statements are ** evaluated outside of any trigger. This is the "top level" ** trigger context. If a trigger fires from the top level, a ** new trigger context is entered for the duration of that one ** trigger. Subtriggers create subcontexts for their duration. ** @@ -1747,20 +1878,12 @@ ** changes in the most recently completed INSERT, UPDATE, or DELETE ** statement within the body of the same trigger. ** However, the number returned does not include changes ** caused by subtriggers since those have their own context. ** -** SQLite implements the command "DELETE FROM table" without a WHERE clause -** by dropping and recreating the table. Doing so is much faster than going -** through and deleting individual elements from the table. Because of this -** optimization, the deletions in "DELETE FROM table" are not row changes and -** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()] -** functions, regardless of the number of elements that were originally -** in the table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. Or recompile using the -** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the -** optimization on all queries. +** See also the [sqlite3_total_changes()] interface and the +** [count_changes pragma]. ** ** Requirements: ** [H12241] [H12243] ** ** If a separate thread makes changes on the same database connection @@ -1770,31 +1893,25 @@ SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified {H12260} <S10600> ** -** This function returns the number of row changes caused by INSERT, -** UPDATE or DELETE statements since the [database connection] was opened. -** The count includes all changes from all trigger contexts. However, -** the count does not include changes used to implement REPLACE constraints, -** do rollbacks or ABORT processing, or DROP table processing. +** This function returns the number of row changes caused by [INSERT], +** [UPDATE] or [DELETE] statements since the [database connection] was opened. +** The count includes all changes from all +** [CREATE TRIGGER | trigger] contexts. However, +** the count does not include changes used to implement [REPLACE] constraints, +** do rollbacks or ABORT processing, or [DROP TABLE] processing. The +** count does not include rows of views that fire an [INSTEAD OF trigger], +** though if the INSTEAD OF trigger makes changes of its own, those changes +** are counted. ** The changes are counted as soon as the statement that makes them is ** completed (when the statement handle is passed to [sqlite3_reset()] or ** [sqlite3_finalize()]). ** -** SQLite implements the command "DELETE FROM table" without a WHERE clause -** by dropping and recreating the table. (This is much faster than going -** through and deleting individual elements from the table.) Because of this -** optimization, the deletions in "DELETE FROM table" are not row changes and -** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()] -** functions, regardless of the number of elements that were originally -** in the table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. Or recompile using the -** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the -** optimization on all queries. -** -** See also the [sqlite3_changes()] interface. +** See also the [sqlite3_changes()] interface and the +** [count_changes pragma]. ** ** Requirements: ** [H12261] [H12263] ** ** If a separate thread makes changes on the same database connection @@ -1824,12 +1941,20 @@ ** An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. ** If the interrupted SQL operation is an INSERT, UPDATE, or DELETE ** that is inside an explicit transaction, then the entire transaction ** will be rolled back automatically. ** -** A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. +** The sqlite3_interrupt(D) call is in effect until all currently running +** SQL statements on [database connection] D complete. Any new SQL statements +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been +** running prior to the sqlite3_interrupt() call. New SQL statements +** that are started after the running statement count reaches zero are +** not effected by the sqlite3_interrupt(). +** A call to sqlite3_interrupt(D) that occurs when there are no running +** SQL statements is a no-op and has no effect on SQL statements +** that are started after the sqlite3_interrupt() call returns. ** ** Requirements: ** [H12271] [H12272] ** ** If the database connection closes while [sqlite3_interrupt()] @@ -1838,23 +1963,33 @@ SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} <S70200> ** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or +** These routines are useful during command-line input to determine if the +** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string +** SQLite for parsing. These routines return 1 if the input string ** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon token and is not a fragment of a -** CREATE TRIGGER statement. Semicolons that are embedded within +** complete if it ends with a semicolon token and is not a prefix of a +** well-formed CREATE TRIGGER statement. Semicolons that are embedded within ** string literals or quoted identifier names or comments are not ** independent tokens (they are part of the token in which they are -** embedded) and thus do not count as a statement terminator. +** embedded) and thus do not count as a statement terminator. Whitespace +** and comments that follow the final semicolon are ignored. +** +** These routines return 0 if the statement is incomplete. If a +** memory allocation fails, then SQLITE_NOMEM is returned. ** ** These routines do not parse the SQL statements thus ** will not detect syntactically incorrect SQL. +** +** If SQLite has not been initialized using [sqlite3_initialize()] prior +** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked +** automatically by sqlite3_complete16(). If that initialization fails, +** then the return value from sqlite3_complete16() will be non-zero +** regardless of whether or not the input SQL is complete. ** ** Requirements: [H10511] [H10512] ** ** The input to [sqlite3_complete()] must be a zero-terminated ** UTF-8 string. @@ -2039,11 +2174,11 @@ SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions {H17400} <S70000><S20000> ** -** These routines are workalikes of the "printf()" family of functions +** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. ** ** The sqlite3_mprintf() and sqlite3_vmprintf() routines write their ** results into memory obtained from [sqlite3_malloc()]. ** The strings returned by these two routines should be @@ -2279,24 +2414,29 @@ ** ** When the callback returns [SQLITE_OK], that means the operation ** requested is ok. When the callback returns [SQLITE_DENY], the ** [sqlite3_prepare_v2()] or equivalent call that triggered the ** authorizer will fail with an error message explaining that -** access is denied. If the authorizer code is [SQLITE_READ] -** and the callback returns [SQLITE_IGNORE] then the -** [prepared statement] statement is constructed to substitute -** a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] -** return can be used to deny an untrusted user access to individual -** columns of a table. +** access is denied. ** ** The first parameter to the authorizer callback is a copy of the third ** parameter to the sqlite3_set_authorizer() interface. The second parameter ** to the callback is an integer [SQLITE_COPY | action code] that specifies ** the particular action to be authorized. The third through sixth parameters ** to the callback are zero-terminated strings that contain additional ** details about the action to be authorized. +** +** If the action code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** If the action code is [SQLITE_DELETE] and the callback returns +** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the +** [truncate optimization] is disabled and all rows are deleted individually. ** ** An authorizer is used when [sqlite3_prepare | preparing] ** SQL statements from an untrusted source, to ensure that the SQL statements ** do not try to access data they are not allowed to see, or that they do not ** try to execute malicious statements that damage the database. For @@ -2321,17 +2461,19 @@ ** the database connection that invoked the authorizer callback. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** When [sqlite3_prepare_v2()] is used to prepare a statement, the -** statement might be reprepared during [sqlite3_step()] due to a +** statement might be re-prepared during [sqlite3_step()] due to a ** schema change. Hence, the application should ensure that the ** correct authorizer callback remains in place during the [sqlite3_step()]. ** ** Note that the authorizer callback is invoked only during ** [sqlite3_prepare()] or its variants. Authorization is not -** performed during statement evaluation in [sqlite3_step()]. +** performed during statement evaluation in [sqlite3_step()], unless +** as stated in the previous paragraph, sqlite3_step() invokes +** sqlite3_prepare_v2() to reprepare a statement after a schema change. ** ** Requirements: ** [H12501] [H12502] [H12503] [H12504] [H12505] [H12506] [H12507] [H12510] ** [H12511] [H12512] [H12520] [H12521] [H12522] */ @@ -2486,11 +2628,12 @@ ** ** The sqlite3_open_v2() interface works like sqlite3_open() ** except that it accepts two additional parameters for additional control ** over the new database connection. The flags parameter can take one of ** the following three values, optionally combined with the -** [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags: +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** and/or [SQLITE_OPEN_PRIVATECACHE] flags: ** ** <dl> ** <dt>[SQLITE_OPEN_READONLY]</dt> ** <dd>The database is opened in read-only mode. If the database does not ** already exist, an error is returned.</dd> @@ -2506,19 +2649,25 @@ ** sqlite3_open() and sqlite3_open16().</dd> ** </dl> ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** combinations shown above or one of the combinations shown above combined -** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags, +** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], +** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_SHAREDCACHE] flags, ** then the behavior is undefined. ** ** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection ** opens in the multi-thread [threading mode] as long as the single-thread ** mode has not been set at compile-time or start-time. If the ** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens ** in the serialized [threading mode] unless single-thread was ** previously selected at compile-time or start-time. +** The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. ** ** If the filename is ":memory:", then a private, temporary in-memory database ** is created for the connection. This in-memory database will vanish when ** the database connection is closed. Future versions of SQLite might ** make use of additional special filenames that begin with the ":" character. @@ -2708,10 +2857,13 @@ ** [GLOB] operators.</dd> ** ** <dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt> ** <dd>The maximum number of variables in an SQL statement that can ** be bound.</dd> +** +** <dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt> +** <dd>The maximum depth of recursion for triggers.</dd> ** </dl> */ #define SQLITE_LIMIT_LENGTH 0 #define SQLITE_LIMIT_SQL_LENGTH 1 #define SQLITE_LIMIT_COLUMN 2 @@ -2720,10 +2872,11 @@ #define SQLITE_LIMIT_VDBE_OP 5 #define SQLITE_LIMIT_FUNCTION_ARG 6 #define SQLITE_LIMIT_ATTACHED 7 #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 #define SQLITE_LIMIT_VARIABLE_NUMBER 9 +#define SQLITE_LIMIT_TRIGGER_DEPTH 10 /* ** CAPI3REF: Compiling An SQL Statement {H13010} <S10000> ** KEYWORDS: {SQL statement compiler} ** @@ -2896,22 +3049,23 @@ ** CAPI3REF: Binding Values To Prepared Statements {H13500} <S70300> ** KEYWORDS: {host parameter} {host parameters} {host parameter name} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} ** ** In the SQL strings input to [sqlite3_prepare_v2()] and its variants, -** literals may be replaced by a [parameter] in one of these forms: +** literals may be replaced by a [parameter] that matches one of following +** templates: ** ** <ul> ** <li> ? ** <li> ?NNN ** <li> :VVV ** <li> @VVV ** <li> $VVV ** </ul> ** -** In the parameter forms shown above NNN is an integer literal, -** and VVV is an alpha-numeric parameter name. The values of these +** In the templates above, NNN represents an integer literal, +** and VVV represents an alphanumeric identifer. The values of these ** parameters (also called "host parameter names" or "SQL parameters") ** can be set using the sqlite3_bind_*() routines defined here. ** ** The first argument to the sqlite3_bind_*() routines is always ** a pointer to the [sqlite3_stmt] object returned from @@ -3549,18 +3703,21 @@ ** characters. Any attempt to create a function with a longer name ** will result in [SQLITE_ERROR] being returned. ** ** The third parameter (nArg) ** is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. +** aggregate takes. If this parameter is -1, then the SQL function or +** aggregate may take any number of arguments between 0 and the limit +** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third +** parameter is less than -1 or greater than 127 then the behavior is +** undefined. ** ** The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for ** its parameters. Any SQL function implementation should be able to work ** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to +** more efficient with one encoding than another. An application may ** invoke sqlite3_create_function() or sqlite3_create_function16() multiple ** times with the same function but with different values of eTextRep. ** When multiple implementations of the same function are available, SQLite ** will pick the one that involves the least amount of data conversion. ** If there is only a single implementation which does not care what text @@ -3578,11 +3735,11 @@ ** SQL function or aggregate, pass NULL for all three function callbacks. ** ** It is permitted to register multiple implementations of the same ** functions with the same name but with either differing numbers of ** arguments or differing preferred text encodings. SQLite will use -** the implementation most closely matches the way in which the +** the implementation that most closely matches the way in which the ** SQL function is used. A function implementation with a non-negative ** nArg parameter is a better match than a function implementation with ** a negative nArg. A function where the preferred text encoding ** matches the database encoding is a better ** match than a function where the encoding is different. @@ -3601,11 +3758,11 @@ ** SQLite interfaces. However, such calls must not ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. ** ** Requirements: -** [H16103] [H16106] [H16109] [H16112] [H16118] [H16121] [H16124] [H16127] +** [H16103] [H16106] [H16109] [H16112] [H16118] [H16121] [H16127] ** [H16130] [H16133] [H16136] [H16139] [H16142] */ SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, @@ -3926,14 +4083,15 @@ ** function result. ** If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that ** function as the destructor on the text or BLOB result when it has ** finished using that result. -** If the 4th parameter to the sqlite3_result_text* interfaces or +** If the 4th parameter to the sqlite3_result_text* interfaces or to ** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite ** assumes that the text or BLOB result is in constant space and does not -** copy the it or call a destructor when it has finished using that result. +** copy the content of the parameter nor call a destructor on the content +** when it has finished using that result. ** If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT ** then SQLite makes a copy of the result into space obtained from ** from [sqlite3_malloc()] before it returns. ** @@ -3983,16 +4141,18 @@ ** for sqlite3_create_collation() and sqlite3_create_collation_v2() ** and a UTF-16 string for sqlite3_create_collation16(). In all cases ** the name is passed as the second function argument. ** ** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied +** [SQLITE_UTF16LE], or [SQLITE_UTF16BE], indicating that the user-supplied ** routine expects to be passed pointers to strings encoded using UTF-8, ** UTF-16 little-endian, or UTF-16 big-endian, respectively. The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that +** third argument might also be [SQLITE_UTF16] to indicate that the routine +** expects pointers to be UTF-16 strings in the native byte order, or the +** argument can be [SQLITE_UTF16_ALIGNED] if the ** the routine expects pointers to 16-bit word aligned strings -** of UTF-16 in the native byte order of the host computer. +** of UTF-16 in the native byte order. ** ** A pointer to the user supplied routine must be passed as the fifth ** argument. If it is NULL, this is the same as deleting the collation ** sequence (so that SQLite cannot call it anymore). ** Each time the application supplied function is invoked, it is passed @@ -4012,10 +4172,12 @@ ** destroyed and is passed a copy of the fourth parameter void* pointer ** of the sqlite3_create_collation_v2(). ** Collations are destroyed when they are overridden by later calls to the ** collation creation functions or when the [database connection] is closed ** using [sqlite3_close()]. +** +** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. ** ** Requirements: ** [H16603] [H16604] [H16606] [H16609] [H16612] [H16615] [H16618] [H16621] ** [H16624] [H16627] [H16630] */ @@ -4212,15 +4374,15 @@ /* ** CAPI3REF: Commit And Rollback Notification Callbacks {H12950} <S60400> ** ** The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. +** function to be invoked whenever a transaction is [COMMIT | committed]. ** Any callback set by a previous call to sqlite3_commit_hook() ** for the same database connection is overridden. ** The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. +** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. ** Any callback set by a previous call to sqlite3_commit_hook() ** for the same database connection is overridden. ** The pArg argument is passed through to the callback. ** If the callback on a commit hook function returns non-zero, ** then the commit is converted into a rollback. @@ -4236,18 +4398,26 @@ ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** Registering a NULL function disables the callback. ** +** When the commit hook callback routine returns zero, the [COMMIT] +** operation is allowed to continue normally. If the commit hook +** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. +** The rollback hook is invoked on a rollback that results from a commit +** hook returning non-zero, just as it would be with any other rollback. +** ** For the purposes of this API, a transaction is said to have been ** rolled back if an explicit "ROLLBACK" statement is executed, or ** an error or constraint causes an implicit rollback to occur. ** The rollback callback is not invoked if a transaction is ** automatically rolled back because the database connection is closed. ** The rollback callback is not invoked if a transaction is ** rolled back because a commit callback returned non-zero. ** <todo> Check on this </todo> +** +** See also the [sqlite3_update_hook()] interface. ** ** Requirements: ** [H12951] [H12952] [H12953] [H12954] [H12955] ** [H12961] [H12962] [H12963] [H12964] */ @@ -4276,19 +4446,29 @@ ** In the case of an update, this is the [rowid] after the update takes place. ** ** The update hook is not invoked when internal system tables are ** modified (i.e. sqlite_master and sqlite_sequence). ** +** In the current implementation, the update hook +** is not invoked when duplication rows are deleted because of an +** [ON CONFLICT | ON CONFLICT REPLACE] clause. Nor is the update hook +** invoked when rows are deleted using the [truncate optimization]. +** The exceptions defined in this paragraph might change in a future +** release of SQLite. +** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the ** completion of the [sqlite3_step()] call that triggered the update hook. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** If another function was previously registered, its pArg value ** is returned. Otherwise NULL is returned. +** +** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] +** interfaces. ** ** Requirements: ** [H12971] [H12973] [H12975] [H12977] [H12979] [H12981] [H12983] [H12986] */ SQLITE_API void *sqlite3_update_hook( @@ -4297,11 +4477,11 @@ void* ); /* ** CAPI3REF: Enable Or Disable Shared Pager Cache {H10330} <S30900> -** KEYWORDS: {shared cache} {shared cache mode} +** KEYWORDS: {shared cache} ** ** This routine enables or disables the sharing of the database cache ** and schema data structures between [database connection | connections] ** to the same database. Sharing is enabled if the argument is true ** and disabled if the argument is false. @@ -4566,19 +4746,24 @@ typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; typedef struct sqlite3_module sqlite3_module; /* ** CAPI3REF: Virtual Table Object {H18000} <S20400> -** KEYWORDS: sqlite3_module -** EXPERIMENTAL -** -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. +** KEYWORDS: sqlite3_module {virtual table module} +** EXPERIMENTAL +** +** This structure, sometimes called a a "virtual table module", +** defines the implementation of a [virtual tables]. +** This structure consists mostly of methods for the module. +** +** A virtual table module is created by filling in a persistent +** instance of this structure and passing a pointer to that instance +** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. +** The registration remains valid until it is replaced by a different +** module or until the [database connection] closes. The content +** of this structure must not change while it is registered with +** any database connection. */ struct sqlite3_module { int iVersion; int (*xCreate)(sqlite3*, void *pAux, int argc, const char *const*argv, @@ -4612,12 +4797,12 @@ ** CAPI3REF: Virtual Table Indexing Information {H18100} <S20400> ** KEYWORDS: sqlite3_index_info ** EXPERIMENTAL ** ** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the +** pass information into and receive the reply from the [xBestIndex] +** method of a [virtual table module]. The fields under **Inputs** are the ** inputs to xBestIndex and are read-only. xBestIndex inserts its ** results into the **Outputs** fields. ** ** The aConstraint[] array records WHERE clause constraints of the form: ** @@ -4636,31 +4821,30 @@ ** form that refer to the particular virtual table being queried. ** ** Information about the ORDER BY clause is stored in aOrderBy[]. ** Each term of aOrderBy records a column of the ORDER BY clause. ** -** The xBestIndex method must fill aConstraintUsage[] with information +** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the ** virtual table and is not checked again by SQLite. ** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in +** The idxNum and idxPtr values are recorded and passed into the +** [xFilter] method. +** [sqlite3_free()] is used to free idxPtr if and only iff +** needToFreeIdxPtr is true. +** +** The orderByConsumed means that output from [xFilter]/[xNext] will occur in ** the correct order to satisfy the ORDER BY clause so that no separate ** sorting step is required. ** ** The estimatedCost value is an estimate of the cost of doing the ** particular lookup. A full scan of a table with N entries should have ** a cost of N. A binary search of a table of N entries should have a ** cost of approximately log(N). -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. */ struct sqlite3_index_info { /* Inputs */ int nConstraint; /* Number of entries in aConstraint */ struct sqlite3_index_constraint { @@ -4694,88 +4878,94 @@ /* ** CAPI3REF: Register A Virtual Table Implementation {H18200} <S20400> ** EXPERIMENTAL ** -** This routine is used to register a new module name with a -** [database connection]. Module names must be registered before -** creating new virtual tables on the module, or before using -** preexisting virtual tables of the module. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. +** This routine is used to register a new [virtual table module] name. +** Module names must be registered before +** creating a new [virtual table] using the module, or before using a +** preexisting [virtual table] for the module. +** +** The module name is registered on the [database connection] specified +** by the first parameter. The name of the module is given by the +** second parameter. The third parameter is a pointer to +** the implementation of the [virtual table module]. The fourth +** parameter is an arbitrary client data pointer that is passed through +** into the [xCreate] and [xConnect] methods of the virtual table module +** when a new virtual table is be being created or reinitialized. +** +** This interface has exactly the same effect as calling +** [sqlite3_create_module_v2()] with a NULL client data destructor. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ ); /* ** CAPI3REF: Register A Virtual Table Implementation {H18210} <S20400> ** EXPERIMENTAL ** -** This routine is identical to the [sqlite3_create_module()] method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. +** This routine is identical to the [sqlite3_create_module()] method, +** except that it has an extra parameter to specify +** a destructor function for the client data pointer. SQLite will +** invoke the destructor function (if it is not NULL) when SQLite +** no longer needs the pClientData pointer. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ void(*xDestroy)(void*) /* Module destructor function */ ); /* ** CAPI3REF: Virtual Table Instance Object {H18010} <S20400> ** KEYWORDS: sqlite3_vtab ** EXPERIMENTAL ** -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will +** Every [virtual table module] implementation uses a subclass +** of the following structure to describe a particular instance +** of the [virtual table]. Each subclass will ** be tailored to the specific needs of the module implementation. ** The purpose of this superclass is to define certain fields that are ** common to all module implementations. ** ** Virtual tables methods can set an error message by assigning a ** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should ** take care that any prior string is freed by a call to [sqlite3_free()] ** prior to assigning a new string to zErrMsg. After the error message ** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. +** freed by sqlite3_free() and the zErrMsg field will be zeroed. */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ + int nRef; /* NO LONGER USED */ char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; /* ** CAPI3REF: Virtual Table Cursor Object {H18020} <S20400> -** KEYWORDS: sqlite3_vtab_cursor -** EXPERIMENTAL -** -** Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used +** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} +** EXPERIMENTAL +** +** Every [virtual table module] implementation uses a subclass of the +** following structure to describe cursors that point into the +** [virtual table] and are used ** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define +** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed +** by the [sqlite3_module.xClose | xClose] method. Cussors are used +** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods +** of the module. Each module implementation will define ** the content of a cursor structure to suit its own needs. ** ** This superclass exists in order to define fields of the cursor that ** are common to all implementations. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. */ struct sqlite3_vtab_cursor { sqlite3_vtab *pVtab; /* Virtual table of this cursor */ /* Virtual table implementations will typically add additional fields */ }; @@ -4782,37 +4972,33 @@ /* ** CAPI3REF: Declare The Schema Of A Virtual Table {H18280} <S20400> ** EXPERIMENTAL ** -** The xCreate and xConnect methods of a module use the following API +** The [xCreate] and [xConnect] methods of a +** [virtual table module] call this interface ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400> ** EXPERIMENTAL ** ** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions +** using the [xFindFunction] method of the [virtual table module]. +** But global versions of those functions ** must exist in order to be overloaded. ** ** This API makes sure a global version of a function with a particular ** name and number of parameters exists. If no such function exists ** before this API is called, a new function is created. The implementation ** of the new function always causes an exception to be thrown. So ** the new function is not good for anything by itself. Its only ** purpose is to be a placeholder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. +** by a [virtual table]. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up @@ -4849,24 +5035,27 @@ ** ** <pre> ** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow; ** </pre> {END} ** -** If the flags parameter is non-zero, the the BLOB is opened for read +** If the flags parameter is non-zero, then the BLOB is opened for read ** and write access. If it is zero, the BLOB is opened for read access. ** ** Note that the database name is not the filename that contains ** the database but rather the symbolic name of the database that ** is assigned when the database is connected using [ATTACH]. ** For the main database file, the database name is "main". ** For TEMP tables, the database name is "temp". ** ** On success, [SQLITE_OK] is returned and the new [BLOB handle] is written -** to *ppBlob. Otherwise an [error code] is returned and any value written -** to *ppBlob should not be used by the caller. +** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set +** to be a null pointer. ** This function sets the [database connection] error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related +** functions. Note that the *ppBlob variable is always initialized in a +** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob +** regardless of the success or failure of this routine. ** ** If the row that a BLOB handle points to is modified by an ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects ** then the BLOB handle is marked as "expired". ** This is true if any column of the row is changed, even a column @@ -4874,10 +5063,23 @@ ** Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for ** a expired BLOB handle fail with an return code of [SQLITE_ABORT]. ** Changes written into a BLOB prior to the BLOB expiring are not ** rollback by the expiration of the BLOB. Such changes will eventually ** commit if the transaction continues to completion. +** +** Use the [sqlite3_blob_bytes()] interface to determine the size of +** the opened blob. The size of a blob may not be changed by this +** interface. Use the [UPDATE] SQL command to change the size of a +** blob. +** +** The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces +** and the built-in [zeroblob] SQL function can be used, if desired, +** to create an empty, zero-filled blob in which to read or write using +** this interface. +** +** To avoid a resource leak, every open [BLOB handle] should eventually +** be released by a call to [sqlite3_blob_close()]. ** ** Requirements: ** [H17813] [H17814] [H17816] [H17819] [H17821] [H17824] */ SQLITE_API int sqlite3_blob_open( @@ -4897,30 +5099,40 @@ ** ** Closing a BLOB shall cause the current transaction to commit ** if there are no other BLOBs, no pending prepared statements, and the ** database connection is in [autocommit mode]. ** If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} +** until the close operation if they will fit. ** ** Closing the BLOB often forces the changes ** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {H17833} Any errors that occur during +** at the time when the BLOB is closed. Any errors that occur during ** closing are reported as a non-zero return value. ** ** The BLOB is closed unconditionally. Even if this routine returns ** an error code, the BLOB is still closed. +** +** Calling this routine with a null pointer (which as would be returned +** by failed call to [sqlite3_blob_open()]) is a harmless no-op. ** ** Requirements: ** [H17833] [H17836] [H17839] */ SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB {H17840} <S30230> ** -** Returns the size in bytes of the BLOB accessible via the open -** []BLOB handle] in its only argument. +** Returns the size in bytes of the BLOB accessible via the +** successfully opened [BLOB handle] in its only argument. The +** incremental blob I/O routines can only read or overwriting existing +** blob content; they cannot change the size of a blob. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. ** ** Requirements: ** [H17843] */ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); @@ -4933,16 +5145,25 @@ ** from the open BLOB, starting at offset iOffset. ** ** If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is read. If N or iOffset is ** less than zero, [SQLITE_ERROR] is returned and no data is read. +** The size of the blob (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. ** ** An attempt to read from an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ** ** On success, SQLITE_OK is returned. ** Otherwise, an [error code] or an [extended error code] is returned. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_write()]. ** ** Requirements: ** [H17853] [H17856] [H17859] [H17862] [H17863] [H17865] [H17868] */ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); @@ -4961,10 +5182,12 @@ ** This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is written. If N is ** less than zero [SQLITE_ERROR] is returned and no data is written. +** The size of the BLOB (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. ** ** An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. Writes to the BLOB that occurred ** before the [BLOB handle] expired are not rolled back by the ** expiration of the handle, though of course those changes might @@ -4971,10 +5194,17 @@ ** have been overwritten by the statement that expired the BLOB handle ** or by other independent statements. ** ** On success, SQLITE_OK is returned. ** Otherwise, an [error code] or an [extended error code] is returned. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_read()]. ** ** Requirements: ** [H17873] [H17874] [H17875] [H17876] [H17877] [H17879] [H17882] [H17885] ** [H17888] */ @@ -5076,11 +5306,11 @@ ** cases where it really needs one. {END} If a faster non-recursive mutex ** implementation is available on the host platform, the mutex subsystem ** might return such a mutex in response to SQLITE_MUTEX_FAST. ** ** {H17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are +** a pointer to a static preexisting mutex. {END} Six static mutexes are ** used by the current version of SQLite. Future versions of SQLite ** may add additional static mutexes. Static mutexes are for internal ** use by SQLite only. Applications that use SQLite mutexes should ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or ** SQLITE_MUTEX_RECURSIVE. @@ -5182,10 +5412,25 @@ ** of a valid mutex handle. The implementations of the methods defined ** by this structure are not required to handle this case, the results ** of passing a NULL pointer instead of a valid mutex handle are undefined ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). +** +** The xMutexInit() method must be threadsafe. It must be harmless to +** invoke xMutexInit() mutiple times within the same process and without +** intervening calls to xMutexEnd(). Second and subsequent calls to +** xMutexInit() must be no-ops. +** +** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). Similarly, xMutexAlloc() must not use SQLite memory +** allocation for a static mutex. However xMutexAlloc() may use SQLite +** memory allocation for a fast or recursive mutex. +** +** SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is +** called, but only if the prior call to xMutexInit returned SQLITE_OK. +** If xMutexInit fails in any way, it is expected to clean up after itself +** prior to returning. */ typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; struct sqlite3_mutex_methods { int (*xMutexInit)(void); int (*xMutexEnd)(void); @@ -5322,10 +5567,13 @@ #define SQLITE_TESTCTRL_PRNG_RESET 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 +#define SQLITE_TESTCTRL_ASSERT 12 +#define SQLITE_TESTCTRL_ALWAYS 13 +#define SQLITE_TESTCTRL_RESERVE 14 /* ** CAPI3REF: SQLite Runtime Status {H17200} <S60200> ** EXPERIMENTAL ** @@ -5344,11 +5592,11 @@ ** value. For these latter parameters nothing is written into *pCurrent. ** ** This routine returns SQLITE_OK on success and a non-zero ** [error code] on failure. ** -** This routine is threadsafe but is not atomic. This routine can +** This routine is threadsafe but is not atomic. This routine can be ** called while other threads are running the same or different SQLite ** interfaces. However the values returned in *pCurrent and ** *pHighwater reflect the status of SQLite at different points in time ** and it is possible that another thread might change the parameter ** in between the times when *pCurrent and *pHighwater are written. @@ -5467,11 +5715,18 @@ /* ** CAPI3REF: Status Parameters for database connections {H17520} <H17500> ** EXPERIMENTAL ** -** Status verbs for [sqlite3_db_status()]. +** These constants are the available integer "verbs" that can be passed as +** the second argument to the [sqlite3_db_status()] interface. +** +** New verbs may be added in future releases of SQLite. Existing verbs +** might be discontinued. Applications should check the return code from +** [sqlite3_db_status()] to make sure that the call worked. +** The [sqlite3_db_status()] interface will return a non-zero error code +** if a discontinued or unsupported verb is invoked. ** ** <dl> ** <dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt> ** <dd>This parameter returns the number of lookaside memory slots currently ** checked out.</dd> @@ -5545,99 +5800,113 @@ */ typedef struct sqlite3_pcache sqlite3_pcache; /* ** CAPI3REF: Application Defined Page Cache. +** KEYWORDS: {page cache} ** EXPERIMENTAL ** ** The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can ** register an alternative page cache implementation by passing in an ** instance of the sqlite3_pcache_methods structure. The majority of the -** heap memory used by sqlite is used by the page cache to cache data read +** heap memory used by SQLite is used by the page cache to cache data read ** from, or ready to be written to, the database file. By implementing a ** custom page cache using this API, an application can control more -** precisely the amount of memory consumed by sqlite, the way in which -** said memory is allocated and released, and the policies used to +** precisely the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to ** determine exactly which parts of a database file are cached and for ** how long. ** -** The contents of the structure are copied to an internal buffer by sqlite -** within the call to [sqlite3_config]. +** The contents of the sqlite3_pcache_methods structure are copied to an +** internal buffer by SQLite within the call to [sqlite3_config]. Hence +** the application may discard the parameter after the call to +** [sqlite3_config()] returns. ** ** The xInit() method is called once for each call to [sqlite3_initialize()] ** (usually only once during the lifetime of the process). It is passed ** a copy of the sqlite3_pcache_methods.pArg value. It can be used to set ** up global structures and mutexes required by the custom page cache -** implementation. The xShutdown() method is called from within -** [sqlite3_shutdown()], if the application invokes this API. It can be used -** to clean up any outstanding resources before process shutdown, if required. -** -** The xCreate() method is used to construct a new cache instance. The +** implementation. +** +** The xShutdown() method is called from within [sqlite3_shutdown()], +** if the application invokes this API. It can be used to clean up +** any outstanding resources before process shutdown, if required. +** +** SQLite holds a [SQLITE_MUTEX_RECURSIVE] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. All other methods must be threadsafe +** in multithreaded applications. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +** +** The xCreate() method is used to construct a new cache instance. SQLite +** will typically create one cache instance for each open database file, +** though this is not guaranteed. The ** first parameter, szPage, is the size in bytes of the pages that must -** be allocated by the cache. szPage will not be a power of two. The -** second argument, bPurgeable, is true if the cache being created will -** be used to cache database pages read from a file stored on disk, or +** be allocated by the cache. szPage will not be a power of two. szPage +** will the page size of the database file that is to be cached plus an +** increment (here called "R") of about 100 or 200. SQLite will use the +** extra R bytes on each page to store metadata about the underlying +** database page on disk. The value of R depends +** on the SQLite version, the target platform, and how SQLite was compiled. +** R is constant for a particular build of SQLite. The second argument to +** xCreate(), bPurgeable, is true if the cache being created will +** be used to cache database pages of a file stored on disk, or ** false if it is used for an in-memory database. The cache implementation -** does not have to do anything special based on the value of bPurgeable, -** it is purely advisory. +** does not have to do anything special based with the value of bPurgeable; +** it is purely advisory. On a cache where bPurgeable is false, SQLite will +** never invoke xUnpin() except to deliberately delete a page. +** In other words, a cache created with bPurgeable set to false will +** never contain any unpinned pages. ** ** The xCachesize() method may be called at any time by SQLite to set the ** suggested maximum cache-size (number of pages stored by) the cache ** instance passed as the first argument. This is the value configured using ** the SQLite "[PRAGMA cache_size]" command. As with the bPurgeable parameter, -** the implementation is not required to do anything special with this -** value, it is advisory only. +** the implementation is not required to do anything with this +** value; it is advisory only. ** ** The xPagecount() method should return the number of pages currently -** stored in the cache supplied as an argument. +** stored in the cache. ** ** The xFetch() method is used to fetch a page and return a pointer to it. ** A 'page', in this context, is a buffer of szPage bytes aligned at an ** 8-byte boundary. The page to be fetched is determined by the key. The ** mimimum key value is 1. After it has been retrieved using xFetch, the page -** is considered to be pinned. -** -** If the requested page is already in the page cache, then a pointer to -** the cached buffer should be returned with its contents intact. If the -** page is not already in the cache, then the expected behaviour of the -** cache is determined by the value of the createFlag parameter passed -** to xFetch, according to the following table: +** is considered to be "pinned". +** +** If the requested page is already in the page cache, then the page cache +** implementation must return a pointer to the page buffer with its content +** intact. If the requested page is not already in the cache, then the +** behavior of the cache implementation is determined by the value of the +** createFlag parameter passed to xFetch, according to the following table: ** ** <table border=1 width=85% align=center> -** <tr><th>createFlag<th>Expected Behaviour -** <tr><td>0<td>NULL should be returned. No new cache entry is created. -** <tr><td>1<td>If createFlag is set to 1, this indicates that -** SQLite is holding pinned pages that can be unpinned -** by writing their contents to the database file (a -** relatively expensive operation). In this situation the -** cache implementation has two choices: it can return NULL, -** in which case SQLite will attempt to unpin one or more -** pages before re-requesting the same page, or it can -** allocate a new page and return a pointer to it. If a new -** page is allocated, then the first sizeof(void*) bytes of -** it (at least) must be zeroed before it is returned. -** <tr><td>2<td>If createFlag is set to 2, then SQLite is not holding any -** pinned pages associated with the specific cache passed -** as the first argument to xFetch() that can be unpinned. The -** cache implementation should attempt to allocate a new -** cache entry and return a pointer to it. Again, the first -** sizeof(void*) bytes of the page should be zeroed before -** it is returned. If the xFetch() method returns NULL when -** createFlag==2, SQLite assumes that a memory allocation -** failed and returns SQLITE_NOMEM to the user. +** <tr><th> createFlag <th> Behaviour when page is not already in cache +** <tr><td> 0 <td> Do not allocate a new page. Return NULL. +** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +** <tr><td> 2 <td> Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. ** </table> +** +** SQLite will normally invoke xFetch() with a createFlag of 0 or 1. If +** a call to xFetch() with createFlag==1 returns NULL, then SQLite will +** attempt to unpin one or more cache pages by spilling the content of +** pinned pages to disk and synching the operating system disk cache. After +** attempting to unpin pages, the xFetch() method will be invoked again with +** a createFlag of 2. ** ** xUnpin() is called by SQLite with a pointer to a currently pinned page ** as its second argument. If the third parameter, discard, is non-zero, ** then the page should be evicted from the cache. In this case SQLite ** assumes that the next time the page is retrieved from the cache using ** the xFetch() method, it will be zeroed. If the discard parameter is ** zero, then the page is considered to be unpinned. The cache implementation -** may choose to reclaim (free or recycle) unpinned pages at any time. -** SQLite assumes that next time the page is retrieved from the cache -** it will either be zeroed, or contain the same data that it did when it -** was unpinned. +** may choose to evict unpinned pages at any time. ** ** The cache is not required to perform any reference counting. A single ** call to xUnpin() unpins the page regardless of the number of prior calls ** to xFetch(). ** @@ -5989,10 +6258,22 @@ sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ ); + +/* +** CAPI3REF: String Comparison +** EXPERIMENTAL +** +** The [sqlite3_strnicmp()] API allows applications and extensions to +** compare the contents of two buffers containing UTF-8 strings in a +** case-indendent fashion, using the same definition of case independence +** that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT @@ -6001,10 +6282,11 @@ #if 0 } /* End of the 'extern "C"' block */ #endif #endif + /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include hash.h in the middle of sqliteInt.h ******************/ /************** Begin file hash.h ********************************************/ @@ -6020,11 +6302,11 @@ ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** -** $Id: hash.h,v 1.12 2008/10/10 17:41:29 drh Exp $ +** $Id: hash.h,v 1.15 2009/05/02 13:29:38 drh Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ @@ -6033,17 +6315,29 @@ /* A complete hash table is an instance of the following structure. ** The internals of this structure are intended to be opaque -- client ** code should not attempt to access or modify the fields of this structure ** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and +** However, some of the "procedures" and "functions" for modifying and ** accessing this structure are really macros, so we can't really make ** this structure opaque. +** +** All elements of the hash table are on a single doubly-linked list. +** Hash.first points to the head of this list. +** +** There are Hash.htsize buckets. Each bucket points to a spot in +** the global doubly-linked list. The contents of the bucket are the +** element pointed to plus the next _ht.count-1 elements in the list. +** +** Hash.htsize and Hash.ht may be zero. In that case lookup is done +** by a linear search of the global list. For small tables, the +** Hash.ht table is never allocated because if there are few elements +** in the table, it is faster to do a linear search than to manage +** the hash table. */ struct Hash { - unsigned int copyKey: 1; /* True if copy of key made on insert */ - unsigned int htsize : 31; /* Number of buckets in the hash table */ + unsigned int htsize; /* Number of buckets in the hash table */ unsigned int count; /* Number of entries in this table */ HashElem *first; /* The first element of the array */ struct _ht { /* the hash table */ int count; /* Number of entries with this hash */ HashElem *chain; /* Pointer to first entry with this hash */ @@ -6055,22 +6349,21 @@ ** ** Again, this structure is intended to be opaque, but it can't really ** be opaque because it is used by macros. */ struct HashElem { - HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ + 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 */ }; /* ** Access routines. To delete, insert a NULL pointer. */ -SQLITE_PRIVATE void sqlite3HashInit(Hash*, int copyKey); -SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData); -SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const void *pKey, int nKey); -SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey); +SQLITE_PRIVATE void sqlite3HashInit(Hash*); +SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData); +SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey); SQLITE_PRIVATE void sqlite3HashClear(Hash*); /* ** Macros for looping over all elements of a hash table. The idiom is ** like this: @@ -6084,17 +6377,17 @@ ** } */ #define sqliteHashFirst(H) ((H)->first) #define sqliteHashNext(E) ((E)->next) #define sqliteHashData(E) ((E)->data) -#define sqliteHashKey(E) ((E)->pKey) -#define sqliteHashKeysize(E) ((E)->nKey) +/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ +/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ /* ** Number of entries in a hash table */ -#define sqliteHashCount(H) ((H)->count) +/* #define sqliteHashCount(H) ((H)->count) // NOT USED */ #endif /* _SQLITE_HASH_H_ */ /************** End of hash.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -6269,15 +6562,16 @@ */ #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite_int64 # define LONGDOUBLE_TYPE sqlite_int64 # ifndef SQLITE_BIG_DBL -# define SQLITE_BIG_DBL (0x7fffffffffffffff) +# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # endif # define SQLITE_OMIT_DATETIME_FUNCS 1 # define SQLITE_OMIT_TRACE 1 # undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +# undef SQLITE_HAVE_ISNAN #endif #ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (1e99) #endif @@ -6313,10 +6607,14 @@ ** that the library can read. */ #define SQLITE_MAX_FILE_FORMAT 4 #ifndef SQLITE_DEFAULT_FILE_FORMAT # define SQLITE_DEFAULT_FILE_FORMAT 1 +#endif + +#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS +# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 #endif /* ** Provide a default value for SQLITE_TEMP_STORE in case it is not specified ** on the command-line @@ -6395,10 +6693,18 @@ typedef INT16_TYPE i16; /* 2-byte signed integer */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef INT8_TYPE i8; /* 1-byte signed integer */ /* +** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value +** that can be stored in a u32 without loss of data. The value +** is 0x00000000ffffffff. But because of quirks of some compilers, we +** have to specify the value in the less intuitive manner shown: +*/ +#define SQLITE_MAX_U32 ((((u64)1)<<32)-1) + +/* ** Macros to determine whether the machine is big or little endian, ** evaluated at runtime. */ #ifdef SQLITE_AMALGAMATION SQLITE_PRIVATE const int sqlite3one = 1; @@ -6437,10 +6743,11 @@ /* ** Assert that the pointer X is aligned to an 8-byte boundary. */ #define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) + /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** @@ -6534,23 +6841,26 @@ /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; +typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; typedef struct RowSet RowSet; typedef struct CollSeq CollSeq; typedef struct Column Column; typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; +typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; +typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; @@ -6561,14 +6871,15 @@ typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; -typedef struct TriggerStack TriggerStack; +typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct Trigger Trigger; typedef struct UnpackedRecord UnpackedRecord; +typedef struct VTable VTable; typedef struct Walker Walker; typedef struct WherePlan WherePlan; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; @@ -6592,11 +6903,11 @@ ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.113 2009/04/10 12:55:17 danielk1977 Exp $ +** @(#) $Id: btree.h,v 1.120 2009/07/22 00:35:24 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It @@ -6637,11 +6948,11 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( const char *zFilename, /* Name of database file to open */ sqlite3 *db, /* Associated database connection */ - Btree **, /* Return open Btree* here */ + Btree **ppBtree, /* Return open Btree* here */ int flags, /* Flags */ int vfsFlags /* Flags passed through to VFS open */ ); /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the @@ -6659,11 +6970,11 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); -SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree*,int,int,int); +SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); @@ -6676,12 +6987,12 @@ SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); -SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *); -SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *, int, u8); +SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); +SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); @@ -6695,13 +7006,35 @@ #define BTREE_ZERODATA 2 /* Table has keys only - no data */ #define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); -SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); +SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); + +SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); -SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); + +/* +** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta +** should be one of the following values. The integer values are assigned +** to constants so that the offset of the corresponding field in an +** SQLite database header may be found using the following formula: +** +** offset = 36 + (idx * 4) +** +** For example, the free-page-count field is located at byte offset 36 of +** the database file header. The incr-vacuum-flag field is located at +** byte offset 64 (== 36+4*7). +*/ +#define BTREE_FREE_PAGE_COUNT 0 +#define BTREE_SCHEMA_VERSION 1 +#define BTREE_FILE_FORMAT 2 +#define BTREE_DEFAULT_CACHE_SIZE 3 +#define BTREE_LARGEST_ROOT_PAGE 4 +#define BTREE_TEXT_ENCODING 5 +#define BTREE_USER_VERSION 6 +#define BTREE_INCR_VACUUM 7 SQLITE_PRIVATE int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ @@ -6709,17 +7042,10 @@ BtCursor *pCursor /* Space to write cursor structure */ ); SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeMoveto( - BtCursor*, - const void *pKey, - i64 nKey, - int bias, - int *pRes -); SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( BtCursor*, UnpackedRecord *pUnKey, i64 intKey, int bias, @@ -6727,20 +7053,18 @@ ); SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*); SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, - int nZero, int bias); + int nZero, int bias, int seekResult); SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeFlags(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); -SQLITE_PRIVATE sqlite3 *sqlite3BtreeCursorDb(const BtCursor*); SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); @@ -6750,10 +7074,14 @@ SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *); SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); + +#ifndef NDEBUG +SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); +#endif #ifndef SQLITE_OMIT_BTREECOUNT SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); #endif @@ -6824,11 +7152,11 @@ ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.141 2009/04/10 00:56:29 drh Exp $ +** $Id: vdbe.h,v 1.142 2009/07/24 17:58:53 danielk1977 Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ /* @@ -6842,10 +7170,11 @@ ** The names of the following types declared in vdbeInt.h are required ** for the VdbeOp definition. */ typedef struct VdbeFunc VdbeFunc; typedef struct Mem Mem; +typedef struct SubProgram SubProgram; /* ** A single instruction of the virtual machine has an opcode ** and as many as three operands. The instruction is recorded ** as an instance of the following structure: @@ -6856,23 +7185,24 @@ u8 opflags; /* Not currently used */ u8 p5; /* Fifth parameter is an unsigned character */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ int p3; /* The third parameter */ - union { /* forth parameter */ + union { /* fourth parameter */ int i; /* Integer value if p4type==P4_INT32 */ void *p; /* Generic pointer */ char *z; /* Pointer to data for string (char array) types */ i64 *pI64; /* Used when p4type is P4_INT64 */ double *pReal; /* Used when p4type is P4_REAL */ FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ - sqlite3_vtab *pVtab; /* Used when p4type is P4_VTAB */ + VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ + SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ } p4; #ifdef SQLITE_DEBUG char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE @@ -6879,10 +7209,23 @@ int cnt; /* Number of times this instruction was executed */ u64 cycles; /* Total time spent executing this instruction */ #endif }; typedef struct VdbeOp VdbeOp; + + +/* +** A sub-routine used to implement a trigger program. +*/ +struct SubProgram { + VdbeOp *aOp; /* Array of opcodes for sub-program */ + int nOp; /* Elements in aOp[] */ + int nMem; /* Number of memory cells required */ + int nCsr; /* Number of cursors required */ + int nRef; /* Number of pointers to this structure */ + void *token; /* id that may be used to recursive triggers */ +}; /* ** A smaller version of VdbeOp used for the VdbeAddOpList() function because ** it takes up less space. */ @@ -6893,11 +7236,11 @@ signed char p3; /* Third parameter */ }; typedef struct VdbeOpList VdbeOpList; /* -** Allowed values of VdbeOp.p3type +** Allowed values of VdbeOp.p4type */ #define P4_NOTUSED 0 /* The P4 parameter is not used */ #define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P4_STATIC (-2) /* Pointer to a static string */ #define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ @@ -6910,10 +7253,11 @@ #define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ +#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still ** gets freed when the Vdbe is finalized so it still should be obtained @@ -6973,26 +7317,26 @@ #define OP_OpenWrite 10 #define OP_NotNull 72 /* same as TK_NOTNULL */ #define OP_If 11 #define OP_ToInt 144 /* same as TK_TO_INT */ #define OP_String8 94 /* same as TK_STRING */ -#define OP_VRowid 12 -#define OP_CollSeq 13 -#define OP_OpenRead 14 -#define OP_Expire 15 -#define OP_AutoCommit 16 +#define OP_CollSeq 12 +#define OP_OpenRead 13 +#define OP_Expire 14 +#define OP_AutoCommit 15 #define OP_Gt 75 /* same as TK_GT */ -#define OP_Pagecount 17 -#define OP_IntegrityCk 18 -#define OP_Sort 20 -#define OP_Copy 21 -#define OP_Trace 22 -#define OP_Function 23 -#define OP_IfNeg 24 +#define OP_Pagecount 16 +#define OP_IntegrityCk 17 +#define OP_Sort 18 +#define OP_Copy 20 +#define OP_Trace 21 +#define OP_Function 22 +#define OP_IfNeg 23 #define OP_And 67 /* same as TK_AND */ #define OP_Subtract 85 /* same as TK_MINUS */ -#define OP_Noop 25 +#define OP_Noop 24 +#define OP_Program 25 #define OP_Return 26 #define OP_Remainder 88 /* same as TK_REM */ #define OP_NewRowid 27 #define OP_Multiply 86 /* same as TK_STAR */ #define OP_Variable 28 @@ -7009,97 +7353,97 @@ #define OP_MustBeInt 39 #define OP_Halt 40 #define OP_Rowid 41 #define OP_IdxLT 42 #define OP_AddImm 43 -#define OP_Statement 44 -#define OP_RowData 45 -#define OP_MemMax 46 +#define OP_RowData 44 +#define OP_MemMax 45 #define OP_Or 66 /* same as TK_OR */ -#define OP_NotExists 47 -#define OP_Gosub 48 +#define OP_NotExists 46 +#define OP_Gosub 47 #define OP_Divide 87 /* same as TK_SLASH */ -#define OP_Integer 49 +#define OP_Integer 48 #define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/ -#define OP_Prev 50 -#define OP_RowSetRead 51 +#define OP_Prev 49 +#define OP_RowSetRead 50 #define OP_Concat 89 /* same as TK_CONCAT */ -#define OP_RowSetAdd 52 +#define OP_RowSetAdd 51 #define OP_BitAnd 80 /* same as TK_BITAND */ -#define OP_VColumn 53 -#define OP_CreateTable 54 -#define OP_Last 55 -#define OP_SeekLe 56 +#define OP_VColumn 52 +#define OP_CreateTable 53 +#define OP_Last 54 +#define OP_SeekLe 55 #define OP_IsNull 71 /* same as TK_ISNULL */ -#define OP_IncrVacuum 57 -#define OP_IdxRowid 58 +#define OP_IncrVacuum 56 +#define OP_IdxRowid 57 #define OP_ShiftRight 83 /* same as TK_RSHIFT */ -#define OP_ResetCount 59 -#define OP_ContextPush 60 -#define OP_Yield 61 -#define OP_DropTrigger 62 -#define OP_DropIndex 63 -#define OP_IdxGE 64 -#define OP_IdxDelete 65 -#define OP_Vacuum 68 -#define OP_IfNot 69 -#define OP_DropTable 70 -#define OP_SeekLt 79 -#define OP_MakeRecord 90 +#define OP_ResetCount 58 +#define OP_Yield 59 +#define OP_DropTrigger 60 +#define OP_DropIndex 61 +#define OP_Param 62 +#define OP_IdxGE 63 +#define OP_IdxDelete 64 +#define OP_Vacuum 65 +#define OP_IfNot 68 +#define OP_DropTable 69 +#define OP_SeekLt 70 +#define OP_MakeRecord 79 #define OP_ToBlob 142 /* same as TK_TO_BLOB */ -#define OP_ResultRow 91 -#define OP_Delete 92 -#define OP_AggFinal 95 -#define OP_Compare 96 +#define OP_ResultRow 90 +#define OP_Delete 91 +#define OP_AggFinal 92 +#define OP_Compare 95 #define OP_ShiftLeft 82 /* same as TK_LSHIFT */ -#define OP_Goto 97 -#define OP_TableLock 98 -#define OP_Clear 99 +#define OP_Goto 96 +#define OP_TableLock 97 +#define OP_Clear 98 #define OP_Le 76 /* same as TK_LE */ -#define OP_VerifyCookie 100 -#define OP_AggStep 101 +#define OP_VerifyCookie 99 +#define OP_AggStep 100 #define OP_ToText 141 /* same as TK_TO_TEXT */ #define OP_Not 19 /* same as TK_NOT */ #define OP_ToReal 145 /* same as TK_TO_REAL */ -#define OP_SetNumColumns 102 -#define OP_Transaction 103 -#define OP_VFilter 104 +#define OP_Transaction 101 +#define OP_VFilter 102 #define OP_Ne 73 /* same as TK_NE */ -#define OP_VDestroy 105 -#define OP_ContextPop 106 +#define OP_VDestroy 103 #define OP_BitOr 81 /* same as TK_BITOR */ -#define OP_Next 107 -#define OP_Count 108 -#define OP_IdxInsert 109 +#define OP_Next 104 +#define OP_Count 105 +#define OP_IdxInsert 106 #define OP_Lt 77 /* same as TK_LT */ -#define OP_SeekGe 110 -#define OP_Insert 111 -#define OP_Destroy 112 -#define OP_ReadCookie 113 -#define OP_LoadAnalysis 114 -#define OP_Explain 115 -#define OP_HaltIfNull 116 -#define OP_OpenPseudo 117 -#define OP_OpenEphemeral 118 -#define OP_Null 119 -#define OP_Move 120 -#define OP_Blob 121 +#define OP_SeekGe 107 +#define OP_Insert 108 +#define OP_Destroy 109 +#define OP_ReadCookie 110 +#define OP_RowSetTest 111 +#define OP_LoadAnalysis 112 +#define OP_Explain 113 +#define OP_HaltIfNull 114 +#define OP_OpenPseudo 115 +#define OP_OpenEphemeral 116 +#define OP_Null 117 +#define OP_Move 118 +#define OP_Blob 119 #define OP_Add 84 /* same as TK_PLUS */ -#define OP_Rewind 122 -#define OP_SeekGt 123 -#define OP_VBegin 124 -#define OP_VUpdate 125 -#define OP_IfZero 126 +#define OP_Rewind 120 +#define OP_SeekGt 121 +#define OP_VBegin 122 +#define OP_VUpdate 123 +#define OP_IfZero 124 #define OP_BitNot 93 /* same as TK_BITNOT */ -#define OP_VCreate 127 -#define OP_Found 128 -#define OP_IfPos 129 -#define OP_NullRow 131 -#define OP_Jump 132 -#define OP_Permutation 133 +#define OP_VCreate 125 +#define OP_Found 126 +#define OP_IfPos 127 +#define OP_NullRow 128 +#define OP_Jump 129 +#define OP_Permutation 131 /* The following opcode values are never used */ +#define OP_NotUsed_132 132 +#define OP_NotUsed_133 133 #define OP_NotUsed_134 134 #define OP_NotUsed_135 135 #define OP_NotUsed_136 136 #define OP_NotUsed_137 137 #define OP_NotUsed_138 138 @@ -7117,26 +7461,26 @@ #define OPFLG_IN2 0x0008 /* in2: P2 is an input */ #define OPFLG_IN3 0x0010 /* in3: P3 is an input */ #define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ /* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x08, 0x02, 0x00,\ -/* 8 */ 0x00, 0x04, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00,\ -/* 16 */ 0x00, 0x02, 0x00, 0x04, 0x01, 0x04, 0x00, 0x00,\ -/* 24 */ 0x05, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x00,\ +/* 8 */ 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,\ +/* 16 */ 0x02, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x05,\ +/* 24 */ 0x00, 0x01, 0x04, 0x02, 0x00, 0x02, 0x04, 0x00,\ /* 32 */ 0x00, 0x00, 0x00, 0x02, 0x11, 0x11, 0x02, 0x05,\ -/* 40 */ 0x00, 0x02, 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11,\ -/* 48 */ 0x01, 0x02, 0x01, 0x21, 0x08, 0x00, 0x02, 0x01,\ -/* 56 */ 0x11, 0x01, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00,\ -/* 64 */ 0x11, 0x00, 0x2c, 0x2c, 0x00, 0x05, 0x00, 0x05,\ -/* 72 */ 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x11,\ +/* 40 */ 0x00, 0x02, 0x11, 0x04, 0x00, 0x08, 0x11, 0x01,\ +/* 48 */ 0x02, 0x01, 0x21, 0x08, 0x00, 0x02, 0x01, 0x11,\ +/* 56 */ 0x01, 0x02, 0x00, 0x04, 0x00, 0x00, 0x02, 0x11,\ +/* 64 */ 0x00, 0x00, 0x2c, 0x2c, 0x05, 0x00, 0x11, 0x05,\ +/* 72 */ 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00,\ /* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\ /* 88 */ 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00,\ -/* 96 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 104 */ 0x01, 0x00, 0x00, 0x01, 0x02, 0x08, 0x11, 0x00,\ -/* 112 */ 0x02, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02,\ -/* 120 */ 0x00, 0x02, 0x01, 0x11, 0x00, 0x00, 0x05, 0x00,\ -/* 128 */ 0x11, 0x05, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,\ +/* 96 */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,\ +/* 104 */ 0x01, 0x02, 0x08, 0x11, 0x00, 0x02, 0x02, 0x15,\ +/* 112 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x02,\ +/* 120 */ 0x01, 0x11, 0x00, 0x00, 0x05, 0x00, 0x11, 0x05,\ +/* 128 */ 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\ /* 144 */ 0x04, 0x04,} /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -7161,15 +7505,16 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); +SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*); #endif SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); @@ -7176,10 +7521,12 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); +SQLITE_PRIVATE void sqlite3VdbeProgramDelete(sqlite3 *, SubProgram *, int); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int); #endif SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int); @@ -7216,11 +7563,11 @@ ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.100 2009/02/03 16:51:25 danielk1977 Exp $ +** @(#) $Id: pager.h,v 1.104 2009/07/24 19:01:19 drh Exp $ */ #ifndef _PAGER_H_ #define _PAGER_H_ @@ -7289,18 +7636,25 @@ ** that make up the Pager sub-system API. See source code comments for ** a detailed description of each routine. */ /* Open and close a Pager connection. */ -SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int); +SQLITE_PRIVATE int sqlite3PagerOpen( + sqlite3_vfs*, + Pager **ppPager, + const char*, + int, + int, + int, + void(*)(DbPage*) +); SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); -SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*)); -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*); +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*, int); SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int); SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *, int); @@ -7322,17 +7676,18 @@ SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); /* Functions used to manage pager transactions and savepoints. */ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*, int*); -SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag); +SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); +SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); /* Functions used to query pager state and configuration. */ SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*); @@ -7343,15 +7698,10 @@ SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); /* Functions used to truncate the database file. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); - -/* Used by encryption extensions. */ -#ifdef SQLITE_HAS_CODEC -SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*); -#endif /* Functions to support testing and debugging. */ #if !defined(NDEBUG) || defined(SQLITE_TEST) SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); @@ -7384,11 +7734,11 @@ ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. ** -** @(#) $Id: pcache.h,v 1.19 2009/01/20 17:06:27 danielk1977 Exp $ +** @(#) $Id: pcache.h,v 1.20 2009/07/25 11:46:49 danielk1977 Exp $ */ #ifndef _PCACHE_H_ typedef struct PgHdr PgHdr; @@ -7496,11 +7846,11 @@ SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); /* Return the total number of pages stored in the cache */ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); -#ifdef SQLITE_CHECK_PAGES +#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* Iterate through all dirty pages currently stored in the cache. This ** interface is only available if SQLITE_CHECK_PAGES is defined when the ** library is built. */ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); @@ -7760,10 +8110,15 @@ #define RESERVED_BYTE (PENDING_BYTE+1) #define SHARED_FIRST (PENDING_BYTE+2) #define SHARED_SIZE 510 /* +** Wrapper around OS specific sqlite3_os_init() function. +*/ +SQLITE_PRIVATE int sqlite3OsInit(void); + +/* ** Functions for accessing sqlite3_file methods */ SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*); SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); @@ -7896,12 +8251,10 @@ struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u8 safety_level; /* How aggressive at syncing data to disk */ - void *pAux; /* Auxiliary data. Usually NULL */ - void (*xFreeAux)(void*); /* Routine to free pAux */ Schema *pSchema; /* Pointer to database schema (possibly shared) */ }; /* ** An instance of the following structure stores a database schema. @@ -7917,11 +8270,10 @@ struct Schema { int schema_cookie; /* Database schema version number for this file */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ - Hash aFKey; /* Foreign keys indexed by to-table */ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ u8 file_format; /* Schema format version for this file */ u8 enc; /* Text encoding used by this database */ u16 flags; /* Flags associated with this schema */ int cache_size; /* Number of pages to use in the cache */ @@ -7955,11 +8307,11 @@ /* ** The number of different kinds of things that can be limited ** using the sqlite3_limit() interface. */ -#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1) +#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_DEPTH+1) /* ** Lookaside malloc is a set of fixed-size buffers that can be used ** to satisfy small transient memory allocation requests for objects ** associated with a particular database connection. The use of @@ -8045,20 +8397,20 @@ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ int nextPagesize; /* Pagesize after VACUUM if >0 */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ i64 lastRowid; /* ROWID of most recent insert (see above) */ - i64 priorNewRowid; /* Last randomly generated ROWID */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ sqlite3_mutex *mutex; /* Connection mutex */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ struct sqlite3InitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ u8 busy; /* TRUE if currently initializing */ + u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ struct Vdbe *pVdbe; /* List of active virtual machines */ int activeVdbeCnt; /* Number of VDBEs currently executing */ @@ -8095,21 +8447,19 @@ int nProgressOps; /* Number of opcodes for progress callback */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE Hash aModule; /* populated by sqlite3_create_module() */ Table *pVTab; /* vtab with active Connect/Create method */ - sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */ + VTable **aVTrans; /* Virtual tables with open transactions */ int nVTrans; /* Allocated size of aVTrans */ + VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ #endif FuncDefHash aFunc; /* Hash table of connection functions */ Hash aCollSeq; /* All collating sequences */ BusyHandler busyHandler; /* Busy callback */ int busyTimeout; /* Busy handler timeout, in msec */ Db aDbStatic[2]; /* Static space for the 2 default backends */ -#ifdef SQLITE_SSE - sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ -#endif Savepoint *pSavepoint; /* List of active savepoints */ int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ @@ -8164,13 +8514,12 @@ #define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ #define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ #define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */ #define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */ -#define SQLITE_SharedCache 0x00080000 /* Cache sharing is enabled */ -#define SQLITE_CommitBusy 0x00200000 /* In the process of committing */ -#define SQLITE_ReverseOrder 0x00400000 /* Reverse unordered SELECTs */ +#define SQLITE_ReverseOrder 0x00100000 /* Reverse unordered SELECTs */ +#define SQLITE_RecTriggers 0x00200000 /* Enable recursive triggers */ /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. @@ -8217,11 +8566,11 @@ ** FUNCTION(zName, nArg, iArg, bNC, xFunc) ** Used to create a scalar function definition of a function zName ** implemented by C function xFunc that accepts nArg arguments. The ** value passed as iArg is cast to a (void*) and made available ** as the user-data (sqlite3_user_data()) for the function. If -** argument bNC is true, then the FuncDef.needCollate flag is set. +** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set. ** ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters ** are interpreted in the same way as the first 4 parameters to @@ -8234,17 +8583,20 @@ ** available as the function user-data (sqlite3_user_data()). The ** FuncDef.flags variable is set to the value passed as the flags ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, bNC*8, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0} + {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0} #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, bNC*8, pArg, 0, xFunc, 0, 0, #zName, 0} + {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + pArg, 0, xFunc, 0, 0, #zName, 0} #define LIKEFUNC(zName, nArg, arg, flags) \ {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0} #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ - {nArg, SQLITE_UTF8, nc*8, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0} + {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \ + SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0} /* ** All current savepoints are stored in a linked list starting at ** sqlite3.pSavepoint. The first element in the list is the most recently ** opened savepoint. Savepoints are added to the list by the vdbe @@ -8281,10 +8633,11 @@ ** of this structure. */ struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ + char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* True if there is a NOT NULL constraint */ u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ char affinity; /* One of the SQLITE_AFF_... values */ @@ -8371,10 +8724,60 @@ */ #define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ #define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ /* +** An object of this type is created for each virtual table present in +** the database schema. +** +** If the database schema is shared, then there is one instance of this +** structure for each database connection (sqlite3*) that uses the shared +** schema. This is because each database connection requires its own unique +** instance of the sqlite3_vtab* handle used to access the virtual table +** implementation. sqlite3_vtab* handles can not be shared between +** database connections, even when the rest of the in-memory database +** schema is shared, as the implementation often stores the database +** connection handle passed to it via the xConnect() or xCreate() method +** during initialization internally. This database connection handle may +** then used by the virtual table implementation to access real tables +** within the database. So that they appear as part of the callers +** transaction, these accesses need to be made via the same database +** connection as that used to execute SQL operations on the virtual table. +** +** All VTable objects that correspond to a single table in a shared +** database schema are initially stored in a linked-list pointed to by +** the Table.pVTable member variable of the corresponding Table object. +** When an sqlite3_prepare() operation is required to access the virtual +** table, it searches the list for the VTable that corresponds to the +** database connection doing the preparing so as to use the correct +** sqlite3_vtab* handle in the compiled query. +** +** When an in-memory Table object is deleted (for example when the +** schema is being reloaded for some reason), the VTable objects are not +** deleted and the sqlite3_vtab* handles are not xDisconnect()ed +** immediately. Instead, they are moved from the Table.pVTable list to +** another linked list headed by the sqlite3.pDisconnect member of the +** corresponding sqlite3 structure. They are then deleted/xDisconnected +** next time a statement is prepared using said sqlite3*. This is done +** to avoid deadlock issues involving multiple sqlite3.mutex mutexes. +** Refer to comments above function sqlite3VtabUnlockList() for an +** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect +** list without holding the corresponding sqlite3.mutex mutex. +** +** The memory for objects of this type is always allocated by +** sqlite3DbMalloc(), using the connection handle stored in VTable.db as +** the first argument. +*/ +struct VTable { + sqlite3 *db; /* Database connection associated with this table */ + Module *pMod; /* Pointer to module implementation */ + sqlite3_vtab *pVtab; /* Pointer to vtab instance */ + int nRef; /* Number of pointers to this structure */ + VTable *pNext; /* Next in linked list (see above) */ +}; + +/* ** Each SQL table is represented in memory by an instance of the ** following structure. ** ** Table.zName is the name of the table. The case of the original ** CREATE TABLE statement is stored, but case is not significant for @@ -8421,12 +8824,11 @@ #endif #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE - Module *pMod; /* Pointer to the implementation of the module */ - sqlite3_vtab *pVtab; /* Pointer to the module instance */ + VTable *pVTable; /* List of VTable objects. */ int nModuleArg; /* Number of arguments to the module */ char **azModuleArg; /* Text of all module args. [0] is module name */ #endif Trigger *pTrigger; /* List of triggers stored in pSchema */ Schema *pSchema; /* Schema that contains this table */ @@ -8473,32 +8875,25 @@ ** ** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". ** ** Each REFERENCES clause generates an instance of the following structure ** which is attached to the from-table. The to-table need not exist when -** the from-table is created. The existence of the to-table is not checked -** until an attempt is made to insert data into the from-table. -** -** The sqlite.aFKey hash table stores pointers to this structure -** given the name of a to-table. For each to-table, all foreign keys -** associated with that table are on a linked list using the FKey.pNextTo -** field. +** the from-table is created. The existence of the to-table is not checked. */ struct FKey { Table *pFrom; /* The table that contains the REFERENCES clause */ FKey *pNextFrom; /* Next foreign key in pFrom */ char *zTo; /* Name of table that the key points to */ - FKey *pNextTo; /* Next foreign key that points to zTo */ - int nCol; /* Number of columns in this key */ - struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ - int iFrom; /* Index of column in pFrom */ - char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ - } *aCol; /* One entry for each of nCol column s */ + int nCol; /* Number of columns in this key */ u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ u8 updateConf; /* How to resolve conflicts that occur on UPDATE */ u8 deleteConf; /* How to resolve conflicts that occur on DELETE */ u8 insertConf; /* How to resolve conflicts that occur on INSERT */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ + } aCol[1]; /* One entry for each of nCol column s */ }; /* ** SQLite supports many different ways to resolve a constraint ** error. ROLLBACK processing means that a constraint violation @@ -8568,10 +8963,11 @@ */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ u16 nField; /* Number of entries in apMem[] */ u16 flags; /* Boolean settings. UNPACKED_... below */ + i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */ Mem *aMem; /* Values */ }; /* ** Allowed values of UnpackedRecord.flags @@ -8579,10 +8975,11 @@ #define UNPACKED_NEED_FREE 0x0001 /* Memory is from sqlite3Malloc() */ #define UNPACKED_NEED_DESTROY 0x0002 /* apMem[]s should all be destroyed */ #define UNPACKED_IGNORE_ROWID 0x0004 /* Ignore trailing rowid on key1 */ #define UNPACKED_INCRKEY 0x0008 /* Make this key an epsilon larger */ #define UNPACKED_PREFIX_MATCH 0x0010 /* A prefix match is considered OK */ +#define UNPACKED_PREFIX_SEARCH 0x0020 /* A prefix match is considered OK */ /* ** Each SQL index is represented in memory by an ** instance of the following structure. ** @@ -8620,10 +9017,24 @@ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ + IndexSample *aSample; /* Array of SQLITE_INDEX_SAMPLES samples */ +}; + +/* +** Each sample stored in the sqlite_stat2 table is represented in memory +** using a structure of this type. +*/ +struct IndexSample { + union { + char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */ + double r; /* Value if eType is SQLITE_FLOAT or SQLITE_INTEGER */ + } u; + u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */ + u8 nByte; /* Size in byte of text or blob. */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. @@ -8631,13 +9042,12 @@ ** Note if Token.z==0 then Token.dyn and Token.n are undefined and ** may contain random values. Do not make any assumptions about Token.dyn ** and Token.n when Token.z==0. */ struct Token { - const unsigned char *z; /* Text of the token. Not NULL-terminated! */ - unsigned dyn : 1; /* True for malloced memory, false for static */ - unsigned n : 31; /* Number of characters in this token */ + const char *z; /* Text of the token. Not NULL-terminated! */ + unsigned int n; /* Number of characters in this token */ }; /* ** An instance of this structure contains information needed to generate ** code for a SELECT that contains aggregate functions. @@ -8734,34 +9144,29 @@ ** ** Expr objects can use a lot of memory space in database schema. To ** help reduce memory requirements, sometimes an Expr object will be ** truncated. And to reduce the number of memory allocations, sometimes ** two or more Expr objects will be stored in a single memory allocation, -** together with Expr.token and/or Expr.span strings. -** -** If the EP_Reduced, EP_SpanToken, and EP_TokenOnly flags are set when +** together with Expr.zToken strings. +** +** If the EP_Reduced and EP_TokenOnly flags are set when ** an Expr object is truncated. When EP_Reduced is set, then all ** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees ** are contained within the same memory allocation. Note, however, that ** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately ** allocated, regardless of whether or not EP_Reduced is set. */ struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ - VVA_ONLY(u8 vvaFlags;) /* Flags used for VV&A only. EVVA_* below. */ u16 flags; /* Various flags. EP_* See below */ - Token token; /* An operand token */ - - /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no - ** space is allocated for the fields below this point. An attempt to - ** access them will result in a segfault or malfunction. - *********************************************************************/ - - Token span; /* Complete text of the expression */ - - /* If the EP_SpanToken flag is set in the Expr.flags mask, then no + union { + char *zToken; /* Token value. Zero terminated and dequoted */ + int iValue; /* Integer value if EP_IntValue */ + } u; + + /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ Expr *pLeft; /* Left subnode */ @@ -8775,15 +9180,19 @@ /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ - int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the - ** iColumn-th field of the iTable-th table. */ - AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ - int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + int iTable; /* TK_COLUMN: cursor number of table holding column + ** TK_REGISTER: register number + ** TK_TRIGGER: 1 -> new, 0 -> old */ + i16 iColumn; /* TK_COLUMN: column index. -1 for rowid */ + i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ + i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + u8 flags2; /* Second set of flags. EP2_... */ + u8 op2; /* If a TK_REGISTER, the original value of Expr.op */ + AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. */ #if SQLITE_MAX_EXPR_DEPTH>0 int nHeight; /* Height of the tree headed by this node */ #endif }; @@ -8795,29 +9204,38 @@ #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ -#define EP_Dequoted 0x0040 /* True if the string has been dequoted */ +#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ #define EP_FixedDest 0x0400 /* Result needed in a specific register */ -#define EP_IntValue 0x0800 /* Integer value contained in iTable */ +#define EP_IntValue 0x0800 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */ #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ -#define EP_SpanToken 0x8000 /* Expr size is EXPR_SPANTOKENSIZE bytes */ - -/* -** The following are the meanings of bits in the Expr.vvaFlags field. -** This information is only used when SQLite is compiled with -** SQLITE_DEBUG defined. -*/ -#ifndef NDEBUG -#define EVVA_ReadOnlyToken 0x01 /* Expr.token.z is read-only */ +#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */ + +/* +** The following are the meanings of bits in the Expr.flags2 field. +*/ +#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */ + +/* +** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible +** flag on an expression structure. This flag is used for VV&A only. The +** routine is implemented as a macro that only works when in debugging mode, +** so as not to burden production code. +*/ +#ifdef SQLITE_DEBUG +# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible +#else +# define ExprSetIrreducible(X) #endif /* ** These macros can be used to test, set, or clear bits in the ** Expr.flags field. @@ -8832,19 +9250,17 @@ ** struct, an Expr struct with the EP_Reduced flag set in Expr.flags ** and an Expr struct with the EP_TokenOnly flag set. */ #define EXPR_FULLSIZE sizeof(Expr) /* Full size */ #define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */ -#define EXPR_SPANTOKENSIZE offsetof(Expr,pLeft) /* Fewer features */ -#define EXPR_TOKENONLYSIZE offsetof(Expr,span) /* Smallest possible */ +#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */ /* ** Flags passed to the sqlite3ExprDup() function. See the header comment ** above sqlite3ExprDup() for details. */ #define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */ -#define EXPRDUP_SPAN 0x0002 /* Make a copy of Expr.span */ /* ** A list of expressions. Each expression may optionally have a ** name. An expr/name combination can be used in several ways, such ** as the list of "expr AS ID" fields following a "SELECT" or in the @@ -8857,15 +9273,27 @@ int nAlloc; /* Number of entries allocated below */ int iECursor; /* VDBE Cursor associated with this ExprList */ struct ExprList_item { Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ + char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ u8 done; /* A flag to indicate when processing is finished */ u16 iCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } *a; /* One entry for each expression */ +}; + +/* +** An instance of this structure is used by the parser to record both +** the parse tree for an expression and the span of input text for an +** expression. +*/ +struct ExprSpan { + Expr *pExpr; /* The expression parse tree */ + const char *zStart; /* First character of input text */ + const char *zEnd; /* One character past the end of input text */ }; /* ** An instance of this structure can hold a simple list of identifiers, ** such as the list "a,b,c" in the following statements: @@ -9020,19 +9448,21 @@ */ sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */ }; /* -** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin(). +** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin() +** and the WhereInfo.wctrlFlags member. */ #define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ #define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ #define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ -#define WHERE_FILL_ROWSET 0x0008 /* Save results in a RowSet object */ -#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */ -#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */ +#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ +#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */ +#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */ +#define WHERE_FORCE_TABLE 0x0040 /* Do not use an index-only search */ /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of @@ -9041,11 +9471,10 @@ */ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */ - int regRowSet; /* Store rowids in this rowset if >=0 */ SrcList *pTabList; /* List of tables in the join */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int nLevel; /* Number of nested loop */ @@ -9170,10 +9599,58 @@ int iMem; /* Base register where results are written */ int nMem; /* Number of registers allocated */ }; /* +** During code generation of statements that do inserts into AUTOINCREMENT +** tables, the following information is attached to the Table.u.autoInc.p +** pointer of each autoincrement table to record some side information that +** the code generator needs. We have to keep per-table autoincrement +** information in case inserts are down within triggers. Triggers do not +** normally coordinate their activities, but we do need to coordinate the +** loading and saving of autoincrement information. +*/ +struct AutoincInfo { + AutoincInfo *pNext; /* Next info block in a list of them all */ + Table *pTab; /* Table this info block refers to */ + int iDb; /* Index in sqlite3.aDb[] of database holding pTab */ + int regCtr; /* Memory register holding the rowid counter */ +}; + +/* +** Size of the column cache +*/ +#ifndef SQLITE_N_COLCACHE +# define SQLITE_N_COLCACHE 10 +#endif + +/* +** At least one instance of the following structure is created for each +** trigger that may be fired while parsing an INSERT, UPDATE or DELETE +** statement. All such objects are stored in the linked list headed at +** Parse.pTriggerPrg and deleted once statement compilation has been +** completed. +** +** A Vdbe sub-program that implements the body and WHEN clause of trigger +** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of +** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable. +** The Parse.pTriggerPrg list never contains two entries with the same +** values for both pTrigger and orconf. +** +** The TriggerPrg.oldmask variable is set to a mask of old.* columns +** accessed (or set to 0 for triggers fired as a result of INSERT +** statements). +*/ +struct TriggerPrg { + Trigger *pTrigger; /* Trigger this program was coded from */ + int orconf; /* Default ON CONFLICT policy */ + SubProgram *pProgram; /* Program implementing pTrigger/orconf */ + u32 oldmask; /* Mask of old.* columns accessed */ + TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ +}; + +/* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code @@ -9205,29 +9682,44 @@ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int ckBase; /* Base register of data during check constraints */ - int disableColCache; /* True to disable adding to column cache */ - int nColCache; /* Number of entries in the column cache */ - int iColCache; /* Next entry of the cache to replace */ + int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ + int iCacheCnt; /* Counter used to generate aColCache[].lru values */ + u8 nColCache; /* Number of entries in the column cache */ + u8 iColCache; /* Next entry of the cache to replace */ struct yColCache { int iTable; /* Table cursor number */ int iColumn; /* Table column number */ - char affChange; /* True if this register has had an affinity change */ - int iReg; /* Register holding value of this column */ - } aColCache[10]; /* One for each valid column cache entry */ + u8 affChange; /* True if this register has had an affinity change */ + u8 tempReg; /* iReg is a temp register that needs to be freed */ + int iLevel; /* Nesting level */ + int iReg; /* Reg with value of this column. 0 means none. */ + int lru; /* Least recently used entry has the smallest value */ + } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ + u8 isMultiWrite; /* True if statement may affect/insert multiple rows */ + u8 mayAbort; /* True if statement may throw an ABORT exception */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ + AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ + int nMaxArg; /* Max args passed to user function by sub-program */ + + /* Information used while coding trigger programs. */ + Parse *pToplevel; /* Parse structure for main program (or NULL) */ + Table *pTriggerTab; /* Table triggers are being coded for */ + u32 oldmask; /* Mask of old.* columns referenced */ + u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ + u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ @@ -9236,27 +9728,25 @@ Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ int nAlias; /* Number of aliased result set columns */ int nAliasAlloc; /* Number of allocated slots for aAlias[] */ int *aAlias; /* Register used to hold aliased result */ u8 explain; /* True if the EXPLAIN flag is found on the query */ - Token sErrToken; /* The token at which the error occurred */ Token sNameToken; /* Token with unqualified schema object name */ Token sLastToken; /* The last token parsed */ - const char *zSql; /* All SQL text */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ - TriggerStack *trigStack; /* Trigger actions being coded */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif int nHeight; /* Expression tree height of current sub-select */ Table *pZombieTab; /* List of Table objects to delete after code gen */ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ }; #ifdef SQLITE_OMIT_VIRTUALTABLE #define IN_DECLARE_VTAB 0 #else @@ -9271,16 +9761,18 @@ const char *zAuthContext; /* Put saved Parse.zAuthContext here */ Parse *pParse; /* The Parse structure */ }; /* -** Bitfield flags for P2 value in OP_Insert and OP_Delete -*/ -#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */ -#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */ -#define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */ -#define OPFLAG_APPEND 8 /* This is likely to be an append */ +** Bitfield flags for P5 value in OP_Insert and OP_Delete +*/ +#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ +#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ +#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ +#define OPFLAG_APPEND 0x08 /* This is likely to be an append */ +#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ +#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * @@ -9294,18 +9786,17 @@ * * The "step_list" member points to the first element of a linked list * containing the SQL statements specified as the trigger program. */ struct Trigger { - char *name; /* The name of the trigger */ + char *zName; /* The name of the trigger */ char *table; /* The table or view to which the trigger applies */ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */ IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger, the <column-list> is stored here */ - Token nameToken; /* Token containing zName. Use during parsing only */ Schema *pSchema; /* Schema containing the trigger */ Schema *pTabSchema; /* Schema containing the table */ TriggerStep *step_list; /* Link list of trigger program steps */ Trigger *pNext; /* Next trigger associated with the table */ }; @@ -9335,84 +9826,42 @@ * * (op == TK_INSERT) * orconf -> stores the ON CONFLICT algorithm * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then * this stores a pointer to the SELECT statement. Otherwise NULL. - * target -> A token holding the name of the table to insert into. + * target -> A token holding the quoted name of the table to insert into. * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ... * statement, then this stores the column-names to be * inserted into. * * (op == TK_DELETE) - * target -> A token holding the name of the table to delete from. + * target -> A token holding the quoted name of the table to delete from. * pWhere -> The WHERE clause of the DELETE statement if one is specified. * Otherwise NULL. * * (op == TK_UPDATE) - * target -> A token holding the name of the table to update rows of. + * target -> A token holding the quoted name of the table to update rows of. * pWhere -> The WHERE clause of the UPDATE statement if one is specified. * Otherwise NULL. * pExprList -> A list of the columns to update and the expressions to update * them to. See sqlite3Update() documentation of "pChanges" * argument. * */ struct TriggerStep { - int op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ - int orconf; /* OE_Rollback etc. */ + u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ + u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ - - Select *pSelect; /* Valid for SELECT and sometimes - INSERT steps (when pExprList == 0) */ - Token target; /* Valid for DELETE, UPDATE, INSERT steps */ - Expr *pWhere; /* Valid for DELETE, UPDATE steps */ - ExprList *pExprList; /* Valid for UPDATE statements and sometimes - INSERT steps (when pSelect == 0) */ - IdList *pIdList; /* Valid for INSERT statements only */ + Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */ + Token target; /* Target table for DELETE, UPDATE, INSERT */ + Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ + ExprList *pExprList; /* SET clause for UPDATE. VALUES clause for INSERT */ + IdList *pIdList; /* Column names for INSERT */ TriggerStep *pNext; /* Next in the link-list */ TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ -}; - -/* - * An instance of struct TriggerStack stores information required during code - * generation of a single trigger program. While the trigger program is being - * coded, its associated TriggerStack instance is pointed to by the - * "pTriggerStack" member of the Parse structure. - * - * The pTab member points to the table that triggers are being coded on. The - * newIdx member contains the index of the vdbe cursor that points at the temp - * table that stores the new.* references. If new.* references are not valid - * for the trigger being coded (for example an ON DELETE trigger), then newIdx - * is set to -1. The oldIdx member is analogous to newIdx, for old.* references. - * - * The ON CONFLICT policy to be used for the trigger program steps is stored - * as the orconf member. If this is OE_Default, then the ON CONFLICT clause - * specified for individual triggers steps is used. - * - * struct TriggerStack has a "pNext" member, to allow linked lists to be - * constructed. When coding nested triggers (triggers fired by other triggers) - * each nested trigger stores its parent trigger's TriggerStack as the "pNext" - * pointer. Once the nested trigger has been coded, the pNext value is restored - * to the pTriggerStack member of the Parse stucture and coding of the parent - * trigger continues. - * - * Before a nested trigger is coded, the linked list pointed to by the - * pTriggerStack is scanned to ensure that the trigger is not about to be coded - * recursively. If this condition is detected, the nested trigger is not coded. - */ -struct TriggerStack { - Table *pTab; /* Table that triggers are currently being coded on */ - int newIdx; /* Index of vdbe cursor to "new" temp table */ - int oldIdx; /* Index of vdbe cursor to "old" temp table */ - u32 newColMask; - u32 oldColMask; - int orconf; /* Current orconf policy */ - int ignoreJump; /* where to jump to for a RAISE(IGNORE) */ - Trigger *pTrigger; /* The trigger currently being coded */ - TriggerStack *pNext; /* Next trigger down on the trigger stack */ }; /* ** The following structure contains information used by the sqliteFix... ** routines as they walk the parse tree to make database references @@ -9481,11 +9930,13 @@ int sharedCacheEnabled; /* true if shared-cache mode enabled */ /* The above might be initialized to non-zero. The following need to always ** initially be zero, however. */ int isInit; /* True after initialization has finished */ int inProgress; /* True while initialization in progress */ + int isMutexInit; /* True after mutexes are initialized */ int isMallocInit; /* True after malloc is initialized */ + int isPCacheInit; /* True after malloc is initialized */ sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ int nRefInitMutex; /* Number of users of pInitMutex */ }; /* @@ -9538,10 +9989,19 @@ #else # define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT #endif /* +** The ctype.h header is needed for non-ASCII systems. It is also +** needed by FTS3 when FTS3 is included in the amalgamation. +*/ +#if !defined(SQLITE_ASCII) || \ + (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION)) +# include <ctype.h> +#endif + +/* ** The following macros mimic the standard library functions toupper(), ** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The ** sqlite versions only work for ASCII characters, regardless of locale. */ #ifdef SQLITE_ASCII @@ -9551,11 +10011,10 @@ # define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02) # define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04) # define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) # define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) #else -# include <ctype.h> # define sqlite3Toupper(x) toupper((unsigned char)(x)) # define sqlite3Isspace(x) isspace((unsigned char)(x)) # define sqlite3Isalnum(x) isalnum((unsigned char)(x)) # define sqlite3Isalpha(x) isalpha((unsigned char)(x)) # define sqlite3Isdigit(x) isdigit((unsigned char)(x)) @@ -9565,14 +10024,13 @@ /* ** Internal function prototypes */ SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *); -SQLITE_PRIVATE int sqlite3StrNICmp(const char *, const char *, int); SQLITE_PRIVATE int sqlite3IsNumber(const char*, int*, u8); -SQLITE_PRIVATE int sqlite3Strlen(sqlite3*, const char*); SQLITE_PRIVATE int sqlite3Strlen30(const char*); +#define sqlite3StrNICmp sqlite3_strnicmp SQLITE_PRIVATE int sqlite3MallocInit(void); SQLITE_PRIVATE void sqlite3MallocEnd(void); SQLITE_PRIVATE void *sqlite3Malloc(int); SQLITE_PRIVATE void *sqlite3MallocZero(int); @@ -9591,10 +10049,28 @@ SQLITE_PRIVATE void *sqlite3PageMalloc(int); SQLITE_PRIVATE void sqlite3PageFree(void*); SQLITE_PRIVATE void sqlite3MemSetDefault(void); SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); SQLITE_PRIVATE int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64); + +/* +** On systems with ample stack space and that support alloca(), make +** use of alloca() to obtain space for large automatic objects. By default, +** obtain space from malloc(). +** +** The alloca() routine never returns NULL. This will cause code paths +** that deal with sqlite3StackAlloc() failures to be unreachable. +*/ +#ifdef SQLITE_USE_ALLOCA +# define sqlite3StackAllocRaw(D,N) alloca(N) +# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N) +# define sqlite3StackFree(D,P) +#else +# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N) +# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N) +# define sqlite3StackFree(D,P) sqlite3DbFree(D,P) +#endif #ifdef SQLITE_ENABLE_MEMSYS3 SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); #endif #ifdef SQLITE_ENABLE_MEMSYS5 @@ -9626,29 +10102,30 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ErrorClear(Parse*); -SQLITE_PRIVATE void sqlite3Dequote(char*); -SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); +SQLITE_PRIVATE int sqlite3Dequote(char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int); SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse*,int,int); -SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*); +SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); +SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); +SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); -SQLITE_PRIVATE Expr *sqlite3RegisterExpr(Parse*,Token*); -SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); -SQLITE_PRIVATE void sqlite3ExprSpan(Expr*,Token*,Token*); +SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprClear(sqlite3*, Expr*); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); -SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*); +SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); +SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int); @@ -9660,25 +10137,26 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*); SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*); SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*); -SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*); +SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*); SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); -SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32); +SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*); SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*); SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*); SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*); SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64); +SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, u8 iBatch, i64); SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*); SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) @@ -9687,10 +10165,17 @@ # define sqlite3ViewGetColumnNames(A,B) 0 #endif SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); SQLITE_PRIVATE void sqlite3DeleteTable(Table*); +#ifndef SQLITE_OMIT_AUTOINCREMENT +SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); +SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); +#else +# define sqlite3AutoincrementBegin(X) +# define sqlite3AutoincrementEnd(X) +#endif SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*); SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); @@ -9716,18 +10201,21 @@ #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *); #endif SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); -SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8, int); +SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int); -SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse*, int); -SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); -SQLITE_PRIVATE void sqlite3ExprWritableRegister(Parse*,int); +SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int); +SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*); +SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int); +SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int); +SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse*,int,int); SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int); @@ -9761,20 +10249,21 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*); SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*); SQLITE_PRIVATE int sqlite3IsRowid(const char*); -SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int); +SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int); SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*); SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, - int*,int,int,int,int); + int*,int,int,int,int,int*); SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int); SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); -SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); -SQLITE_PRIVATE void sqlite3TokenCopy(sqlite3*,Token*,const Token*); +SQLITE_PRIVATE void sqlite3MayAbort(Parse *); +SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, char*, int); +SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); @@ -9803,28 +10292,32 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); SQLITE_PRIVATE void sqlite3DropTrigger(Parse*, SrcList*, int); SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse*, Trigger*); SQLITE_PRIVATE Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask); SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *, Table *); -SQLITE_PRIVATE int sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *, - int, int, int, int, u32*, u32*); +SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *, + int, int, int, int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, - ExprList*,Select*,int); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, int); + ExprList*,Select*,u8); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); +SQLITE_PRIVATE u32 sqlite3TriggerOldmask(Parse*,Trigger*,int,ExprList*,Table*,int); +# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) -# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J,K,L) 0 +# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J) # define sqlite3TriggerList(X, Y) 0 +# define sqlite3ParseToplevel(p) p +# define sqlite3TriggerOldmask(A,B,C,D,E,F) 0 #endif SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); @@ -9890,11 +10383,11 @@ #define putVarint32(A,B) (u8)(((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B))) #define getVarint sqlite3GetVarint #define putVarint sqlite3PutVarint -SQLITE_PRIVATE void sqlite3IndexAffinityStr(Vdbe *, Index *); +SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *); SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *); SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*); @@ -9901,12 +10394,12 @@ SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...); SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); SQLITE_PRIVATE const char *sqlite3ErrStr(int); SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); -SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int); -SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName); +SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); +SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); @@ -9916,10 +10409,13 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*); SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *); SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int); +#ifdef SQLITE_ENABLE_STAT2 +SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *); +#endif SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; @@ -9937,20 +10433,21 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); -SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int); +SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); -SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int); -SQLITE_PRIVATE char sqlite3AffinityType(const Token*); +SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(sqlite3*, u8, CollSeq *, const char*); +SQLITE_PRIVATE char sqlite3AffinityType(const char*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); +SQLITE_PRIVATE void sqlite3DeleteIndexSamples(Index*); SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*); SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int); SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int); SQLITE_PRIVATE void sqlite3SchemaFree(void *); @@ -9980,11 +10477,11 @@ SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); #ifdef YYTRACKMAXSTACKDEPTH SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); #endif -SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3*); +SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3*); #ifndef SQLITE_OMIT_LOAD_EXTENSION SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*); #else # define sqlite3CloseExtensions(X) #endif @@ -9998,39 +10495,46 @@ #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*); #endif #ifdef SQLITE_OMIT_VIRTUALTABLE -# define sqlite3VtabClear(X) +# define sqlite3VtabClear(Y) # define sqlite3VtabSync(X,Y) SQLITE_OK # define sqlite3VtabRollback(X) # define sqlite3VtabCommit(X) # define sqlite3VtabInSync(db) 0 +# define sqlite3VtabLock(X) +# define sqlite3VtabUnlock(X) +# define sqlite3VtabUnlockList(X) #else SQLITE_PRIVATE void sqlite3VtabClear(Table*); SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **); SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db); SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db); +SQLITE_PRIVATE void sqlite3VtabLock(VTable *); +SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *); +SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); -SQLITE_PRIVATE void sqlite3VtabLock(sqlite3_vtab*); -SQLITE_PRIVATE void sqlite3VtabUnlock(sqlite3*, sqlite3_vtab*); SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*); SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*); SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); -SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *); +SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); +SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); +SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); + /* ** Available fault injectors. Should be numbered beginning with 0. */ @@ -10088,15 +10592,10 @@ #define sqlite3ConnectionBlocked(x,y) #define sqlite3ConnectionUnlocked(x) #define sqlite3ConnectionClosed(x) #endif - -#ifdef SQLITE_SSE -#include "sseInt.h" -#endif - #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); #endif /* @@ -10128,12 +10627,10 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains definitions of global variables and contants. -** -** $Id: global.c,v 1.12 2009/02/05 16:31:46 drh Exp $ */ /* An array to map all upper-case characters into their corresponding ** lower-case character. @@ -10269,14 +10766,16 @@ (void*)0, /* pPage */ 0, /* szPage */ 0, /* nPage */ 0, /* mxParserStack */ 0, /* sharedCacheEnabled */ - /* All the rest need to always be zero */ + /* All the rest should always be initialized to zero */ 0, /* isInit */ 0, /* inProgress */ + 0, /* isMutexInit */ 0, /* isMallocInit */ + 0, /* isPCacheInit */ 0, /* pInitMutex */ 0, /* nRefInitMutex */ }; @@ -10449,11 +10948,11 @@ ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.105 2009/04/03 12:04:37 drh Exp $ +** $Id: date.c,v 1.107 2009/05/03 20:23:53 drh Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. @@ -10774,18 +11273,19 @@ static int parseDateOrTime( sqlite3_context *context, const char *zDate, DateTime *p ){ + int isRealNum; /* Return from sqlite3IsNumber(). Not used */ if( parseYyyyMmDd(zDate,p)==0 ){ return 0; }else if( parseHhMmSs(zDate, p)==0 ){ return 0; }else if( sqlite3StrICmp(zDate,"now")==0){ setDateTimeToCurrent(context, p); return 0; - }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ + }else if( sqlite3IsNumber(zDate, &isRealNum, SQLITE_UTF8) ){ double r; getValue(zDate, &r); p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); p->validJD = 1; return 0; @@ -10877,11 +11377,11 @@ x.s = s; } x.tz = 0; x.validJD = 0; computeJD(&x); - t = x.iJD/1000 - 21086676*(i64)10000; + t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); #ifdef HAVE_LOCALTIME_R { struct tm sLocal; localtime_r(&t, &sLocal); y.Y = sLocal.tm_year + 1900; @@ -10979,11 +11479,11 @@ ** ** Treat the current value of p->iJD as the number of ** seconds since 1970. Convert to a real julian day number. */ if( strcmp(z, "unixepoch")==0 && p->validJD ){ - p->iJD = p->iJD/86400 + 21086676*(i64)10000000; + p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000; clearYMD_HMS_TZ(p); rc = 0; } #ifndef SQLITE_OMIT_LOCALTIME else if( strcmp(z, "utc")==0 ){ @@ -11553,11 +12053,11 @@ ****************************************************************************** ** ** This file contains OS interface code that is common to all ** architectures. ** -** $Id: os.c,v 1.126 2009/03/25 14:24:42 drh Exp $ +** $Id: os.c,v 1.127 2009/07/27 11:41:21 danielk1977 Exp $ */ #define _SQLITE_OS_C_ 1 #undef _SQLITE_OS_C_ /* @@ -11576,17 +12076,17 @@ ** sqlite3OsSync() ** sqlite3OsLock() ** */ #if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) - #define DO_OS_MALLOC_TEST if (1) { \ - void *pTstAlloc = sqlite3Malloc(10); \ - if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ - sqlite3_free(pTstAlloc); \ - } -#else - #define DO_OS_MALLOC_TEST + #define DO_OS_MALLOC_TEST(x) if (!x || !sqlite3IsMemJournal(x)) { \ + void *pTstAlloc = sqlite3Malloc(10); \ + if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ + sqlite3_free(pTstAlloc); \ + } +#else + #define DO_OS_MALLOC_TEST(x) #endif /* ** The following routines are convenience wrappers around methods ** of the sqlite3_file object. This is mostly just syntactic sugar. All @@ -11600,37 +12100,37 @@ pId->pMethods = 0; } return rc; } SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ - DO_OS_MALLOC_TEST; + DO_OS_MALLOC_TEST(id); return id->pMethods->xRead(id, pBuf, amt, offset); } SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ - DO_OS_MALLOC_TEST; + DO_OS_MALLOC_TEST(id); return id->pMethods->xWrite(id, pBuf, amt, offset); } SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){ return id->pMethods->xTruncate(id, size); } SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){ - DO_OS_MALLOC_TEST; + DO_OS_MALLOC_TEST(id); return id->pMethods->xSync(id, flags); } SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ - DO_OS_MALLOC_TEST; + DO_OS_MALLOC_TEST(id); return id->pMethods->xFileSize(id, pSize); } SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){ - DO_OS_MALLOC_TEST; + DO_OS_MALLOC_TEST(id); return id->pMethods->xLock(id, lockType); } SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){ return id->pMethods->xUnlock(id, lockType); } SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ - DO_OS_MALLOC_TEST; + DO_OS_MALLOC_TEST(id); return id->pMethods->xCheckReservedLock(id, pResOut); } SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ return id->pMethods->xFileControl(id, op, pArg); } @@ -11652,12 +12152,16 @@ sqlite3_file *pFile, int flags, int *pFlagsOut ){ int rc; - DO_OS_MALLOC_TEST; - rc = pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut); + DO_OS_MALLOC_TEST(0); + /* 0x7f1f is a mask of SQLITE_OPEN_ flags that are valid to be passed + ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, + ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before + ** reaching the VFS. */ + rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut); assert( rc==SQLITE_OK || pFile->pMethods==0 ); return rc; } SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ return pVfs->xDelete(pVfs, zPath, dirSync); @@ -11666,11 +12170,11 @@ sqlite3_vfs *pVfs, const char *zPath, int flags, int *pResOut ){ - DO_OS_MALLOC_TEST; + DO_OS_MALLOC_TEST(0); return pVfs->xAccess(pVfs, zPath, flags, pResOut); } SQLITE_PRIVATE int sqlite3OsFullPathname( sqlite3_vfs *pVfs, const char *zPath, @@ -11727,10 +12231,23 @@ int rc = SQLITE_OK; assert( pFile ); rc = sqlite3OsClose(pFile); sqlite3_free(pFile); return rc; +} + +/* +** This function is a wrapper around the OS specific implementation of +** sqlite3_os_init(). The purpose of the wrapper is to provide the +** ability to simulate a malloc failure, so that the handling of an +** error in sqlite3_os_init() by the upper layers can be tested. +*/ +SQLITE_PRIVATE int sqlite3OsInit(void){ + void *p = sqlite3_malloc(10); + if( p==0 ) return SQLITE_NOMEM; + sqlite3_free(p); + return sqlite3_os_init(); } /* ** The list of all registered VFS implementations. */ @@ -13274,21 +13791,44 @@ ************************************************************************* ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** ** This version of the memory allocation subsystem omits all -** use of malloc(). The SQLite user supplies a block of memory +** use of malloc(). The application gives SQLite a block of memory ** before calling sqlite3_initialize() from which allocations ** are made and returned by the xMalloc() and xRealloc() ** implementations. Once sqlite3_initialize() has been called, ** the amount of memory available to SQLite is fixed and cannot ** be changed. ** ** This version of the memory allocation subsystem is included ** in the build only if SQLITE_ENABLE_MEMSYS5 is defined. ** -** $Id: mem5.c,v 1.19 2008/11/19 16:52:44 danielk1977 Exp $ +** This memory allocator uses the following algorithm: +** +** 1. All memory allocations sizes are rounded up to a power of 2. +** +** 2. If two adjacent free blocks are the halves of a larger block, +** then the two blocks are coalesed into the single larger block. +** +** 3. New memory is allocated from the first available free block. +** +** This algorithm is described in: J. M. Robson. "Bounds for Some Functions +** Concerning Dynamic Storage Allocation". Journal of the Association for +** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499. +** +** Let n be the size of the largest allocation divided by the minimum +** allocation size (after rounding all sizes up to a power of 2.) Let M +** be the maximum amount of memory ever outstanding at one time. Let +** N be the total amount of memory available for allocation. Robson +** proved that this memory allocator will never breakdown due to +** fragmentation as long as the following constraint holds: +** +** N >= M*(1 + log2(n)/2) - n + 1 +** +** The sqlite3_status() logic tracks the maximum values of n and M so +** that an application can, at any time, verify this constraint. */ /* ** This version of the memory allocator is used only when ** SQLITE_ENABLE_MEMSYS5 is defined. @@ -13297,28 +13837,31 @@ /* ** A minimum allocation is an instance of the following structure. ** Larger allocations are an array of these structures where the ** size of the array is a power of 2. +** +** The size of this object must be a power of two. That fact is +** verified in memsys5Init(). */ typedef struct Mem5Link Mem5Link; struct Mem5Link { int next; /* Index of next free chunk */ int prev; /* Index of previous free chunk */ }; /* -** Maximum size of any allocation is ((1<<LOGMAX)*mem5.nAtom). Since -** mem5.nAtom is always at least 8, this is not really a practical -** limitation. +** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since +** mem5.szAtom is always at least 8 and 32-bit integers are used, +** it is not actually possible to reach this limit. */ #define LOGMAX 30 /* ** Masks used for mem5.aCtrl[] elements. */ -#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block relative to POW2_MIN */ +#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block */ #define CTRL_FREE 0x20 /* True if not checked out */ /* ** All of the static variables used by this module are collected ** into a single structure named "mem5". This is to keep the @@ -13327,13 +13870,13 @@ */ static SQLITE_WSD struct Mem5Global { /* ** Memory available for allocation */ - int nAtom; /* Smallest possible allocation in bytes */ - int nBlock; /* Number of nAtom sized blocks in zPool */ - u8 *zPool; + int szAtom; /* Smallest possible allocation in bytes */ + int nBlock; /* Number of szAtom sized blocks in zPool */ + u8 *zPool; /* Memory available to be allocated */ /* ** Mutex to control access to the memory allocation subsystem. */ sqlite3_mutex *mutex; @@ -13349,25 +13892,34 @@ u32 maxOut; /* Maximum instantaneous currentOut */ u32 maxCount; /* Maximum instantaneous currentCount */ u32 maxRequest; /* Largest allocation (exclusive of internal frag) */ /* - ** Lists of free blocks of various sizes. + ** Lists of free blocks. aiFreelist[0] is a list of free blocks of + ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2. + ** and so forth. */ int aiFreelist[LOGMAX+1]; /* ** Space for tracking which blocks are checked out and the size ** of each block. One byte per block. */ u8 *aCtrl; -} mem5 = { 19804167 }; - +} mem5 = { 0 }; + +/* +** Access the static variable through a macro for SQLITE_OMIT_WSD +*/ #define mem5 GLOBAL(struct Mem5Global, mem5) -#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.nAtom])) +/* +** Assuming mem5.zPool is divided up into an array of Mem5Link +** structures, return a pointer to the idx-th such lik. +*/ +#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom])) /* ** Unlink the chunk at mem5.aPool[i] from list it is currently ** on. It should be found on mem5.aiFreelist[iLogsize]. */ @@ -13413,13 +13965,10 @@ ** If the STATIC_MEM mutex is not already held, obtain it now. The mutex ** will already be held (obtained by code in malloc.c) if ** sqlite3GlobalConfig.bMemStat is true. */ static void memsys5Enter(void){ - if( sqlite3GlobalConfig.bMemstat==0 && mem5.mutex==0 ){ - mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); - } sqlite3_mutex_enter(mem5.mutex); } static void memsys5Leave(void){ sqlite3_mutex_leave(mem5.mutex); } @@ -13430,13 +13979,13 @@ ** works for chunks that are currently checked out. */ static int memsys5Size(void *p){ int iSize = 0; if( p ){ - int i = ((u8 *)p-mem5.zPool)/mem5.nAtom; + int i = ((u8 *)p-mem5.zPool)/mem5.szAtom; assert( i>=0 && i<mem5.nBlock ); - iSize = mem5.nAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE)); + iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE)); } return iSize; } /* @@ -13458,26 +14007,42 @@ return iFirst; } /* ** Return a block of memory of at least nBytes in size. -** Return NULL if unable. +** Return NULL if unable. Return NULL if nBytes==0. +** +** The caller guarantees that nByte positive. +** +** The caller has obtained a mutex prior to invoking this +** routine so there is never any chance that two or more +** threads can be in this routine at the same time. */ static void *memsys5MallocUnsafe(int nByte){ int i; /* Index of a mem5.aPool[] slot */ int iBin; /* Index into mem5.aiFreelist[] */ int iFullSz; /* Size of allocation rounded up to power of 2 */ int iLogsize; /* Log2 of iFullSz/POW2_MIN */ + /* nByte must be a positive */ + assert( nByte>0 ); + /* Keep track of the maximum allocation request. Even unfulfilled ** requests are counted */ if( (u32)nByte>mem5.maxRequest ){ mem5.maxRequest = nByte; } + /* Abort if the requested allocation size is larger than the largest + ** power of two that we can represent using 32-bit signed integers. + */ + if( nByte > 0x40000000 ){ + return 0; + } + /* Round nByte up to the next valid power of two */ - for(iFullSz=mem5.nAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){} + for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){} /* Make sure mem5.aiFreelist[iLogsize] contains at least one free ** block. If not, then split a block of the next larger power of ** two in order to create a new free block of size iLogsize. */ @@ -13502,11 +14067,11 @@ mem5.currentOut += iFullSz; if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount; if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut; /* Return a pointer to the allocated memory. */ - return (void*)&mem5.zPool[i*mem5.nAtom]; + return (void*)&mem5.zPool[i*mem5.szAtom]; } /* ** Free an outstanding memory allocation. */ @@ -13513,34 +14078,34 @@ static void memsys5FreeUnsafe(void *pOld){ u32 size, iLogsize; int iBlock; /* Set iBlock to the index of the block pointed to by pOld in - ** the array of mem5.nAtom byte blocks pointed to by mem5.zPool. - */ - iBlock = ((u8 *)pOld-mem5.zPool)/mem5.nAtom; + ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool. + */ + iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom; /* Check that the pointer pOld points to a valid, non-free block. */ assert( iBlock>=0 && iBlock<mem5.nBlock ); - assert( ((u8 *)pOld-mem5.zPool)%mem5.nAtom==0 ); + assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 ); assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 ); iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE; size = 1<<iLogsize; assert( iBlock+size-1<(u32)mem5.nBlock ); mem5.aCtrl[iBlock] |= CTRL_FREE; mem5.aCtrl[iBlock+size-1] |= CTRL_FREE; assert( mem5.currentCount>0 ); - assert( mem5.currentOut>=(size*mem5.nAtom) ); + assert( mem5.currentOut>=(size*mem5.szAtom) ); mem5.currentCount--; - mem5.currentOut -= size*mem5.nAtom; + mem5.currentOut -= size*mem5.szAtom; assert( mem5.currentOut>0 || mem5.currentCount==0 ); assert( mem5.currentCount>0 || mem5.currentOut==0 ); mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; - while( iLogsize<LOGMAX ){ + while( ALWAYS(iLogsize<LOGMAX) ){ int iBuddy; if( (iBlock>>iLogsize) & 1 ){ iBuddy = iBlock - size; }else{ iBuddy = iBlock + size; @@ -13576,32 +14141,40 @@ return (void*)p; } /* ** Free memory. +** +** The outer layer memory allocator prevents this routine from +** being called with pPrior==0. */ static void memsys5Free(void *pPrior){ - if( pPrior==0 ){ -assert(0); - return; - } + assert( pPrior!=0 ); memsys5Enter(); memsys5FreeUnsafe(pPrior); memsys5Leave(); } /* -** Change the size of an existing memory allocation +** Change the size of an existing memory allocation. +** +** The outer layer memory allocator prevents this routine from +** being called with pPrior==0. +** +** nBytes is always a value obtained from a prior call to +** memsys5Round(). Hence nBytes is always a non-negative power +** of two. If nBytes==0 that means that an oversize allocation +** (an allocation larger than 0x40000000) was requested and this +** routine should return 0 without freeing pPrior. */ static void *memsys5Realloc(void *pPrior, int nBytes){ int nOld; void *p; - if( pPrior==0 ){ - return memsys5Malloc(nBytes); - } - if( nBytes<=0 ){ - memsys5Free(pPrior); + assert( pPrior!=0 ); + assert( (nBytes&(nBytes-1))==0 ); + assert( nBytes>=0 ); + if( nBytes==0 ){ return 0; } nOld = memsys5Size(pPrior); if( nBytes<=nOld ){ return pPrior; @@ -13615,49 +14188,77 @@ memsys5Leave(); return p; } /* -** Round up a request size to the next valid allocation size. +** Round up a request size to the next valid allocation size. If +** the allocation is too large to be handled by this allocation system, +** return 0. +** +** All allocations must be a power of two and must be expressed by a +** 32-bit signed integer. Hence the largest allocation is 0x40000000 +** or 1073741824 bytes. */ static int memsys5Roundup(int n){ int iFullSz; - for(iFullSz=mem5.nAtom; iFullSz<n; iFullSz *= 2); + if( n > 0x40000000 ) return 0; + for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2); return iFullSz; } +/* +** Return the ceiling of the logarithm base 2 of iValue. +** +** Examples: memsys5Log(1) -> 0 +** memsys5Log(2) -> 1 +** memsys5Log(4) -> 2 +** memsys5Log(5) -> 3 +** memsys5Log(8) -> 3 +** memsys5Log(9) -> 4 +*/ static int memsys5Log(int iValue){ int iLog; for(iLog=0; (1<<iLog)<iValue; iLog++); return iLog; } /* -** Initialize this module. +** Initialize the memory allocator. +** +** This routine is not threadsafe. The caller must be holding a mutex +** to prevent multiple threads from entering at the same time. */ static int memsys5Init(void *NotUsed){ - int ii; - int nByte = sqlite3GlobalConfig.nHeap; - u8 *zByte = (u8 *)sqlite3GlobalConfig.pHeap; - int nMinLog; /* Log of minimum allocation size in bytes*/ - int iOffset; - - UNUSED_PARAMETER(NotUsed); - - if( !zByte ){ - return SQLITE_ERROR; - } + int ii; /* Loop counter */ + int nByte; /* Number of bytes of memory available to this allocator */ + u8 *zByte; /* Memory usable by this allocator */ + int nMinLog; /* Log base 2 of minimum allocation size in bytes */ + int iOffset; /* An offset into mem5.aCtrl[] */ + + UNUSED_PARAMETER(NotUsed); + + /* For the purposes of this routine, disable the mutex */ + mem5.mutex = 0; + + /* The size of a Mem5Link object must be a power of two. Verify that + ** this is case. + */ + assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 ); + + nByte = sqlite3GlobalConfig.nHeap; + zByte = (u8*)sqlite3GlobalConfig.pHeap; + assert( zByte!=0 ); /* sqlite3_config() does not allow otherwise */ nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq); - mem5.nAtom = (1<<nMinLog); - while( (int)sizeof(Mem5Link)>mem5.nAtom ){ - mem5.nAtom = mem5.nAtom << 1; - } - - mem5.nBlock = (nByte / (mem5.nAtom+sizeof(u8))); + mem5.szAtom = (1<<nMinLog); + while( (int)sizeof(Mem5Link)>mem5.szAtom ){ + mem5.szAtom = mem5.szAtom << 1; + } + + mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8))); mem5.zPool = zByte; - mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.nAtom]; + mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom]; for(ii=0; ii<=LOGMAX; ii++){ mem5.aiFreelist[ii] = -1; } @@ -13670,27 +14271,33 @@ iOffset += nAlloc; } assert((iOffset+nAlloc)>mem5.nBlock); } + /* If a mutex is required for normal operation, allocate one */ + if( sqlite3GlobalConfig.bMemstat==0 ){ + mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + return SQLITE_OK; } /* ** Deinitialize this module. */ static void memsys5Shutdown(void *NotUsed){ UNUSED_PARAMETER(NotUsed); - return; -} - + mem5.mutex = 0; + return; +} + +#ifdef SQLITE_TEST /* ** Open the file indicated and write a log of all unfreed memory ** allocations into that log. */ SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){ -#ifdef SQLITE_DEBUG FILE *out; int i, j, n; int nMinLog; if( zFilename==0 || zFilename[0]==0 ){ @@ -13702,14 +14309,14 @@ zFilename); return; } } memsys5Enter(); - nMinLog = memsys5Log(mem5.nAtom); + nMinLog = memsys5Log(mem5.szAtom); for(i=0; i<=LOGMAX && i+nMinLog<32; i++){ for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){} - fprintf(out, "freelist items of size %d: %d\n", mem5.nAtom << i, n); + fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n); } fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc); fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc); fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess); fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut); @@ -13721,14 +14328,12 @@ if( out==stdout ){ fflush(stdout); }else{ fclose(out); } -#else - UNUSED_PARAMETER(zFilename); -#endif -} +} +#endif /* ** This routine is the only routine in this file with external ** linkage. It returns a pointer to a static sqlite3_mem_methods ** struct populated with the memsys5 methods. @@ -13765,12 +14370,22 @@ ** This file contains the C functions that implement mutexes. ** ** This file contains code that is common across all mutex implementations. ** -** $Id: mutex.c,v 1.30 2009/02/17 16:29:11 danielk1977 Exp $ -*/ +** $Id: mutex.c,v 1.31 2009/07/16 18:21:18 drh Exp $ +*/ + +#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) +/* +** For debugging purposes, record when the mutex subsystem is initialized +** and uninitialized so that we can assert() if there is an attempt to +** allocate a mutex while the system is uninitialized. +*/ +static SQLITE_WSD int mutexIsInit = 0; +#endif /* SQLITE_DEBUG */ + #ifndef SQLITE_MUTEX_OMIT /* ** Initialize the mutex system. */ @@ -13780,37 +14395,25 @@ if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ /* If the xMutexAlloc method has not been set, then the user did not ** install a mutex implementation via sqlite3_config() prior to ** sqlite3_initialize() being called. This block copies pointers to ** the default implementation into the sqlite3GlobalConfig structure. - ** - ** The danger is that although sqlite3_config() is not a threadsafe - ** API, sqlite3_initialize() is, and so multiple threads may be - ** attempting to run this function simultaneously. To guard write - ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex - ** is obtained before modifying it. - */ - sqlite3_mutex_methods *p = sqlite3DefaultMutex(); - sqlite3_mutex *pMaster = 0; - - rc = p->xMutexInit(); - if( rc==SQLITE_OK ){ - pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); - assert(pMaster); - p->xMutexEnter(pMaster); - assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0 - || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc - ); - if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ - sqlite3GlobalConfig.mutex = *p; - } - p->xMutexLeave(pMaster); - } - }else{ - rc = sqlite3GlobalConfig.mutex.xMutexInit(); - } - } + */ + sqlite3_mutex_methods *pFrom = sqlite3DefaultMutex(); + sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; + + memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc)); + memcpy(&pTo->xMutexFree, &pFrom->xMutexFree, + sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree)); + pTo->xMutexAlloc = pFrom->xMutexAlloc; + } + rc = sqlite3GlobalConfig.mutex.xMutexInit(); + } + +#ifdef SQLITE_DEBUG + GLOBAL(int, mutexIsInit) = 1; +#endif return rc; } /* @@ -13820,10 +14423,15 @@ SQLITE_PRIVATE int sqlite3MutexEnd(void){ int rc = SQLITE_OK; if( sqlite3GlobalConfig.mutex.xMutexEnd ){ rc = sqlite3GlobalConfig.mutex.xMutexEnd(); } + +#ifdef SQLITE_DEBUG + GLOBAL(int, mutexIsInit) = 0; +#endif + return rc; } /* ** Retrieve a pointer to a static mutex or allocate a new dynamic one. @@ -13837,10 +14445,11 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){ if( !sqlite3GlobalConfig.bCoreMutex ){ return 0; } + assert( GLOBAL(int, mutexIsInit) ); return sqlite3GlobalConfig.mutex.xMutexAlloc(id); } /* ** Free a dynamic mutex. @@ -14455,10 +15064,11 @@ ** <li> SQLITE_MUTEX_STATIC_MASTER ** <li> SQLITE_MUTEX_STATIC_MEM ** <li> SQLITE_MUTEX_STATIC_MEM2 ** <li> SQLITE_MUTEX_STATIC_PRNG ** <li> SQLITE_MUTEX_STATIC_LRU +** <li> SQLITE_MUTEX_STATIC_LRU2 ** </ul> ** ** The first two constants cause sqlite3_mutex_alloc() to create ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. @@ -14468,11 +15078,11 @@ ** cases where it really needs one. If a faster non-recursive mutex ** implementation is available on the host platform, the mutex subsystem ** might return such a mutex in response to SQLITE_MUTEX_FAST. ** ** The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. Three static mutexes are +** a pointer to a static preexisting mutex. Six static mutexes are ** used by the current version of SQLite. Future versions of SQLite ** may add additional static mutexes. Static mutexes are for internal ** use by SQLite only. Applications that use SQLite mutexes should ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or ** SQLITE_MUTEX_RECURSIVE. @@ -14706,11 +15316,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for win32 ** -** $Id: mutex_w32.c,v 1.15 2009/01/30 16:09:23 shane Exp $ +** $Id: mutex_w32.c,v 1.18 2009/08/10 03:23:21 shane Exp $ */ /* ** The code in this file is only used if we are compiling multithreaded ** on a win32 system. @@ -14776,26 +15386,67 @@ /* ** Initialize and deinitialize the mutex subsystem. */ -static int winMutexInit(void){ return SQLITE_OK; } -static int winMutexEnd(void){ return SQLITE_OK; } +static sqlite3_mutex winMutex_staticMutexes[6]; +static int winMutex_isInit = 0; +/* As winMutexInit() and winMutexEnd() are called as part +** of the sqlite3_initialize and sqlite3_shutdown() +** processing, the "interlocked" magic is probably not +** strictly necessary. +*/ +static long winMutex_lock = 0; + +static int winMutexInit(void){ + /* The first to increment to 1 does actual initialization */ + if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ + int i; + for(i=0; i<ArraySize(winMutex_staticMutexes); i++){ + InitializeCriticalSection(&winMutex_staticMutexes[i].mutex); + } + winMutex_isInit = 1; + }else{ + /* Someone else is in the process of initing the static mutexes */ + while( !winMutex_isInit ){ + Sleep(1); + } + } + return SQLITE_OK; +} + +static int winMutexEnd(void){ + /* The first to decrement to 0 does actual shutdown + ** (which should be the last to shutdown.) */ + if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){ + if( winMutex_isInit==1 ){ + int i; + for(i=0; i<ArraySize(winMutex_staticMutexes); i++){ + DeleteCriticalSection(&winMutex_staticMutexes[i].mutex); + } + winMutex_isInit = 0; + } + } + return SQLITE_OK; +} /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. SQLite ** will unwind its stack and return an error. The argument ** to sqlite3_mutex_alloc() is one of these integer constants: ** ** <ul> -** <li> SQLITE_MUTEX_FAST 0 -** <li> SQLITE_MUTEX_RECURSIVE 1 -** <li> SQLITE_MUTEX_STATIC_MASTER 2 -** <li> SQLITE_MUTEX_STATIC_MEM 3 -** <li> SQLITE_MUTEX_STATIC_PRNG 4 +** <li> SQLITE_MUTEX_FAST +** <li> SQLITE_MUTEX_RECURSIVE +** <li> SQLITE_MUTEX_STATIC_MASTER +** <li> SQLITE_MUTEX_STATIC_MEM +** <li> SQLITE_MUTEX_STATIC_MEM2 +** <li> SQLITE_MUTEX_STATIC_PRNG +** <li> SQLITE_MUTEX_STATIC_LRU +** <li> SQLITE_MUTEX_STATIC_LRU2 ** </ul> ** ** The first two constants cause sqlite3_mutex_alloc() to create ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. @@ -14805,11 +15456,11 @@ ** cases where it really needs one. If a faster non-recursive mutex ** implementation is available on the host platform, the mutex subsystem ** might return such a mutex in response to SQLITE_MUTEX_FAST. ** ** The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. Three static mutexes are +** a pointer to a static preexisting mutex. Six static mutexes are ** used by the current version of SQLite. Future versions of SQLite ** may add additional static mutexes. Static mutexes are for internal ** use by SQLite only. Applications that use SQLite mutexes should ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or ** SQLITE_MUTEX_RECURSIVE. @@ -14832,27 +15483,14 @@ InitializeCriticalSection(&p->mutex); } break; } default: { - static sqlite3_mutex staticMutexes[6]; - static int isInit = 0; - while( !isInit ){ - static long lock = 0; - if( InterlockedIncrement(&lock)==1 ){ - int i; - for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){ - InitializeCriticalSection(&staticMutexes[i].mutex); - } - isInit = 1; - }else{ - Sleep(1); - } - } + assert( winMutex_isInit==1 ); assert( iType-2 >= 0 ); - assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); - p = &staticMutexes[iType-2]; + assert( iType-2 < ArraySize(winMutex_staticMutexes) ); + p = &winMutex_staticMutexes[iType-2]; p->id = iType; break; } } return p; @@ -14965,11 +15603,11 @@ ** ************************************************************************* ** ** Memory allocation functions used throughout sqlite. ** -** $Id: malloc.c,v 1.61 2009/03/24 15:08:10 drh Exp $ +** $Id: malloc.c,v 1.66 2009/07/17 11:44:07 drh Exp $ */ /* ** This routine runs when the memory allocator sees that the ** total memory allocation is about to exceed the soft heap @@ -14994,11 +15632,13 @@ if( n<0 ){ iLimit = 0; }else{ iLimit = n; } +#ifndef SQLITE_OMIT_AUTOINIT sqlite3_initialize(); +#endif if( iLimit>0 ){ sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit); }else{ sqlite3MemoryAlarm(0, 0, 0); } @@ -15039,26 +15679,24 @@ /* ** The alarm callback and its arguments. The mem0.mutex lock will ** be held while the callback is running. Recursive calls into ** the memory subsystem are allowed, but no new callbacks will be - ** issued. The alarmBusy variable is set to prevent recursive - ** callbacks. + ** issued. */ sqlite3_int64 alarmThreshold; void (*alarmCallback)(void*, sqlite3_int64,int); void *alarmArg; - int alarmBusy; /* ** Pointers to the end of sqlite3GlobalConfig.pScratch and ** sqlite3GlobalConfig.pPage to a block of memory that records ** which pages are available. */ u32 *aScratchFree; u32 *aPageFree; -} mem0 = { 62560955, 0, 0, 0, 0, 0, 0, 0, 0 }; +} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 }; #define mem0 GLOBAL(struct Mem0Global, mem0) /* ** Initialize the memory allocation subsystem. @@ -15171,19 +15809,20 @@ */ static void sqlite3MallocAlarm(int nByte){ void (*xCallback)(void*,sqlite3_int64,int); sqlite3_int64 nowUsed; void *pArg; - if( mem0.alarmCallback==0 || mem0.alarmBusy ) return; - mem0.alarmBusy = 1; + if( mem0.alarmCallback==0 ) return; xCallback = mem0.alarmCallback; nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); pArg = mem0.alarmArg; + mem0.alarmCallback = 0; sqlite3_mutex_leave(mem0.mutex); xCallback(pArg, nowUsed, nByte); sqlite3_mutex_enter(mem0.mutex); - mem0.alarmBusy = 0; + mem0.alarmCallback = xCallback; + mem0.alarmArg = pArg; } /* ** Do a memory allocation with statistics and alarms. Assume the ** lock is already held. @@ -15217,19 +15856,16 @@ ** Allocate memory. This routine is like sqlite3_malloc() except that it ** assumes the memory subsystem has already been initialized. */ SQLITE_PRIVATE void *sqlite3Malloc(int n){ void *p; - if( n<=0 || NEVER(n>=0x7fffff00) ){ - /* The NEVER(n>=0x7fffff00) term is added out of paranoia. We want to make - ** absolutely sure that there is nothing within SQLite that can cause a - ** memory allocation of a number of bytes which is near the maximum signed - ** integer value and thus cause an integer overflow inside of the xMalloc() - ** implementation. The n>=0x7fffff00 gives us 255 bytes of headroom. The - ** test should never be true because SQLITE_MAX_LENGTH should be much - ** less than 0x7fffff00 and it should catch large memory allocations - ** before they reach this point. */ + if( n<=0 || n>=0x7fffff00 ){ + /* A memory allocation of a number of bytes which is near the maximum + ** signed integer value might cause an integer overflow inside of the + ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving + ** 255 bytes of overhead. SQLite itself will never use anything near + ** this amount. The only way to reach the limit is with sqlite3_malloc() */ p = 0; }else if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); mallocWithAlarm(n, &p); sqlite3_mutex_leave(mem0.mutex); @@ -15378,13 +16014,11 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){ return sqlite3GlobalConfig.m.xSize(p); } SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ assert( db==0 || sqlite3_mutex_held(db->mutex) ); - if( p==0 ){ - return 0; - }else if( isLookaside(db, p) ){ + if( isLookaside(db, p) ){ return db->lookaside.sz; }else{ return sqlite3GlobalConfig.m.xSize(p); } } @@ -15427,40 +16061,41 @@ int nOld, nNew; void *pNew; if( pOld==0 ){ return sqlite3Malloc(nBytes); } - if( nBytes<=0 || NEVER(nBytes>=0x7fffff00) ){ - /* The NEVER(...) term is explained in comments on sqlite3Malloc() */ + if( nBytes<=0 ){ sqlite3_free(pOld); return 0; } + if( nBytes>=0x7fffff00 ){ + /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */ + return 0; + } nOld = sqlite3MallocSize(pOld); - if( sqlite3GlobalConfig.bMemstat ){ + nNew = sqlite3GlobalConfig.m.xRoundup(nBytes); + if( nOld==nNew ){ + pNew = pOld; + }else if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes); - nNew = sqlite3GlobalConfig.m.xRoundup(nBytes); - if( nOld==nNew ){ - pNew = pOld; - }else{ - if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= - mem0.alarmThreshold ){ - sqlite3MallocAlarm(nNew-nOld); - } + if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= + mem0.alarmThreshold ){ + sqlite3MallocAlarm(nNew-nOld); + } + pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); + if( pNew==0 && mem0.alarmCallback ){ + sqlite3MallocAlarm(nBytes); pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); - if( pNew==0 && mem0.alarmCallback ){ - sqlite3MallocAlarm(nBytes); - pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); - } - if( pNew ){ - nNew = sqlite3MallocSize(pNew); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld); - } + } + if( pNew ){ + nNew = sqlite3MallocSize(pNew); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld); } sqlite3_mutex_leave(mem0.mutex); }else{ - pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nBytes); + pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); } return pNew; } /* @@ -15602,11 +16237,11 @@ char *zNew; size_t n; if( z==0 ){ return 0; } - n = (db ? sqlite3Strlen(db, z) : sqlite3Strlen30(z))+1; + n = sqlite3Strlen30(z) + 1; assert( (n&0x7fffffff)==n ); zNew = sqlite3DbMallocRaw(db, (int)n); if( zNew ){ memcpy(zNew, z, n); } @@ -15677,11 +16312,11 @@ ** the public domain. The original comments are included here for ** completeness. They are very out-of-date but might be useful as ** an historical reference. Most of the "enhancements" have been backed ** out so that the functionality is now the same as standard printf(). ** -** $Id: printf.c,v 1.102 2009/04/08 16:10:04 drh Exp $ +** $Id: printf.c,v 1.104 2009/06/03 01:24:54 drh Exp $ ** ************************************************************************** ** ** The following modules is an enhanced replacement for the "printf" subroutines ** found in the standard C library. The following enhancements are @@ -15860,15 +16495,18 @@ } } /* ** On machines with a small stack size, you can redefine the -** SQLITE_PRINT_BUF_SIZE to be less than 350. But beware - for -** smaller values some %f conversions may go into an infinite loop. +** SQLITE_PRINT_BUF_SIZE to be less than 350. */ #ifndef SQLITE_PRINT_BUF_SIZE -# define SQLITE_PRINT_BUF_SIZE 350 +# if defined(SQLITE_SMALL_STACK) +# define SQLITE_PRINT_BUF_SIZE 50 +# else +# define SQLITE_PRINT_BUF_SIZE 350 +# endif #endif #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ /* ** The root program. All variations call this core. @@ -16062,13 +16700,17 @@ /* Fall through into the next case */ case etORDINAL: case etRADIX: if( infop->flags & FLAG_SIGNED ){ i64 v; - if( flag_longlong ) v = va_arg(ap,i64); - else if( flag_long ) v = va_arg(ap,long int); - else v = va_arg(ap,int); + if( flag_longlong ){ + v = va_arg(ap,i64); + }else if( flag_long ){ + v = va_arg(ap,long int); + }else{ + v = va_arg(ap,int); + } if( v<0 ){ longvalue = -v; prefix = '-'; }else{ longvalue = v; @@ -16075,13 +16717,17 @@ if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; } }else{ - if( flag_longlong ) longvalue = va_arg(ap,u64); - else if( flag_long ) longvalue = va_arg(ap,unsigned long int); - else longvalue = va_arg(ap,unsigned int); + if( flag_longlong ){ + longvalue = va_arg(ap,u64); + }else if( flag_long ){ + longvalue = va_arg(ap,unsigned long int); + }else{ + longvalue = va_arg(ap,unsigned int); + } prefix = 0; } if( longvalue==0 ) flag_alternateform = 0; if( flag_zeropad && precision<width-(prefix!=0) ){ precision = width-(prefix!=0); @@ -16824,22 +17470,14 @@ ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. ** -** $Id: vdbeInt.h,v 1.167 2009/04/10 12:55:17 danielk1977 Exp $ +** $Id: vdbeInt.h,v 1.174 2009/06/23 14:15:04 drh Exp $ */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ - -/* -** intToKey() and keyToInt() used to transform the rowid. But with -** the latest versions of the design they are no-ops. -*/ -#define keyToInt(X) (X) -#define intToKey(X) (X) - /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance ** of the following structure. @@ -16873,38 +17511,75 @@ Bool zeroed; /* True if zeroed out and ready for reuse */ Bool rowidIsValid; /* True if lastRowid is valid */ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ - Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ - Bool ephemPseudoTable; Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ - int nData; /* Number of bytes in pData */ - char *pData; /* Data for a NEW or OLD pseudo-table */ - i64 iKey; /* Key for the NEW or OLD pseudo-table row */ + int pseudoTableReg; /* Register holding pseudotable content. */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ int nField; /* Number of fields in the header */ i64 seqCount; /* Sequence counter */ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ const sqlite3_module *pModule; /* Module for cursor pVtabCursor */ + /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or + ** OP_IsUnique opcode on this cursor. */ + int seekResult; + /* Cached information about the header for the data record that the - ** cursor is currently pointing to. Only valid if cacheValid is true. + ** cursor is currently pointing to. Only valid if cacheStatus matches + ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of + ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that + ** the cache is out of date. + ** ** aRow might point to (ephemeral) data for the current row, or it might ** be NULL. */ - int cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ + u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ int payloadSize; /* Total number of bytes in the record */ u32 *aType; /* Type values for all entries in the record */ u32 *aOffset; /* Cached offsets to the start of each columns data */ u8 *aRow; /* Data for the current row, if all on one page */ }; typedef struct VdbeCursor VdbeCursor; + +/* +** When a sub-program is executed (OP_Program), a structure of this type +** is allocated to store the current value of the program counter, as +** well as the current memory cell array and various other frame specific +** values stored in the Vdbe struct. When the sub-program is finished, +** these values are copied back to the Vdbe from the VdbeFrame structure, +** restoring the state of the VM to as it was before the sub-program +** began executing. +** +** Frames are stored in a linked list headed at Vdbe.pParent. Vdbe.pParent +** is the parent of the current frame, or zero if the current frame +** is the main Vdbe program. +*/ +typedef struct VdbeFrame VdbeFrame; +struct VdbeFrame { + Vdbe *v; /* VM this frame belongs to */ + int pc; /* Program Counter */ + Op *aOp; /* Program instructions */ + int nOp; /* Size of aOp array */ + Mem *aMem; /* Array of memory cells */ + int nMem; /* Number of entries in aMem */ + VdbeCursor **apCsr; /* Element of Vdbe cursors */ + u16 nCursor; /* Number of entries in apCsr */ + void *token; /* Copy of SubProgram.token */ + int nChildMem; /* Number of memory cells for child frame */ + int nChildCsr; /* Number of cursors for child frame */ + i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + int nChange; /* Statement changes (Vdbe.nChanges) */ + VdbeFrame *pParent; /* Parent of this frame */ +}; + +#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) /* ** A value for VdbeCursor.cacheValid that means the cache is always invalid. */ #define CACHE_STALE 0 @@ -16924,10 +17599,11 @@ union { i64 i; /* Integer value. */ int nZero; /* Used when bit MEM_Zero is set in flags */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ + VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u; double r; /* Real value */ sqlite3 *db; /* The associated database connection */ char *z; /* String or BLOB value */ int n; /* Number of characters in string value, excluding '\0' */ @@ -16957,10 +17633,11 @@ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ +#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ #define MEM_TypeMask 0x00ff /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of ** the following flags must be set to determine the memory management ** policy for Mem.z. The MEM_Term flag tells us whether or not the @@ -17037,25 +17714,10 @@ Hash hash; /* A set is just a hash table */ HashElem *prev; /* Previously accessed hash elemen */ }; /* -** A Context stores the last insert rowid, the last statement change count, -** and the current statement change count (i.e. changes since last statement). -** The current keylist is also stored in the context. -** Elements of Context structure type make up the ContextStack, which is -** updated by the ContextPush and ContextPop opcodes (used by triggers). -** The context is pushed before executing a trigger a popped when the -** trigger finishes. -*/ -typedef struct Context Context; -struct Context { - i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ - int nChange; /* Statement changes (Vdbe.nChanges) */ -}; - -/* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile() ** is really a pointer to an instance of this structure. @@ -17067,67 +17729,57 @@ ** "DROP TABLE" statements and to prevent some nasty side effects of ** malloc failure when SQLite is invoked recursively by a virtual table ** method function. */ struct Vdbe { - sqlite3 *db; /* The whole database */ - Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ - int nOp; /* Number of instructions in the program */ - int nOpAlloc; /* Number of slots allocated for aOp[] */ - Op *aOp; /* Space to hold the virtual machine's program */ - int nLabel; /* Number of labels used */ - int nLabelAlloc; /* Number of slots allocated in aLabel[] */ - int *aLabel; /* Space to hold the labels */ - Mem **apArg; /* Arguments to currently executing user function */ - Mem *aColName; /* Column names to return */ - int nCursor; /* Number of slots in apCsr[] */ - VdbeCursor **apCsr; /* One element of this array for each open cursor */ - int nVar; /* Number of entries in aVar[] */ - Mem *aVar; /* Values for the OP_Variable opcode. */ - char **azVar; /* Name of variables */ - int okVar; /* True if azVar[] has been initialized */ + sqlite3 *db; /* The database connection that owns this statement */ + Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ + int nOp; /* Number of instructions in the program */ + int nOpAlloc; /* Number of slots allocated for aOp[] */ + Op *aOp; /* Space to hold the virtual machine's program */ + int nLabel; /* Number of labels used */ + int nLabelAlloc; /* Number of slots allocated in aLabel[] */ + int *aLabel; /* Space to hold the labels */ + Mem **apArg; /* Arguments to currently executing user function */ + Mem *aColName; /* Column names to return */ + Mem *pResultSet; /* Pointer to an array of results */ + u16 nResColumn; /* Number of columns in one row of the result set */ + u16 nCursor; /* Number of slots in apCsr[] */ + VdbeCursor **apCsr; /* One element of this array for each open cursor */ + u8 errorAction; /* Recovery action to do in case of an error */ + u8 okVar; /* True if azVar[] has been initialized */ + u16 nVar; /* Number of entries in aVar[] */ + Mem *aVar; /* Values for the OP_Variable opcode. */ + char **azVar; /* Name of variables */ u32 magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ - int cacheCtr; /* VdbeCursor row cache generation counter */ - int contextStackTop; /* Index of top element in the context stack */ - int contextStackDepth; /* The size of the "context" stack */ - Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ + u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ - int errorAction; /* Recovery action to do in case of an error */ - int nResColumn; /* Number of columns in one row of the result set */ - char **azResColumn; /* Values for one row of result */ - char *zErrMsg; /* Error message written here */ - Mem *pResultSet; /* Pointer to an array of results */ + char *zErrMsg; /* Error message written here */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 expired; /* True if the VM needs to be recompiled */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ u8 usesStmtJournal; /* True if uses a statement journal */ u8 readOnly; /* True for read-only statements */ u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ - i64 startTime; /* Time when query started - used for profiling */ int btreeMask; /* Bitmask of db->aDb[] entries referenced */ + i64 startTime; /* Time when query started - used for profiling */ BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */ int aCounter[2]; /* Counters used by sqlite3_stmt_status() */ - char *zSql; /* Text of the SQL statement that generated this */ - void *pFree; /* Free this when deleting the vdbe */ -#ifdef SQLITE_DEBUG - FILE *trace; /* Write an execution trace here, if not NULL */ -#endif + char *zSql; /* Text of the SQL statement that generated this */ + void *pFree; /* Free this when deleting the vdbe */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ -#ifdef SQLITE_SSE - int fetchId; /* Statement number used by sqlite3_fetch_statement */ - int lru; /* Counter used for LRU cache replacement */ -#endif -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - Vdbe *pLruPrev; - Vdbe *pLruNext; -#endif +#ifdef SQLITE_DEBUG + FILE *trace; /* Write an execution trace here, if not NULL */ +#endif + VdbeFrame *pFrame; /* Parent frame */ + int nFrame; /* Number of frames in pFrame list */ }; /* ** The following are allowed values for Vdbe.magic */ @@ -17143,19 +17795,19 @@ void sqliteVdbePopStack(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); #endif -SQLITE_PRIVATE int sqlite3VdbeSerialTypeLen(u32); +SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int); -SQLITE_PRIVATE int sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int); -SQLITE_PRIVATE int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int); +SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*); -SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *); +SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *); SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); @@ -17184,10 +17836,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); SQLITE_PRIVATE const char *sqlite3OpcodeName(int); SQLITE_PRIVATE int sqlite3VdbeOpcodeHasProperty(int, int); SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); +SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); +SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT SQLITE_PRIVATE int sqlite3VdbeReleaseBuffers(Vdbe *p); #endif #ifndef SQLITE_OMIT_SHARED_CACHE @@ -17628,10 +18282,36 @@ assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z); } /* +** Convert a UTF-8 string to the UTF-16 encoding specified by parameter +** enc. A pointer to the new string is returned, and the value of *pnOut +** is set to the length of the returned string in bytes. The call should +** arrange to call sqlite3DbFree() on the returned pointer when it is +** no longer required. +** +** If a malloc failure occurs, NULL is returned and the db.mallocFailed +** flag set. +*/ +#ifdef SQLITE_ENABLE_STAT2 +SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){ + Mem m; + memset(&m, 0, sizeof(m)); + m.db = db; + sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC); + if( sqlite3VdbeMemTranslate(&m, enc) ){ + assert( db->mallocFailed ); + return 0; + } + assert( m.z==m.zMalloc ); + *pnOut = m.n; + return m.z; +} +#endif + +/* ** pZ is a UTF-16 encoded unicode string at least nChar characters long. ** Return the number of bytes in the first nChar unicode characters ** in pZ. nChar must be non-negative. */ SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){ @@ -17732,12 +18412,14 @@ ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.249 2009/03/01 22:29:20 drh Exp $ -*/ +*/ +#ifdef SQLITE_HAVE_ISNAN +# include <math.h> +#endif /* ** Routine needed to support the testcase() macro. */ #ifdef SQLITE_COVERAGE_TEST @@ -17746,35 +18428,25 @@ dummy += x; } #endif /* -** Routine needed to support the ALWAYS() and NEVER() macros. -** -** The argument to ALWAYS() should always be true and the argument -** to NEVER() should always be false. If either is not the case -** then this routine is called in order to throw an error. -** -** This routine only exists if assert() is operational. It always -** throws an assert on its first invocation. The variable has a long -** name to help the assert() message be more readable. The variable -** is used to prevent a too-clever optimizer from optimizing out the -** entire call. -*/ -#ifndef NDEBUG -SQLITE_PRIVATE int sqlite3Assert(void){ - static volatile int ALWAYS_was_false_or_NEVER_was_true = 0; - assert( ALWAYS_was_false_or_NEVER_was_true ); /* Always fails */ - return ALWAYS_was_false_or_NEVER_was_true++; /* Not Reached */ -} -#endif - -/* ** Return true if the floating point value is Not a Number (NaN). +** +** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. +** Otherwise, we have our own implementation that works on most systems. */ SQLITE_PRIVATE int sqlite3IsNaN(double x){ - /* This NaN test sometimes fails if compiled on GCC with -ffast-math. + int rc; /* The value return */ +#if !defined(SQLITE_HAVE_ISNAN) + /* + ** Systems that support the isnan() library function should probably + ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have + ** found that many systems do not have a working isnan() function so + ** this implementation is provided as an alternative. + ** + ** This NaN test sometimes fails if compiled on GCC with -ffast-math. ** On the other hand, the use of -ffast-math comes with the following ** warning: ** ** This option [-ffast-math] should never be turned on by any ** -O option since it can result in incorrect output for programs @@ -17792,39 +18464,31 @@ #ifdef __FAST_MATH__ # error SQLite will not work correctly with the -ffast-math option of GCC. #endif volatile double y = x; volatile double z = y; - return y!=z; + rc = (y!=z); +#else /* if defined(SQLITE_HAVE_ISNAN) */ + rc = isnan(x); +#endif /* SQLITE_HAVE_ISNAN */ + testcase( rc ); + return rc; } /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. +** +** The value returned will never be negative. Nor will it ever be greater +** than the actual length of the string. For very long strings (greater +** than 1GiB) the value returned might be less than the true string length. */ SQLITE_PRIVATE int sqlite3Strlen30(const char *z){ const char *z2 = z; + if( z==0 ) return 0; while( *z2 ){ z2++; } return 0x3fffffff & (int)(z2 - z); -} - -/* -** Return the length of a string, except do not allow the string length -** to exceed the SQLITE_LIMIT_LENGTH setting. -*/ -SQLITE_PRIVATE int sqlite3Strlen(sqlite3 *db, const char *z){ - const char *z2 = z; - int len; - int x; - while( *z2 ){ z2++; } - x = (int)(z2 - z); - len = 0x7fffffff & x; - if( len!=x || len > db->aLimit[SQLITE_LIMIT_LENGTH] ){ - return db->aLimit[SQLITE_LIMIT_LENGTH]; - }else{ - return len; - } } /* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". @@ -17885,13 +18549,11 @@ pParse->nErr++; sqlite3DbFree(db, pParse->zErrMsg); va_start(ap, zFormat); pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); - if( pParse->rc==SQLITE_OK ){ - pParse->rc = SQLITE_ERROR; - } + pParse->rc = SQLITE_ERROR; } /* ** Clear the error message in pParse, if any */ @@ -17905,39 +18567,47 @@ ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the ** input does not begin with a quote character, then this routine ** is a no-op. ** +** The input string must be zero-terminated. A new zero-terminator +** is added to the dequoted string. +** +** The return value is -1 if no dequoting occurs or the length of the +** dequoted string, exclusive of the zero terminator, if dequoting does +** occur. +** ** 2002-Feb-14: This routine is extended to remove MS-Access style ** brackets from around identifers. For example: "[a-b-c]" becomes ** "a-b-c". */ -SQLITE_PRIVATE void sqlite3Dequote(char *z){ +SQLITE_PRIVATE int sqlite3Dequote(char *z){ char quote; int i, j; - if( z==0 ) return; + if( z==0 ) return -1; quote = z[0]; switch( quote ){ case '\'': break; case '"': break; case '`': break; /* For MySQL compatibility */ case '[': quote = ']'; break; /* For MS SqlServer compatibility */ - default: return; - } - for(i=1, j=0; z[i]; i++){ + default: return -1; + } + for(i=1, j=0; ALWAYS(z[i]); i++){ if( z[i]==quote ){ if( z[i+1]==quote ){ z[j++] = quote; i++; }else{ - z[j++] = 0; break; } }else{ z[j++] = z[i]; } } + z[j] = 0; + return j; } /* Convenient short-hand */ #define UpperToLower sqlite3UpperToLower @@ -17950,23 +18620,28 @@ a = (unsigned char *)zLeft; b = (unsigned char *)zRight; while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } return UpperToLower[*a] - UpperToLower[*b]; } -SQLITE_PRIVATE int sqlite3StrNICmp(const char *zLeft, const char *zRight, int N){ +SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; } /* -** Return TRUE if z is a pure numeric string. Return FALSE if the -** string contains any character which is not part of a number. If -** the string is numeric and contains the '.' character, set *realnum -** to TRUE (otherwise FALSE). +** Return TRUE if z is a pure numeric string. Return FALSE and leave +** *realnum unchanged if the string contains any character which is not +** part of a number. +** +** If the string is pure numeric, set *realnum to TRUE if the string +** contains the '.' character or an "E+000" style exponentiation suffix. +** Otherwise set *realnum to FALSE. Note that just becaue *realnum is +** false does not mean that the number can be successfully converted into +** an integer - it might be too big. ** ** An empty string is considered non-numeric. */ SQLITE_PRIVATE int sqlite3IsNumber(const char *z, int *realnum, u8 enc){ int incr = (enc==SQLITE_UTF8?1:2); @@ -17974,30 +18649,30 @@ if( *z=='-' || *z=='+' ) z += incr; if( !sqlite3Isdigit(*z) ){ return 0; } z += incr; - if( realnum ) *realnum = 0; + *realnum = 0; while( sqlite3Isdigit(*z) ){ z += incr; } if( *z=='.' ){ z += incr; if( !sqlite3Isdigit(*z) ) return 0; while( sqlite3Isdigit(*z) ){ z += incr; } - if( realnum ) *realnum = 1; + *realnum = 1; } if( *z=='e' || *z=='E' ){ z += incr; if( *z=='+' || *z=='-' ) z += incr; if( !sqlite3Isdigit(*z) ) return 0; while( sqlite3Isdigit(*z) ){ z += incr; } - if( realnum ) *realnum = 1; + *realnum = 1; } return *z==0; } /* -** The string z[] is an ascii representation of a real number. +** The string z[] is an ASCII representation of a real number. ** Convert this string to a double. ** ** This routine assumes that z[] really is a valid number. If it ** is not, the result is undefined. ** @@ -18006,74 +18681,130 @@ ** of "." depending on how locale is set. But that would cause problems ** for SQL. So this routine always uses "." regardless of locale. */ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){ #ifndef SQLITE_OMIT_FLOATING_POINT - int sign = 1; const char *zBegin = z; - LONGDOUBLE_TYPE v1 = 0.0; - int nSignificant = 0; + /* sign * significand * (10 ^ (esign * exponent)) */ + int sign = 1; /* sign of significand */ + i64 s = 0; /* significand */ + int d = 0; /* adjust exponent for shifting decimal point */ + int esign = 1; /* sign of exponent */ + int e = 0; /* exponent */ + double result; + int nDigits = 0; + + /* skip leading spaces */ while( sqlite3Isspace(*z) ) z++; + /* get sign of significand */ if( *z=='-' ){ sign = -1; z++; }else if( *z=='+' ){ z++; } - while( z[0]=='0' ){ - z++; - } - while( sqlite3Isdigit(*z) ){ - v1 = v1*10.0 + (*z - '0'); - z++; - nSignificant++; - } - if( *z=='.' ){ - LONGDOUBLE_TYPE divisor = 1.0; + /* skip leading zeroes */ + while( z[0]=='0' ) z++, nDigits++; + + /* copy max significant digits to significand */ + while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ + s = s*10 + (*z - '0'); + z++, nDigits++; + } + /* skip non-significant significand digits + ** (increase exponent by d to shift decimal left) */ + while( sqlite3Isdigit(*z) ) z++, nDigits++, d++; + + /* if decimal point is present */ + if( *z=='.' ){ z++; - if( nSignificant==0 ){ - while( z[0]=='0' ){ - divisor *= 10.0; - z++; - } - } - while( sqlite3Isdigit(*z) ){ - if( nSignificant<18 ){ - v1 = v1*10.0 + (*z - '0'); - divisor *= 10.0; - nSignificant++; - } - z++; - } - v1 /= divisor; - } + /* copy digits from after decimal to significand + ** (decrease exponent by d to shift decimal right) */ + while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ + s = s*10 + (*z - '0'); + z++, nDigits++, d--; + } + /* skip non-significant digits */ + while( sqlite3Isdigit(*z) ) z++, nDigits++; + } + + /* if exponent is present */ if( *z=='e' || *z=='E' ){ - int esign = 1; - int eval = 0; - LONGDOUBLE_TYPE scale = 1.0; z++; + /* get sign of exponent */ if( *z=='-' ){ esign = -1; z++; }else if( *z=='+' ){ z++; } + /* copy digits to exponent */ while( sqlite3Isdigit(*z) ){ - eval = eval*10 + *z - '0'; + e = e*10 + (*z - '0'); z++; } - while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; } - while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; } - while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; } - while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; } - if( esign<0 ){ - v1 /= scale; - }else{ - v1 *= scale; - } - } - *pResult = (double)(sign<0 ? -v1 : v1); + } + + /* adjust exponent by d, and update sign */ + e = (e*esign) + d; + if( e<0 ) { + esign = -1; + e *= -1; + } else { + esign = 1; + } + + /* if 0 significand */ + if( !s ) { + /* In the IEEE 754 standard, zero is signed. + ** Add the sign if we've seen at least one digit */ + result = (sign<0 && nDigits) ? -(double)0 : (double)0; + } else { + /* attempt to reduce exponent */ + if( esign>0 ){ + while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10; + }else{ + while( !(s%10) && e>0 ) e--,s/=10; + } + + /* adjust the sign of significand */ + s = sign<0 ? -s : s; + + /* if exponent, scale significand as appropriate + ** and store in result. */ + if( e ){ + double scale = 1.0; + /* attempt to handle extremely small/large numbers better */ + if( e>307 && e<342 ){ + while( e%308 ) { scale *= 1.0e+1; e -= 1; } + if( esign<0 ){ + result = s / scale; + result /= 1.0e+308; + }else{ + result = s * scale; + result *= 1.0e+308; + } + }else{ + /* 1.0e+22 is the largest power of 10 than can be + ** represented exactly. */ + while( e%22 ) { scale *= 1.0e+1; e -= 1; } + while( e>0 ) { scale *= 1.0e+22; e -= 22; } + if( esign<0 ){ + result = s / scale; + }else{ + result = s * scale; + } + } + } else { + result = (double)s; + } + } + + /* store the result */ + *pResult = result; + + /* return number of characters used */ return (int)(z - zBegin); #else return sqlite3Atoi64(z, pResult); #endif /* SQLITE_OMIT_FLOATING_POINT */ } @@ -18091,11 +18822,11 @@ ** ** will return -8. */ static int compare2pow63(const char *zNum){ int c; - c = memcmp(zNum,"922337203685477580",18); + c = memcmp(zNum,"922337203685477580",18)*10; if( c==0 ){ c = zNum[18] - '8'; } return c; } @@ -18146,34 +18877,37 @@ return compare2pow63(zNum)<neg; } } /* -** The string zNum represents an integer. There might be some other -** information following the integer too, but that part is ignored. -** If the integer that the prefix of zNum represents will fit in a +** The string zNum represents an unsigned integer. The zNum string +** consists of one or more digit characters and is terminated by +** a zero character. Any stray characters in zNum result in undefined +** behavior. +** +** If the unsigned integer that zNum represents will fit in a ** 64-bit signed integer, return TRUE. Otherwise return FALSE. ** -** This routine returns FALSE for the string -9223372036854775808 even that -** that number will, in theory fit in a 64-bit integer. Positive -** 9223373036854775808 will not fit in 64 bits. So it seems safer to return -** false. +** If the negFlag parameter is true, that means that zNum really represents +** a negative number. (The leading "-" is omitted from zNum.) This +** parameter is needed to determine a boundary case. A string +** of "9223373036854775808" returns false if negFlag is false or true +** if negFlag is true. +** +** Leading zeros are ignored. */ SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *zNum, int negFlag){ - int i, c; + int i; int neg = 0; - if( *zNum=='-' ){ - neg = 1; - zNum++; - }else if( *zNum=='+' ){ - zNum++; - } + + assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */ + if( negFlag ) neg = 1-neg; while( *zNum=='0' ){ zNum++; /* Skip leading zeros. Ticket #2454 */ } - for(i=0; (c=zNum[i])>='0' && c<='9'; i++){} + for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); } if( i<19 ){ /* Guaranteed to fit if less than 19 digits */ return 1; }else if( i>19 ){ /* Guaranteed to be too big if greater than 19 digits */ @@ -18462,57 +19196,99 @@ } /* ** Read a 32-bit variable-length integer from memory starting at p[0]. ** Return the number of bytes read. The value is stored in *v. +** +** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned +** integer, then set *v to 0xffffffff. +** ** A MACRO version, getVarint32, 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. */ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ u32 a,b; + /* The 1-byte case. Overwhelmingly the most common. Handled inline + ** by the getVarin32() macro */ a = *p; /* a: p0 (unmasked) */ #ifndef getVarint32 if (!(a&0x80)) { + /* Values between 0 and 127 */ *v = a; return 1; } #endif + /* The 2-byte case */ p++; b = *p; /* b: p1 (unmasked) */ if (!(b&0x80)) { + /* Values between 128 and 16383 */ a &= 0x7f; a = a<<7; *v = a | b; return 2; } + /* The 3-byte case */ p++; a = a<<14; a |= *p; /* a: p0<<14 | p2 (unmasked) */ if (!(a&0x80)) { + /* Values between 16384 and 2097151 */ a &= (0x7f<<14)|(0x7f); b &= 0x7f; b = b<<7; *v = a | b; return 3; } + /* A 32-bit varint is used to store size information in btrees. + ** Objects are rarely larger than 2MiB limit of a 3-byte varint. + ** A 3-byte varint is sufficient, for example, to record the size + ** of a 1048569-byte BLOB or string. + ** + ** We only unroll the first 1-, 2-, and 3- byte cases. The very + ** rare larger cases can be handled by the slower 64-bit varint + ** routine. + */ +#if 1 + { + u64 v64; + u8 n; + + p -= 2; + n = sqlite3GetVarint(p, &v64); + assert( n>3 && n<=9 ); + if( (v64 & SQLITE_MAX_U32)!=v64 ){ + *v = 0xffffffff; + }else{ + *v = (u32)v64; + } + return n; + } + +#else + /* For following code (kept for historical record only) shows an + ** unrolling for the 3- and 4-byte varint cases. This code is + ** slightly faster, but it is also larger and much harder to test. + */ p++; b = b<<14; b |= *p; /* b: p1<<14 | p3 (unmasked) */ if (!(b&0x80)) { + /* Values between 2097152 and 268435455 */ b &= (0x7f<<14)|(0x7f); a &= (0x7f<<14)|(0x7f); a = a<<7; *v = a | b; return 4; @@ -18522,10 +19298,11 @@ a = a<<14; a |= *p; /* a: p0<<28 | p2<<14 | p4 (unmasked) */ if (!(a&0x80)) { + /* Walues between 268435456 and 34359738367 */ a &= (0x1f<<28)|(0x7f<<14)|(0x7f); b &= (0x1f<<28)|(0x7f<<14)|(0x7f); b = b<<7; *v = a | b; return 5; @@ -18543,10 +19320,11 @@ n = sqlite3GetVarint(p, &v64); assert( n>5 && n<=9 ); *v = (u32)v64; return n; } +#endif } /* ** Return the number of bytes that will be needed to store the given ** 64-bit integer. @@ -18554,11 +19332,11 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){ int i = 0; do{ i++; v >>= 7; - }while( v!=0 && i<9 ); + }while( v!=0 && ALWAYS(i<9) ); return i; } /* @@ -18577,11 +19355,11 @@ #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) /* ** Translate a single byte of Hex into an integer. -** This routinen only works if h really is a valid hexadecimal +** This routine only works if h really is a valid hexadecimal ** character: 0..9a..fA..F */ static u8 hexToInt(int h){ assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); #ifdef SQLITE_ASCII @@ -18692,17 +19470,22 @@ */ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ u32 magic; if( db==0 ) return 0; magic = db->magic; - if( magic!=SQLITE_MAGIC_OPEN && - magic!=SQLITE_MAGIC_BUSY ) return 0; - return 1; + if( magic!=SQLITE_MAGIC_OPEN +#ifdef SQLITE_DEBUG + && magic!=SQLITE_MAGIC_BUSY +#endif + ){ + return 0; + }else{ + return 1; + } } SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ u32 magic; - if( db==0 ) return 0; magic = db->magic; if( magic!=SQLITE_MAGIC_SICK && magic!=SQLITE_MAGIC_OPEN && magic!=SQLITE_MAGIC_BUSY ) return 0; return 1; @@ -18722,23 +19505,20 @@ ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** -** $Id: hash.c,v 1.33 2009/01/09 01:12:28 drh Exp $ +** $Id: hash.c,v 1.38 2009/05/09 23:29:12 drh Exp $ */ /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** ** "pNew" is a pointer to the hash table that is to be initialized. -** "copyKey" is true if the hash table should make its own private -** copy of keys and false if it should just use the supplied pointer. -*/ -SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew, int copyKey){ - assert( pNew!=0 ); - pNew->copyKey = copyKey!=0; +*/ +SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){ + assert( pNew!=0 ); pNew->first = 0; pNew->count = 0; pNew->htsize = 0; pNew->ht = 0; } @@ -18756,47 +19536,46 @@ sqlite3_free(pH->ht); pH->ht = 0; pH->htsize = 0; while( elem ){ HashElem *next_elem = elem->next; - if( pH->copyKey ){ - sqlite3_free(elem->pKey); - } sqlite3_free(elem); elem = next_elem; } pH->count = 0; } /* -** Hash and comparison functions when the mode is SQLITE_HASH_STRING -*/ -static int strHash(const void *pKey, int nKey){ - const char *z = (const char *)pKey; +** The hashing function. +*/ +static unsigned int strHash(const char *z, int nKey){ int h = 0; - if( nKey<=0 ) nKey = sqlite3Strlen30(z); + assert( nKey>=0 ); while( nKey > 0 ){ h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++]; nKey--; } - return h & 0x7fffffff; -} -static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1); -} - - -/* Link an element into the hash table + return h; +} + + +/* Link pNew element into the hash table pH. If pEntry!=0 then also +** insert pNew into the pEntry hash bucket. */ static void insertElement( Hash *pH, /* The complete hash table */ struct _ht *pEntry, /* The entry into which pNew is inserted */ HashElem *pNew /* The element to be inserted */ ){ HashElem *pHead; /* First element already in pEntry */ - pHead = pEntry->chain; + if( pEntry ){ + pHead = pEntry->count ? pEntry->chain : 0; + pEntry->count++; + pEntry->chain = pNew; + }else{ + pHead = 0; + } if( pHead ){ pNew->next = pHead; pNew->prev = pHead->prev; if( pHead->prev ){ pHead->prev->next = pNew; } else { pH->first = pNew; } @@ -18805,73 +19584,77 @@ pNew->next = pH->first; if( pH->first ){ pH->first->prev = pNew; } pNew->prev = 0; pH->first = pNew; } - pEntry->count++; - pEntry->chain = pNew; } /* Resize the hash table so that it cantains "new_size" buckets. -** "new_size" must be a power of 2. The hash table might fail -** to resize if sqlite3_malloc() fails. -*/ -static void rehash(Hash *pH, int new_size){ +** +** The hash table might fail to resize if sqlite3_malloc() fails or +** if the new size is the same as the prior size. +** Return TRUE if the resize occurs and false if not. +*/ +static int rehash(Hash *pH, unsigned int new_size){ struct _ht *new_ht; /* The new hash table */ HashElem *elem, *next_elem; /* For looping over existing elements */ -#ifdef SQLITE_MALLOC_SOFT_LIMIT +#if SQLITE_MALLOC_SOFT_LIMIT>0 if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){ new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht); } - if( new_size==pH->htsize ) return; -#endif - - /* There is a call to sqlite3_malloc() inside rehash(). If there is - ** already an allocation at pH->ht, then if this malloc() fails it - ** is benign (since failing to resize a hash table is a performance - ** hit only, not a fatal error). - */ - if( pH->htsize>0 ) sqlite3BeginBenignMalloc(); - new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) ); - if( pH->htsize>0 ) sqlite3EndBenignMalloc(); - - if( new_ht==0 ) return; + if( new_size==pH->htsize ) return 0; +#endif + + /* The inability to allocates space for a larger hash table is + ** a performance hit but it is not a fatal error. So mark the + ** allocation as a benign. + */ + sqlite3BeginBenignMalloc(); + new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) ); + sqlite3EndBenignMalloc(); + + if( new_ht==0 ) return 0; sqlite3_free(pH->ht); pH->ht = new_ht; - pH->htsize = 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){ - int h = strHash(elem->pKey, elem->nKey) & (new_size-1); + unsigned int h = strHash(elem->pKey, elem->nKey) % new_size; next_elem = elem->next; insertElement(pH, &new_ht[h], elem); } + return 1; } /* 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. */ static HashElem *findElementGivenHash( const Hash *pH, /* The pH to be searched */ - const void *pKey, /* The key we are searching for */ - int nKey, - int h /* The hash for this key. */ + 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. */ ){ HashElem *elem; /* Used to loop thru the element list */ int count; /* Number of elements left to test */ if( pH->ht ){ struct _ht *pEntry = &pH->ht[h]; elem = pEntry->chain; count = pEntry->count; - while( count-- && elem ){ - if( strCompare(elem->pKey,elem->nKey,pKey,nKey)==0 ){ - return elem; - } - elem = elem->next; - } + }else{ + elem = pH->first; + count = pH->count; + } + while( count-- && ALWAYS(elem) ){ + if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; } return 0; } /* Remove a single entry from the hash table given a pointer to that @@ -18878,11 +19661,11 @@ ** element and a hash on the element's key. */ static void removeElementGivenHash( Hash *pH, /* The pH containing "elem" */ HashElem* elem, /* The element to be removed from the pH */ - int h /* Hash value for the element */ + unsigned int h /* Hash value for the element */ ){ struct _ht *pEntry; if( elem->prev ){ elem->prev->next = elem->next; }else{ @@ -18889,20 +19672,17 @@ pH->first = elem->next; } if( elem->next ){ elem->next->prev = elem->prev; } - pEntry = &pH->ht[h]; - if( pEntry->chain==elem ){ - pEntry->chain = elem->next; - } - pEntry->count--; - if( pEntry->count<=0 ){ - pEntry->chain = 0; - } - if( pH->copyKey ){ - sqlite3_free(elem->pKey); + if( pH->ht ){ + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + assert( pEntry->count>=0 ); } sqlite3_free( elem ); pH->count--; if( pH->count<=0 ){ assert( pH->first==0 ); @@ -18910,107 +19690,86 @@ sqlite3HashClear(pH); } } /* Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return a pointer to the corresponding -** HashElem structure for this element if it is found, or NULL -** otherwise. -*/ -SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){ - int h; /* A hash on key */ - HashElem *elem; /* The element that matches key */ - - if( pH==0 || pH->ht==0 ) return 0; - h = strHash(pKey,nKey); - elem = findElementGivenHash(pH,pKey,nKey, h % pH->htsize); - return elem; -} - -/* 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 ** found, or NULL if there is no match. */ -SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){ +SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){ HashElem *elem; /* The element that matches key */ - elem = sqlite3HashFindElem(pH, pKey, nKey); + 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); return elem ? elem->data : 0; } /* Insert an element into the hash table pH. The key is pKey,nKey ** and the data is "data". ** ** If no element exists with a matching key, then a new -** element is created. A copy of the key is made if the copyKey -** flag is set. NULL is returned. +** element is created and NULL is returned. ** ** If another element already exists with the same key, then the ** new data replaces the old data and the old data is returned. ** The key is not copied in this instance. If a malloc fails, then ** the new data is returned and the hash table is unchanged. ** ** If the "data" parameter to this function is NULL, then the ** element corresponding to "key" is removed from the hash table. */ -SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){ - int hraw; /* Raw hash value of the key */ - int h; /* the hash of the key modulo hash table size */ +SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, 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 ); - hraw = strHash(pKey, nKey); + assert( pKey!=0 ); + assert( nKey>=0 ); if( pH->htsize ){ - h = hraw % pH->htsize; - elem = findElementGivenHash(pH,pKey,nKey,h); - if( elem ){ - void *old_data = elem->data; - if( data==0 ){ - removeElementGivenHash(pH,elem,h); - }else{ - elem->data = data; - if( !pH->copyKey ){ - elem->pKey = (void *)pKey; - } - assert(nKey==elem->nKey); - } - return old_data; - } + h = strHash(pKey, nKey) % pH->htsize; + }else{ + h = 0; + } + elem = findElementGivenHash(pH,pKey,nKey,h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + removeElementGivenHash(pH,elem,h); + }else{ + elem->data = data; + elem->pKey = pKey; + assert(nKey==elem->nKey); + } + return old_data; } if( data==0 ) return 0; new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); if( new_elem==0 ) return data; - if( pH->copyKey && pKey!=0 ){ - new_elem->pKey = sqlite3Malloc( nKey ); - if( new_elem->pKey==0 ){ - sqlite3_free(new_elem); - return data; - } - memcpy((void*)new_elem->pKey, pKey, nKey); - }else{ - new_elem->pKey = (void*)pKey; - } + new_elem->pKey = pKey; new_elem->nKey = nKey; + new_elem->data = data; pH->count++; - if( pH->htsize==0 ){ - rehash(pH, 128/sizeof(pH->ht[0])); - if( pH->htsize==0 ){ - pH->count = 0; - if( pH->copyKey ){ - sqlite3_free(new_elem->pKey); - } - sqlite3_free(new_elem); - return data; - } - } - if( pH->count > pH->htsize ){ - rehash(pH,pH->htsize*2); - } - assert( pH->htsize>0 ); - h = hraw % pH->htsize; - insertElement(pH, &pH->ht[h], new_elem); - new_elem->data = data; + 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; + } + } + if( pH->ht ){ + insertElement(pH, &pH->ht[h], new_elem); + }else{ + insertElement(pH, 0, new_elem); + } return 0; } /************** End of hash.c ************************************************/ /************** Begin file opcodes.c *****************************************/ @@ -19028,24 +19787,24 @@ /* 7 */ "Savepoint", /* 8 */ "RowKey", /* 9 */ "SCopy", /* 10 */ "OpenWrite", /* 11 */ "If", - /* 12 */ "VRowid", - /* 13 */ "CollSeq", - /* 14 */ "OpenRead", - /* 15 */ "Expire", - /* 16 */ "AutoCommit", - /* 17 */ "Pagecount", - /* 18 */ "IntegrityCk", + /* 12 */ "CollSeq", + /* 13 */ "OpenRead", + /* 14 */ "Expire", + /* 15 */ "AutoCommit", + /* 16 */ "Pagecount", + /* 17 */ "IntegrityCk", + /* 18 */ "Sort", /* 19 */ "Not", - /* 20 */ "Sort", - /* 21 */ "Copy", - /* 22 */ "Trace", - /* 23 */ "Function", - /* 24 */ "IfNeg", - /* 25 */ "Noop", + /* 20 */ "Copy", + /* 21 */ "Trace", + /* 22 */ "Function", + /* 23 */ "IfNeg", + /* 24 */ "Noop", + /* 25 */ "Program", /* 26 */ "Return", /* 27 */ "NewRowid", /* 28 */ "Variable", /* 29 */ "String", /* 30 */ "RealAffinity", @@ -19060,46 +19819,46 @@ /* 39 */ "MustBeInt", /* 40 */ "Halt", /* 41 */ "Rowid", /* 42 */ "IdxLT", /* 43 */ "AddImm", - /* 44 */ "Statement", - /* 45 */ "RowData", - /* 46 */ "MemMax", - /* 47 */ "NotExists", - /* 48 */ "Gosub", - /* 49 */ "Integer", - /* 50 */ "Prev", - /* 51 */ "RowSetRead", - /* 52 */ "RowSetAdd", - /* 53 */ "VColumn", - /* 54 */ "CreateTable", - /* 55 */ "Last", - /* 56 */ "SeekLe", - /* 57 */ "IncrVacuum", - /* 58 */ "IdxRowid", - /* 59 */ "ResetCount", - /* 60 */ "ContextPush", - /* 61 */ "Yield", - /* 62 */ "DropTrigger", - /* 63 */ "DropIndex", - /* 64 */ "IdxGE", - /* 65 */ "IdxDelete", + /* 44 */ "RowData", + /* 45 */ "MemMax", + /* 46 */ "NotExists", + /* 47 */ "Gosub", + /* 48 */ "Integer", + /* 49 */ "Prev", + /* 50 */ "RowSetRead", + /* 51 */ "RowSetAdd", + /* 52 */ "VColumn", + /* 53 */ "CreateTable", + /* 54 */ "Last", + /* 55 */ "SeekLe", + /* 56 */ "IncrVacuum", + /* 57 */ "IdxRowid", + /* 58 */ "ResetCount", + /* 59 */ "Yield", + /* 60 */ "DropTrigger", + /* 61 */ "DropIndex", + /* 62 */ "Param", + /* 63 */ "IdxGE", + /* 64 */ "IdxDelete", + /* 65 */ "Vacuum", /* 66 */ "Or", /* 67 */ "And", - /* 68 */ "Vacuum", - /* 69 */ "IfNot", - /* 70 */ "DropTable", + /* 68 */ "IfNot", + /* 69 */ "DropTable", + /* 70 */ "SeekLt", /* 71 */ "IsNull", /* 72 */ "NotNull", /* 73 */ "Ne", /* 74 */ "Eq", /* 75 */ "Gt", /* 76 */ "Le", /* 77 */ "Lt", /* 78 */ "Ge", - /* 79 */ "SeekLt", + /* 79 */ "MakeRecord", /* 80 */ "BitAnd", /* 81 */ "BitOr", /* 82 */ "ShiftLeft", /* 83 */ "ShiftRight", /* 84 */ "Add", @@ -19106,54 +19865,54 @@ /* 85 */ "Subtract", /* 86 */ "Multiply", /* 87 */ "Divide", /* 88 */ "Remainder", /* 89 */ "Concat", - /* 90 */ "MakeRecord", - /* 91 */ "ResultRow", - /* 92 */ "Delete", + /* 90 */ "ResultRow", + /* 91 */ "Delete", + /* 92 */ "AggFinal", /* 93 */ "BitNot", /* 94 */ "String8", - /* 95 */ "AggFinal", - /* 96 */ "Compare", - /* 97 */ "Goto", - /* 98 */ "TableLock", - /* 99 */ "Clear", - /* 100 */ "VerifyCookie", - /* 101 */ "AggStep", - /* 102 */ "SetNumColumns", - /* 103 */ "Transaction", - /* 104 */ "VFilter", - /* 105 */ "VDestroy", - /* 106 */ "ContextPop", - /* 107 */ "Next", - /* 108 */ "Count", - /* 109 */ "IdxInsert", - /* 110 */ "SeekGe", - /* 111 */ "Insert", - /* 112 */ "Destroy", - /* 113 */ "ReadCookie", - /* 114 */ "LoadAnalysis", - /* 115 */ "Explain", - /* 116 */ "HaltIfNull", - /* 117 */ "OpenPseudo", - /* 118 */ "OpenEphemeral", - /* 119 */ "Null", - /* 120 */ "Move", - /* 121 */ "Blob", - /* 122 */ "Rewind", - /* 123 */ "SeekGt", - /* 124 */ "VBegin", - /* 125 */ "VUpdate", - /* 126 */ "IfZero", - /* 127 */ "VCreate", - /* 128 */ "Found", - /* 129 */ "IfPos", + /* 95 */ "Compare", + /* 96 */ "Goto", + /* 97 */ "TableLock", + /* 98 */ "Clear", + /* 99 */ "VerifyCookie", + /* 100 */ "AggStep", + /* 101 */ "Transaction", + /* 102 */ "VFilter", + /* 103 */ "VDestroy", + /* 104 */ "Next", + /* 105 */ "Count", + /* 106 */ "IdxInsert", + /* 107 */ "SeekGe", + /* 108 */ "Insert", + /* 109 */ "Destroy", + /* 110 */ "ReadCookie", + /* 111 */ "RowSetTest", + /* 112 */ "LoadAnalysis", + /* 113 */ "Explain", + /* 114 */ "HaltIfNull", + /* 115 */ "OpenPseudo", + /* 116 */ "OpenEphemeral", + /* 117 */ "Null", + /* 118 */ "Move", + /* 119 */ "Blob", + /* 120 */ "Rewind", + /* 121 */ "SeekGt", + /* 122 */ "VBegin", + /* 123 */ "VUpdate", + /* 124 */ "IfZero", + /* 125 */ "VCreate", + /* 126 */ "Found", + /* 127 */ "IfPos", + /* 128 */ "NullRow", + /* 129 */ "Jump", /* 130 */ "Real", - /* 131 */ "NullRow", - /* 132 */ "Jump", - /* 133 */ "Permutation", + /* 131 */ "Permutation", + /* 132 */ "NotUsed_132", + /* 133 */ "NotUsed_133", /* 134 */ "NotUsed_134", /* 135 */ "NotUsed_135", /* 136 */ "NotUsed_136", /* 137 */ "NotUsed_137", /* 138 */ "NotUsed_138", @@ -20565,12 +21324,10 @@ ** methods plus "finder" functions for each locking method. ** * sqlite3_vfs method implementations. ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). -** -** $Id: os_unix.c,v 1.250 2009/04/07 05:35:04 chw Exp $ */ #if SQLITE_OS_UNIX /* This file is used on unix only */ /* ** There are various methods for file locking used for concurrency @@ -20690,10 +21447,23 @@ */ #define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) /* +** Sometimes, after a file handle is closed by SQLite, the file descriptor +** cannot be closed immediately. In these cases, instances of the following +** structure are used to store the file descriptor while waiting for an +** opportunity to either close or reuse it. +*/ +typedef struct UnixUnusedFd UnixUnusedFd; +struct UnixUnusedFd { + int fd; /* File descriptor to close */ + int flags; /* Flags this file descriptor was opened with */ + UnixUnusedFd *pNext; /* Next unused file descriptor on same file */ +}; + +/* ** The unixFile structure is subclass of sqlite3_file specific to the unix ** VFS implementations. */ typedef struct unixFile unixFile; struct unixFile { @@ -20703,10 +21473,12 @@ int h; /* The file descriptor */ int dirfd; /* File descriptor for the directory */ unsigned char locktype; /* The type of lock held on this fd */ int lastErrno; /* The unix errno from the last I/O error */ void *lockingContext; /* Locking style specific state */ + UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ + int fileFlags; /* Miscellanous flags */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_THREADSAFE && defined(__linux__) pthread_t tid; /* The thread that "owns" this unixFile */ @@ -20724,23 +21496,23 @@ ** one described by ticket #3584. */ unsigned char transCntrChng; /* True if the transaction counter changed */ unsigned char dbUpdate; /* True if any part of database file changed */ unsigned char inNormalWrite; /* True if in a normal write operation */ - - /* If true, that means we are dealing with a database file that has - ** a range of locking bytes from PENDING_BYTE through PENDING_BYTE+511 - ** which should never be read or written. Asserts() will verify this */ - unsigned char isLockable; /* True if file might be locked */ #endif #ifdef SQLITE_TEST /* In test mode, increase the size of this structure a bit so that ** it is larger than the struct CrashFile defined in test6.c. */ char aPadding[32]; #endif }; + +/* +** The following macros define bits in unixFile.fileFlags +*/ +#define SQLITE_WHOLE_FILE_LOCKING 0x0001 /* Use whole-file locking */ /* ** Include code that is common to all os_*.c files */ /************** Include os_common.h in the middle of os_unix.c ***************/ @@ -21005,18 +21777,34 @@ #define threadid 0 #endif /* -** Helper functions to obtain and relinquish the global mutex. +** Helper functions to obtain and relinquish the global mutex. The +** global mutex is used to protect the unixOpenCnt, unixLockInfo and +** vxworksFileId objects used by this file, all of which may be +** shared by multiple threads. +** +** Function unixMutexHeld() is used to assert() that the global mutex +** is held when required. This function is only used as part of assert() +** statements. e.g. +** +** unixEnterMutex() +** assert( unixMutexHeld() ); +** unixEnterLeave() */ static void unixEnterMutex(void){ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } static void unixLeaveMutex(void){ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } +#ifdef SQLITE_DEBUG +static int unixMutexHeld(void) { + return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +} +#endif #ifdef SQLITE_DEBUG /* ** Helper function for printing out trace information from debugging @@ -21023,15 +21811,15 @@ ** binaries. This returns the string represetation of the supplied ** integer lock-type. */ static const char *locktypeName(int locktype){ switch( locktype ){ - case NO_LOCK: return "NONE"; - case SHARED_LOCK: return "SHARED"; - case RESERVED_LOCK: return "RESERVED"; - case PENDING_LOCK: return "PENDING"; - case EXCLUSIVE_LOCK: return "EXCLUSIVE"; + case NO_LOCK: return "NONE"; + case SHARED_LOCK: return "SHARED"; + case RESERVED_LOCK: return "RESERVED"; + case PENDING_LOCK: return "PENDING"; + case EXCLUSIVE_LOCK: return "EXCLUSIVE"; } return "ERROR"; } #endif @@ -21481,15 +22269,14 @@ */ struct unixOpenCnt { struct unixFileId fileId; /* The lookup key */ int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ - int nPending; /* Number of pending close() operations */ - int *aPending; /* Malloced space holding fd's awaiting a close() */ + UnixUnusedFd *pUnused; /* Unused file descriptors to close */ #if OS_VXWORKS sem_t *pSem; /* Named POSIX semaphore */ - char aSemName[MAX_PATHNAME+1]; /* Name of that semaphore */ + char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */ #endif struct unixOpenCnt *pNext, *pPrev; /* List of all unixOpenCnt objects */ }; /* @@ -21582,22 +22369,27 @@ if( rc!=0 ) return; memset(&d, 0, sizeof(d)); d.fd = fd; d.lock = l; d.lock.l_type = F_WRLCK; - pthread_create(&t, 0, threadLockingTest, &d); - pthread_join(t, 0); + if( pthread_create(&t, 0, threadLockingTest, &d)==0 ){ + pthread_join(t, 0); + } close(fd); if( d.result!=0 ) return; threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK); } -#endif /* SQLITE_THERADSAFE && defined(__linux__) */ +#endif /* SQLITE_THREADSAFE && defined(__linux__) */ /* ** Release a unixLockInfo structure previously allocated by findLockInfo(). +** +** The mutex entered using the unixEnterMutex() function must be held +** when this function is called. */ static void releaseLockInfo(struct unixLockInfo *pLock){ + assert( unixMutexHeld() ); if( pLock ){ pLock->nRef--; if( pLock->nRef==0 ){ if( pLock->pPrev ){ assert( pLock->pPrev->pNext==pLock ); @@ -21615,12 +22407,16 @@ } } /* ** Release a unixOpenCnt structure previously allocated by findLockInfo(). +** +** The mutex entered using the unixEnterMutex() function must be held +** when this function is called. */ static void releaseOpenCnt(struct unixOpenCnt *pOpen){ + assert( unixMutexHeld() ); if( pOpen ){ pOpen->nRef--; if( pOpen->nRef==0 ){ if( pOpen->pPrev ){ assert( pOpen->pPrev->pNext==pOpen ); @@ -21631,20 +22427,33 @@ } if( pOpen->pNext ){ assert( pOpen->pNext->pPrev==pOpen ); pOpen->pNext->pPrev = pOpen->pPrev; } - sqlite3_free(pOpen->aPending); +#if SQLITE_THREADSAFE && defined(__linux__) + assert( !pOpen->pUnused || threadsOverrideEachOthersLocks==0 ); +#endif + + /* If pOpen->pUnused is not null, then memory and file-descriptors + ** are leaked. + ** + ** This will only happen if, under Linuxthreads, the user has opened + ** a transaction in one thread, then attempts to close the database + ** handle from another thread (without first unlocking the db file). + ** This is a misuse. */ sqlite3_free(pOpen); } } } /* ** Given a file descriptor, locate unixLockInfo and unixOpenCnt structures that ** describes that file descriptor. Create new ones if necessary. The ** return values might be uninitialized if an error occurs. +** +** The mutex entered using the unixEnterMutex() function must be held +** when this function is called. ** ** Return an appropriate error code. */ static int findLockInfo( unixFile *pFile, /* Unix file with file desc used in the key */ @@ -21654,12 +22463,14 @@ int rc; /* System call return code */ int fd; /* The file descriptor for pFile */ struct unixLockKey lockKey; /* Lookup key for the unixLockInfo structure */ struct unixFileId fileId; /* Lookup key for the unixOpenCnt struct */ struct stat statbuf; /* Low-level file information */ - struct unixLockInfo *pLock; /* Candidate unixLockInfo object */ + struct unixLockInfo *pLock = 0;/* Candidate unixLockInfo object */ struct unixOpenCnt *pOpen; /* Candidate unixOpenCnt object */ + + assert( unixMutexHeld() ); /* Get low-level information about the file that we can used to ** create a unique name for the file. */ fd = pFile->h; @@ -21744,23 +22555,16 @@ if( pOpen==0 ){ releaseLockInfo(pLock); rc = SQLITE_NOMEM; goto exit_findlockinfo; } + memset(pOpen, 0, sizeof(*pOpen)); pOpen->fileId = fileId; pOpen->nRef = 1; - pOpen->nLock = 0; - pOpen->nPending = 0; - pOpen->aPending = 0; - pOpen->pNext = openList; - pOpen->pPrev = 0; + pOpen->pNext = openList; if( openList ) openList->pPrev = pOpen; openList = pOpen; -#if OS_VXWORKS - pOpen->pSem = NULL; - pOpen->aSemName[0] = '\0'; -#endif }else{ pOpen->nRef++; } *ppOpen = pOpen; } @@ -21864,10 +22668,66 @@ *pResOut = reserved; return rc; } /* +** Perform a file locking operation on a range of bytes in a file. +** The "op" parameter should be one of F_RDLCK, F_WRLCK, or F_UNLCK. +** Return 0 on success or -1 for failure. On failure, write the error +** code into *pErrcode. +** +** If the SQLITE_WHOLE_FILE_LOCKING bit is clear, then only lock +** the range of bytes on the locking page between SHARED_FIRST and +** SHARED_SIZE. If SQLITE_WHOLE_FILE_LOCKING is set, then lock all +** bytes from 0 up to but not including PENDING_BYTE, and all bytes +** that follow SHARED_FIRST. +** +** In other words, of SQLITE_WHOLE_FILE_LOCKING if false (the historical +** default case) then only lock a small range of bytes from SHARED_FIRST +** through SHARED_FIRST+SHARED_SIZE-1. But if SQLITE_WHOLE_FILE_LOCKING is +** true then lock every byte in the file except for PENDING_BYTE and +** RESERVED_BYTE. +** +** SQLITE_WHOLE_FILE_LOCKING=true overlaps SQLITE_WHOLE_FILE_LOCKING=false +** and so the locking schemes are compatible. One type of lock will +** effectively exclude the other type. The reason for using the +** SQLITE_WHOLE_FILE_LOCKING=true is that by indicating the full range +** of bytes to be read or written, we give hints to NFS to help it +** maintain cache coherency. On the other hand, whole file locking +** is slower, so we don't want to use it except for NFS. +*/ +static int rangeLock(unixFile *pFile, int op, int *pErrcode){ + struct flock lock; + int rc; + lock.l_type = op; + lock.l_start = SHARED_FIRST; + lock.l_whence = SEEK_SET; + if( (pFile->fileFlags & SQLITE_WHOLE_FILE_LOCKING)==0 ){ + lock.l_len = SHARED_SIZE; + rc = fcntl(pFile->h, F_SETLK, &lock); + *pErrcode = errno; + }else{ + lock.l_len = 0; + rc = fcntl(pFile->h, F_SETLK, &lock); + *pErrcode = errno; + if( NEVER(op==F_UNLCK) || rc!=(-1) ){ + lock.l_start = 0; + lock.l_len = PENDING_BYTE; + rc = fcntl(pFile->h, F_SETLK, &lock); + if( ALWAYS(op!=F_UNLCK) && rc==(-1) ){ + *pErrcode = errno; + lock.l_type = F_UNLCK; + lock.l_start = SHARED_FIRST; + lock.l_len = 0; + fcntl(pFile->h, F_SETLK, &lock); + } + } + } + return rc; +} + +/* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK @@ -21930,11 +22790,12 @@ */ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; struct unixLockInfo *pLock = pFile->pLock; struct flock lock; - int s; + int s = 0; + int tErrno; assert( pFile ); OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), locktypeName(pLock->locktype), pLock->cnt , getpid()); @@ -21947,11 +22808,14 @@ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, locktypeName(locktype)); return SQLITE_OK; } - /* Make sure the locking sequence is correct + /* Make sure the locking sequence is correct. + ** (1) We never move from unlocked to anything higher than shared lock. + ** (2) SQLite never explicitly requests a pendig lock. + ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); @@ -21991,26 +22855,25 @@ pLock->cnt++; pFile->pOpen->nLock++; goto end_lock; } - lock.l_len = 1L; - - lock.l_whence = SEEK_SET; /* A PENDING lock is needed before acquiring a SHARED lock and before ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will ** be released. */ + lock.l_len = 1L; + lock.l_whence = SEEK_SET; if( locktype==SHARED_LOCK || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK) ){ lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK); lock.l_start = PENDING_BYTE; s = fcntl(pFile->h, F_SETLK, &lock); if( s==(-1) ){ - int tErrno = errno; + tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } goto end_lock; @@ -22020,20 +22883,16 @@ /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ if( locktype==SHARED_LOCK ){ - int tErrno = 0; assert( pLock->cnt==0 ); assert( pLock->locktype==0 ); /* Now get the read-lock */ - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; - if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){ - tErrno = errno; - } + s = rangeLock(pFile, F_RDLCK, &tErrno); + /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ @@ -22069,21 +22928,20 @@ assert( 0!=pFile->locktype ); lock.l_type = F_WRLCK; switch( locktype ){ case RESERVED_LOCK: lock.l_start = RESERVED_BYTE; + s = fcntl(pFile->h, F_SETLK, &lock); + tErrno = errno; break; case EXCLUSIVE_LOCK: - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; + s = rangeLock(pFile, F_WRLCK, &tErrno); break; default: assert(0); } - s = fcntl(pFile->h, F_SETLK, &lock); - if( s==(-1) ){ - int tErrno = errno; + if( s==(-1) ){ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } } @@ -22121,22 +22979,66 @@ rc==SQLITE_OK ? "ok" : "failed"); return rc; } /* +** Close all file descriptors accumuated in the unixOpenCnt->pUnused list. +** If all such file descriptors are closed without error, the list is +** cleared and SQLITE_OK returned. +** +** Otherwise, if an error occurs, then successfully closed file descriptor +** entries are removed from the list, and SQLITE_IOERR_CLOSE returned. +** not deleted and SQLITE_IOERR_CLOSE returned. +*/ +static int closePendingFds(unixFile *pFile){ + int rc = SQLITE_OK; + struct unixOpenCnt *pOpen = pFile->pOpen; + UnixUnusedFd *pError = 0; + UnixUnusedFd *p; + UnixUnusedFd *pNext; + for(p=pOpen->pUnused; p; p=pNext){ + pNext = p->pNext; + if( close(p->fd) ){ + pFile->lastErrno = errno; + rc = SQLITE_IOERR_CLOSE; + p->pNext = pError; + pError = p; + }else{ + sqlite3_free(p); + } + } + pOpen->pUnused = pError; + return rc; +} + +/* +** Add the file descriptor used by file handle pFile to the corresponding +** pUnused list. +*/ +static void setPendingFd(unixFile *pFile){ + struct unixOpenCnt *pOpen = pFile->pOpen; + UnixUnusedFd *p = pFile->pUnused; + p->pNext = pOpen->pUnused; + pOpen->pUnused = p; + pFile->h = -1; + pFile->pUnused = 0; +} + +/* ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int unixUnlock(sqlite3_file *id, int locktype){ - struct unixLockInfo *pLock; - struct flock lock; - int rc = SQLITE_OK; - unixFile *pFile = (unixFile*)id; - int h; + unixFile *pFile = (unixFile*)id; /* The open file */ + struct unixLockInfo *pLock; /* Structure describing current lock state */ + struct flock lock; /* Information passed into fcntl() */ + int rc = SQLITE_OK; /* Return code from this interface */ + int h; /* The underlying file descriptor */ + int tErrno; /* Error code from system call errors */ assert( pFile ); OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); @@ -22172,16 +23074,11 @@ pFile->inNormalWrite = 0; #endif if( locktype==SHARED_LOCK ){ - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; - if( fcntl(h, F_SETLK, &lock)==(-1) ){ - int tErrno = errno; + if( rangeLock(pFile, F_RDLCK, &tErrno)==(-1) ){ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } goto end_unlock; @@ -22192,21 +23089,20 @@ lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); if( fcntl(h, F_SETLK, &lock)!=(-1) ){ pLock->locktype = SHARED_LOCK; }else{ - int tErrno = errno; + tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } goto end_unlock; } } if( locktype==NO_LOCK ){ struct unixOpenCnt *pOpen; - int rc2 = SQLITE_OK; /* Decrement the shared lock counter. Release the lock using an ** OS call only when all threads in this same process have released ** the lock. */ @@ -22219,11 +23115,11 @@ SimulateIOError( h=(-1) ) SimulateIOErrorBenign(0); if( fcntl(h, F_SETLK, &lock)!=(-1) ){ pLock->locktype = NO_LOCK; }else{ - int tErrno = errno; + tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } pLock->locktype = NO_LOCK; @@ -22236,32 +23132,15 @@ ** was deferred because of outstanding locks. */ pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); - if( pOpen->nLock==0 && pOpen->nPending>0 ){ - int i; - for(i=0; i<pOpen->nPending; i++){ - /* close pending fds, but if closing fails don't free the array - ** assign -1 to the successfully closed descriptors and record the - ** error. The next attempt to unlock will try again. */ - if( pOpen->aPending[i] < 0 ) continue; - if( close(pOpen->aPending[i]) ){ - pFile->lastErrno = errno; - rc2 = SQLITE_IOERR_CLOSE; - }else{ - pOpen->aPending[i] = -1; - } - } - if( rc2==SQLITE_OK ){ - sqlite3_free(pOpen->aPending); - pOpen->nPending = 0; - pOpen->aPending = 0; - } - } - if( rc==SQLITE_OK ){ - rc = rc2; + if( pOpen->nLock==0 ){ + int rc2 = closePendingFds(pFile); + if( rc==SQLITE_OK ){ + rc = rc2; + } } } end_unlock: unixLeaveMutex(); @@ -22307,10 +23186,11 @@ pFile->pId = 0; } #endif OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); + sqlite3_free(pFile->pUnused); memset(pFile, 0, sizeof(unixFile)); } return SQLITE_OK; } @@ -22324,24 +23204,14 @@ unixUnlock(id, NO_LOCK); unixEnterMutex(); if( pFile->pOpen && pFile->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file - ** descriptor to pOpen->aPending. It will be automatically closed when - ** the last lock is cleared. - */ - int *aNew; - struct unixOpenCnt *pOpen = pFile->pOpen; - aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); - if( aNew==0 ){ - /* If a malloc fails, just leak the file descriptor */ - }else{ - pOpen->aPending = aNew; - pOpen->aPending[pOpen->nPending] = pFile->h; - pOpen->nPending++; - pFile->h = -1; - } + ** descriptor to pOpen->pUnused list. It will be automatically closed + ** when the last lock is cleared. + */ + setPendingFd(pFile); } releaseLockInfo(pFile->pLock); releaseOpenCnt(pFile->pOpen); rc = closeUnixFile(id); unixLeaveMutex(); @@ -22394,11 +23264,11 @@ ******************************************************************************/ /****************************************************************************** ************************* Begin dot-file Locking ****************************** ** -** The dotfile locking implementation uses the existing of separate lock +** The dotfile locking implementation uses the existance of separate lock ** files in order to control access to the database. This works on just ** about every filesystem imaginable. But there are serious downsides: ** ** (1) There is zero concurrency. A single reader blocks all other ** connections from reading or writing the database. @@ -22558,11 +23428,12 @@ } /* To fully unlock the database, delete the lock file */ assert( locktype==NO_LOCK ); if( unlink(zLockFile) ){ - int rc, tErrno = errno; + int rc = 0; + int tErrno = errno; if( ENOENT != tErrno ){ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); } if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; @@ -23305,31 +24176,19 @@ if( rc==SQLITE_OK ){ if( locktype==NO_LOCK ){ struct unixOpenCnt *pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); - if( pOpen->nLock==0 && pOpen->nPending>0 ){ - int i; - for(i=0; i<pOpen->nPending; i++){ - if( pOpen->aPending[i] < 0 ) continue; - if( close(pOpen->aPending[i]) ){ - pFile->lastErrno = errno; - rc = SQLITE_IOERR_CLOSE; - }else{ - pOpen->aPending[i] = -1; - } - } - if( rc==SQLITE_OK ){ - sqlite3_free(pOpen->aPending); - pOpen->nPending = 0; - pOpen->aPending = 0; - } + if( pOpen->nLock==0 ){ + rc = closePendingFds(pFile); } } } unixLeaveMutex(); - if( rc==SQLITE_OK ) pFile->locktype = locktype; + if( rc==SQLITE_OK ){ + pFile->locktype = locktype; + } return rc; } /* ** Close a file & cleanup AFP specific locking context @@ -23343,21 +24202,11 @@ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ - int *aNew; - struct unixOpenCnt *pOpen = pFile->pOpen; - aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); - if( aNew==0 ){ - /* If a malloc fails, just leak the file descriptor */ - }else{ - pOpen->aPending = aNew; - pOpen->aPending[pOpen->nPending] = pFile->h; - pOpen->nPending++; - pFile->h = -1; - } + setPendingFd(pFile); } releaseOpenCnt(pFile->pOpen); sqlite3_free(pFile->lockingContext); closeUnixFile(id); unixLeaveMutex(); @@ -23439,26 +24288,29 @@ sqlite3_file *id, void *pBuf, int amt, sqlite3_int64 offset ){ + unixFile *pFile = (unixFile *)id; int got; assert( id ); - /* Never read or write any of the bytes in the locking range */ - assert( ((unixFile*)id)->isLockable==0 - || offset>=PENDING_BYTE+512 - || offset+amt<=PENDING_BYTE ); - - got = seekAndRead((unixFile*)id, offset, pBuf, amt); + /* If this is a database file (not a journal, master-journal or temp + ** file), the bytes in the locking range should never be read or written. */ + assert( pFile->pUnused==0 + || offset>=PENDING_BYTE+512 + || offset+amt<=PENDING_BYTE + ); + + got = seekAndRead(pFile, offset, pBuf, amt); if( got==amt ){ return SQLITE_OK; }else if( got<0 ){ /* lastErrno set by seekAndRead */ return SQLITE_IOERR_READ; }else{ - ((unixFile*)id)->lastErrno = 0; /* not a system error */ + pFile->lastErrno = 0; /* not a system error */ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[got], 0, amt-got); return SQLITE_IOERR_SHORT_READ; } } @@ -23508,28 +24360,30 @@ sqlite3_file *id, const void *pBuf, int amt, sqlite3_int64 offset ){ + unixFile *pFile = (unixFile*)id; int wrote = 0; assert( id ); assert( amt>0 ); - /* Never read or write any of the bytes in the locking range */ - assert( ((unixFile*)id)->isLockable==0 - || offset>=PENDING_BYTE+512 - || offset+amt<=PENDING_BYTE ); + /* If this is a database file (not a journal, master-journal or temp + ** file), the bytes in the locking range should never be read or written. */ + assert( pFile->pUnused==0 + || offset>=PENDING_BYTE+512 + || offset+amt<=PENDING_BYTE + ); #ifndef NDEBUG /* If we are doing a normal write to a database file (as opposed to ** doing a hot-journal rollback or a write to some file other than a ** normal database file) then record the fact that the database ** has changed. If the transaction counter is modified, record that ** fact too. */ - if( ((unixFile*)id)->inNormalWrite ){ - unixFile *pFile = (unixFile*)id; + if( pFile->inNormalWrite ){ pFile->dbUpdate = 1; /* The database has been modified */ if( offset<=24 && offset+amt>=27 ){ int rc; char oldCntr[4]; SimulateIOErrorBenign(1); @@ -23540,11 +24394,11 @@ } } } #endif - while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){ + while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ amt -= wrote; offset += wrote; pBuf = &((char*)pBuf)[wrote]; } SimulateIOError(( wrote=(-1), amt=1 )); @@ -23552,11 +24406,11 @@ if( amt>0 ){ if( wrote<0 ){ /* lastErrno set by seekAndWrite */ return SQLITE_IOERR_WRITE; }else{ - ((unixFile*)id)->lastErrno = 0; /* not a system error */ + pFile->lastErrno = 0; /* not a system error */ return SQLITE_FULL; } } return SQLITE_OK; } @@ -23880,11 +24734,11 @@ ** ** For finder-funtion F, two objects are created: ** ** (1) The real finder-function named "FImpt()". ** -** (2) A constant pointer to this functio named just "F". +** (2) A constant pointer to this function named just "F". ** ** ** A pointer to the F pointer is used as the pAppData value for VFS ** objects. We have to do this instead of letting pAppData point ** directly at the finder-function since C90 rules prevent a void* @@ -23913,15 +24767,15 @@ CKLOCK, /* xCheckReservedLock */ \ unixFileControl, /* xFileControl */ \ unixSectorSize, /* xSectorSize */ \ unixDeviceCharacteristics /* xDeviceCapabilities */ \ }; \ -static const sqlite3_io_methods *FINDER##Impl(const char *z, int h){ \ - UNUSED_PARAMETER(z); UNUSED_PARAMETER(h); \ +static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \ + UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \ return &METHOD; \ } \ -static const sqlite3_io_methods *(*const FINDER)(const char*,int) \ +static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \ = FINDER##Impl; /* ** Here are all of the sqlite3_io_methods objects for each of the ** locking strategies. Functions that return pointers to these methods @@ -23984,10 +24838,27 @@ afpCheckReservedLock /* xCheckReservedLock method */ ) #endif /* +** The "Whole File Locking" finder returns the same set of methods as +** the posix locking finder. But it also sets the SQLITE_WHOLE_FILE_LOCKING +** flag to force the posix advisory locks to cover the whole file instead +** of just a small span of bytes near the 1GiB boundary. Whole File Locking +** is useful on NFS-mounted files since it helps NFS to maintain cache +** coherency. But it is a detriment to other filesystems since it runs +** slower. +*/ +static const sqlite3_io_methods *posixWflIoFinderImpl(const char*z, unixFile*p){ + UNUSED_PARAMETER(z); + p->fileFlags = SQLITE_WHOLE_FILE_LOCKING; + return &posixIoMethods; +} +static const sqlite3_io_methods + *(*const posixWflIoFinder)(const char*,unixFile *p) = posixWflIoFinderImpl; + +/* ** The proxy locking method is a "super-method" in the sense that it ** opens secondary file descriptors for the conch and lock files and ** it uses proxy, dot-file, AFP, and flock() locking methods on those ** secondary files. For this reason, the division that implements ** proxy locking is located much further down in the file. But we need @@ -24018,11 +24889,11 @@ ** ** This is for MacOSX only. */ static const sqlite3_io_methods *autolockIoFinderImpl( const char *filePath, /* name of the database file */ - int fd /* file descriptor open on the database file */ + unixFile *pNew /* open file object for the database file */ ){ static const struct Mapping { const char *zFilesystem; /* Filesystem type name */ const sqlite3_io_methods *pMethods; /* Appropriate locking method */ } aMap[] = { @@ -24063,18 +24934,19 @@ */ lockInfo.l_len = 1; lockInfo.l_start = 0; lockInfo.l_whence = SEEK_SET; lockInfo.l_type = F_RDLCK; - if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) { + if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { + pNew->fileFlags = SQLITE_WHOLE_FILE_LOCKING; return &posixIoMethods; }else{ return &dotlockIoMethods; } } -static const sqlite3_io_methods *(*const autolockIoFinder)(const char*,int) - = autolockIoFinderImpl; +static const sqlite3_io_methods + *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ #if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE /* @@ -24084,11 +24956,11 @@ ** ** This is for VXWorks only. */ static const sqlite3_io_methods *autolockIoFinderImpl( const char *filePath, /* name of the database file */ - int fd /* file descriptor open on the database file */ + unixFile *pNew /* the open file object */ ){ struct flock lockInfo; if( !filePath ){ /* If filePath==NULL that means we are dealing with a transient file @@ -24101,25 +24973,25 @@ */ lockInfo.l_len = 1; lockInfo.l_start = 0; lockInfo.l_whence = SEEK_SET; lockInfo.l_type = F_RDLCK; - if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) { + if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { return &posixIoMethods; }else{ return &semIoMethods; } } -static const sqlite3_io_methods *(*const autolockIoFinder)(const char*,int) - = autolockIoFinderImpl; +static const sqlite3_io_methods + *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; #endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */ /* ** An abstract type for a pointer to a IO method finder function: */ -typedef const sqlite3_io_methods *(*finder_type)(const char*,int); +typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*); /**************************************************************************** **************************** sqlite3_vfs methods **************************** ** @@ -24144,22 +25016,20 @@ int rc = SQLITE_OK; assert( pNew->pLock==NULL ); assert( pNew->pOpen==NULL ); - /* Parameter isDelete is only used on vxworks. - ** Express this explicitly here to prevent compiler warnings - ** about unused parameters. - */ -#if !OS_VXWORKS - UNUSED_PARAMETER(isDelete); -#endif + /* Parameter isDelete is only used on vxworks. Express this explicitly + ** here to prevent compiler warnings about unused parameters. + */ + UNUSED_PARAMETER(isDelete); OSTRACE3("OPEN %-3d %s\n", h, zFilename); pNew->h = h; pNew->dirfd = dirfd; SET_THREADID(pNew); + pNew->fileFlags = 0; #if OS_VXWORKS pNew->pId = vxworksFindFileId(zFilename); if( pNew->pId==0 ){ noLock = 1; @@ -24168,11 +25038,11 @@ #endif if( noLock ){ pLockingStyle = &nolockIoMethods; }else{ - pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, h); + pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew); #if SQLITE_ENABLE_LOCKING_STYLE /* Cache zFilename in the locking context (AFP and dotlock override) for ** proxyLock activation is possible (remote proxy is based on db name) ** zFilename remains valid until file is closed, to support */ pNew->lockingContext = (void*)zFilename; @@ -24180,10 +25050,32 @@ } if( pLockingStyle == &posixIoMethods ){ unixEnterMutex(); rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); + if( rc!=SQLITE_OK ){ + /* If an error occured in findLockInfo(), close the file descriptor + ** immediately, before releasing the mutex. findLockInfo() may fail + ** in two scenarios: + ** + ** (a) A call to fstat() failed. + ** (b) A malloc failed. + ** + ** Scenario (b) may only occur if the process is holding no other + ** file descriptors open on the same file. If there were other file + ** descriptors on this file, then no malloc would be required by + ** findLockInfo(). If this is the case, it is quite safe to close + ** handle h - as it is guaranteed that no posix locks will be released + ** by doing so. + ** + ** If scenario (a) caused the error then things are not so safe. The + ** implicit assumption here is that if fstat() fails, things are in + ** such bad shape that dropping a lock or two doesn't matter much. + */ + close(h); + h = -1; + } unixLeaveMutex(); } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) else if( pLockingStyle == &afpIoMethods ){ @@ -24231,13 +25123,13 @@ unixEnterMutex(); rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){ char *zSemName = pNew->pOpen->aSemName; int n; - sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", + sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem", pNew->pId->zCanonicalName); - for( n=0; zSemName[n]; n++ ) + for( n=1; zSemName[n]; n++ ) if( zSemName[n]=='/' ) zSemName[n] = '_'; pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1); if( pNew->pOpen->pSem == SEM_FAILED ){ rc = SQLITE_NOMEM; pNew->pOpen->aSemName[0] = '\0'; @@ -24255,11 +25147,11 @@ } pNew->isDelete = isDelete; #endif if( rc!=SQLITE_OK ){ if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */ - close(h); + if( h>=0 ) close(h); }else{ pNew->pMethod = pLockingStyle; OpenCounter(+1); } return rc; @@ -24364,10 +25256,66 @@ ** if SQLITE_PREFER_PROXY_LOCKING is defined. */ static int proxyTransformUnixFile(unixFile*, const char*); #endif +/* +** Search for an unused file descriptor that was opened on the database +** file (not a journal or master-journal file) identified by pathname +** zPath with SQLITE_OPEN_XXX flags matching those passed as the second +** argument to this function. +** +** Such a file descriptor may exist if a database connection was closed +** but the associated file descriptor could not be closed because some +** other file descriptor open on the same file is holding a file-lock. +** Refer to comments in the unixClose() function and the lengthy comment +** describing "Posix Advisory Locking" at the start of this file for +** further details. Also, ticket #4018. +** +** If a suitable file descriptor is found, then it is returned. If no +** such file descriptor is located, -1 is returned. +*/ +static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ + UnixUnusedFd *pUnused = 0; + + /* Do not search for an unused file descriptor on vxworks. Not because + ** vxworks would not benefit from the change (it might, we're not sure), + ** but because no way to test it is currently available. It is better + ** not to risk breaking vxworks support for the sake of such an obscure + ** feature. */ +#if !OS_VXWORKS + struct stat sStat; /* Results of stat() call */ + + /* A stat() call may fail for various reasons. If this happens, it is + ** almost certain that an open() call on the same path will also fail. + ** For this reason, if an error occurs in the stat() call here, it is + ** ignored and -1 is returned. The caller will try to open a new file + ** descriptor on the same path, fail, and return an error to SQLite. + ** + ** Even if a subsequent open() call does succeed, the consequences of + ** not searching for a resusable file descriptor are not dire. */ + if( 0==stat(zPath, &sStat) ){ + struct unixOpenCnt *pO; + struct unixFileId id; + id.dev = sStat.st_dev; + id.ino = sStat.st_ino; + + unixEnterMutex(); + for(pO=openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO=pO->pNext); + if( pO ){ + UnixUnusedFd **pp; + for(pp=&pO->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); + pUnused = *pp; + if( pUnused ){ + *pp = pUnused->pNext; + } + } + unixLeaveMutex(); + } +#endif /* if !OS_VXWORKS */ + return pUnused; +} /* ** Open the file zPath. ** ** Previously, the SQLite OS layer used three functions in place of this @@ -24394,16 +25342,17 @@ const char *zPath, /* Pathname of file to be opened */ sqlite3_file *pFile, /* The file descriptor to be filled in */ int flags, /* Input flags to control the opening */ int *pOutFlags /* Output flags returned to SQLite core */ ){ - int fd = -1; /* File descriptor returned by open() */ + unixFile *p = (unixFile *)pFile; + int fd = -1; /* File descriptor returned by open() */ int dirfd = -1; /* Directory file descriptor */ int openFlags = 0; /* Flags to pass to open() */ int eType = flags&0xFFFFFF00; /* Type of file to open */ int noLock; /* True to omit locking primitives */ - int rc = SQLITE_OK; + int rc = SQLITE_OK; /* Function Return Code */ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); int isCreate = (flags & SQLITE_OPEN_CREATE); int isReadonly = (flags & SQLITE_OPEN_READONLY); @@ -24434,79 +25383,106 @@ assert(isCreate==0 || isReadWrite); assert(isExclusive==0 || isCreate); assert(isDelete==0 || isCreate); /* The main DB, main journal, and master journal are never automatically - ** deleted - */ - assert( eType!=SQLITE_OPEN_MAIN_DB || !isDelete ); - assert( eType!=SQLITE_OPEN_MAIN_JOURNAL || !isDelete ); - assert( eType!=SQLITE_OPEN_MASTER_JOURNAL || !isDelete ); + ** deleted. Nor are they ever temporary files. */ + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); /* Assert that the upper layer has set one of the "file-type" flags. */ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_TRANSIENT_DB ); - memset(pFile, 0, sizeof(unixFile)); - - if( !zName ){ + memset(p, 0, sizeof(unixFile)); + + if( eType==SQLITE_OPEN_MAIN_DB ){ + UnixUnusedFd *pUnused; + pUnused = findReusableFd(zName, flags); + if( pUnused ){ + fd = pUnused->fd; + }else{ + pUnused = sqlite3_malloc(sizeof(*pUnused)); + if( !pUnused ){ + return SQLITE_NOMEM; + } + } + p->pUnused = pUnused; + }else if( !zName ){ + /* If zName is NULL, the upper layer is requesting a temp file. */ assert(isDelete && !isOpenDirectory); rc = getTempname(MAX_PATHNAME+1, zTmpname); if( rc!=SQLITE_OK ){ return rc; } zName = zTmpname; } + /* Determine the value of the flags parameter passed to POSIX function + ** open(). These must be calculated even if open() is not called, as + ** they may be stored as part of the file handle and used by the + ** 'conch file' locking functions later on. */ if( isReadonly ) openFlags |= O_RDONLY; if( isReadWrite ) openFlags |= O_RDWR; if( isCreate ) openFlags |= O_CREAT; if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW); openFlags |= (O_LARGEFILE|O_BINARY); - fd = open(zName, openFlags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); - OSTRACE4("OPENX %-3d %s 0%o\n", fd, zName, openFlags); - if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ - /* Failed to open the file for read/write access. Try read-only. */ - flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); - flags |= SQLITE_OPEN_READONLY; - return unixOpen(pVfs, zPath, pFile, flags, pOutFlags); - } if( fd<0 ){ - return SQLITE_CANTOPEN; - } + mode_t openMode = (isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); + fd = open(zName, openFlags, openMode); + OSTRACE4("OPENX %-3d %s 0%o\n", fd, zName, openFlags); + if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ + /* Failed to open the file for read/write access. Try read-only. */ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + openFlags &= ~(O_RDWR|O_CREAT); + flags |= SQLITE_OPEN_READONLY; + openFlags |= O_RDONLY; + fd = open(zName, openFlags, openMode); + } + if( fd<0 ){ + rc = SQLITE_CANTOPEN; + goto open_finished; + } + } + assert( fd>=0 ); + if( pOutFlags ){ + *pOutFlags = flags; + } + + if( p->pUnused ){ + p->pUnused->fd = fd; + p->pUnused->flags = flags; + } + if( isDelete ){ #if OS_VXWORKS zPath = zName; #else unlink(zName); #endif } #if SQLITE_ENABLE_LOCKING_STYLE else{ - ((unixFile*)pFile)->openFlags = openFlags; - } -#endif - if( pOutFlags ){ - *pOutFlags = flags; - } - -#ifndef NDEBUG - if( (flags & SQLITE_OPEN_MAIN_DB)!=0 ){ - ((unixFile*)pFile)->isLockable = 1; - } -#endif - - assert( fd>=0 ); + p->openFlags = openFlags; + } +#endif + if( isOpenDirectory ){ rc = openDirectory(zPath, &dirfd); if( rc!=SQLITE_OK ){ - close(fd); /* silently leak if fail, already in error */ - return rc; + /* It is safe to close fd at this point, because it is guaranteed not + ** to be open on a database file. If it were open on a database file, + ** it would not be safe to close as this would release any locks held + ** on the file by this process. */ + assert( eType!=SQLITE_OPEN_MAIN_DB ); + close(fd); /* silently leak if fail, already in error */ + goto open_finished; } } #ifdef FD_CLOEXEC fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); @@ -24513,42 +25489,56 @@ #endif noLock = eType!=SQLITE_OPEN_MAIN_DB; #if SQLITE_PREFER_PROXY_LOCKING - if( zPath!=NULL && !noLock ){ + if( zPath!=NULL && !noLock && pVfs->xOpen ){ char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); int useProxy = 0; - /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, - ** 0 means never use proxy, NULL means use proxy for non-local files only - */ + /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means + ** never use proxy, NULL means use proxy for non-local files only. */ if( envforce!=NULL ){ useProxy = atoi(envforce)>0; }else{ struct statfs fsInfo; - if( statfs(zPath, &fsInfo) == -1 ){ - ((unixFile*)pFile)->lastErrno = errno; - if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */ + /* In theory, the close(fd) call is sub-optimal. If the file opened + ** with fd is a database file, and there are other connections open + ** on that file that are currently holding advisory locks on it, + ** then the call to close() will cancel those locks. In practice, + ** we're assuming that statfs() doesn't fail very often. At least + ** not while other file descriptors opened by the same process on + ** the same file are working. */ + p->lastErrno = errno; + if( dirfd>=0 ){ + close(dirfd); /* silently leak if fail, in error */ + } close(fd); /* silently leak if fail, in error */ - return SQLITE_IOERR_ACCESS; + rc = SQLITE_IOERR_ACCESS; + goto open_finished; } useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); if( rc==SQLITE_OK ){ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); } - return rc; - } - } -#endif - - return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); -} + goto open_finished; + } + } +#endif + + rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); +open_finished: + if( rc!=SQLITE_OK ){ + sqlite3_free(p->pUnused); + } + return rc; +} + /* ** Delete the file at zPath. If the dirSync argument is true, fsync() ** the directory after deleting the file. */ @@ -24808,11 +25798,15 @@ ** Find the current time (in Universal Coordinated Time). Write the ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){ -#if defined(NO_GETTOD) +#if defined(SQLITE_OMIT_FLOATING_POINT) + time_t t; + time(&t); + *prNow = (((sqlite3_int64)t)/8640 + 24405875)/10; +#elif defined(NO_GETTOD) time_t t; time(&t); *prNow = t/86400.0 + 2440587.5; #elif OS_VXWORKS struct timespec sNow; @@ -25170,12 +26164,12 @@ { confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen); len = strlcat(lPath, "sqliteplocks", maxLen); if( mkdir(lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ /* if mkdir fails, handle as lock file creation failure */ - int err = errno; # ifdef SQLITE_DEBUG + int err = errno; if( err!=EEXIST ){ fprintf(stderr, "proxyGetLockPath: mkdir(%s,0%o) error %d %s\n", lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS, err, strerror(err)); } # endif @@ -25210,37 +26204,47 @@ ** ** The caller is responsible not only for closing the file descriptor ** but also for freeing the memory associated with the file descriptor. */ static int proxyCreateUnixFile(const char *path, unixFile **ppFile) { - int fd; - int dirfd = -1; unixFile *pNew; + int flags = SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; int rc = SQLITE_OK; sqlite3_vfs dummyVfs; - fd = open(path, O_RDWR | O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( fd<0 ){ - return SQLITE_CANTOPEN; - } - pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile)); - if( pNew==NULL ){ - rc = SQLITE_NOMEM; - goto end_create_proxy; + if( !pNew ){ + return SQLITE_NOMEM; } memset(pNew, 0, sizeof(unixFile)); + /* Call unixOpen() to open the proxy file. The flags passed to unixOpen() + ** suggest that the file being opened is a "main database". This is + ** necessary as other file types do not necessarily support locking. It + ** is better to use unixOpen() instead of opening the file directly with + ** open(), as unixOpen() sets up the various mechanisms required to + ** make sure a call to close() does not cause the system to discard + ** POSIX locks prematurely. + ** + ** It is important that the xOpen member of the VFS object passed to + ** unixOpen() is NULL. This tells unixOpen() may try to open a proxy-file + ** for the proxy-file (creating a potential infinite loop). + */ dummyVfs.pAppData = (void*)&autolockIoFinder; - rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0); - if( rc==SQLITE_OK ){ - *ppFile = pNew; - return SQLITE_OK; - } -end_create_proxy: - close(fd); /* silently leak fd if error, we're already in error */ - sqlite3_free(pNew); + dummyVfs.xOpen = 0; + rc = unixOpen(&dummyVfs, path, (sqlite3_file *)pNew, flags, &flags); + if( rc==SQLITE_OK && (flags&SQLITE_OPEN_READONLY) ){ + pNew->pMethod->xClose((sqlite3_file *)pNew); + rc = SQLITE_CANTOPEN; + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(pNew); + pNew = 0; + } + + *ppFile = pNew; return rc; } /* takes the conch by taking a shared lock and read the contents conch, if ** lockPath is non-NULL, the host ID and lock file path must match. A NULL @@ -25849,10 +26853,11 @@ #else UNIXVFS("unix", posixIoFinder ), #endif UNIXVFS("unix-none", nolockIoFinder ), UNIXVFS("unix-dotfile", dotlockIoFinder ), + UNIXVFS("unix-wfl", posixWflIoFinder ), #if OS_VXWORKS UNIXVFS("unix-namedsem", semIoFinder ), #endif #if SQLITE_ENABLE_LOCKING_STYLE UNIXVFS("unix-posix", posixIoFinder ), @@ -25900,12 +26905,10 @@ ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code that is specific to windows. -** -** $Id: os_win.c,v 1.154 2009/04/09 14:27:07 chw Exp $ */ #if SQLITE_OS_WIN /* This file is used for windows only */ /* @@ -26419,12 +27422,12 @@ FILETIME uTm, lTm; SYSTEMTIME pTm; sqlite3_int64 t64; t64 = *t; t64 = (t64 + 11644473600)*10000000; - uTm.dwLowDateTime = t64 & 0xFFFFFFFF; - uTm.dwHighDateTime= t64 >> 32; + uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); + uTm.dwHighDateTime= (DWORD)(t64 >> 32); FileTimeToLocalFileTime(&uTm,&lTm); FileTimeToSystemTime(&lTm,&pTm); y.tm_year = pTm.wYear - 1900; y.tm_mon = pTm.wMonth - 1; y.tm_wday = pTm.wDayOfWeek; @@ -26440,11 +27443,11 @@ #define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) #define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) #define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) -#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)] +#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] /* ** Acquire a lock on the handle h */ static void winceMutexAcquire(HANDLE h){ @@ -26579,27 +27582,29 @@ DWORD nNumberOfBytesToLockHigh ){ winFile *pFile = HANDLE_TO_WINFILE(phFile); BOOL bReturn = FALSE; + UNUSED_PARAMETER(dwFileOffsetHigh); + UNUSED_PARAMETER(nNumberOfBytesToLockHigh); + if (!pFile->hMutex) return TRUE; winceMutexAcquire(pFile->hMutex); /* Wanting an exclusive lock? */ - if (dwFileOffsetLow == SHARED_FIRST - && nNumberOfBytesToLockLow == SHARED_SIZE){ + if (dwFileOffsetLow == (DWORD)SHARED_FIRST + && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ pFile->shared->bExclusive = TRUE; pFile->local.bExclusive = TRUE; bReturn = TRUE; } } /* Want a read-only lock? */ - else if ((dwFileOffsetLow >= SHARED_FIRST && - dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) && - nNumberOfBytesToLockLow == 1){ + else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && + nNumberOfBytesToLockLow == 1){ if (pFile->shared->bExclusive == 0){ pFile->local.nReaders ++; if (pFile->local.nReaders == 1){ pFile->shared->nReaders ++; } @@ -26606,20 +27611,21 @@ bReturn = TRUE; } } /* Want a pending lock? */ - else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){ + else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){ /* If no pending lock has been acquired, then acquire it */ if (pFile->shared->bPending == 0) { pFile->shared->bPending = TRUE; pFile->local.bPending = TRUE; bReturn = TRUE; } } + /* Want a reserved lock? */ - else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ + else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ if (pFile->shared->bReserved == 0) { pFile->shared->bReserved = TRUE; pFile->local.bReserved = TRUE; bReturn = TRUE; } @@ -26640,25 +27646,29 @@ DWORD nNumberOfBytesToUnlockHigh ){ winFile *pFile = HANDLE_TO_WINFILE(phFile); BOOL bReturn = FALSE; + UNUSED_PARAMETER(dwFileOffsetHigh); + UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); + if (!pFile->hMutex) return TRUE; winceMutexAcquire(pFile->hMutex); /* Releasing a reader lock or an exclusive lock */ - if (dwFileOffsetLow >= SHARED_FIRST && - dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){ + if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ /* Did we have an exclusive lock? */ if (pFile->local.bExclusive){ + assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); pFile->local.bExclusive = FALSE; pFile->shared->bExclusive = FALSE; bReturn = TRUE; } /* Did we just have a reader lock? */ else if (pFile->local.nReaders){ + assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1); pFile->local.nReaders --; if (pFile->local.nReaders == 0) { pFile->shared->nReaders --; } @@ -26665,19 +27675,19 @@ bReturn = TRUE; } } /* Releasing a pending lock */ - else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ + else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ if (pFile->local.bPending){ pFile->local.bPending = FALSE; pFile->shared->bPending = FALSE; bReturn = TRUE; } } /* Releasing a reserved lock */ - else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ + else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ if (pFile->local.bReserved) { pFile->local.bReserved = FALSE; pFile->shared->bReserved = FALSE; bReturn = TRUE; } @@ -26696,15 +27706,18 @@ DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped ){ + UNUSED_PARAMETER(dwReserved); + UNUSED_PARAMETER(nNumberOfBytesToLockHigh); + /* If the caller wants a shared read lock, forward this call ** to winceLockFile */ - if (lpOverlapped->Offset == SHARED_FIRST && + if (lpOverlapped->Offset == (DWORD)SHARED_FIRST && dwFlags == 1 && - nNumberOfBytesToLockLow == SHARED_SIZE){ + nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); } return FALSE; } /* @@ -27422,20 +28435,27 @@ if( flags & SQLITE_OPEN_READWRITE ){ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; }else{ dwDesiredAccess = GENERIC_READ; } - if( flags & SQLITE_OPEN_CREATE ){ + /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is + ** created. SQLite doesn't use it to indicate "exclusive access" + ** as it is usually understood. + */ + assert(!(flags & SQLITE_OPEN_EXCLUSIVE) || (flags & SQLITE_OPEN_CREATE)); + if( flags & SQLITE_OPEN_EXCLUSIVE ){ + /* Creates a new file, only if it does not already exist. */ + /* If the file exists, it fails. */ + dwCreationDisposition = CREATE_NEW; + }else if( flags & SQLITE_OPEN_CREATE ){ + /* Open existing file, or create if it doesn't exist */ dwCreationDisposition = OPEN_ALWAYS; }else{ + /* Opens a file, only if it exists. */ dwCreationDisposition = OPEN_EXISTING; } - if( flags & SQLITE_OPEN_MAIN_DB ){ - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - }else{ - dwShareMode = 0; - } + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; if( flags & SQLITE_OPEN_DELETEONCLOSE ){ #if SQLITE_OS_WINCE dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; isTemp = 1; #else @@ -27695,13 +28715,19 @@ static int getSectorSize( sqlite3_vfs *pVfs, const char *zRelative /* UTF-8 file name */ ){ DWORD bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; + /* GetDiskFreeSpace is not supported under WINCE */ +#if SQLITE_OS_WINCE + UNUSED_PARAMETER(pVfs); + UNUSED_PARAMETER(zRelative); +#else char zFullpath[MAX_PATH+1]; int rc; - DWORD dwRet = 0, dwDummy; + DWORD dwRet = 0; + DWORD dwDummy; /* ** We need to get the full path name of the file ** to get the drive letter to look up the sector ** size. @@ -27710,50 +28736,45 @@ if( rc == SQLITE_OK ) { void *zConverted = convertUtf8Filename(zFullpath); if( zConverted ){ if( isNT() ){ - int i; /* trim path to just drive reference */ WCHAR *p = zConverted; - for(i=0;i<MAX_PATH;i++){ - if( p[i] == '\\' ){ - i++; - p[i] = '\0'; + for(;*p;p++){ + if( *p == '\\' ){ + *p = '\0'; break; } } dwRet = GetDiskFreeSpaceW((WCHAR*)zConverted, &dwDummy, &bytesPerSector, &dwDummy, &dwDummy); -#if SQLITE_OS_WINCE==0 - }else{ - int i; + }else{ /* trim path to just drive reference */ CHAR *p = (CHAR *)zConverted; - for(i=0;i<MAX_PATH;i++){ - if( p[i] == '\\' ){ - i++; - p[i] = '\0'; + for(;*p;p++){ + if( *p == '\\' ){ + *p = '\0'; break; } } dwRet = GetDiskFreeSpaceA((CHAR*)zConverted, &dwDummy, &bytesPerSector, &dwDummy, &dwDummy); -#endif } free(zConverted); } if( !dwRet ){ bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; } } +#endif return (int) bytesPerSector; } #ifndef SQLITE_OMIT_LOAD_EXTENSION /* @@ -27976,10 +28997,11 @@ winRandomness, /* xRandomness */ winSleep, /* xSleep */ winCurrentTime, /* xCurrentTime */ winGetLastError /* xGetLastError */ }; + sqlite3_vfs_register(&winVfs, 1); return SQLITE_OK; } SQLITE_API int sqlite3_os_end(void){ return SQLITE_OK; @@ -28023,15 +29045,15 @@ ** sometimes grow into tens of thousands or larger. The size of the ** Bitvec object is the number of pages in the database file at the ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. ** -** @(#) $Id: bitvec.c,v 1.14 2009/04/01 23:49:04 drh Exp $ +** @(#) $Id: bitvec.c,v 1.17 2009/07/25 17:33:26 drh Exp $ */ /* Size of the Bitvec structure in bytes. */ -#define BITVEC_SZ 512 +#define BITVEC_SZ (sizeof(void*)*128) /* 512 on 32bit. 1024 on 64bit */ /* Round the union size down to the nearest pointer boundary, since that's how ** it will be aligned within the Bitvec struct. */ #define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) @@ -28134,12 +29156,11 @@ return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0; } else{ u32 h = BITVEC_HASH(i++); while( p->u.aHash[h] ){ if( p->u.aHash[h]==i ) return 1; - h++; - if( h>=BITVEC_NINT ) h = 0; + h = (h+1) % BITVEC_NINT; } return 0; } } @@ -28155,11 +29176,11 @@ ** and that the value for "i" is within range of the Bitvec object. ** Otherwise the behavior is undefined. */ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ u32 h; - assert( p!=0 ); + if( p==0 ) return SQLITE_OK; assert( i>0 ); assert( i<=p->iSize ); i--; while((p->iSize > BITVEC_NBIT) && p->iDivisor) { u32 bin = i/p->iDivisor; @@ -28197,31 +29218,39 @@ /* make our hash too "full". */ bitvec_set_rehash: if( p->nSet>=BITVEC_MXHASH ){ unsigned int j; int rc; - u32 aiValues[BITVEC_NINT]; - memcpy(aiValues, p->u.aHash, sizeof(aiValues)); - memset(p->u.apSub, 0, sizeof(aiValues)); - p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; - rc = sqlite3BitvecSet(p, i); - for(j=0; j<BITVEC_NINT; j++){ - if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]); - } - return rc; + u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash)); + if( aiValues==0 ){ + return SQLITE_NOMEM; + }else{ + memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); + memset(p->u.apSub, 0, sizeof(p->u.apSub)); + p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; + rc = sqlite3BitvecSet(p, i); + for(j=0; j<BITVEC_NINT; j++){ + if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]); + } + sqlite3StackFree(0, aiValues); + return rc; + } } bitvec_set_end: p->nSet++; p->u.aHash[h] = i; return SQLITE_OK; } /* ** Clear the i-th bit. -*/ -SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i){ - assert( p!=0 ); +** +** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage +** that BitvecClear can use to rebuilt its hash table. +*/ +SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){ + if( p==0 ) return; assert( i>0 ); i--; while( p->iDivisor ){ u32 bin = i/p->iDivisor; i = i%p->iDivisor; @@ -28232,13 +29261,13 @@ } if( p->iSize<=BITVEC_NBIT ){ p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1))); }else{ unsigned int j; - u32 aiValues[BITVEC_NINT]; - memcpy(aiValues, p->u.aHash, sizeof(aiValues)); - memset(p->u.aHash, 0, sizeof(aiValues)); + u32 *aiValues = pBuf; + memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); + memset(p->u.aHash, 0, sizeof(p->u.aHash)); p->nSet = 0; for(j=0; j<BITVEC_NINT; j++){ if( aiValues[j] && aiValues[j]!=(i+1) ){ u32 h = BITVEC_HASH(aiValues[j]-1); p->nSet++; @@ -28318,17 +29347,23 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ Bitvec *pBitvec = 0; unsigned char *pV = 0; int rc = -1; int i, nx, pc, op; + void *pTmpSpace; /* Allocate the Bitvec to be tested and a linear array of ** bits to act as the reference */ pBitvec = sqlite3BitvecCreate( sz ); pV = sqlite3_malloc( (sz+7)/8 + 1 ); - if( pBitvec==0 || pV==0 ) goto bitvec_end; + pTmpSpace = sqlite3_malloc(BITVEC_SZ); + if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; memset(pV, 0, (sz+7)/8 + 1); + + /* NULL pBitvec tests */ + sqlite3BitvecSet(0, 1); + sqlite3BitvecClear(0, 1, pTmpSpace); /* Run the program */ pc = 0; while( (op = aOp[pc])!=0 ){ switch( op ){ @@ -28356,11 +29391,11 @@ if( op!=5 ){ if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; } }else{ CLEARBIT(pV, (i+1)); - sqlite3BitvecClear(pBitvec, i+1); + sqlite3BitvecClear(pBitvec, i+1, pTmpSpace); } } /* Test to make sure the linear array exactly matches the ** Bitvec object. Start with the assumption that they do @@ -28377,10 +29412,11 @@ } } /* Free allocated structure */ bitvec_end: + sqlite3_free(pTmpSpace); sqlite3_free(pV); sqlite3BitvecDestroy(pBitvec); return rc; } #endif /* SQLITE_OMIT_BUILTIN_TEST */ @@ -28398,11 +29434,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file implements that page cache. ** -** @(#) $Id: pcache.c,v 1.44 2009/03/31 01:32:18 drh Exp $ +** @(#) $Id: pcache.c,v 1.47 2009/07/25 11:46:49 danielk1977 Exp $ */ /* ** A complete page cache is an instance of this structure. */ @@ -28594,10 +29630,11 @@ ){ PgHdr *pPage = 0; int eCreate; assert( pCache!=0 ); + assert( createFlag==1 || createFlag==0 ); assert( pgno>0 ); /* If the pluggable cache (sqlite3_pcache*) has not been allocated, ** allocate it now. */ @@ -28611,14 +29648,11 @@ } sqlite3GlobalConfig.pcache.xCachesize(p, pCache->nMax); pCache->pCache = p; } - eCreate = createFlag ? 1 : 0; - if( eCreate && (!pCache->bPurgeable || !pCache->pDirty) ){ - eCreate = 2; - } + eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty)); if( pCache->pCache ){ pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, eCreate); } if( !pPage && eCreate==1 ){ @@ -28856,41 +29890,37 @@ /* ** Sort the list of pages in accending order by pgno. Pages are ** connected by pDirty pointers. The pDirtyPrev pointers are ** corrupted by this sort. -*/ -#define N_SORT_BUCKET_ALLOC 25 -#define N_SORT_BUCKET 25 -#ifdef SQLITE_TEST - int sqlite3_pager_n_sort_bucket = 0; - #undef N_SORT_BUCKET - #define N_SORT_BUCKET \ - (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC) -#endif +** +** Since there cannot be more than 2^31 distinct pages in a database, +** there cannot be more than 31 buckets required by the merge sorter. +** One extra bucket is added to catch overflow in case something +** ever changes to make the previous sentence incorrect. +*/ +#define N_SORT_BUCKET 32 static PgHdr *pcacheSortDirtyList(PgHdr *pIn){ - PgHdr *a[N_SORT_BUCKET_ALLOC], *p; + PgHdr *a[N_SORT_BUCKET], *p; int i; memset(a, 0, sizeof(a)); while( pIn ){ p = pIn; pIn = p->pDirty; p->pDirty = 0; - for(i=0; i<N_SORT_BUCKET-1; i++){ + for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){ if( a[i]==0 ){ a[i] = p; break; }else{ p = pcacheMergeDirtyList(a[i], p); a[i] = 0; } } - if( i==N_SORT_BUCKET-1 ){ - /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET) - ** elements in the input list. This is possible, but impractical. - ** Testing this line is the point of global variable - ** sqlite3_pager_n_sort_bucket. + if( NEVER(i==N_SORT_BUCKET-1) ){ + /* To get here, there need to be 2^(N_SORT_BUCKET) elements in + ** the input list. But that is impossible. */ a[i] = pcacheMergeDirtyList(a[i], p); } } p = a[0]; @@ -28953,11 +29983,11 @@ if( pCache->pCache ){ sqlite3GlobalConfig.pcache.xCachesize(pCache->pCache, mxPage); } } -#ifdef SQLITE_CHECK_PAGES +#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* ** For all dirty pages currently in the cache, invoke the specified ** callback. This is only used if the SQLITE_CHECK_PAGES macro is ** defined. */ @@ -28987,11 +30017,11 @@ ** sqlite3_pcache interface). It also contains part of the implementation ** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features. ** If the default page cache implementation is overriden, then neither of ** these two features are available. ** -** @(#) $Id: pcache1.c,v 1.10 2009/03/23 04:33:33 danielk1977 Exp $ +** @(#) $Id: pcache1.c,v 1.19 2009/07/17 11:44:07 drh Exp $ */ typedef struct PCache1 PCache1; typedef struct PgHdr1 PgHdr1; @@ -29024,11 +30054,11 @@ }; /* ** Each cache entry is represented by an instance of the following ** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated -** directly after the structure in memory (see the PGHDR1_TO_PAGE() +** directly before this structure in memory (see the PGHDR1_TO_PAGE() ** macro below). */ struct PgHdr1 { unsigned int iKey; /* Key value (page number) */ PgHdr1 *pNext; /* Next in hash table chain */ @@ -29058,10 +30088,11 @@ /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */ int szSlot; /* Size of each free slot */ void *pStart, *pEnd; /* Bounds of pagecache malloc range */ PgFreeslot *pFree; /* Free page blocks */ + int isInit; /* True if initialized */ } pcache1_g; /* ** All code in this file should access the global structure above via the ** alias "pcache1". This ensures that the WSD emulation is used when @@ -29069,22 +30100,22 @@ */ #define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) /* ** When a PgHdr1 structure is allocated, the associated PCache1.szPage -** bytes of data are located directly after it in memory (i.e. the total +** bytes of data are located directly before it in memory (i.e. the total ** size of the allocation is sizeof(PgHdr1)+PCache1.szPage byte). The ** PGHDR1_TO_PAGE() macro takes a pointer to a PgHdr1 structure as ** an argument and returns a pointer to the associated block of szPage ** bytes. The PAGE_TO_PGHDR1() macro does the opposite: its argument is ** a pointer to a block of szPage bytes of data and the return value is ** a pointer to the associated PgHdr1 structure. ** -** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(X))==X ); -*/ -#define PGHDR1_TO_PAGE(p) (void *)(&((unsigned char *)p)[sizeof(PgHdr1)]) -#define PAGE_TO_PGHDR1(p) (PgHdr1 *)(&((unsigned char *)p)[-1*(int)sizeof(PgHdr1)]) +** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X ); +*/ +#define PGHDR1_TO_PAGE(p) (void*)(((char*)p) - p->pCache->szPage) +#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage) /* ** Macros to enter and leave the global LRU mutex. */ #define pcache1EnterMutex() sqlite3_mutex_enter(pcache1.mutex) @@ -29098,22 +30129,24 @@ ** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE ** verb to sqlite3_config(). Parameter pBuf points to an allocation large ** enough to contain 'n' buffers of 'sz' bytes each. */ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ - PgFreeslot *p; - sz = ROUNDDOWN8(sz); - pcache1.szSlot = sz; - pcache1.pStart = pBuf; - pcache1.pFree = 0; - while( n-- ){ - p = (PgFreeslot*)pBuf; - p->pNext = pcache1.pFree; - pcache1.pFree = p; - pBuf = (void*)&((char*)pBuf)[sz]; - } - pcache1.pEnd = pBuf; + if( pcache1.isInit ){ + PgFreeslot *p; + sz = ROUNDDOWN8(sz); + pcache1.szSlot = sz; + pcache1.pStart = pBuf; + pcache1.pFree = 0; + while( n-- ){ + p = (PgFreeslot*)pBuf; + p->pNext = pcache1.pFree; + pcache1.pFree = p; + pBuf = (void*)&((char*)pBuf)[sz]; + } + pcache1.pEnd = pBuf; + } } /* ** Malloc function used within this file to allocate space from the buffer ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no @@ -29122,10 +30155,11 @@ */ static void *pcache1Alloc(int nByte){ void *p; assert( sqlite3_mutex_held(pcache1.mutex) ); if( nByte<=pcache1.szSlot && pcache1.pFree ){ + assert( pcache1.isInit ); p = (PgHdr1 *)pcache1.pFree; pcache1.pFree = pcache1.pFree->pNext; sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); }else{ @@ -29169,28 +30203,36 @@ /* ** Allocate a new page object initially associated with cache pCache. */ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ int nByte = sizeof(PgHdr1) + pCache->szPage; - PgHdr1 *p = (PgHdr1 *)pcache1Alloc(nByte); - if( p ){ + void *pPg = pcache1Alloc(nByte); + PgHdr1 *p; + if( pPg ){ + p = PAGE_TO_PGHDR1(pCache, pPg); if( pCache->bPurgeable ){ pcache1.nCurrentPage++; } + }else{ + p = 0; } return p; } /* ** Free a page object allocated by pcache1AllocPage(). +** +** The pointer is allowed to be NULL, which is prudent. But it turns out +** that the current implementation happens to never call this routine +** with a NULL pointer, so we mark the NULL test with ALWAYS(). */ static void pcache1FreePage(PgHdr1 *p){ - if( p ){ + if( ALWAYS(p) ){ if( p->pCache->bPurgeable ){ pcache1.nCurrentPage--; } - pcache1Free(p); + pcache1Free(PGHDR1_TO_PAGE(p)); } } /* ** Malloc function used by SQLite to obtain space from the buffer configured @@ -29330,25 +30372,29 @@ */ static void pcache1TruncateUnsafe( PCache1 *pCache, unsigned int iLimit ){ + TESTONLY( unsigned int nPage = 0; ) /* Used to assert pCache->nPage is correct */ unsigned int h; assert( sqlite3_mutex_held(pcache1.mutex) ); for(h=0; h<pCache->nHash; h++){ PgHdr1 **pp = &pCache->apHash[h]; PgHdr1 *pPage; while( (pPage = *pp)!=0 ){ if( pPage->iKey>=iLimit ){ - pcache1PinPage(pPage); + pCache->nPage--; *pp = pPage->pNext; + pcache1PinPage(pPage); pcache1FreePage(pPage); }else{ pp = &pPage->pNext; - } - } - } + TESTONLY( nPage++; ) + } + } + } + assert( pCache->nPage==nPage ); } /******************************************************************************/ /******** sqlite3_pcache Methods **********************************************/ @@ -29355,23 +30401,28 @@ /* ** Implementation of the sqlite3_pcache.xInit method. */ static int pcache1Init(void *NotUsed){ UNUSED_PARAMETER(NotUsed); + assert( pcache1.isInit==0 ); memset(&pcache1, 0, sizeof(pcache1)); if( sqlite3GlobalConfig.bCoreMutex ){ pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); } + pcache1.isInit = 1; return SQLITE_OK; } /* ** Implementation of the sqlite3_pcache.xShutdown method. +** Note that the static mutex allocated in xInit does +** not need to be freed. */ static void pcache1Shutdown(void *NotUsed){ UNUSED_PARAMETER(NotUsed); - /* no-op */ + assert( pcache1.isInit!=0 ); + memset(&pcache1, 0, sizeof(pcache1)); } /* ** Implementation of the sqlite3_pcache.xCreate method. ** @@ -29426,11 +30477,18 @@ ** Implementation of the sqlite3_pcache.xFetch method. ** ** Fetch a page by key value. ** ** Whether or not a new page may be allocated by this function depends on -** the value of the createFlag argument. +** the value of the createFlag argument. 0 means do not allocate a new +** page. 1 means allocate a new page if space is easily available. 2 +** means to try really hard to allocate a new page. +** +** For a non-purgeable cache (a cache used as the storage for an in-memory +** database) there is really no difference between createFlag 1 and 2. So +** the calling function (pcache.c) will never have a createFlag of 1 on +** a non-purgable cache. ** ** There are three different approaches to obtaining space for a page, ** depending on the value of parameter createFlag (which may be 0, 1 or 2). ** ** 1. Regardless of the value of createFlag, the cache is searched for a @@ -29437,13 +30495,12 @@ ** copy of the requested page. If one is found, it is returned. ** ** 2. If createFlag==0 and the page is not already in the cache, NULL is ** returned. ** -** 3. If createFlag is 1, the cache is marked as purgeable and the page is -** not already in the cache, and if either of the following are true, -** return NULL: +** 3. If createFlag is 1, and the page is not already in the cache, +** and if either of the following are true, return NULL: ** ** (a) the number of pages pinned by the cache is greater than ** PCache1.nMax, or ** (b) the number of pages pinned by the cache is greater than ** the sum of nMax for all purgeable caches, less the sum of @@ -29468,10 +30525,11 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){ unsigned int nPinned; PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage = 0; + assert( pCache->bPurgeable || createFlag!=1 ); pcache1EnterMutex(); if( createFlag==1 ) sqlite3BeginBenignMalloc(); /* Search the hash table for an existing entry. */ if( pCache->nHash>0 ){ @@ -29484,11 +30542,11 @@ goto fetch_out; } /* Step 3 of header comment. */ nPinned = pCache->nPage - pCache->nRecyclable; - if( createFlag==1 && pCache->bPurgeable && ( + if( createFlag==1 && ( nPinned>=(pcache1.nMaxPage+pCache->nMin-pcache1.nMinPage) || nPinned>=(pCache->nMax * 9 / 10) )){ goto fetch_out; } @@ -29497,11 +30555,11 @@ goto fetch_out; } /* Step 4. Try to recycle a page buffer if appropriate. */ if( pCache->bPurgeable && pcache1.pLruTail && ( - pCache->nPage>=pCache->nMax-1 || pcache1.nCurrentPage>=pcache1.nMaxPage + (pCache->nPage+1>=pCache->nMax) || pcache1.nCurrentPage>=pcache1.nMaxPage )){ pPage = pcache1.pLruTail; pcache1RemoveFromHash(pPage); pcache1PinPage(pPage); if( pPage->pCache->szPage!=pCache->szPage ){ @@ -29519,17 +30577,17 @@ pPage = pcache1AllocPage(pCache); } if( pPage ){ unsigned int h = iKey % pCache->nHash; - *(void **)(PGHDR1_TO_PAGE(pPage)) = 0; pCache->nPage++; pPage->iKey = iKey; pPage->pNext = pCache->apHash[h]; pPage->pCache = pCache; pPage->pLruPrev = 0; pPage->pLruNext = 0; + *(void **)(PGHDR1_TO_PAGE(pPage)) = 0; pCache->apHash[h] = pPage; } fetch_out: if( pPage && iKey>pCache->iMaxKey ){ @@ -29546,12 +30604,13 @@ ** ** Mark a page as unpinned (eligible for asynchronous recycling). */ static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){ PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg); - + PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg); + + assert( pPage->pCache==pCache ); pcache1EnterMutex(); /* It is an error to call this function if the page is already ** part of the global LRU list. */ @@ -29589,14 +30648,15 @@ void *pPg, unsigned int iOld, unsigned int iNew ){ PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg); + PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg); PgHdr1 **pp; unsigned int h; assert( pPage->iKey==iOld ); + assert( pPage->pCache==pCache ); pcache1EnterMutex(); h = iOld%pCache->nHash; pp = &pCache->apHash[h]; @@ -29608,11 +30668,18 @@ h = iNew%pCache->nHash; pPage->iKey = iNew; pPage->pNext = pCache->apHash[h]; pCache->apHash[h] = pPage; - if( iNew>pCache->iMaxKey ){ + /* The xRekey() interface is only used to move pages earlier in the + ** database file (in order to move all free pages to the end of the + ** file where they can be truncated off.) Hence, it is not possible + ** for the new page number to be greater than the largest previously + ** fetched page. But we retain the following test in case xRekey() + ** begins to be used in different ways in the future. + */ + if( NEVER(iNew>pCache->iMaxKey) ){ pCache->iMaxKey = iNew; } pcache1LeaveMutex(); } @@ -29687,11 +30754,11 @@ int nFree = 0; if( pcache1.pStart==0 ){ PgHdr1 *p; pcache1EnterMutex(); while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){ - nFree += sqlite3MallocSize(p); + nFree += sqlite3MallocSize(PGHDR1_TO_PAGE(p)); pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(p); } pcache1LeaveMutex(); @@ -29735,50 +30802,92 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** -** This module implements an object we call a "Row Set". -** -** The RowSet object is a bag of rowids. Rowids -** are inserted into the bag in an arbitrary order. Then they are -** pulled from the bag in sorted order. Rowids only appear in the -** bag once. If the same rowid is inserted multiple times, the -** second and subsequent inserts make no difference on the output. -** -** This implementation accumulates rowids in a linked list. For -** output, it first sorts the linked list (removing duplicates during -** the sort) then returns elements one by one by walking the list. -** -** Big chunks of rowid/next-ptr pairs are allocated at a time, to -** reduce the malloc overhead. -** -** $Id: rowset.c,v 1.4 2009/04/01 19:35:55 drh Exp $ -*/ +** This module implements an object we call a "RowSet". +** +** The RowSet object is a collection of rowids. Rowids +** are inserted into the RowSet in an arbitrary order. Inserts +** can be intermixed with tests to see if a given rowid has been +** previously inserted into the RowSet. +** +** After all inserts are finished, it is possible to extract the +** elements of the RowSet in sorted order. Once this extraction +** process has started, no new elements may be inserted. +** +** Hence, the primitive operations for a RowSet are: +** +** CREATE +** INSERT +** TEST +** SMALLEST +** DESTROY +** +** The CREATE and DESTROY primitives are the constructor and destructor, +** obviously. The INSERT primitive adds a new element to the RowSet. +** TEST checks to see if an element is already in the RowSet. SMALLEST +** extracts the least value from the RowSet. +** +** The INSERT primitive might allocate additional memory. Memory is +** allocated in chunks so most INSERTs do no allocation. There is an +** upper bound on the size of allocated memory. No memory is freed +** until DESTROY. +** +** The TEST primitive includes a "batch" number. The TEST primitive +** will only see elements that were inserted before the last change +** in the batch number. In other words, if an INSERT occurs between +** two TESTs where the TESTs have the same batch nubmer, then the +** value added by the INSERT will not be visible to the second TEST. +** The initial batch number is zero, so if the very first TEST contains +** a non-zero batch number, it will see all prior INSERTs. +** +** No INSERTs may occurs after a SMALLEST. An assertion will fail if +** that is attempted. +** +** The cost of an INSERT is roughly constant. (Sometime new memory +** has to be allocated on an INSERT.) The cost of a TEST with a new +** batch number is O(NlogN) where N is the number of elements in the RowSet. +** The cost of a TEST using the same batch number is O(logN). The cost +** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST +** primitives are constant time. The cost of DESTROY is O(N). +** +** There is an added cost of O(N) when switching between TEST and +** SMALLEST primitives. +** +** $Id: rowset.c,v 1.7 2009/05/22 01:00:13 drh Exp $ +*/ + + +/* +** Target size for allocation chunks. +*/ +#define ROWSET_ALLOCATION_SIZE 1024 /* ** The number of rowset entries per allocation chunk. */ -#define ROWSET_ENTRY_PER_CHUNK 63 - -/* -** Each entry in a RowSet is an instance of the following -** structure: +#define ROWSET_ENTRY_PER_CHUNK \ + ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry)) + +/* +** Each entry in a RowSet is an instance of the following object. */ struct RowSetEntry { i64 v; /* ROWID value for this entry */ - struct RowSetEntry *pNext; /* Next entry on a list of all entries */ -}; - -/* -** Index entries are allocated in large chunks (instances of the + struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ + struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ +}; + +/* +** RowSetEntry objects are allocated in large chunks (instances of the ** following structure) to reduce memory allocation overhead. The ** chunks are kept on a linked list so that they can be deallocated ** when the RowSet is destroyed. */ struct RowSetChunk { - struct RowSetChunk *pNext; /* Next chunk on list of them all */ + struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */ struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */ }; /* ** A RowSet in an instance of the following structure. @@ -29786,15 +30895,17 @@ ** A typedef of this structure if found in sqliteInt.h. */ struct RowSet { struct RowSetChunk *pChunk; /* List of all chunk allocations */ sqlite3 *db; /* The database connection */ - struct RowSetEntry *pEntry; /* List of entries in the rowset */ + struct RowSetEntry *pEntry; /* List of entries using pRight */ struct RowSetEntry *pLast; /* Last entry on the pEntry list */ struct RowSetEntry *pFresh; /* Source of new entry objects */ + struct RowSetEntry *pTree; /* Binary tree of entries */ u16 nFresh; /* Number of objects on pFresh */ - u8 isSorted; /* True if content is sorted */ + u8 isSorted; /* True if pEntry is sorted */ + u8 iBatch; /* Current insert batch */ }; /* ** Turn bulk memory into a RowSet object. N bytes of memory ** are available at pSpace. The db pointer is used as a memory context @@ -29807,35 +30918,40 @@ ** If N is larger than the minimum, use the surplus as an initial ** allocation of entries available to be filled. */ SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ RowSet *p; - assert( N >= sizeof(*p) ); + assert( N >= ROUND8(sizeof(*p)) ); p = pSpace; p->pChunk = 0; p->db = db; p->pEntry = 0; p->pLast = 0; - p->pFresh = (struct RowSetEntry*)&p[1]; - p->nFresh = (u16)((N - sizeof(*p))/sizeof(struct RowSetEntry)); + p->pTree = 0; + p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); + p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); p->isSorted = 1; - return p; -} - -/* -** Deallocate all chunks from a RowSet. + p->iBatch = 0; + return p; +} + +/* +** Deallocate all chunks from a RowSet. This frees all memory that +** the RowSet has allocated over its lifetime. This routine is +** the destructor for the RowSet. */ SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ struct RowSetChunk *pChunk, *pNextChunk; for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ - pNextChunk = pChunk->pNext; + pNextChunk = pChunk->pNextChunk; sqlite3DbFree(p->db, pChunk); } p->pChunk = 0; p->nFresh = 0; p->pEntry = 0; p->pLast = 0; + p->pTree = 0; p->isSorted = 1; } /* ** Insert a new value into a RowSet. @@ -29842,127 +30958,264 @@ ** ** The mallocFailed flag of the database connection is set if a ** memory allocation fails. */ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ - struct RowSetEntry *pEntry; - struct RowSetEntry *pLast; + struct RowSetEntry *pEntry; /* The new entry */ + struct RowSetEntry *pLast; /* The last prior entry */ assert( p!=0 ); if( p->nFresh==0 ){ struct RowSetChunk *pNew; pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); if( pNew==0 ){ return; } - pNew->pNext = p->pChunk; + pNew->pNextChunk = p->pChunk; p->pChunk = pNew; p->pFresh = pNew->aEntry; p->nFresh = ROWSET_ENTRY_PER_CHUNK; } pEntry = p->pFresh++; p->nFresh--; pEntry->v = rowid; - pEntry->pNext = 0; + pEntry->pRight = 0; pLast = p->pLast; if( pLast ){ if( p->isSorted && rowid<=pLast->v ){ p->isSorted = 0; } - pLast->pNext = pEntry; - }else{ - assert( p->pEntry==0 ); + pLast->pRight = pEntry; + }else{ + assert( p->pEntry==0 ); /* Fires if INSERT after SMALLEST */ p->pEntry = pEntry; } p->pLast = pEntry; } /* -** Merge two lists of RowSet entries. Remove duplicates. -** -** The input lists are assumed to be in sorted order. -*/ -static struct RowSetEntry *boolidxMerge( +** Merge two lists of RowSetEntry objects. Remove duplicates. +** +** The input lists are connected via pRight pointers and are +** assumed to each already be in sorted order. +*/ +static struct RowSetEntry *rowSetMerge( struct RowSetEntry *pA, /* First sorted list to be merged */ struct RowSetEntry *pB /* Second sorted list to be merged */ ){ struct RowSetEntry head; struct RowSetEntry *pTail; pTail = &head; while( pA && pB ){ - assert( pA->pNext==0 || pA->v<=pA->pNext->v ); - assert( pB->pNext==0 || pB->v<=pB->pNext->v ); + assert( pA->pRight==0 || pA->v<=pA->pRight->v ); + assert( pB->pRight==0 || pB->v<=pB->pRight->v ); if( pA->v<pB->v ){ - pTail->pNext = pA; - pA = pA->pNext; - pTail = pTail->pNext; + pTail->pRight = pA; + pA = pA->pRight; + pTail = pTail->pRight; }else if( pB->v<pA->v ){ - pTail->pNext = pB; - pB = pB->pNext; - pTail = pTail->pNext; - }else{ - pA = pA->pNext; + pTail->pRight = pB; + pB = pB->pRight; + pTail = pTail->pRight; + }else{ + pA = pA->pRight; } } if( pA ){ - assert( pA->pNext==0 || pA->v<=pA->pNext->v ); - pTail->pNext = pA; - }else{ - assert( pB==0 || pB->pNext==0 || pB->v<=pB->pNext->v ); - pTail->pNext = pB; - } - return head.pNext; -} - -/* -** Sort all elements of the RowSet into ascending order. -*/ -static void sqlite3RowSetSort(RowSet *p){ + assert( pA->pRight==0 || pA->v<=pA->pRight->v ); + pTail->pRight = pA; + }else{ + assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v ); + pTail->pRight = pB; + } + return head.pRight; +} + +/* +** Sort all elements on the pEntry list of the RowSet into ascending order. +*/ +static void rowSetSort(RowSet *p){ unsigned int i; struct RowSetEntry *pEntry; struct RowSetEntry *aBucket[40]; assert( p->isSorted==0 ); memset(aBucket, 0, sizeof(aBucket)); while( p->pEntry ){ pEntry = p->pEntry; - p->pEntry = pEntry->pNext; - pEntry->pNext = 0; + p->pEntry = pEntry->pRight; + pEntry->pRight = 0; for(i=0; aBucket[i]; i++){ - pEntry = boolidxMerge(aBucket[i],pEntry); + pEntry = rowSetMerge(aBucket[i], pEntry); aBucket[i] = 0; } aBucket[i] = pEntry; } pEntry = 0; for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){ - pEntry = boolidxMerge(pEntry,aBucket[i]); + pEntry = rowSetMerge(pEntry, aBucket[i]); } p->pEntry = pEntry; p->pLast = 0; p->isSorted = 1; } -/* -** Extract the next (smallest) element from the RowSet. -** Write the element into *pRowid. Return 1 on success. Return -** 0 if the RowSet is already empty. -*/ -SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ + +/* +** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects. +** Convert this tree into a linked list connected by the pRight pointers +** and return pointers to the first and last elements of the new list. +*/ +static void rowSetTreeToList( + struct RowSetEntry *pIn, /* Root of the input tree */ + struct RowSetEntry **ppFirst, /* Write head of the output list here */ + struct RowSetEntry **ppLast /* Write tail of the output list here */ +){ + assert( pIn!=0 ); + if( pIn->pLeft ){ + struct RowSetEntry *p; + rowSetTreeToList(pIn->pLeft, ppFirst, &p); + p->pRight = pIn; + }else{ + *ppFirst = pIn; + } + if( pIn->pRight ){ + rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast); + }else{ + *ppLast = pIn; + } + assert( (*ppLast)->pRight==0 ); +} + + +/* +** Convert a sorted list of elements (connected by pRight) into a binary +** tree with depth of iDepth. A depth of 1 means the tree contains a single +** node taken from the head of *ppList. A depth of 2 means a tree with +** three nodes. And so forth. +** +** Use as many entries from the input list as required and update the +** *ppList to point to the unused elements of the list. If the input +** list contains too few elements, then construct an incomplete tree +** and leave *ppList set to NULL. +** +** Return a pointer to the root of the constructed binary tree. +*/ +static struct RowSetEntry *rowSetNDeepTree( + struct RowSetEntry **ppList, + int iDepth +){ + struct RowSetEntry *p; /* Root of the new tree */ + struct RowSetEntry *pLeft; /* Left subtree */ + if( *ppList==0 ){ + return 0; + } + if( iDepth==1 ){ + p = *ppList; + *ppList = p->pRight; + p->pLeft = p->pRight = 0; + return p; + } + pLeft = rowSetNDeepTree(ppList, iDepth-1); + p = *ppList; + if( p==0 ){ + return pLeft; + } + p->pLeft = pLeft; + *ppList = p->pRight; + p->pRight = rowSetNDeepTree(ppList, iDepth-1); + return p; +} + +/* +** Convert a sorted list of elements into a binary tree. Make the tree +** as deep as it needs to be in order to contain the entire list. +*/ +static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){ + int iDepth; /* Depth of the tree so far */ + struct RowSetEntry *p; /* Current tree root */ + struct RowSetEntry *pLeft; /* Left subtree */ + + assert( pList!=0 ); + p = pList; + pList = p->pRight; + p->pLeft = p->pRight = 0; + for(iDepth=1; pList; iDepth++){ + pLeft = p; + p = pList; + pList = p->pRight; + p->pLeft = pLeft; + p->pRight = rowSetNDeepTree(&pList, iDepth); + } + return p; +} + +/* +** Convert the list in p->pEntry into a sorted list if it is not +** sorted already. If there is a binary tree on p->pTree, then +** convert it into a list too and merge it into the p->pEntry list. +*/ +static void rowSetToList(RowSet *p){ if( !p->isSorted ){ - sqlite3RowSetSort(p); - } + rowSetSort(p); + } + if( p->pTree ){ + struct RowSetEntry *pHead, *pTail; + rowSetTreeToList(p->pTree, &pHead, &pTail); + p->pTree = 0; + p->pEntry = rowSetMerge(p->pEntry, pHead); + } +} + +/* +** Extract the smallest element from the RowSet. +** Write the element into *pRowid. Return 1 on success. Return +** 0 if the RowSet is already empty. +** +** After this routine has been called, the sqlite3RowSetInsert() +** routine may not be called again. +*/ +SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ + rowSetToList(p); if( p->pEntry ){ *pRowid = p->pEntry->v; - p->pEntry = p->pEntry->pNext; + p->pEntry = p->pEntry->pRight; if( p->pEntry==0 ){ sqlite3RowSetClear(p); } return 1; }else{ return 0; } +} + +/* +** Check to see if element iRowid was inserted into the the rowset as +** part of any insert batch prior to iBatch. Return 1 or 0. +*/ +SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){ + struct RowSetEntry *p; + if( iBatch!=pRowSet->iBatch ){ + if( pRowSet->pEntry ){ + rowSetToList(pRowSet); + pRowSet->pTree = rowSetListToTree(pRowSet->pEntry); + pRowSet->pEntry = 0; + pRowSet->pLast = 0; + } + pRowSet->iBatch = iBatch; + } + p = pRowSet->pTree; + while( p ){ + if( p->v<iRowid ){ + p = p->pRight; + }else if( p->v>iRowid ){ + p = p->pLeft; + }else{ + return 1; + } + } + return 0; } /************** End of rowset.c **********************************************/ /************** Begin file pager.c *******************************************/ /* @@ -29983,11 +31236,11 @@ ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.580 2009/04/11 16:27:50 drh Exp $ +** @(#) $Id: pager.c,v 1.629 2009/08/10 17:48:57 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO /* ** Macros for troubleshooting. Normally turned off @@ -30067,24 +31320,27 @@ /* ** A macro used for invoking the codec if there is one */ #ifdef SQLITE_HAS_CODEC -# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } -# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) -#else -# define CODEC1(P,D,N,X) /* NO-OP */ -# define CODEC2(P,D,N,X) ((char*)D) -#endif - -/* -** The maximum allowed sector size. 16MB. If the xSectorsize() method +# define CODEC1(P,D,N,X,E) \ + if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; } +# define CODEC2(P,D,N,X,E,O) \ + if( P->xCodec==0 ){ O=(char*)D; }else \ + if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; } +#else +# define CODEC1(P,D,N,X,E) /* NO-OP */ +# define CODEC2(P,D,N,X,E,O) O=(char*)D +#endif + +/* +** The maximum allowed sector size. 64KiB. If the xSectorsize() method ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. ** This could conceivably cause corruption following a power failure on ** such a system. This is currently an undocumented limit. */ -#define MAX_SECTOR_SIZE 0x0100000 +#define MAX_SECTOR_SIZE 0x10000 /* ** An instance of the following structure is allocated for each active ** savepoint and statement transaction in the system. All such structures ** are stored in the Pager.aSavepoint[] array, which is allocated and @@ -30193,10 +31449,16 @@ ** needSync ** ** TODO: It might be easier to set this variable in writeJournalHdr() ** and writeMasterJournal() only. Change its meaning to "unsynced data ** has been written to the journal". +** +** subjInMemory +** +** This is a boolean variable. If true, then any required sub-journal +** is opened as an in-memory journal file. If false, then in-memory +** sub-journals are only used for in-memory pager files. */ struct Pager { sqlite3_vfs *pVfs; /* OS functions to use for IO */ u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ u8 journalMode; /* On of the PAGER_JOURNALMODE_* values */ @@ -30226,10 +31488,11 @@ u8 journalStarted; /* True if header of journal is synced */ u8 changeCountDone; /* Set after incrementing the change-counter */ u8 setMaster; /* True if a m-j name has been written to jrnl */ u8 doNotSync; /* Boolean. While true, do not spill the cache */ u8 dbSizeValid; /* Set when dbSize is correct */ + u8 subjInMemory; /* True to use in-memory sub-journals */ Pgno dbSize; /* Number of pages in the database */ Pgno dbOrigSize; /* dbSize before the current transaction */ Pgno dbFileSize; /* Number of pages in the database file */ int errCode; /* One of several kinds of errors */ int nRec; /* Pages journalled since last j-header written */ @@ -30244,11 +31507,12 @@ PagerSavepoint *aSavepoint; /* Array of active savepoints */ int nSavepoint; /* Number of elements in aSavepoint[] */ char dbFileVers[16]; /* Changes whenever database file changes */ u32 sectorSize; /* Assumed sector size during rollback */ - int nExtra; /* Add this many bytes to each in-memory page */ + u16 nExtra; /* Add this many bytes to each in-memory page */ + i16 nReserve; /* Number of unused bytes at end of each page */ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ int pageSize; /* Number of bytes in a page */ Pgno mxPgno; /* Maximum allowed size of the database */ char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ @@ -30259,11 +31523,13 @@ int nRead, nWrite; /* Database pages read/written */ #endif void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ #ifdef SQLITE_HAS_CODEC void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ - void *pCodecArg; /* First argument to xCodec() */ + void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ + void (*xCodecFree)(void*); /* Destructor for the codec */ + void *pCodec; /* First argument to xCodec... methods */ #endif char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ i64 journalSizeLimit; /* Size limit for persistent journal files */ PCache *pPCache; /* Pointer to page cache object */ sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ @@ -30708,11 +31974,10 @@ pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff; } } pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager); - memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); /* ** Write the nRec Field - the number of page records that follow this ** journal header. Normally, zero is written to this value at this time. ** After the records are added to the journal (and the journal synced, @@ -30734,13 +31999,14 @@ */ assert( isOpen(pPager->fd) || pPager->noSync ); if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) ){ + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); }else{ - put32bits(&zHeader[sizeof(aJournalMagic)], 0); + memset(zHeader, 0, sizeof(aJournalMagic)+4); } /* The random check-hash initialiser */ sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); @@ -30803,10 +32069,11 @@ ** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes ** cannot be read from the journal file an error code is returned. */ static int readJournalHdr( Pager *pPager, /* Pager object */ + int isHot, i64 journalSize, /* Size of the open journal file in bytes */ u32 *pNRec, /* OUT: Value read from the nRec field */ u32 *pDbSize /* OUT: Value of original database size field */ ){ int rc; /* Return code */ @@ -30828,16 +32095,18 @@ /* Read in the first 8 bytes of the journal header. If they do not match ** the magic string found at the start of each journal header, return ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise, ** proceed. */ - rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff); - if( rc ){ - return rc; - } - if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ - return SQLITE_DONE; + if( isHot || iHdrOff!=pPager->journalHdr ){ + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff); + if( rc ){ + return rc; + } + if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ + return SQLITE_DONE; + } } /* Read the first three 32-bit fields of the journal header: The nRec ** field, the checksum-initializer and the database size at the start ** of the transaction. Return an error code if anything goes wrong. @@ -30881,11 +32150,11 @@ /* Update the page-size to match the value read from the journal. ** Use a testcase() macro to make sure that malloc failure within ** PagerSetPagesize() is tested. */ iPageSize16 = (u16)iPageSize; - rc = sqlite3PagerSetPagesize(pPager, &iPageSize16); + rc = sqlite3PagerSetPagesize(pPager, &iPageSize16, -1); testcase( rc!=SQLITE_OK ); assert( rc!=SQLITE_OK || iPageSize16==(u16)iPageSize ); /* Update the assumed sector-size to match the value used by ** the process that created this journal. If this journal was @@ -31005,10 +32274,11 @@ */ static void pager_reset(Pager *pPager){ if( SQLITE_OK==pPager->errCode ){ sqlite3BackupRestart(pPager->pBackup); sqlite3PcacheClear(pPager->pPCache); + pPager->dbSizeValid = 0; } } /* ** Free all structures in the Pager.aSavepoint[] array and set both @@ -31018,11 +32288,11 @@ static void releaseAllSavepoints(Pager *pPager){ int ii; /* Iterator for looping through Pager.aSavepoint */ for(ii=0; ii<pPager->nSavepoint; ii++){ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); } - if( !pPager->exclusiveMode ){ + if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){ sqlite3OsClose(pPager->sjfd); } sqlite3_free(pPager->aSavepoint); pPager->aSavepoint = 0; pPager->nSavepoint = 0; @@ -31073,11 +32343,11 @@ releaseAllSavepoints(pPager); /* If the file is unlocked, somebody else might change it. The ** values stored in Pager.dbSize etc. might become invalid if ** this happens. TODO: Really, this doesn't need to be cleared - ** until the change-counter check fails in pagerSharedLock(). + ** until the change-counter check fails in PagerSharedLock(). */ pPager->dbSizeValid = 0; rc = osUnlock(pPager->fd, NO_LOCK); if( rc ){ @@ -31120,30 +32390,18 @@ ** to be replayed to restore the contents of the database file (as if ** it were a hot-journal). */ static int pager_error(Pager *pPager, int rc){ int rc2 = rc & 0xff; + assert( rc==SQLITE_OK || !MEMDB ); assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK || (pPager->errCode & 0xff)==SQLITE_IOERR ); - if( - rc2==SQLITE_FULL || - rc2==SQLITE_IOERR || - rc2==SQLITE_CORRUPT - ){ - pPager->errCode = rc; - if( pPager->state==PAGER_UNLOCK - && sqlite3PcacheRefCount(pPager->pPCache)==0 - ){ - /* If the pager is already unlocked, call pager_unlock() now to - ** clear the error state and ensure that the pager-cache is - ** completely empty. - */ - pager_unlock(pPager); - } + if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ + pPager->errCode = rc; } return rc; } /* @@ -31238,27 +32496,20 @@ releaseAllSavepoints(pPager); assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); if( isOpen(pPager->jfd) ){ - /* TODO: There's a problem here if a journal-file was opened in MEMORY - ** mode and then the journal-mode is changed to TRUNCATE or PERSIST - ** during the transaction. This code should be changed to assume - ** that the journal mode has not changed since the transaction was - ** started. And the sqlite3PagerJournalMode() function should be - ** changed to make sure that this is the case too. - */ - /* Finalize the journal file. */ - if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ - int isMemoryJournal = sqlite3IsMemJournal(pPager->jfd); + if( sqlite3IsMemJournal(pPager->jfd) ){ + assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); sqlite3OsClose(pPager->jfd); - if( !isMemoryJournal ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); - } }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){ - rc = sqlite3OsTruncate(pPager->jfd, 0); + if( pPager->journalOff==0 ){ + rc = SQLITE_OK; + }else{ + rc = sqlite3OsTruncate(pPager->jfd, 0); + } pPager->journalOff = 0; pPager->journalStarted = 0; }else if( pPager->exclusiveMode || pPager->journalMode==PAGER_JOURNALMODE_PERSIST ){ @@ -31265,13 +32516,19 @@ rc = zeroJournalHdr(pPager, hasMaster); pager_error(pPager, rc); pPager->journalOff = 0; pPager->journalStarted = 0; }else{ - assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || rc ); + /* This branch may be executed with Pager.journalMode==MEMORY if + ** a hot-journal was just rolled back. In this case the journal + ** file should be closed and deleted. If this connection writes to + ** the database file, it will do so using an in-memory journal. */ + assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE + || pPager->journalMode==PAGER_JOURNALMODE_MEMORY + ); sqlite3OsClose(pPager->jfd); - if( rc==SQLITE_OK && !pPager->tempFile ){ + if( !pPager->tempFile ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } #ifdef SQLITE_CHECK_PAGES @@ -31478,11 +32735,15 @@ i64 ofst = (pgno-1)*(i64)pPager->pageSize; rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst); if( pgno>pPager->dbFileSize ){ pPager->dbFileSize = pgno; } - sqlite3BackupUpdate(pPager->pBackup, pgno, aData); + if( pPager->pBackup ){ + CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM); + sqlite3BackupUpdate(pPager->pBackup, pgno, aData); + CODEC1(pPager, aData, pgno, 0, rc=SQLITE_NOMEM); + } }else if( !isMainJrnl && pPg==0 ){ /* If this is a rollback of a savepoint and data was not written to ** the database and the page is not in-memory, there is a potential ** problem. When the page is next fetched by the b-tree layer, it ** will be read from the database file, which may or may not be @@ -31513,13 +32774,11 @@ ** sqlite3PagerRollback(). */ void *pData; pData = pPg->pData; memcpy(pData, aData, pPager->pageSize); - if( pPager->xReiniter ){ - pPager->xReiniter(pPg); - } + pPager->xReiniter(pPg); if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){ /* If the contents of this page were just restored from the main ** journal file, then its content must be as they were when the ** transaction was first opened. In this case we can mark the page ** as clean, since there will be no need to write it out to the. @@ -31547,55 +32806,15 @@ if( pgno==1 ){ memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); } /* Decode the page just read from disk */ - CODEC1(pPager, pData, pPg->pgno, 3); + CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM); sqlite3PcacheRelease(pPg); } return rc; } - -#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) -/* -** This routine looks ahead into the main journal file and determines -** whether or not the next record (the record that begins at file -** offset pPager->journalOff) is a well-formed page record consisting -** of a valid page number, pPage->pageSize bytes of content, followed -** by a valid checksum. -** -** The pager never needs to know this in order to do its job. This -** routine is only used from with assert() and testcase() macros. -*/ -static int pagerNextJournalPageIsValid(Pager *pPager){ - Pgno pgno; /* The page number of the page */ - u32 cksum; /* The page checksum */ - int rc; /* Return code from read operations */ - sqlite3_file *fd; /* The file descriptor from which we are reading */ - u8 *aData; /* Content of the page */ - - /* Read the page number header */ - fd = pPager->jfd; - rc = read32bits(fd, pPager->journalOff, &pgno); - if( rc!=SQLITE_OK ){ return 0; } /*NO_TEST*/ - if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ return 0; } /*NO_TEST*/ - if( pgno>(Pgno)pPager->dbSize ){ return 0; } /*NO_TEST*/ - - /* Read the checksum */ - rc = read32bits(fd, pPager->journalOff+pPager->pageSize+4, &cksum); - if( rc!=SQLITE_OK ){ return 0; } /*NO_TEST*/ - - /* Read the data and verify the checksum */ - aData = (u8*)pPager->pTmpSpace; - rc = sqlite3OsRead(fd, aData, pPager->pageSize, pPager->journalOff+4); - if( rc!=SQLITE_OK ){ return 0; } /*NO_TEST*/ - if( pager_cksum(pPager, aData)!=cksum ){ return 0; } /*NO_TEST*/ - - /* Reach this point only if the page is valid */ - return 1; -} -#endif /* !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) */ /* ** Parameter zMaster is the name of a master journal file. A single journal ** file that referred to the master journal file has just been rolled back. ** This routine checks if it is possible to delete the master journal file, @@ -31668,18 +32887,19 @@ int nMasterPtr = pVfs->mxPathname+1; /* Load the entire master journal file into space obtained from ** sqlite3_malloc() and pointed to by zMasterJournal. */ - zMasterJournal = (char *)sqlite3Malloc((int)nMasterJournal + nMasterPtr); + zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1); if( !zMasterJournal ){ rc = SQLITE_NOMEM; goto delmaster_out; } - zMasterPtr = &zMasterJournal[nMasterJournal]; + zMasterPtr = &zMasterJournal[nMasterJournal+1]; rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0); if( rc!=SQLITE_OK ) goto delmaster_out; + zMasterJournal[nMasterJournal] = 0; zJournal = zMasterJournal; while( (zJournal-zMasterJournal)<nMasterJournal ){ int exists; rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists); @@ -31919,11 +33139,11 @@ /* Read the next journal header from the journal file. If there are ** not enough bytes left in the journal file for a complete header, or ** it is corrupted, then a process must of failed while writing it. ** This indicates nothing more needs to be rolled back. */ - rc = readJournalHdr(pPager, szJ, &nRec, &mxPg); + rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; } goto end_playback; @@ -31951,15 +33171,10 @@ ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in ** the journal, it means that the journal might contain additional ** pages that need to be rolled back and that the number of pages ** should be computed based on the journal file size. */ - testcase( nRec==0 && !isHot - && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)!=pPager->journalOff - && ((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager))>0 - && pagerNextJournalPageIsValid(pPager) - ); if( nRec==0 && !isHot && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager)); isUnsync = 1; } @@ -32139,23 +33354,18 @@ */ while( rc==SQLITE_OK && pPager->journalOff<szJ ){ u32 ii; /* Loop counter */ u32 nJRec = 0; /* Number of Journal Records */ u32 dummy; - rc = readJournalHdr(pPager, szJ, &nJRec, &dummy); + rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy); assert( rc!=SQLITE_DONE ); /* ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff" ** test is related to ticket #2565. See the discussion in the ** pager_playback() function for additional information. */ - assert( !(nJRec==0 - && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)!=pPager->journalOff - && ((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager))>0 - && pagerNextJournalPageIsValid(pPager)) - ); if( nJRec==0 && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager)); } @@ -32300,19 +33510,23 @@ pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; } /* -** Set the reinitializer for this pager. If not NULL, the reinitializer -** is called when the content of a page in cache is modified (restored) -** as part of a transaction or savepoint rollback. The callback gives -** higher-level code an opportunity to restore the EXTRA section to -** agree with the restored page data. -*/ -SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*)){ - pPager->xReiniter = xReinit; -} +** Report the current page size and number of reserved bytes back +** to the codec. +*/ +#ifdef SQLITE_HAS_CODEC +static void pagerReportSize(Pager *pPager){ + if( pPager->xCodecSizeChng ){ + pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize, + (int)pPager->nReserve); + } +} +#else +# define pagerReportSize(X) /* No-op if we do not support a codec */ +#endif /* ** Change the page size used by the Pager object. The new page size ** is passed in *pPageSize. ** @@ -32340,18 +33554,19 @@ ** If the page size is not changed, either because one of the enumerated ** conditions above is not true, the pager was in error state when this ** function was called, or because the memory allocation attempt failed, ** then *pPageSize is set to the old, retained page size before returning. */ -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){ +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){ int rc = pPager->errCode; + if( rc==SQLITE_OK ){ u16 pageSize = *pPageSize; assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); - if( pageSize && pageSize!=pPager->pageSize - && (pPager->memDb==0 || pPager->dbSize==0) + if( (pPager->memDb==0 || pPager->dbSize==0) && sqlite3PcacheRefCount(pPager->pPCache)==0 + && pageSize && pageSize!=pPager->pageSize ){ char *pNew = (char *)sqlite3PageMalloc(pageSize); if( !pNew ){ rc = SQLITE_NOMEM; }else{ @@ -32361,10 +33576,14 @@ pPager->pTmpSpace = pNew; sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); } } *pPageSize = (u16)pPager->pageSize; + if( nReserve<0 ) nReserve = pPager->nReserve; + assert( nReserve>=0 && nReserve<1000 ); + pPager->nReserve = (i16)nReserve; + pagerReportSize(pPager); } return rc; } /* @@ -32557,10 +33776,44 @@ } return rc; } /* +** Function assertTruncateConstraint(pPager) checks that one of the +** following is true for all dirty pages currently in the page-cache: +** +** a) The page number is less than or equal to the size of the +** current database image, in pages, OR +** +** b) if the page content were written at this time, it would not +** be necessary to write the current content out to the sub-journal +** (as determined by function subjRequiresPage()). +** +** If the condition asserted by this function were not true, and the +** dirty page were to be discarded from the cache via the pagerStress() +** routine, pagerStress() would not write the current page content to +** the database file. If a savepoint transaction were rolled back after +** this happened, the correct behaviour would be to restore the current +** content of the page. However, since this content is not present in either +** the database file or the portion of the rollback journal and +** sub-journal rolled back the content could not be restored and the +** database image would become corrupt. It is therefore fortunate that +** this circumstance cannot arise. +*/ +#if defined(SQLITE_DEBUG) +static void assertTruncateConstraintCb(PgHdr *pPg){ + assert( pPg->flags&PGHDR_DIRTY ); + assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize ); +} +static void assertTruncateConstraint(Pager *pPager){ + sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); +} +#else +# define assertTruncateConstraint(pPager) +#endif + +/* ** Truncate the in-memory database file image to nPage pages. This ** function does not actually modify the database file on disk. It ** just sets the internal state of the pager object so that the ** truncation will be done when the current transaction is committed. */ @@ -32567,10 +33820,11 @@ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ assert( pPager->dbSizeValid ); assert( pPager->dbSize>=nPage ); assert( pPager->state>=PAGER_RESERVED ); pPager->dbSize = nPage; + assertTruncateConstraint(pPager); } /* ** Shutdown the page cache. Free all memory and close all files. ** @@ -32608,10 +33862,14 @@ PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); IOTRACE(("CLOSE %p\n", pPager)) sqlite3OsClose(pPager->fd); sqlite3PageFree(pPager->pTmpSpace); sqlite3PcacheClose(pPager->pPCache); + +#ifdef SQLITE_HAS_CODEC + if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); +#endif assert( !pPager->aSavepoint && !pPager->pInJournal ); assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ); sqlite3_free(pPager); @@ -32679,16 +33937,10 @@ int rc; /* Return code */ const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); assert( isOpen(pPager->jfd) ); if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ - /* Variable iNRecOffset is set to the offset in the journal file - ** of the nRec field of the most recently written journal header. - ** This field will be updated following the xSync() operation - ** on the journal file. */ - i64 iNRecOffset = pPager->journalHdr + sizeof(aJournalMagic); - /* This block deals with an obscure problem. If the last connection ** that wrote to this database was operating in persistent-journal ** mode, then the journal file may at this point actually be larger ** than Pager.journalOff bytes. If the next thing in the journal ** file happens to be a journal-header (written as part of the @@ -32707,12 +33959,18 @@ ** Variable iNextHdrOffset is set to the offset at which this ** problematic header will occur, if it exists. aMagic is used ** as a temporary buffer to inspect the first couple of bytes of ** the potential journal header. */ - i64 iNextHdrOffset = journalHdrOffset(pPager); + i64 iNextHdrOffset; u8 aMagic[8]; + u8 zHeader[sizeof(aJournalMagic)+4]; + + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec); + + iNextHdrOffset = journalHdrOffset(pPager); rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset); if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){ static const u8 zerobyte = 0; rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset); } @@ -32735,12 +33993,14 @@ PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); IOTRACE(("JSYNC %p\n", pPager)) rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags); if( rc!=SQLITE_OK ) return rc; } - IOTRACE(("JHDR %p %lld %d\n", pPager, iNRecOffset, 4)); - rc = write32bits(pPager->jfd, iNRecOffset, pPager->nRec); + IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr)); + rc = sqlite3OsWrite( + pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr + ); if( rc!=SQLITE_OK ) return rc; } if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); IOTRACE(("JSYNC %p\n", pPager)) @@ -32796,11 +34056,11 @@ */ static int pager_write_pagelist(PgHdr *pList){ Pager *pPager; /* Pager object */ int rc; /* Return code */ - if( pList==0 ) return SQLITE_OK; + if( NEVER(pList==0) ) return SQLITE_OK; pPager = pList->pPager; /* At this point there may be either a RESERVED or EXCLUSIVE lock on the ** database file. If there is already an EXCLUSIVE lock, the following ** call is a no-op. @@ -32839,12 +34099,15 @@ ** ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag ** set (set by sqlite3PagerDontWrite()). */ if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ - i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ - char *pData = CODEC2(pPager, pList->pData, pgno, 6); /* Data to write */ + i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ + char *pData; /* Data to write */ + + /* Encode the database */ + CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData); /* Write out the page data. */ rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); /* If page 1 was just written, update Pager.dbFileVers to match @@ -32857,11 +34120,11 @@ if( pgno>pPager->dbFileSize ){ pPager->dbFileSize = pgno; } /* Update any backup objects copying the contents of this pager. */ - sqlite3BackupUpdate(pPager->pBackup, pgno, (u8 *)pData); + sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData); PAGERTRACE(("STORE %d page %d hash(%08x)\n", PAGERID(pPager), pgno, pager_pagehash(pList))); IOTRACE(("PGOUT %p %d\n", pPager, pgno)); PAGER_INCR(sqlite3_pager_writedb_count); @@ -32895,12 +34158,13 @@ int rc = SQLITE_OK; Pager *pPager = pPg->pPager; if( isOpen(pPager->sjfd) ){ void *pData = pPg->pData; i64 offset = pPager->nSubRec*(4+pPager->pageSize); - char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7); - + char *pData2; + + CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno)); assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize ); rc = write32bits(pPager->sjfd, offset, pPg->pgno); if( rc==SQLITE_OK ){ @@ -32909,11 +34173,10 @@ } if( rc==SQLITE_OK ){ pPager->nSubRec++; assert( pPager->nSavepoint>0 ); rc = addToSavepointBitvecs(pPager, pPg->pgno); - testcase( rc!=SQLITE_OK ); } return rc; } @@ -32954,11 +34217,13 @@ ** reusing pPg. ** ** Similarly, if the pager has already entered the error state, do not ** try to write the contents of pPg to disk. */ - if( pPager->errCode || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC) ){ + if( NEVER(pPager->errCode) + || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC) + ){ return SQLITE_OK; } /* Sync the journal file if required. */ if( pPg->flags&PGHDR_NEED_SYNC ){ @@ -32997,11 +34262,13 @@ ** The solution is to write the current data for page X into the ** sub-journal file now (if it is not already there), so that it will ** be restored to its current value when the "ROLLBACK TO sp" is ** executed. */ - if( rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg) ){ + if( NEVER( + rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg) + ) ){ rc = subjournalPage(pPg); } /* Write the contents of the page out to the database file. */ if( rc==SQLITE_OK ){ @@ -33053,11 +34320,12 @@ sqlite3_vfs *pVfs, /* The virtual file system to use */ Pager **ppPager, /* OUT: Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int nExtra, /* Extra bytes append to each in-memory page */ int flags, /* flags controlling this file */ - int vfsFlags /* flags passed through to sqlite3_vfs.xOpen() */ + int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ + void (*xReinit)(DbPage*) /* Function to reinitialize pages */ ){ u8 *pPtr; Pager *pPager = 0; /* Pager object to allocate and return */ int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ @@ -33143,11 +34411,11 @@ ROUND8(pVfs->szOsFile) + /* The main db file */ journalFileSize * 2 + /* The two journal files */ nPathname + 1 + /* zFilename */ nPathname + 8 + 1 /* zJournal */ ); - assert( EIGHT_BYTE_ALIGNMENT(journalFileSize) ); + assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); if( !pPtr ){ sqlite3_free(zPathname); return SQLITE_NOMEM; } pPager = (Pager*)(pPtr); @@ -33162,10 +34430,11 @@ if( zPathname ){ pPager->zJournal = (char*)(pPtr += nPathname + 1); memcpy(pPager->zFilename, zPathname, nPathname); memcpy(pPager->zJournal, zPathname, nPathname); memcpy(&pPager->zJournal[nPathname], "-journal", 8); + if( pPager->zFilename[0]==0 ) pPager->zJournal[0] = 0; sqlite3_free(zPathname); } pPager->pVfs = pVfs; pPager->vfsFlags = vfsFlags; @@ -33218,18 +34487,19 @@ ** database is the same as a temp-file that is never written out to ** disk and uses an in-memory rollback journal. */ tempFile = 1; pPager->state = PAGER_EXCLUSIVE; + readOnly = (vfsFlags&SQLITE_OPEN_READONLY); } /* The following call to PagerSetPagesize() serves to set the value of ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. */ if( rc==SQLITE_OK ){ assert( pPager->memDb==0 ); - rc = sqlite3PagerSetPagesize(pPager, &szPageDflt); + rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1); testcase( rc!=SQLITE_OK ); } /* If an error occurred in either of the blocks above, free the ** Pager structure and close the file. @@ -33240,10 +34510,11 @@ sqlite3_free(pPager); return rc; } /* Initialize the PCache object. */ + assert( nExtra<1000 ); nExtra = ROUND8(nExtra); sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename)); @@ -33269,25 +34540,29 @@ pPager->exclusiveMode = (u8)tempFile; pPager->changeCountDone = pPager->tempFile; pPager->memDb = (u8)memDb; pPager->readOnly = (u8)readOnly; /* pPager->needSync = 0; */ - pPager->noSync = (pPager->tempFile || !useJournal) ?1:0; + assert( useJournal || pPager->tempFile ); + pPager->noSync = pPager->tempFile; pPager->fullSync = pPager->noSync ?0:1; pPager->sync_flags = SQLITE_SYNC_NORMAL; /* pPager->pFirst = 0; */ /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ - pPager->nExtra = nExtra; + pPager->nExtra = (u16)nExtra; pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; assert( isOpen(pPager->fd) || tempFile ); setSectorSize(pPager); - if( memDb ){ + if( !useJournal ){ + pPager->journalMode = PAGER_JOURNALMODE_OFF; + }else if( memDb ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ + pPager->xReiniter = xReinit; /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; return SQLITE_OK; } @@ -33331,27 +34606,44 @@ assert( pPager!=0 ); assert( pPager->useJournal ); assert( isOpen(pPager->fd) ); assert( !isOpen(pPager->jfd) ); + assert( pPager->state <= PAGER_SHARED ); *pExists = 0; rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists); if( rc==SQLITE_OK && exists ){ int locked; /* True if some process holds a RESERVED lock */ + + /* Race condition here: Another process might have been holding the + ** the RESERVED lock and have a journal open at the sqlite3OsAccess() + ** call above, but then delete the journal and drop the lock before + ** we get to the following sqlite3OsCheckReservedLock() call. If that + ** is the case, this routine might think there is a hot journal when + ** in fact there is none. This results in a false-positive which will + ** be dealt with by the playback routine. Ticket #3883. + */ rc = sqlite3OsCheckReservedLock(pPager->fd, &locked); if( rc==SQLITE_OK && !locked ){ int nPage; /* Check the size of the database file. If it consists of 0 pages, ** then delete the journal file. See the header comment above for - ** the reasoning here. + ** the reasoning here. Delete the obsolete journal file under + ** a RESERVED lock to avoid race conditions and to avoid violating + ** [H33020]. */ rc = sqlite3PagerPagecount(pPager, &nPage); if( rc==SQLITE_OK ){ if( nPage==0 ){ - rc = sqlite3OsDelete(pVfs, pPager->zJournal, 0); + sqlite3BeginBenignMalloc(); + if( sqlite3OsLock(pPager->fd, RESERVED_LOCK)==SQLITE_OK ){ + sqlite3OsDelete(pVfs, pPager->zJournal, 0); + sqlite3OsUnlock(pPager->fd, SHARED_LOCK); + } + sqlite3EndBenignMalloc(); }else{ /* The journal file exists and no other connection has a reserved ** or greater lock on the database file. Now check that there is ** at least one non-zero bytes at the start of the journal file. ** If there is, then we consider this journal to be hot. If not, @@ -33365,10 +34657,22 @@ if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; } sqlite3OsClose(pPager->jfd); *pExists = (first!=0); + }else if( rc==SQLITE_CANTOPEN ){ + /* If we cannot open the rollback journal file in order to see if + ** its has a zero header, that might be due to an I/O error, or + ** it might be due to the race condition described above and in + ** ticket #3883. Either way, assume that the journal is hot. + ** This might be a false positive. But if it is, then the + ** automatic journal playback and recovery mechanism will deal + ** with it under an EXCLUSIVE lock where we do not need to + ** worry so much with race conditions. + */ + *pExists = 1; + rc = SQLITE_OK; } } } } } @@ -33392,12 +34696,13 @@ Pgno pgno = pPg->pgno; /* Page number to read */ int rc; /* Return code */ i64 iOffset; /* Byte offset of file to read from */ assert( pPager->state>=PAGER_SHARED && !MEMDB ); - - if( !isOpen(pPager->fd) ){ + assert( isOpen(pPager->fd) ); + + if( NEVER(!isOpen(pPager->fd)) ){ assert( pPager->tempFile ); memset(pPg->pData, 0, pPager->pageSize); return SQLITE_OK; } iOffset = (pgno-1)*(i64)pPager->pageSize; @@ -33407,11 +34712,11 @@ } if( pgno==1 ){ u8 *dbFileVers = &((u8*)pPg->pData)[24]; memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); } - CODEC1(pPager, pPg->pData, pgno, 3); + CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM); PAGER_INCR(sqlite3_pager_readdb_count); PAGER_INCR(pPager->nRead); IOTRACE(("PGIN %p %d\n", pPager, pgno)); PAGERTRACE(("FETCH %d page %d hash(%08x)\n", @@ -33419,14 +34724,16 @@ return rc; } /* -** This function is called whenever the upper layer requests a database -** page is requested, before the cache is checked for a suitable page -** or any data is read from the database. It performs the following -** two functions: +** This function is called to obtain a shared lock on the database file. +** It is illegal to call sqlite3PagerAcquire() until after this function +** has been successfully called. If a shared-lock is already held when +** this function is called, it is a no-op. +** +** The following operations are also performed by this function. ** ** 1) If the pager is currently in PAGER_UNLOCK state (no lock held ** on the database file), then an attempt is made to obtain a ** SHARED lock on the database file. Immediately after obtaining ** the SHARED lock, the file-system is checked for a hot-journal, @@ -33448,57 +34755,53 @@ ** ** Otherwise, if everything is successful, SQLITE_OK is returned. If an ** IO error occurs while locking the database, checking for a hot-journal ** file or rolling back a journal file, the IO error code is returned. */ -static int pagerSharedLock(Pager *pPager){ +SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ int isErrorReset = 0; /* True if recovering from error state */ - /* If this database is opened for exclusive access, has no outstanding - ** page references and is in an error-state, this is a chance to clear - ** the error. Discard the contents of the pager-cache and treat any - ** open journal file as a hot-journal. - */ - if( !MEMDB && pPager->exclusiveMode - && sqlite3PcacheRefCount(pPager->pPCache)==0 && pPager->errCode - ){ - if( isOpen(pPager->jfd) ){ + /* This routine is only called from b-tree and only when there are no + ** outstanding pages */ + assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); + if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } + + /* If this database is in an error-state, now is a chance to clear + ** the error. Discard the contents of the pager-cache and rollback + ** any hot journal in the file-system. + */ + if( pPager->errCode ){ + if( isOpen(pPager->jfd) || pPager->zJournal ){ isErrorReset = 1; } pPager->errCode = SQLITE_OK; pager_reset(pPager); - } - - /* If the pager is still in an error state, do not proceed. The error - ** state will be cleared at some point in the future when all page - ** references are dropped and the cache can be discarded. - */ - if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ - return pPager->errCode; } if( pPager->state==PAGER_UNLOCK || isErrorReset ){ sqlite3_vfs * const pVfs = pPager->pVfs; int isHotJournal = 0; assert( !MEMDB ); assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); - if( !pPager->noReadlock ){ + if( pPager->noReadlock ){ + assert( pPager->readOnly ); + pPager->state = PAGER_SHARED; + }else{ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ assert( pPager->state==PAGER_UNLOCK ); return pager_error(pPager, rc); } - }else if( pPager->state==PAGER_UNLOCK ){ - pPager->state = PAGER_SHARED; } assert( pPager->state>=SHARED_LOCK ); /* If a journal file exists, and there is no RESERVED lock on the ** database file, then it either needs to be played back or deleted. */ if( !isErrorReset ){ + assert( pPager->state <= PAGER_SHARED ); rc = hasHotJournal(pPager, &isHotJournal); if( rc!=SQLITE_OK ){ goto failed; } } @@ -33543,13 +34846,16 @@ if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ rc = SQLITE_CANTOPEN; sqlite3OsClose(pPager->jfd); } }else{ - /* If the journal does not exist, that means some other process - ** has already rolled it back */ - rc = SQLITE_BUSY; + /* If the journal does not exist, it usually means that some + ** other connection managed to get in and roll it back before + ** this connection obtained the exclusive lock above. Or, it + ** may mean that the pager was in the error-state when this + ** function was called and the journal file does not exist. */ + rc = pager_end_transaction(pPager, 0); } } } if( rc!=SQLITE_OK ){ goto failed; @@ -33564,21 +34870,23 @@ /* Playback and delete the journal. Drop the database write ** lock and reacquire the read lock. Purge the cache before ** playing back the hot-journal so that we don't end up with ** an inconsistent cache. */ - rc = pager_playback(pPager, 1); - if( rc!=SQLITE_OK ){ - rc = pager_error(pPager, rc); - goto failed; + if( isOpen(pPager->jfd) ){ + rc = pager_playback(pPager, 1); + if( rc!=SQLITE_OK ){ + rc = pager_error(pPager, rc); + goto failed; + } } assert( (pPager->state==PAGER_SHARED) || (pPager->exclusiveMode && pPager->state>PAGER_SHARED) ); } - if( sqlite3PcachePagecount(pPager->pPCache)>0 ){ + if( pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0 ){ /* The shared-lock has just been acquired on the database file ** and there are already pages in the cache (from a previous ** read or write transaction). Check to see if the database ** has been modified. If the database has changed, flush the ** cache. @@ -33628,38 +34936,27 @@ } /* ** If the reference count has reached zero, rollback any active ** transaction and unlock the pager. +** +** Except, in locking_mode=EXCLUSIVE when there is nothing to in +** the rollback journal, the unlock is not performed and there is +** nothing to rollback, so this routine is a no-op. */ static void pagerUnlockIfUnused(Pager *pPager){ - if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){ + if( (sqlite3PcacheRefCount(pPager->pPCache)==0) + && (!pPager->exclusiveMode || pPager->journalOff>0) + ){ pagerUnlockAndRollback(pPager); } -} - -/* -** Drop a page from the cache using sqlite3PcacheDrop(). -** -** If this means there are now no pages with references to them, a rollback -** occurs and the lock on the database is removed. -*/ -static void pagerDropPage(DbPage *pPg){ - Pager *pPager = pPg->pPager; - sqlite3PcacheDrop(pPg); - pagerUnlockIfUnused(pPager); } /* ** Acquire a reference to page number pgno in pager pPager (a page ** reference has type DbPage*). If the requested reference is ** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. -** -** This function calls pagerSharedLock() to obtain a SHARED lock on -** the database file if such a lock or greater is not already held. -** This may cause hot-journal rollback or a cache purge. See comments -** above function pagerSharedLock() for details. ** ** If the requested page is already in the cache, it is returned. ** Otherwise, a new page object is allocated and populated with data ** read from the database file. In some cases, the pcache module may ** choose not to allocate a new page object and may reuse an existing @@ -33708,65 +35005,70 @@ Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int noContent /* Do not bother reading content from disk if true */ ){ - PgHdr *pPg = 0; - int rc; + int rc; + PgHdr *pPg; assert( assert_pager_state(pPager) ); - assert( pPager->state==PAGER_UNLOCK - || sqlite3PcacheRefCount(pPager->pPCache)>0 - || pgno==1 - ); - - /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page - ** number greater than this, or zero, is requested. - */ - if( pgno>PAGER_MAX_PGNO || pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + assert( pPager->state>PAGER_UNLOCK ); + + if( pgno==0 ){ return SQLITE_CORRUPT_BKPT; } - /* Make sure we have not hit any critical errors. - */ - assert( pPager!=0 ); - *ppPage = 0; - - /* If this is the first page accessed, then get a SHARED lock - ** on the database file. pagerSharedLock() is a no-op if - ** a database lock is already held. - */ - rc = pagerSharedLock(pPager); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pPager->state!=PAGER_UNLOCK ); - - rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pPg->pgno==pgno ); - assert( pPg->pPager==pPager || pPg->pPager==0 ); - if( pPg->pPager==0 ){ + /* If the pager is in the error state, return an error immediately. + ** Otherwise, request the page from the PCache layer. */ + if( pPager->errCode!=SQLITE_OK && pPager->errCode!=SQLITE_FULL ){ + rc = pPager->errCode; + }else{ + rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage); + } + + if( rc!=SQLITE_OK ){ + /* Either the call to sqlite3PcacheFetch() returned an error or the + ** pager was already in the error-state when this function was called. + ** Set pPg to 0 and jump to the exception handler. */ + pPg = 0; + goto pager_acquire_err; + } + assert( (*ppPage)->pgno==pgno ); + assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 ); + + if( (*ppPage)->pPager ){ + /* In this case the pcache already contains an initialized copy of + ** the page. Return without further ado. */ + assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); + PAGER_INCR(pPager->nHit); + return SQLITE_OK; + + }else{ /* The pager cache has created a new page. Its content needs to - ** be initialized. - */ + ** be initialized. */ int nMax; + PAGER_INCR(pPager->nMiss); + pPg = *ppPage; pPg->pPager = pPager; + + /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page + ** number greater than this, or the unused locking-page, is requested. */ + if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ + rc = SQLITE_CORRUPT_BKPT; + goto pager_acquire_err; + } rc = sqlite3PagerPagecount(pPager, &nMax); if( rc!=SQLITE_OK ){ - sqlite3PagerUnref(pPg); - return rc; + goto pager_acquire_err; } if( nMax<(int)pgno || MEMDB || noContent ){ if( pgno>pPager->mxPgno ){ - sqlite3PagerUnref(pPg); - return SQLITE_FULL; + rc = SQLITE_FULL; + goto pager_acquire_err; } if( noContent ){ /* Failure to set the bits in the InJournal bit-vectors is benign. ** It merely means that we might do some extra work to journal a ** page that does not need to be journaled. Nevertheless, be sure @@ -33787,24 +35089,29 @@ IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ assert( pPg->pPager==pPager ); rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ - pagerDropPage(pPg); - return rc; + goto pager_acquire_err; } } #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif - }else{ - /* The requested page is in the page cache. */ - PAGER_INCR(pPager->nHit); - } - - *ppPage = pPg; - return SQLITE_OK; + } + + return SQLITE_OK; + +pager_acquire_err: + assert( rc!=SQLITE_OK ); + if( pPg ){ + sqlite3PcacheDrop(pPg); + } + pagerUnlockIfUnused(pPager); + + *ppPage = 0; + return rc; } /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, @@ -33820,17 +35127,13 @@ */ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ PgHdr *pPg = 0; assert( pPager!=0 ); assert( pgno!=0 ); - - if( (pPager->state!=PAGER_UNLOCK) - && (pPager->errCode==SQLITE_OK || pPager->errCode==SQLITE_FULL) - ){ - sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); - } - + assert( pPager->pPCache!=0 ); + assert( pPager->state > PAGER_UNLOCK ); + sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); return pPg; } /* ** Release a page reference. @@ -33858,11 +35161,11 @@ ** sqlite3OsOpen() fails. */ static int openSubJournal(Pager *pPager){ int rc = SQLITE_OK; if( isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ){ - if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ + if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){ sqlite3MemJournalOpen(pPager->sjfd); }else{ rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL); } } @@ -33895,16 +35198,17 @@ int rc = SQLITE_OK; /* Return code */ sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */ assert( pPager->state>=PAGER_RESERVED ); assert( pPager->useJournal ); + assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF ); assert( pPager->pInJournal==0 ); - /* If already in the error state, this function is a no-op. */ - if( pPager->errCode ){ - return pPager->errCode; - } + /* If already in the error state, this function is a no-op. But on + ** the other hand, this routine is never called if we are already in + ** an error state. */ + if( NEVER(pPager->errCode) ) return pPager->errCode; /* TODO: Is it really possible to get here with dbSizeValid==0? If not, ** the call to PagerPagecount() can be removed. */ testcase( pPager->dbSizeValid==0 ); @@ -33977,14 +35281,23 @@ ** of the journal file is deferred until there is an actual need to ** write to the journal. TODO: Why handle temporary files differently? ** ** If the journal file is opened (or if it is already open), then a ** journal-header is written to the start of it. -*/ -SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag){ +** +** If the subjInMemory argument is non-zero, then any sub-journal opened +** within this transaction will be opened as an in-memory file. This +** has no effect if the sub-journal is already opened (as it may be when +** running in exclusive mode) or if the transaction does not require a +** sub-journal. If the subjInMemory argument is zero, then any required +** sub-journal is implemented in-memory if pPager is an in-memory database, +** or using a temporary file otherwise. +*/ +SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ int rc = SQLITE_OK; assert( pPager->state!=PAGER_UNLOCK ); + pPager->subjInMemory = (u8)subjInMemory; if( pPager->state==PAGER_SHARED ){ assert( pPager->pInJournal==0 ); assert( !MEMDB && !pPager->tempFile ); /* Obtain a RESERVED lock on the database file. If the exFlag parameter @@ -34001,13 +35314,11 @@ } /* If the required locks were successfully obtained, open the journal ** file and write the first journal-header to it. */ - if( rc==SQLITE_OK && pPager->useJournal - && pPager->journalMode!=PAGER_JOURNALMODE_OFF - ){ + if( rc==SQLITE_OK && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ rc = pager_open_journal(pPager); } }else if( isOpen(pPager->jfd) && pPager->journalOff==0 ){ /* This happens when the pager was in exclusive-access mode the last ** time a (read or write) transaction was successfully concluded @@ -34021,10 +35332,19 @@ rc = pager_open_journal(pPager); } PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); assert( !isOpen(pPager->jfd) || pPager->journalOff>0 || rc!=SQLITE_OK ); + if( rc!=SQLITE_OK ){ + assert( !pPager->dbModified ); + /* Ignore any IO error that occurs within pager_end_transaction(). The + ** purpose of this call is to reset the internal state of the pager + ** sub-system. It doesn't matter if the journal-file is not properly + ** finalized at this point (since it is not a valid journal file anyway). + */ + pager_end_transaction(pPager, 0); + } return rc; } /* ** Mark a single data page as writeable. The page is written into the @@ -34036,18 +35356,23 @@ static int pager_write(PgHdr *pPg){ void *pData = pPg->pData; Pager *pPager = pPg->pPager; int rc = SQLITE_OK; - /* Check for errors - */ - if( pPager->errCode ){ - return pPager->errCode; - } - if( pPager->readOnly ){ - return SQLITE_PERM; - } + /* This routine is not called unless a transaction has already been + ** started. + */ + assert( pPager->state>=PAGER_RESERVED ); + + /* If an error has been previously detected, we should not be + ** calling this routine. Repeat the error for robustness. + */ + if( NEVER(pPager->errCode) ) return pPager->errCode; + + /* Higher-level routines never call this function if database is not + ** writable. But check anyway, just for robustness. */ + if( NEVER(pPager->readOnly) ) return SQLITE_PERM; assert( !pPager->setMaster ); CHECK_PAGE(pPg); @@ -34061,21 +35386,20 @@ /* If we get this far, it means that the page needs to be ** written to the transaction journal or the ckeckpoint journal ** or both. ** - ** First check to see that the transaction journal exists and - ** create it if it does not. - */ - assert( pPager->state!=PAGER_UNLOCK ); - rc = sqlite3PagerBegin(pPager, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pPager->state>=PAGER_RESERVED ); - if( !isOpen(pPager->jfd) && pPager->useJournal - && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ + ** Higher level routines should have already started a transaction, + ** which means they have acquired the necessary locks and opened + ** a rollback journal. Double-check to makes sure this is the case. + */ + rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory); + if( NEVER(rc!=SQLITE_OK) ){ + return rc; + } + if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ + assert( pPager->useJournal ); rc = pager_open_journal(pPager); if( rc!=SQLITE_OK ) return rc; } pPager->dbModified = 1; @@ -34090,11 +35414,11 @@ /* We should never write to the journal file the page that ** contains the database locks. The following assert verifies ** that we do not. */ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); - pData2 = CODEC2(pPager, pData, pPg->pgno, 7); + CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); cksum = pager_cksum(pPager, (u8*)pData2); rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, pPager->journalOff + 4); @@ -34250,13 +35574,13 @@ ** 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( needSync ){ + if( rc==SQLITE_OK && needSync ){ assert( !MEMDB && pPager->noSync==0 ); - for(ii=0; ii<nPage && needSync; ii++){ + for(ii=0; ii<nPage; ii++){ PgHdr *pPage = pager_lookup(pPager, pg1+ii); if( pPage ){ pPage->flags |= PGHDR_NEED_SYNC; sqlite3PagerUnref(pPage); } @@ -34312,16 +35636,16 @@ /* ** This routine is called to increment the value of the database file ** change-counter, stored as a 4-byte big-endian integer starting at ** byte offset 24 of the pager file. ** -** If the isDirect flag is zero, then this is done by calling +** If the isDirectMode flag is zero, then this is done by calling ** sqlite3PagerWrite() on page 1, then modifying the contents of the ** page data. In this case the file will be updated when the current ** transaction is committed. ** -** The isDirect flag may only be non-zero if the library was compiled +** The isDirectMode flag may only be non-zero if the library was compiled ** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case, ** if isDirect is non-zero, then the database file is updated directly ** by writing an updated version of page 1 using a call to the ** sqlite3OsWrite() function. */ @@ -34337,19 +35661,19 @@ ** enabled at compile time, the compiler can omit the tests of ** 'isDirect' below, as well as the block enclosed in the ** "if( isDirect )" condition. */ #ifndef SQLITE_ENABLE_ATOMIC_WRITE - const int isDirect = 0; +# define DIRECT_MODE 0 assert( isDirectMode==0 ); UNUSED_PARAMETER(isDirectMode); #else - const int isDirect = isDirectMode; +# define DIRECT_MODE isDirectMode #endif assert( pPager->state>=PAGER_RESERVED ); - if( !pPager->changeCountDone && pPager->dbSize>0 ){ + if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){ PgHdr *pPgHdr; /* Reference to page 1 */ u32 change_counter; /* Initial value of change-counter field */ assert( !pPager->tempFile && isOpen(pPager->fd) ); @@ -34356,13 +35680,15 @@ /* Open page 1 of the file for writing. */ rc = sqlite3PagerGet(pPager, 1, &pPgHdr); assert( pPgHdr==0 || rc==SQLITE_OK ); /* If page one was fetched successfully, and this function is not - ** operating in direct-mode, make page 1 writable. - */ - if( rc==SQLITE_OK && !isDirect ){ + ** operating in direct-mode, make page 1 writable. When not in + ** direct mode, page 1 is always held in cache and hence the PagerGet() + ** above is always successful - hence the ALWAYS on rc==SQLITE_OK. + */ + if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){ rc = sqlite3PagerWrite(pPgHdr); } if( rc==SQLITE_OK ){ /* Increment the value just read and write it back to byte 24. */ @@ -34369,18 +35695,18 @@ change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers); change_counter++; put32bits(((char*)pPgHdr->pData)+24, change_counter); /* If running in direct mode, write the contents of page 1 to the file. */ - if( isDirect ){ + if( DIRECT_MODE ){ const void *zBuf = pPgHdr->pData; assert( pPager->dbFileSize>0 ); rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); - } - - /* If everything worked, set the changeCountDone flag. */ - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ + pPager->changeCountDone = 1; + } + }else{ pPager->changeCountDone = 1; } } /* Release the page reference. */ @@ -34396,11 +35722,12 @@ ** If successful, or called on a pager for which it is a no-op, this ** function returns SQLITE_OK. Otherwise, an IO error code is returned. */ SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){ int rc; /* Return code */ - if( MEMDB || pPager->noSync ){ + assert( !MEMDB ); + if( pPager->noSync ){ rc = SQLITE_OK; }else{ rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); } return rc; @@ -34437,21 +35764,26 @@ const char *zMaster, /* If not NULL, the master journal name */ int noSync /* True to omit the xSync on the db file */ ){ int rc = SQLITE_OK; /* Return code */ - if( pPager->errCode ){ - return pPager->errCode; - } + /* The dbOrigSize is never set if journal_mode=OFF */ + assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 ); + + /* If a prior error occurred, this routine should not be called. ROLLBACK + ** is the appropriate response to an error, not COMMIT. Guard against + ** coding errors by repeating the prior error. */ + if( NEVER(pPager->errCode) ) return pPager->errCode; PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", pPager->zFilename, zMaster, pPager->dbSize)); - /* If this is an in-memory db, or no pages have been written to, or this - ** function has already been called, it is a no-op. - */ if( MEMDB && pPager->dbModified ){ + /* If this is an in-memory db, or no pages have been written to, or this + ** function has already been called, it is mostly a no-op. However, any + ** backup in progress needs to be restarted. + */ sqlite3BackupRestart(pPager->pBackup); }else if( pPager->state!=PAGER_SYNCED && pPager->dbModified ){ /* The following block updates the change-counter. Exactly how it ** does this depends on whether or not the atomic-update optimization @@ -34509,14 +35841,17 @@ ** Before reading the pages with page numbers larger than the ** current value of Pager.dbSize, set dbSize back to the value ** that it took at the start of the transaction. Otherwise, the ** calls to sqlite3PagerGet() return zeroed pages instead of ** reading data from the database file. + ** + ** When journal_mode==OFF the dbOrigSize is always zero, so this + ** block never runs if journal_mode=OFF. */ #ifndef SQLITE_OMIT_AUTOVACUUM if( pPager->dbSize<pPager->dbOrigSize - && pPager->journalMode!=PAGER_JOURNALMODE_OFF + && ALWAYS(pPager->journalMode!=PAGER_JOURNALMODE_OFF) ){ Pgno i; /* Iterator variable */ const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */ const Pgno dbSize = pPager->dbSize; /* Database image size */ pPager->dbSize = pPager->dbOrigSize; @@ -34574,18 +35909,10 @@ pPager->state = PAGER_SYNCED; } commit_phase_one_exit: - if( rc==SQLITE_IOERR_BLOCKED ){ - /* pager_incr_changecounter() may attempt to obtain an exclusive - ** lock to spill the cache and return IOERR_BLOCKED. But since - ** there is no chance the cache is inconsistent, it is - ** better to return SQLITE_BUSY. - **/ - rc = SQLITE_BUSY; - } return rc; } /* @@ -34604,22 +35931,20 @@ ** moves into the error state. Otherwise, SQLITE_OK is returned. */ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ - /* Do not proceed if the pager is already in the error state. */ - if( pPager->errCode ){ - return pPager->errCode; - } + /* This routine should not be called if a prior error has occurred. + ** But if (due to a coding error elsewhere in the system) it does get + ** called, just return the same error code without doing anything. */ + if( NEVER(pPager->errCode) ) return pPager->errCode; /* This function should not be called if the pager is not in at least ** PAGER_RESERVED state. And indeed SQLite never does this. But it is - ** nice to have this defensive block here anyway. - */ - if( NEVER(pPager->state<PAGER_RESERVED) ){ - return SQLITE_ERROR; - } + ** nice to have this defensive test here anyway. + */ + if( NEVER(pPager->state<PAGER_RESERVED) ) return SQLITE_ERROR; /* An optimization. If the database was not actually modified during ** this transaction, the pager is running in exclusive-mode and is ** using persistent journals, then this function is a no-op. ** @@ -34810,11 +36135,11 @@ /* Populate the PagerSavepoint structures just allocated. */ for(ii=nCurrent; ii<nSavepoint; ii++){ assert( pPager->dbSizeValid ); aNew[ii].nOrig = pPager->dbSize; - if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ + if( isOpen(pPager->jfd) && ALWAYS(pPager->journalOff>0) ){ aNew[ii].iOffset = pPager->journalOff; }else{ aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); } aNew[ii].iSubRec = pPager->nSubRec; @@ -34824,10 +36149,11 @@ } } /* Open the sub-journal, if it is not already opened. */ rc = openSubJournal(pPager); + assertTruncateConstraint(pPager); } return rc; } @@ -34941,19 +36267,28 @@ return pPager->noSync; } #ifdef SQLITE_HAS_CODEC /* -** Set the codec for this pager -*/ -SQLITE_PRIVATE void sqlite3PagerSetCodec( +** Set or retrieve the codec for this pager +*/ +static void sqlite3PagerSetCodec( Pager *pPager, void *(*xCodec)(void*,void*,Pgno,int), - void *pCodecArg -){ + void (*xCodecSizeChng)(void*,int,int), + void (*xCodecFree)(void*), + void *pCodec +){ + if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); pPager->xCodec = xCodec; - pPager->pCodecArg = pCodecArg; + pPager->xCodecSizeChng = xCodecSizeChng; + pPager->xCodecFree = xCodecFree; + pPager->pCodec = pCodec; + pagerReportSize(pPager); +} +static void *sqlite3PagerGetCodec(Pager *pPager){ + return pPager->pCodec; } #endif #ifndef SQLITE_OMIT_AUTOVACUUM /* @@ -35070,12 +36405,13 @@ */ PgHdr *pPgHdr; assert( pPager->needSync ); rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); if( rc!=SQLITE_OK ){ - if( pPager->pInJournal && needSyncPgno<=pPager->dbOrigSize ){ - sqlite3BitvecClear(pPager->pInJournal, needSyncPgno); + if( needSyncPgno<=pPager->dbOrigSize ){ + assert( pPager->pTmpSpace!=0 ); + sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace); } return rc; } pPager->needSync = 1; assert( pPager->noSync==0 && !MEMDB ); @@ -35091,11 +36427,14 @@ ** with an out-of-memory error now. Ticket #3761. */ if( MEMDB ){ DbPage *pNew; rc = sqlite3PagerAcquire(pPager, origPgno, &pNew, 1); - if( rc!=SQLITE_OK ) return rc; + if( rc!=SQLITE_OK ){ + sqlite3PcacheMove(pPg, origPgno); + return rc; + } sqlite3PagerUnref(pNew); } return SQLITE_OK; } @@ -35112,12 +36451,11 @@ /* ** Return a pointer to the Pager.nExtra bytes of "extra" space ** allocated along with the specified page. */ SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){ - Pager *pPager = pPg->pPager; - return (pPager?pPg->pExtra:0); + return pPg->pExtra; } /* ** Get/set the locking-mode for this pager. Parameter eMode must be one ** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or @@ -35148,15 +36486,18 @@ ** PAGER_JOURNALMODE_TRUNCATE ** PAGER_JOURNALMODE_PERSIST ** PAGER_JOURNALMODE_OFF ** PAGER_JOURNALMODE_MEMORY ** -** If the parameter is not _QUERY, then the journal-mode is set to the -** value specified. Except, an in-memory database can only have its -** journal mode set to _OFF or _MEMORY. Attempts to change the journal -** mode of an in-memory database to something other than _OFF or _MEMORY -** are silently ignored. +** If the parameter is not _QUERY, then the journal_mode is set to the +** value specified if the change is allowed. The change is disallowed +** for the following reasons: +** +** * An in-memory database can only have its journal_mode set to _OFF +** or _MEMORY. +** +** * The journal mode may not be changed while a transaction is active. ** ** The returned indicate the current (possibly updated) journal-mode. */ SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *pPager, int eMode){ assert( eMode==PAGER_JOURNALMODE_QUERY @@ -35164,12 +36505,19 @@ || eMode==PAGER_JOURNALMODE_TRUNCATE || eMode==PAGER_JOURNALMODE_PERSIST || eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ); assert( PAGER_JOURNALMODE_QUERY<0 ); - if( eMode>=0 && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY - || eMode==PAGER_JOURNALMODE_OFF) ){ + if( eMode>=0 + && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY + || eMode==PAGER_JOURNALMODE_OFF) + && !pPager->dbModified + && (!isOpen(pPager->jfd) || 0==pPager->journalOff) + ){ + if( isOpen(pPager->jfd) ){ + sqlite3OsClose(pPager->jfd); + } pPager->journalMode = (u8)eMode; } return (int)pPager->journalMode; } @@ -35210,11 +36558,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** -** $Id: btmutex.c,v 1.15 2009/04/10 12:55:17 danielk1977 Exp $ +** $Id: btmutex.c,v 1.17 2009/07/20 12:33:33 drh Exp $ ** ** This file contains code used to implement mutexes on Btree objects. ** This code really belongs in btree.c. But btree.c is getting too ** big and we want to break it down some. This packaged seemed like ** a good breakout. @@ -35230,11 +36578,11 @@ ** 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. ** ************************************************************************* -** $Id: btreeInt.h,v 1.46 2009/03/20 14:18:52 danielk1977 Exp $ +** $Id: btreeInt.h,v 1.52 2009/07/15 17:25:46 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: @@ -35291,10 +36639,21 @@ ** 24 4 File change counter ** 28 4 Reserved for future use ** 32 4 First freelist page ** 36 4 Number of freelist pages in the file ** 40 60 15 4-byte meta values passed to higher layers +** +** 40 4 Schema cookie +** 44 4 File format of schema layer +** 48 4 Size of page cache +** 52 4 Largest root-page (auto/incr_vacuum) +** 56 4 1=UTF-8 2=UTF16le 3=UTF16be +** 60 4 User version +** 64 4 Incremental vacuum mode +** 68 4 unused +** 72 4 unused +** 76 4 unused ** ** All of the integer values are big-endian (most significant byte first). ** ** The file change counter is incremented when the database is changed ** This counter allows other processes to know when the file has changed @@ -35511,10 +36870,28 @@ ** to the end. EXTRA_SIZE is the number of bytes of space needed to hold ** that extra information. */ #define EXTRA_SIZE sizeof(MemPage) +/* +** A linked list of the following structures is stored at BtShared.pLock. +** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor +** is opened on the table with root page BtShared.iTable. Locks are removed +** from this list when a transaction is committed or rolled back, or when +** a btree handle is closed. +*/ +struct BtLock { + Btree *pBtree; /* Btree handle holding this lock */ + Pgno iTable; /* Root page of table */ + u8 eLock; /* READ_LOCK or WRITE_LOCK */ + BtLock *pNext; /* Next in BtShared.pLock list */ +}; + +/* Candidate values for BtLock.eLock */ +#define READ_LOCK 1 +#define WRITE_LOCK 2 + /* A Btree handle ** ** A database connection contains a pointer to an instance of ** this object for every database file that it has open. This structure ** is opaque to the database connection. The database connection cannot @@ -35542,10 +36919,13 @@ u8 locked; /* True if db currently has pBt locked */ int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ int nBackup; /* Number of backup operations reading this btree */ Btree *pNext; /* List of other sharable Btrees from the same db */ Btree *pPrev; /* Back pointer of the same list */ +#ifndef SQLITE_OMIT_SHARED_CACHE + BtLock lock; /* Object used to lock page 1 */ +#endif }; /* ** Btree.inTrans may take one of the following values. ** @@ -35680,17 +37060,14 @@ u8 atLast; /* Cursor pointing to the last entry */ u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ void *pKey; /* Saved key that was cursor's last known position */ i64 nKey; /* Size of pKey, or last integer key */ - int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */ + int skipNext; /* Prev() is noop if negative. Next() is noop if positive */ #ifndef SQLITE_OMIT_INCRBLOB u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ Pgno *aOverflow; /* Cache of overflow page locations */ -#endif -#ifndef NDEBUG - u8 pagesShuffled; /* True if Btree pages are rearranged by balance()*/ #endif i16 iPage; /* Index of current page in apPage */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ }; @@ -35727,28 +37104,10 @@ /* ** The database page the PENDING_BYTE occupies. This page is never used. */ # define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt) - -/* -** A linked list of the following structures is stored at BtShared.pLock. -** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor -** is opened on the table with root page BtShared.iTable. Locks are removed -** from this list when a transaction is committed or rolled back, or when -** a btree handle is closed. -*/ -struct BtLock { - Btree *pBtree; /* Btree handle holding this lock */ - Pgno iTable; /* Root page of table */ - u8 eLock; /* READ_LOCK or WRITE_LOCK */ - BtLock *pNext; /* Next in BtShared.pLock list */ -}; - -/* Candidate values for BtLock.eLock */ -#define READ_LOCK 1 -#define WRITE_LOCK 2 /* ** These macros define the location of the pointer-map entry for a ** database page. The first argument to each is the number of usable ** bytes on each page of the database (often 1024). The second is the @@ -35847,22 +37206,10 @@ */ #define get2byte(x) ((x)[0]<<8 | (x)[1]) #define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v)) #define get4byte sqlite3Get4byte #define put4byte sqlite3Put4byte - -/* -** Internal routines that should be accessed by the btree layer only. -*/ -SQLITE_PRIVATE int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int); -SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage); -SQLITE_PRIVATE void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*); -SQLITE_PRIVATE void sqlite3BtreeParseCell(MemPage*, int, CellInfo*); -SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur); -SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur); -SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur); -SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur); /************** End of btreeInt.h ********************************************/ /************** Continuing where we left off in btmutex.c ********************/ #ifndef SQLITE_OMIT_SHARED_CACHE #if SQLITE_THREADSAFE @@ -36041,11 +37388,13 @@ if( p && p->sharable ){ p->wantToLock++; if( !p->locked ){ assert( p->wantToLock==1 ); while( p->pPrev ) p = p->pPrev; - while( p->locked && p->pNext ) p = p->pNext; + /* Reason for ALWAYS: There must be at least on unlocked Btree in + ** the chain. Otherwise the !p->locked test above would have failed */ + while( p->locked && ALWAYS(p->pNext) ) p = p->pNext; for(pLater = p->pNext; pLater; pLater=pLater->pNext){ if( pLater->locked ){ unlockBtreeMutex(pLater); } } @@ -36152,12 +37501,16 @@ assert( !p->locked || p->wantToLock>0 ); /* We should already hold a lock on the database connection */ assert( sqlite3_mutex_held(p->db->mutex) ); + /* The Btree is sharable because only sharable Btrees are entered + ** into the array in the first place. */ + assert( p->sharable ); + p->wantToLock++; - if( !p->locked && p->sharable ){ + if( !p->locked ){ lockBtreeMutex(p); } } } @@ -36168,18 +37521,18 @@ int i; for(i=0; i<pArray->nMutex; i++){ Btree *p = pArray->aBtree[i]; /* Some basic sanity checking */ assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt ); - assert( p->locked || !p->sharable ); + assert( p->locked ); assert( p->wantToLock>0 ); /* We should already hold a lock on the database connection */ assert( sqlite3_mutex_held(p->db->mutex) ); p->wantToLock--; - if( p->wantToLock==0 && p->locked ){ + if( p->wantToLock==0 ){ unlockBtreeMutex(p); } } } @@ -36210,11 +37563,11 @@ ** 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. ** ************************************************************************* -** $Id: btree.c,v 1.595 2009/04/11 16:06:15 danielk1977 Exp $ +** $Id: btree.c,v 1.705 2009/08/10 03:57:58 shane Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ @@ -36228,11 +37581,11 @@ /* ** Set this global variable to 1 to enable tracing using the TRACE ** macro. */ #if 0 -int sqlite3BtreeTrace=0; /* True to enable tracing */ +int sqlite3BtreeTrace=1; /* True to enable tracing */ # define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);} #else # define TRACE(X) #endif @@ -36267,15 +37620,10 @@ return SQLITE_OK; } #endif -/* -** Forward declaration -*/ -static int checkForReadConflicts(Btree*, Pgno, BtCursor*, i64); - #ifdef SQLITE_OMIT_SHARED_CACHE /* ** The functions querySharedCacheTableLock(), setSharedCacheTableLock(), ** and clearAllSharedCacheTableLocks() @@ -36286,13 +37634,118 @@ ** So define the lock related functions as no-ops. */ #define querySharedCacheTableLock(a,b,c) SQLITE_OK #define setSharedCacheTableLock(a,b,c) SQLITE_OK #define clearAllSharedCacheTableLocks(a) -#endif - -#ifndef SQLITE_OMIT_SHARED_CACHE + #define downgradeAllSharedCacheTableLocks(a) + #define hasSharedCacheTableLock(a,b,c,d) 1 + #define hasReadConflicts(a, b) 0 +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE + +#ifdef SQLITE_DEBUG +/* +** This function is only used as part of an assert() statement. It checks +** that connection p holds the required locks to read or write to the +** b-tree with root page iRoot. If so, true is returned. Otherwise, false. +** For example, when writing to a table b-tree with root-page iRoot via +** Btree connection pBtree: +** +** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) ); +** +** When writing to an index b-tree that resides in a sharable database, the +** caller should have first obtained a lock specifying the root page of +** the corresponding table b-tree. This makes things a bit more complicated, +** as this module treats each b-tree as a separate structure. To determine +** the table b-tree corresponding to the index b-tree being written, this +** function has to search through the database schema. +** +** Instead of a lock on the b-tree rooted at page iRoot, the caller may +** hold a write-lock on the schema table (root page 1). This is also +** acceptable. +*/ +static int hasSharedCacheTableLock( + Btree *pBtree, /* Handle that must hold lock */ + Pgno iRoot, /* Root page of b-tree */ + int isIndex, /* True if iRoot is the root of an index b-tree */ + int eLockType /* Required lock type (READ_LOCK or WRITE_LOCK) */ +){ + Schema *pSchema = (Schema *)pBtree->pBt->pSchema; + Pgno iTab = 0; + BtLock *pLock; + + /* If this b-tree database is not shareable, or if the client is reading + ** and has the read-uncommitted flag set, then no lock is required. + ** In these cases return true immediately. If the client is reading + ** or writing an index b-tree, but the schema is not loaded, then return + ** true also. In this case the lock is required, but it is too difficult + ** to check if the client actually holds it. This doesn't happen very + ** often. */ + if( (pBtree->sharable==0) + || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted)) + || (isIndex && (!pSchema || (pSchema->flags&DB_SchemaLoaded)==0 )) + ){ + return 1; + } + + /* Figure out the root-page that the lock should be held on. For table + ** b-trees, this is just the root page of the b-tree being read or + ** written. For index b-trees, it is the root page of the associated + ** table. */ + if( isIndex ){ + HashElem *p; + for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ + Index *pIdx = (Index *)sqliteHashData(p); + if( pIdx->tnum==(int)iRoot ){ + iTab = pIdx->pTable->tnum; + } + } + }else{ + iTab = iRoot; + } + + /* Search for the required lock. Either a write-lock on root-page iTab, a + ** write-lock on the schema table, or (if the client is reading) a + ** read-lock on iTab will suffice. Return 1 if any of these are found. */ + for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){ + if( pLock->pBtree==pBtree + && (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1)) + && pLock->eLock>=eLockType + ){ + return 1; + } + } + + /* Failed to find the required lock. */ + return 0; +} + +/* +** This function is also used as part of assert() statements only. It +** returns true if there exist one or more cursors open on the table +** with root page iRoot that do not belong to either connection pBtree +** or some other connection that has the read-uncommitted flag set. +** +** For example, before writing to page iRoot: +** +** assert( !hasReadConflicts(pBtree, iRoot) ); +*/ +static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ + BtCursor *p; + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + if( p->pgnoRoot==iRoot + && p->pBtree!=pBtree + && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted) + ){ + return 1; + } + } + return 0; +} +#endif /* #ifdef SQLITE_DEBUG */ + /* ** Query to see if btree handle p may obtain a lock of type eLock ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return ** SQLITE_OK if the lock may be obtained (by calling ** setSharedCacheTableLock()), or SQLITE_LOCKED if not. @@ -36302,10 +37755,11 @@ BtLock *pIter; assert( sqlite3BtreeHoldsMutex(p) ); assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); assert( p->db!=0 ); + assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 ); /* If requesting a write-lock, then the Btree must have an open write ** transaction on this file. And, obviously, for this to be so there ** must be an open write transaction on the file itself. */ @@ -36323,51 +37777,29 @@ if( pBt->pWriter!=p && pBt->isExclusive ){ sqlite3ConnectionBlocked(p->db, pBt->pWriter->db); return SQLITE_LOCKED_SHAREDCACHE; } - /* This (along with setSharedCacheTableLock()) is where - ** the ReadUncommitted flag is dealt with. - ** If the caller is querying for a read-lock on any table - ** other than the sqlite_master table (table 1) and if the ReadUncommitted - ** flag is set, then the lock granted even if there are write-locks - ** on the table. If a write-lock is requested, the ReadUncommitted flag - ** is not considered. - ** - ** In function setSharedCacheTableLock(), if a read-lock is demanded and the - ** ReadUncommitted flag is set, no entry is added to the locks list - ** (BtShared.pLock). - ** - ** To summarize: If the ReadUncommitted flag is set, then read cursors - ** on non-schema tables do not create or respect table locks. The locking - ** procedure for a write-cursor does not change. - */ - if( - 0==(p->db->flags&SQLITE_ReadUncommitted) || - eLock==WRITE_LOCK || - iTab==MASTER_ROOT - ){ - for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - /* The condition (pIter->eLock!=eLock) in the following if(...) - ** statement is a simplification of: - ** - ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK) - ** - ** since we know that if eLock==WRITE_LOCK, then no other connection - ** may hold a WRITE_LOCK on any table in this file (since there can - ** only be a single writer). - */ - assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK ); - assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK); - if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){ - sqlite3ConnectionBlocked(p->db, pIter->pBtree->db); - if( eLock==WRITE_LOCK ){ - assert( p==pBt->pWriter ); - pBt->isPending = 1; - } - return SQLITE_LOCKED_SHAREDCACHE; - } + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + /* The condition (pIter->eLock!=eLock) in the following if(...) + ** statement is a simplification of: + ** + ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK) + ** + ** since we know that if eLock==WRITE_LOCK, then no other connection + ** may hold a WRITE_LOCK on any table in this file (since there can + ** only be a single writer). + */ + assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK ); + assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK); + if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){ + sqlite3ConnectionBlocked(p->db, pIter->pBtree->db); + if( eLock==WRITE_LOCK ){ + assert( p==pBt->pWriter ); + pBt->isPending = 1; + } + return SQLITE_LOCKED_SHAREDCACHE; } } return SQLITE_OK; } #endif /* !SQLITE_OMIT_SHARED_CACHE */ @@ -36376,12 +37808,21 @@ /* ** Add a lock on the table with root-page iTable to the shared-btree used ** by Btree handle p. Parameter eLock must be either READ_LOCK or ** WRITE_LOCK. ** -** SQLITE_OK is returned if the lock is added successfully. SQLITE_BUSY and -** SQLITE_NOMEM may also be returned. +** This function assumes the following: +** +** (a) The specified b-tree connection handle is connected to a sharable +** b-tree database (one with the BtShared.sharable) flag set, and +** +** (b) No other b-tree connection handle holds a lock that conflicts +** with the requested lock (i.e. querySharedCacheTableLock() has +** already been called and returned SQLITE_OK). +** +** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM +** is returned if a malloc attempt fails. */ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pLock = 0; BtLock *pIter; @@ -36388,30 +37829,20 @@ assert( sqlite3BtreeHoldsMutex(p) ); assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); assert( p->db!=0 ); - /* This is a no-op if the shared-cache is not enabled */ - if( !p->sharable ){ - return SQLITE_OK; - } - - assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) ); - - /* If the read-uncommitted flag is set and a read-lock is requested on - ** a non-schema table, then the lock is always granted. Return early - ** without adding an entry to the BtShared.pLock list. See - ** comment in function querySharedCacheTableLock() for more info - ** on handling the ReadUncommitted flag. - */ - if( - (p->db->flags&SQLITE_ReadUncommitted) && - (eLock==READ_LOCK) && - iTable!=MASTER_ROOT - ){ - return SQLITE_OK; - } + /* A connection with the read-uncommitted flag set will never try to + ** obtain a read-lock using this function. The only read-lock obtained + ** by a connection in read-uncommitted mode is on the sqlite_master + ** table, and that lock is obtained in BtreeBeginTrans(). */ + assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK ); + + /* This function should only be called on a sharable b-tree after it + ** has been determined that no other b-tree holds a conflicting lock. */ + assert( p->sharable ); + assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) ); /* First search the list for an existing lock on this table. */ for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ if( pIter->iTable==iTable && pIter->pBtree==p ){ pLock = pIter; @@ -36467,11 +37898,14 @@ BtLock *pLock = *ppIter; assert( pBt->isExclusive==0 || pBt->pWriter==pLock->pBtree ); assert( pLock->pBtree->inTrans>=pLock->eLock ); if( pLock->pBtree==p ){ *ppIter = pLock->pNext; - sqlite3_free(pLock); + assert( pLock->iTable!=1 || pLock==&p->lock ); + if( pLock->iTable!=1 ){ + sqlite3_free(pLock); + } }else{ ppIter = &pLock->pNext; } } @@ -36491,10 +37925,28 @@ ** be zero already. So this next line is harmless in that case. */ pBt->isPending = 0; } } + +/* +** This function changes all write-locks held by connection p to read-locks. +*/ +static void downgradeAllSharedCacheTableLocks(Btree *p){ + BtShared *pBt = p->pBt; + if( pBt->pWriter==p ){ + BtLock *pLock; + pBt->pWriter = 0; + pBt->isExclusive = 0; + pBt->isPending = 0; + for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ + assert( pLock->eLock==READ_LOCK || pLock->pBtree==p ); + pLock->eLock = READ_LOCK; + } + } +} + #endif /* SQLITE_OMIT_SHARED_CACHE */ static void releasePage(MemPage *pPage); /* Forward reference */ /* @@ -36526,13 +37978,43 @@ assert( sqlite3_mutex_held(pBt->mutex) ); for(p=pBt->pCursor; p; p=p->pNext){ invalidateOverflowCache(p); } } + +/* +** This function is called before modifying the contents of a table +** b-tree to invalidate any incrblob cursors that are open on the +** row or one of the rows being modified. +** +** If argument isClearTable is true, then the entire contents of the +** table is about to be deleted. In this case invalidate all incrblob +** cursors open on any row within the table with root-page pgnoRoot. +** +** Otherwise, if argument isClearTable is false, then the row with +** rowid iRow is being replaced or deleted. In this case invalidate +** only those incrblob cursors open on this specific row. +*/ +static void invalidateIncrblobCursors( + Btree *pBtree, /* The database file to check */ + i64 iRow, /* The rowid that might be changing */ + int isClearTable /* True if all rows are being deleted */ +){ + BtCursor *p; + BtShared *pBt = pBtree->pBt; + assert( sqlite3BtreeHoldsMutex(pBtree) ); + for(p=pBt->pCursor; p; p=p->pNext){ + if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){ + p->eState = CURSOR_INVALID; + } + } +} + #else #define invalidateOverflowCache(x) #define invalidateAllOverflowCache(x) + #define invalidateIncrblobCursors(x,y,z) #endif /* ** Set bit pgno of the BtShared.pHasContent bitvec. This is called ** when a page that previously contained data becomes a free-list leaf @@ -36569,17 +38051,17 @@ ** at the end of every transaction. */ static int btreeSetHasContent(BtShared *pBt, Pgno pgno){ int rc = SQLITE_OK; if( !pBt->pHasContent ){ - int nPage; - rc = sqlite3PagerPagecount(pBt->pPager, &nPage); - if( rc==SQLITE_OK ){ - pBt->pHasContent = sqlite3BitvecCreate((u32)nPage); - if( !pBt->pHasContent ){ - rc = SQLITE_NOMEM; - } + int nPage = 100; + sqlite3PagerPagecount(pBt->pPager, &nPage); + /* If sqlite3PagerPagecount() fails there is no harm because the + ** nPage variable is unchanged from its default value of 100 */ + pBt->pHasContent = sqlite3BitvecCreate((u32)nPage); + if( !pBt->pHasContent ){ + rc = SQLITE_NOMEM; } } if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){ rc = sqlite3BitvecSet(pBt->pHasContent, pgno); } @@ -36608,27 +38090,31 @@ } /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. +** +** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) +** prior to calling this routine. */ static int saveCursorPosition(BtCursor *pCur){ int rc; assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); + assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ /* If this is an intKey table, then the above call to BtreeKeySize() ** stores the integer key in pCur->nKey. In this case this value is ** all that is required. Otherwise, if pCur is not open on an intKey ** table, then malloc space for and store the pCur->nKey bytes of key ** data. */ - if( rc==SQLITE_OK && 0==pCur->apPage[0]->intKey){ + if( 0==pCur->apPage[0]->intKey ){ void *pKey = sqlite3Malloc( (int)pCur->nKey ); if( pKey ){ rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); if( rc==SQLITE_OK ){ pCur->pKey = pKey; @@ -36685,25 +38171,56 @@ pCur->pKey = 0; pCur->eState = CURSOR_INVALID; } /* +** In this version of BtreeMoveto, pKey is a packed index record +** such as is generated by the OP_MakeRecord opcode. Unpack the +** record and then call BtreeMovetoUnpacked() to do the work. +*/ +static int btreeMoveto( + BtCursor *pCur, /* Cursor open on the btree to be searched */ + const void *pKey, /* Packed key if the btree is an index */ + i64 nKey, /* Integer key for tables. Size of pKey for indices */ + int bias, /* Bias search to the high end */ + int *pRes /* Write search results here */ +){ + int rc; /* Status code */ + UnpackedRecord *pIdxKey; /* Unpacked index key */ + char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */ + + if( pKey ){ + assert( nKey==(i64)(int)nKey ); + pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, + aSpace, sizeof(aSpace)); + if( pIdxKey==0 ) return SQLITE_NOMEM; + }else{ + pIdxKey = 0; + } + rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); + if( pKey ){ + sqlite3VdbeDeleteUnpackedRecord(pIdxKey); + } + return rc; +} + +/* ** Restore the cursor to the position it was in (or as close to as possible) ** when saveCursorPosition() was called. Note that this call deletes the ** saved position info stored by saveCursorPosition(), so there can be ** at most one effective restoreCursorPosition() call after each ** saveCursorPosition(). */ -SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){ +static int btreeRestoreCursorPosition(BtCursor *pCur){ int rc; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ - return pCur->skip; + return pCur->skipNext; } pCur->eState = CURSOR_INVALID; - rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); } @@ -36710,11 +38227,11 @@ return rc; } #define restoreCursorPosition(p) \ (p->eState>=CURSOR_REQUIRESEEK ? \ - sqlite3BtreeRestoreCursorPosition(p) : \ + btreeRestoreCursorPosition(p) : \ 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 @@ -36729,11 +38246,11 @@ rc = restoreCursorPosition(pCur); if( rc ){ *pHasMoved = 1; return rc; } - if( pCur->eState!=CURSOR_VALID || pCur->skip!=0 ){ + if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){ *pHasMoved = 1; }else{ *pHasMoved = 0; } return SQLITE_OK; @@ -36761,46 +38278,57 @@ /* ** Write an entry into the pointer map. ** ** This routine updates the pointer map entry for page number 'key' ** so that it maps to type 'eType' and parent page number 'pgno'. -** An error code is returned if something goes wrong, otherwise SQLITE_OK. -*/ -static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ +** +** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is +** a no-op. If an error occurs, the appropriate error code is written +** into *pRC. +*/ +static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ DbPage *pDbPage; /* The pointer map page */ u8 *pPtrmap; /* The pointer map data */ Pgno iPtrmap; /* The pointer map page number */ int offset; /* Offset in pointer map page */ - int rc; + int rc; /* Return code from subfunctions */ + + if( *pRC ) return; assert( sqlite3_mutex_held(pBt->mutex) ); /* The master-journal page number must never be used as a pointer map page */ assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); assert( pBt->autoVacuum ); if( key==0 ){ - return SQLITE_CORRUPT_BKPT; + *pRC = SQLITE_CORRUPT_BKPT; + return; } iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); if( rc!=SQLITE_OK ){ - return rc; + *pRC = rc; + return; } offset = PTRMAP_PTROFFSET(iPtrmap, key); + if( offset<0 ){ + *pRC = SQLITE_CORRUPT_BKPT; + goto ptrmap_exit; + } pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); - rc = sqlite3PagerWrite(pDbPage); + *pRC= rc = sqlite3PagerWrite(pDbPage); if( rc==SQLITE_OK ){ pPtrmap[offset] = eType; put4byte(&pPtrmap[offset+1], parent); } } - sqlite3PagerUnref(pDbPage); - return rc; +ptrmap_exit: + sqlite3PagerUnref(pDbPage); } /* ** Read an entry from the pointer map. ** @@ -36833,13 +38361,13 @@ if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; return SQLITE_OK; } #else /* if defined SQLITE_OMIT_AUTOVACUUM */ - #define ptrmapPut(w,x,y,z) SQLITE_OK + #define ptrmapPut(w,x,y,z,rc) #define ptrmapGet(w,x,y,z) SQLITE_OK - #define ptrmapPutOvfl(y,z) SQLITE_OK + #define ptrmapPutOvflPtr(x, y, rc) #endif /* ** Given a btree page and a cell index (0 means the first cell on ** the page, 1 means the second cell, and so forth) return a pointer @@ -36850,11 +38378,11 @@ #define findCell(P,I) \ ((P)->aData + ((P)->maskPage & get2byte(&(P)->aData[(P)->cellOffset+2*(I)]))) /* ** This a more complex version of findCell() that works for -** pages that do contain overflow cells. See insert +** pages that do contain overflow cells. */ static u8 *findOverflowCell(MemPage *pPage, int iCell){ int i; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); for(i=pPage->nOverflow-1; i>=0; i--){ @@ -36872,18 +38400,18 @@ return findCell(pPage, iCell); } /* ** Parse a cell content block and fill in the CellInfo structure. There -** are two versions of this function. sqlite3BtreeParseCell() takes a -** cell index as the second argument and sqlite3BtreeParseCellPtr() +** are two versions of this function. btreeParseCell() takes a +** cell index as the second argument and btreeParseCellPtr() ** takes a pointer to the body of the cell as its second argument. ** ** Within this file, the parseCell() macro can be called instead of -** sqlite3BtreeParseCellPtr(). Using some compilers, this will be faster. -*/ -SQLITE_PRIVATE void sqlite3BtreeParseCellPtr( +** btreeParseCellPtr(). Using some compilers, this will be faster. +*/ +static void btreeParseCellPtr( MemPage *pPage, /* Page containing the cell */ u8 *pCell, /* Pointer to the cell text. */ CellInfo *pInfo /* Fill in this structure */ ){ u16 n; /* Number bytes in cell content header */ @@ -36908,10 +38436,12 @@ n += getVarint32(&pCell[n], nPayload); pInfo->nKey = nPayload; } pInfo->nPayload = nPayload; pInfo->nHeader = n; + testcase( nPayload==pPage->maxLocal ); + testcase( nPayload==pPage->maxLocal+1 ); if( likely(nPayload<=pPage->maxLocal) ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. */ int nSize; /* Total size of cell content in bytes */ @@ -36937,10 +38467,12 @@ int surplus; /* Overflow payload available for local storage */ minLocal = pPage->minLocal; maxLocal = pPage->maxLocal; surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4); + testcase( surplus==maxLocal ); + testcase( surplus==maxLocal+1 ); if( surplus <= maxLocal ){ pInfo->nLocal = (u16)surplus; }else{ pInfo->nLocal = (u16)minLocal; } @@ -36947,12 +38479,12 @@ pInfo->iOverflow = (u16)(pInfo->nLocal + n); pInfo->nSize = pInfo->iOverflow + 4; } } #define parseCell(pPage, iCell, pInfo) \ - sqlite3BtreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) -SQLITE_PRIVATE void sqlite3BtreeParseCell( + btreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) +static void btreeParseCell( MemPage *pPage, /* Page containing the cell */ int iCell, /* The cell index. First cell is 0 */ CellInfo *pInfo /* Fill in this structure */ ){ parseCell(pPage, iCell, pInfo); @@ -36962,50 +38494,84 @@ ** Compute the total number of bytes that a Cell needs in the cell ** data area of the btree-page. The return number includes the cell ** data header and the local payload, but not any overflow page or ** the space used by the cell pointer. */ -#ifndef NDEBUG -static u16 cellSize(MemPage *pPage, int iCell){ - CellInfo info; - sqlite3BtreeParseCell(pPage, iCell, &info); - return info.nSize; -} -#endif static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ - CellInfo info; - sqlite3BtreeParseCellPtr(pPage, pCell, &info); - return info.nSize; -} + u8 *pIter = &pCell[pPage->childPtrSize]; + u32 nSize; + +#ifdef SQLITE_DEBUG + /* The value returned by this function should always be the same as + ** the (CellInfo.nSize) value found by doing a full parse of the + ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of + ** this function verifies that this invariant is not violated. */ + CellInfo debuginfo; + btreeParseCellPtr(pPage, pCell, &debuginfo); +#endif + + if( pPage->intKey ){ + u8 *pEnd; + if( pPage->hasData ){ + pIter += getVarint32(pIter, nSize); + }else{ + nSize = 0; + } + + /* pIter now points at the 64-bit integer key value, a variable length + ** integer. The following block moves pIter to point at the first byte + ** past the end of the key value. */ + pEnd = &pIter[9]; + while( (*pIter++)&0x80 && pIter<pEnd ); + }else{ + pIter += getVarint32(pIter, nSize); + } + + testcase( nSize==pPage->maxLocal ); + testcase( nSize==pPage->maxLocal+1 ); + if( nSize>pPage->maxLocal ){ + int minLocal = pPage->minLocal; + nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); + testcase( nSize==pPage->maxLocal ); + testcase( nSize==pPage->maxLocal+1 ); + if( nSize>pPage->maxLocal ){ + nSize = minLocal; + } + nSize += 4; + } + nSize += (u32)(pIter - pCell); + + /* The minimum size of any cell is 4 bytes. */ + if( nSize<4 ){ + nSize = 4; + } + + assert( nSize==debuginfo.nSize ); + return (u16)nSize; +} +#ifndef NDEBUG +static u16 cellSize(MemPage *pPage, int iCell){ + return cellSizePtr(pPage, findCell(pPage, iCell)); +} +#endif #ifndef SQLITE_OMIT_AUTOVACUUM /* ** If the cell pCell, part of page pPage contains a pointer ** to an overflow page, insert an entry into the pointer-map ** for the overflow page. */ -static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){ +static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){ CellInfo info; + if( *pRC ) return; assert( pCell!=0 ); - sqlite3BtreeParseCellPtr(pPage, pCell, &info); + btreeParseCellPtr(pPage, pCell, &info); assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); - if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ + if( info.iOverflow ){ Pgno ovfl = get4byte(&pCell[info.iOverflow]); - return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno); - } - return SQLITE_OK; -} -/* -** If the cell with index iCell on page pPage contains a pointer -** to an overflow page, insert an entry into the pointer-map -** for the overflow page. -*/ -static int ptrmapPutOvfl(MemPage *pPage, int iCell){ - u8 *pCell; - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pCell = findOverflowCell(pPage, iCell); - return ptrmapPutOvflPtr(pPage, pCell); + ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC); + } } #endif /* @@ -37015,19 +38581,21 @@ ** pointer array and the cell content area. */ static int defragmentPage(MemPage *pPage){ int i; /* Loop counter */ int pc; /* Address of a i-th cell */ - int addr; /* Offset of first byte after cell pointer array */ int hdr; /* Offset to the page header */ int size; /* Size of a cell */ int usableSize; /* Number of usable bytes on a page */ int cellOffset; /* Offset to the cell pointer array */ int cbrk; /* Offset to the cell content area */ int nCell; /* Number of cells on the page */ unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ + int iCellFirst; /* First allowable cell index */ + int iCellLast; /* Last possible cell index */ + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); @@ -37040,110 +38608,151 @@ assert( nCell==get2byte(&data[hdr+3]) ); usableSize = pPage->pBt->usableSize; cbrk = get2byte(&data[hdr+5]); memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk); cbrk = usableSize; + iCellFirst = cellOffset + 2*nCell; + iCellLast = usableSize - 4; for(i=0; i<nCell; i++){ u8 *pAddr; /* The i-th cell pointer */ pAddr = &data[cellOffset + i*2]; pc = get2byte(pAddr); - if( pc>=usableSize ){ - return SQLITE_CORRUPT_BKPT; - } + testcase( pc==iCellFirst ); + testcase( pc==iCellLast ); +#if !defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) + /* These conditions have already been verified in btreeInitPage() + ** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined + */ + if( pc<iCellFirst || pc>iCellLast ){ + return SQLITE_CORRUPT_BKPT; + } +#endif + assert( pc>=iCellFirst && pc<=iCellLast ); size = cellSizePtr(pPage, &temp[pc]); cbrk -= size; - if( cbrk<cellOffset+2*nCell || pc+size>usableSize ){ +#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) + if( cbrk<iCellFirst ){ + return SQLITE_CORRUPT_BKPT; + } +#else + if( cbrk<iCellFirst || pc+size>usableSize ){ return SQLITE_CORRUPT_BKPT; } - assert( cbrk+size<=usableSize && cbrk>=0 ); +#endif + assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); + testcase( cbrk+size==usableSize ); + testcase( pc+size==usableSize ); memcpy(&data[cbrk], &temp[pc], size); put2byte(pAddr, cbrk); } - assert( cbrk>=cellOffset+2*nCell ); + assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); data[hdr+1] = 0; data[hdr+2] = 0; data[hdr+7] = 0; - addr = cellOffset+2*nCell; - memset(&data[addr], 0, cbrk-addr); + memset(&data[iCellFirst], 0, cbrk-iCellFirst); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - if( cbrk-addr!=pPage->nFree ){ + if( cbrk-iCellFirst!=pPage->nFree ){ return SQLITE_CORRUPT_BKPT; } return SQLITE_OK; } /* ** Allocate nByte bytes of space from within the B-Tree page passed -** as the first argument. Return the index into pPage->aData[] of the -** first byte of allocated space. -** -** The caller guarantees that the space between the end of the cell-offset -** array and the start of the cell-content area is at least nByte bytes -** in size. So this routine can never fail. -** -** If there are already 60 or more bytes of fragments within the page, -** the page is defragmented before returning. If this were not done there -** is a chance that the number of fragmented bytes could eventually -** overflow the single-byte field of the page-header in which this value -** is stored. -*/ -static int allocateSpace(MemPage *pPage, int nByte){ +** as the first argument. Write into *pIdx the index into pPage->aData[] +** of the first byte of allocated space. Return either SQLITE_OK or +** an error code (usually SQLITE_CORRUPT). +** +** The caller guarantees that there is sufficient space to make the +** allocation. This routine might need to defragment in order to bring +** all the space together, however. This routine will avoid using +** the first two bytes past the cell pointer area since presumably this +** allocation is being made in order to insert a new cell, so we will +** also end up needing a new cell pointer. +*/ +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; + 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 */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( nByte>=0 ); /* Minimum cell size is 4 */ assert( pPage->nFree>=nByte ); assert( pPage->nOverflow==0 ); - - /* Assert that the space between the cell-offset array and the - ** cell-content area is greater than nByte bytes. - */ - assert( nByte <= ( - get2byte(&data[hdr+5])-(hdr+8+(pPage->leaf?0:4)+2*get2byte(&data[hdr+3])) - )); - - pPage->nFree -= (u16)nByte; + assert( nByte<pPage->pBt->usableSize-8 ); + nFrag = data[hdr+7]; + assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); + gap = pPage->cellOffset + 2*pPage->nCell; + top = get2byte(&data[hdr+5]); + if( gap>top ) return SQLITE_CORRUPT_BKPT; + testcase( gap+2==top ); + testcase( gap+1==top ); + testcase( gap==top ); + if( nFrag>=60 ){ - defragmentPage(pPage); - }else{ + /* Always defragment highly fragmented pages */ + rc = defragmentPage(pPage); + if( rc ) return rc; + top = get2byte(&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 accomadate it. */ int pc, addr; for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ int size = get2byte(&data[pc+2]); /* Size of free slot */ if( size>=nByte ){ int x = size - nByte; + testcase( x==4 ); + testcase( x==3 ); if( x<4 ){ - /* Remove the slot from the free-list. Update the number of - ** fragmented bytes within the page. */ + /* 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); }else{ - /* The slot remains on the free-list. Reduce its size to account - ** for the portion used by the new allocation. */ + /* The slot remains on the free-list. Reduce its size to account + ** for the portion used by the new allocation. */ put2byte(&data[pc+2], x); } - return pc + x; - } - } - } + *pIdx = pc + x; + return SQLITE_OK; + } + } + } + + /* Check to make sure there is enough space in the gap to satisfy + ** the allocation. If not, defragment. + */ + testcase( gap+2+nByte==top ); + if( gap+2+nByte>top ){ + rc = defragmentPage(pPage); + if( rc ) return rc; + top = get2byte(&data[hdr+5]); + assert( gap+nByte<=top ); + } + /* Allocate memory from the gap in between the cell pointer array - ** and the cell content area. - */ - top = get2byte(&data[hdr+5]) - nByte; + ** and the cell content area. The btreeInitPage() call has already + ** validated the freelist. Given that the freelist is valid, there + ** is no way that the allocation can extend off the end of the page. + ** The assert() below verifies the previous sentence. + */ + top -= nByte; put2byte(&data[hdr+5], top); - return top; + assert( top+nByte <= pPage->pBt->usableSize ); + *pIdx = top; + return SQLITE_OK; } /* ** Return a section of the pPage->aData to the freelist. ** The first byte of the new free block is pPage->aDisk[start] @@ -37152,15 +38761,16 @@ ** 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; assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); + assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); assert( (start + size)<=pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( size>=0 ); /* Minimum cell size is 4 */ #ifdef SQLITE_SECURE_DELETE @@ -37167,43 +38777,52 @@ /* Overwrite deleted information with zeros when the SECURE_DELETE ** option is enabled at compile-time */ memset(&data[start], 0, size); #endif - /* Add the space back into the linked list of freeblocks */ + /* 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. + */ hdr = pPage->hdrOffset; addr = hdr + 1; + iLast = pPage->pBt->usableSize - 4; + assert( start<=iLast ); while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){ - assert( pbegin<=pPage->pBt->usableSize-4 ); - if( pbegin<=addr ) { + if( pbegin<addr+4 ){ return SQLITE_CORRUPT_BKPT; } addr = pbegin; } - if ( pbegin>pPage->pBt->usableSize-4 ) { + if( pbegin>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 += (u16)size; + pPage->nFree = pPage->nFree + (u16)size; /* Coalesce adjacent free blocks */ - addr = pPage->hdrOffset + 1; + addr = hdr + 1; while( (pbegin = get2byte(&data[addr]))>0 ){ int pnext, psize, x; assert( pbegin>addr ); assert( pbegin<=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[pPage->hdrOffset+7]) ){ + if( (frag<0) || (frag>(int)data[hdr+7]) ){ return SQLITE_CORRUPT_BKPT; } - data[pPage->hdrOffset+7] -= (u8)frag; + 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); }else{ @@ -37267,11 +38886,11 @@ ** not contain a well-formed database page, then return ** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not ** guarantee that the page is well-formed. It only shows that ** we failed to detect any corruption. */ -SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage){ +static int btreeInitPage(MemPage *pPage){ assert( pPage->pBt!=0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); @@ -37284,10 +38903,12 @@ BtShared *pBt; /* The main btree structure */ u16 usableSize; /* Amount of usable space on each page */ u16 cellOffset; /* Offset from start of page to first cell pointer */ u16 nFree; /* Number of unused bytes on the page */ u16 top; /* First byte of the cell content area */ + int iCellFirst; /* First allowable cell or freeblock offset */ + int iCellLast; /* Last possible cell or freeblock offset */ pBt = pPage->pBt; hdr = pPage->hdrOffset; data = pPage->aData; @@ -37301,55 +38922,75 @@ pPage->nCell = get2byte(&data[hdr+3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ return SQLITE_CORRUPT_BKPT; } + testcase( pPage->nCell==MX_CELL(pBt) ); + + /* A malformed database page might cause us to read past the end + ** of page when parsing a cell. + ** + ** The following block of code checks early to see if a cell extends + ** past the end of a page boundary and causes SQLITE_CORRUPT to be + ** returned if it does. + */ + iCellFirst = cellOffset + 2*pPage->nCell; + iCellLast = usableSize - 4; +#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) + { + int i; /* Index into the cell pointer array */ + int sz; /* Size of a cell */ + + if( !pPage->leaf ) iCellLast--; + for(i=0; i<pPage->nCell; i++){ + pc = get2byte(&data[cellOffset+i*2]); + testcase( pc==iCellFirst ); + testcase( pc==iCellLast ); + if( pc<iCellFirst || pc>iCellLast ){ + return SQLITE_CORRUPT_BKPT; + } + sz = cellSizePtr(pPage, &data[pc]); + testcase( pc+sz==usableSize ); + if( pc+sz>usableSize ){ + return SQLITE_CORRUPT_BKPT; + } + } + if( !pPage->leaf ) iCellLast++; + } +#endif /* Compute the total free space on the page */ pc = get2byte(&data[hdr+1]); - nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell); + nFree = data[hdr+7] + top; while( pc>0 ){ u16 next, size; - if( pc>usableSize-4 ){ - /* Free block is off the page */ + if( pc<iCellFirst || pc>iCellLast ){ + /* Start of free block is off the page */ return SQLITE_CORRUPT_BKPT; } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); - if( next>0 && next<=pc+size+3 ){ - /* Free blocks must be in accending order */ + if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){ + /* Free blocks must be in ascending order. And the last byte of + ** the free-block must lie on the database page. */ return SQLITE_CORRUPT_BKPT; } - nFree += size; + nFree = nFree + size; pc = next; } - pPage->nFree = (u16)nFree; - if( nFree>=usableSize ){ - /* Free space cannot exceed total page size */ + + /* At this point, nFree contains the sum of the offset to the start + ** of the cell-content area plus the number of free bytes within + ** the cell-content area. If this is greater than the usable-size + ** of the page, then the page must be corrupted. This check also + ** serves to verify that the offset to the start of the cell-content + ** area, according to the page header, lies within the page. + */ + if( nFree>usableSize ){ return SQLITE_CORRUPT_BKPT; } - -#if 0 - /* Check that all the offsets in the cell offset array are within range. - ** - ** Omitting this consistency check and using the pPage->maskPage mask - ** to prevent overrunning the page buffer in findCell() results in a - ** 2.5% performance gain. - */ - { - u8 *pOff; /* Iterator used to check all cell offsets are in range */ - u8 *pEnd; /* Pointer to end of cell offset array */ - u8 mask; /* Mask of bits that must be zero in MSB of cell offsets */ - mask = ~(((u8)(pBt->pageSize>>8))-1); - pEnd = &data[cellOffset + pPage->nCell*2]; - for(pOff=&data[cellOffset]; pOff!=pEnd && !((*pOff)&mask); pOff+=2); - if( pOff!=pEnd ){ - return SQLITE_CORRUPT_BKPT; - } - } -#endif - + pPage->nFree = (u16)(nFree - iCellFirst); pPage->isInit = 1; } return SQLITE_OK; } @@ -37409,11 +39050,11 @@ ** to fetch the content. Just fill in the content with zeros for now. ** If in the future we call sqlite3PagerWrite() on this page, that ** means we have started to be concerned about content and the disk ** read should occur at that point. */ -SQLITE_PRIVATE int sqlite3BtreeGetPage( +static int btreeGetPage( BtShared *pBt, /* The btree */ Pgno pgno, /* Number of the page to fetch */ MemPage **ppPage, /* Return the page in this parameter */ int noContent /* Do not load page content if true */ ){ @@ -37454,58 +39095,48 @@ assert( rc==SQLITE_OK || nPage==-1 ); return (Pgno)nPage; } /* -** Get a page from the pager and initialize it. This routine -** is just a convenience wrapper around separate calls to -** sqlite3BtreeGetPage() and sqlite3BtreeInitPage(). +** Get a page from the pager and initialize it. This routine is just a +** convenience wrapper around separate calls to btreeGetPage() and +** btreeInitPage(). +** +** If an error occurs, then the value *ppPage is set to is undefined. It +** may remain unchanged, or it may be set to an invalid value. */ static int getAndInitPage( BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage /* Write the page pointer here */ ){ int rc; - MemPage *pPage; - - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pgno==0 ){ - return SQLITE_CORRUPT_BKPT; - } - - /* It is often the case that the page we want is already in cache. - ** If so, get it directly. This saves us from having to call - ** pagerPagecount() to make sure pgno is within limits, which results - ** in a measureable performance improvements. - */ - *ppPage = pPage = btreePageLookup(pBt, pgno); - if( pPage ){ - /* Page is already in cache */ - rc = SQLITE_OK; - }else{ - /* Page not in cache. Acquire it. */ - if( pgno>pagerPagecount(pBt) ){ - return SQLITE_CORRUPT_BKPT; - } - rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); - if( rc ) return rc; - pPage = *ppPage; - } - if( !pPage->isInit ){ - rc = sqlite3BtreeInitPage(pPage); - } - if( rc!=SQLITE_OK ){ - releasePage(pPage); - *ppPage = 0; - } + TESTONLY( Pgno iLastPg = pagerPagecount(pBt); ) + assert( sqlite3_mutex_held(pBt->mutex) ); + + rc = btreeGetPage(pBt, pgno, ppPage, 0); + if( rc==SQLITE_OK ){ + rc = btreeInitPage(*ppPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } + } + + /* If the requested page number was either 0 or greater than the page + ** number of the last page in the database, this function should return + ** SQLITE_CORRUPT or some other error (i.e. SQLITE_FULL). Check that this + ** is the case. */ + assert( (pgno>0 && pgno<=iLastPg) || rc!=SQLITE_OK ); + testcase( pgno==0 ); + testcase( pgno==iLastPg ); + return rc; } /* ** Release a MemPage. This should be called once for each prior -** call to sqlite3BtreeGetPage. +** call to btreeGetPage. */ static void releasePage(MemPage *pPage){ if( pPage ){ assert( pPage->nOverflow==0 || sqlite3PagerPageRefcount(pPage->pDbPage)>1 ); assert( pPage->aData ); @@ -37533,15 +39164,15 @@ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pPage->isInit = 0; if( sqlite3PagerPageRefcount(pData)>1 ){ /* pPage might not be a btree page; it might be an overflow page ** or ptrmap page or a free page. In those cases, the following - ** call to sqlite3BtreeInitPage() will likely return SQLITE_CORRUPT. + ** call to btreeInitPage() will likely return SQLITE_CORRUPT. ** But no harm is done by this. And it is very important that - ** sqlite3BtreeInitPage() be called on every btree page so we make + ** btreeInitPage() be called on every btree page so we make ** the call for every page that comes in for re-initing. */ - sqlite3BtreeInitPage(pPage); + btreeInitPage(pPage); } } } /* @@ -37560,10 +39191,16 @@ ** zFilename is the name of the database file. If zFilename is NULL ** a new database with a random name is created. This randomly named ** database file will be deleted when sqlite3BtreeClose() is called. ** If zFilename is ":memory:" then an in-memory database is created ** that is automatically destroyed when it is closed. +** +** If the database is already opened in the same database connection +** and we are in shared cache mode, then the open will fail with an +** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared +** objects in the same database connection since doing so will lead +** to problems with locking. */ SQLITE_PRIVATE int sqlite3BtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ sqlite3 *db, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ @@ -37599,23 +39236,26 @@ if( !p ){ return SQLITE_NOMEM; } p->inTrans = TRANS_NONE; p->db = db; +#ifndef SQLITE_OMIT_SHARED_CACHE + p->lock.pBtree = p; + p->lock.iTable = 1; +#endif #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) /* ** If this Btree is a candidate for shared cache, try to find an ** existing BtShared object that we can share with */ if( isMemdb==0 && zFilename && zFilename[0] ){ - if( sqlite3GlobalConfig.sharedCacheEnabled ){ + if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ int nFullPathname = pVfs->mxPathname+1; char *zFullPathname = sqlite3Malloc(nFullPathname); sqlite3_mutex *mutexShared; p->sharable = 1; - db->flags |= SQLITE_SharedCache; if( !zFullPathname ){ sqlite3_free(p); return SQLITE_NOMEM; } sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); @@ -37625,10 +39265,21 @@ sqlite3_mutex_enter(mutexShared); for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) && sqlite3PagerVfs(pBt->pPager)==pVfs ){ + int iDb; + for(iDb=db->nDb-1; iDb>=0; iDb--){ + Btree *pExisting = db->aDb[iDb].pBt; + if( pExisting && pExisting->pBt==pBt ){ + sqlite3_mutex_leave(mutexShared); + sqlite3_mutex_leave(mutexOpen); + sqlite3_free(zFullPathname); + sqlite3_free(p); + return SQLITE_CONSTRAINT; + } + } p->pBt = pBt; pBt->nRef++; break; } } @@ -37663,11 +39314,11 @@ if( pBt==0 ){ rc = SQLITE_NOMEM; goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, - EXTRA_SIZE, flags, vfsFlags); + EXTRA_SIZE, flags, vfsFlags, pageReinit); if( rc==SQLITE_OK ){ rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); } if( rc!=SQLITE_OK ){ goto btree_open_out; @@ -37674,19 +39325,17 @@ } pBt->db = db; sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); p->pBt = pBt; - sqlite3PagerSetReiniter(pBt->pPager, pageReinit); pBt->pCursor = 0; pBt->pPage1 = 0; pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); pBt->pageSize = get2byte(&zDbHeader[16]); if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ pBt->pageSize = 0; - sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); #ifndef SQLITE_OMIT_AUTOVACUUM /* If the magic name ":memory:" will create an in-memory database, then ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a @@ -37704,13 +39353,14 @@ #ifndef SQLITE_OMIT_AUTOVACUUM pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0); #endif } + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); + if( rc ) goto btree_open_out; pBt->usableSize = pBt->pageSize - nReserve; assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ - sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) /* Add the new BtShared object to the linked list sharable BtShareds. */ if( p->sharable ){ @@ -37994,12 +39644,12 @@ ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); assert( !pBt->pPage1 && !pBt->pCursor ); pBt->pageSize = (u16)pageSize; freeTempSpace(pBt); - rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); - } + } + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); pBt->usableSize = pBt->pageSize - (u16)nReserve; if( iFix ) pBt->pageSizeFixed = 1; sqlite3BtreeLeave(p); return rc; } @@ -38099,11 +39749,13 @@ MemPage *pPage1; int nPage; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pBt->pPage1==0 ); - rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); + rc = sqlite3PagerSharedLock(pBt->pPager); + if( rc!=SQLITE_OK ) return rc; + rc = btreeGetPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; /* Do some checking to help insure the file we opened really is ** a valid database file. */ @@ -38150,14 +39802,15 @@ */ releasePage(pPage1); pBt->usableSize = (u16)usableSize; pBt->pageSize = (u16)pageSize; freeTempSpace(pBt); - sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); - return SQLITE_OK; - } - if( usableSize<500 ){ + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, + pageSize-usableSize); + return rc; + } + if( usableSize<480 ){ goto page1_init_failed; } pBt->pageSize = (u16)pageSize; pBt->usableSize = (u16)usableSize; #ifndef SQLITE_OMIT_AUTOVACUUM @@ -38192,74 +39845,46 @@ pBt->pPage1 = 0; return rc; } /* -** This routine works like lockBtree() except that it also invokes the -** busy callback if there is lock contention. -*/ -static int lockBtreeWithRetry(Btree *pRef){ - int rc = SQLITE_OK; - - assert( sqlite3BtreeHoldsMutex(pRef) ); - if( pRef->inTrans==TRANS_NONE ){ - u8 inTransaction = pRef->pBt->inTransaction; - btreeIntegrity(pRef); - rc = sqlite3BtreeBeginTrans(pRef, 0); - pRef->pBt->inTransaction = inTransaction; - pRef->inTrans = TRANS_NONE; - if( rc==SQLITE_OK ){ - pRef->pBt->nTransaction--; - } - btreeIntegrity(pRef); - } - return rc; -} - - -/* ** If there are no outstanding cursors and we are not in the middle ** of a transaction but there is a read lock on the database, then ** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock. ** -** If there are any outstanding cursors, this routine is a no-op. -** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ assert( sqlite3_mutex_held(pBt->mutex) ); - if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ - if( sqlite3PagerRefcount(pBt->pPager)>=1 ){ - assert( pBt->pPage1->aData ); -#if 0 - if( pBt->pPage1->aData==0 ){ - MemPage *pPage = pBt->pPage1; - pPage->aData = sqlite3PagerGetData(pPage->pDbPage); - pPage->pBt = pBt; - pPage->pgno = 1; - } -#endif - releasePage(pBt->pPage1); - } + assert( pBt->pCursor==0 || pBt->inTransaction>TRANS_NONE ); + if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ + assert( pBt->pPage1->aData ); + assert( sqlite3PagerRefcount(pBt->pPager)==1 ); + assert( pBt->pPage1->aData ); + releasePage(pBt->pPage1); pBt->pPage1 = 0; } } /* -** Create a new database by initializing the first page of the -** file. +** If pBt points to an empty file then convert that empty file +** into a new empty database by initializing the first page of +** the database. */ static int newDatabase(BtShared *pBt){ MemPage *pP1; unsigned char *data; int rc; int nPage; assert( sqlite3_mutex_held(pBt->mutex) ); + /* The database size has already been measured and cached, so failure + ** is impossible here. If the original size measurement failed, then + ** processing aborts before entering this routine. */ rc = sqlite3PagerPagecount(pBt->pPager, &nPage); - if( rc!=SQLITE_OK || nPage>0 ){ + if( NEVER(rc!=SQLITE_OK) || nPage>0 ){ return rc; } pP1 = pBt->pPage1; assert( pP1!=0 ); data = pP1->aData; @@ -38365,10 +39990,16 @@ rc = SQLITE_LOCKED_SHAREDCACHE; goto trans_begun; } #endif + /* Any read-only or read-write transaction implies a read-lock on + ** page 1. So if some other shared-cache client already has a write-lock + ** on page 1, the transaction cannot be opened. */ + rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); + if( SQLITE_OK!=rc ) goto trans_begun; + do { /* Call lockBtree() until either pBt->pPage1 is populated or ** lockBtree() returns something other than SQLITE_OK. lockBtree() ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after ** reading page 1 it discovers that the page-size of the database @@ -38379,11 +40010,11 @@ if( rc==SQLITE_OK && wrflag ){ if( pBt->readOnly ){ rc = SQLITE_READONLY; }else{ - rc = sqlite3PagerBegin(pBt->pPager, wrflag>1); + rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); } } } @@ -38395,10 +40026,18 @@ btreeInvokeBusyHandler(pBt) ); if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ pBt->nTransaction++; +#ifndef SQLITE_OMIT_SHARED_CACHE + if( p->sharable ){ + assert( p->lock.pBtree==p && p->lock.iTable==1 ); + p->lock.eLock = READ_LOCK; + p->lock.pNext = pBt->pLock; + pBt->pLock = &p->lock; + } +#endif } p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); if( p->inTrans>pBt->inTransaction ){ pBt->inTransaction = p->inTrans; } @@ -38440,46 +40079,41 @@ BtShared *pBt = pPage->pBt; u8 isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - rc = sqlite3BtreeInitPage(pPage); + rc = btreeInitPage(pPage); if( rc!=SQLITE_OK ){ goto set_child_ptrmaps_out; } nCell = pPage->nCell; for(i=0; i<nCell; i++){ u8 *pCell = findCell(pPage, i); - rc = ptrmapPutOvflPtr(pPage, pCell); - if( rc!=SQLITE_OK ){ - goto set_child_ptrmaps_out; - } + ptrmapPutOvflPtr(pPage, pCell, &rc); if( !pPage->leaf ){ Pgno childPgno = get4byte(pCell); - rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); - if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out; + ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); } } if( !pPage->leaf ){ Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); } set_child_ptrmaps_out: pPage->isInit = isInitOrig; return rc; } /* -** Somewhere on pPage, which is guaranteed to be a btree page, not an overflow -** page, is a pointer to page iFrom. Modify this pointer so that it points to -** iTo. Parameter eType describes the type of pointer to be modified, as -** follows: +** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so +** that it points to iTo. Parameter eType describes the type of pointer to +** be modified, as follows: ** ** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child ** page of pPage. ** ** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow @@ -38500,18 +40134,18 @@ }else{ u8 isInitOrig = pPage->isInit; int i; int nCell; - sqlite3BtreeInitPage(pPage); + btreeInitPage(pPage); nCell = pPage->nCell; for(i=0; i<nCell; i++){ u8 *pCell = findCell(pPage, i); if( eType==PTRMAP_OVERFLOW1 ){ CellInfo info; - sqlite3BtreeParseCellPtr(pPage, pCell, &info); + btreeParseCellPtr(pPage, pCell, &info); if( info.iOverflow ){ if( iFrom==get4byte(&pCell[info.iOverflow]) ){ put4byte(&pCell[info.iOverflow], iTo); break; } @@ -38539,18 +40173,23 @@ /* ** Move the open database page pDbPage to location iFreePage in the ** database. The pDbPage reference remains valid. +** +** The isCommit flag indicates that there is no need to remember that +** the journal needs to be sync()ed before database page pDbPage->pgno +** can be written to. The caller has already promised not to write to that +** page. */ static int relocatePage( BtShared *pBt, /* Btree */ MemPage *pDbPage, /* Open page to move */ u8 eType, /* Pointer map 'type' entry for pDbPage */ Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */ Pgno iFreePage, /* The location to move pDbPage to */ - int isCommit + int isCommit /* isCommit flag passed to sqlite3PagerMovepage */ ){ MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ Pgno iDbPage = pDbPage->pgno; Pager *pPager = pBt->pPager; int rc; @@ -38583,11 +40222,11 @@ return rc; } }else{ Pgno nextOvfl = get4byte(pDbPage->aData); if( nextOvfl!=0 ){ - rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage); + ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage, &rc); if( rc!=SQLITE_OK ){ return rc; } } } @@ -38595,11 +40234,11 @@ /* Fix the database pointer on page iPtrPage that pointed at iDbPage so ** that it points at iFreePage. Also fix the pointer map entry for ** iPtrPage. */ if( eType!=PTRMAP_ROOTPAGE ){ - rc = sqlite3BtreeGetPage(pBt, iPtrPage, &pPtrPage, 0); + rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0); if( rc!=SQLITE_OK ){ return rc; } rc = sqlite3PagerWrite(pPtrPage->pDbPage); if( rc!=SQLITE_OK ){ @@ -38607,11 +40246,11 @@ return rc; } rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); releasePage(pPtrPage); if( rc==SQLITE_OK ){ - rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage); + ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc); } } return rc; } @@ -38625,15 +40264,18 @@ ** ** More specificly, this function attempts to re-organize the ** database so that the last page of the file currently in use ** is no longer in use. ** -** If the nFin parameter is non-zero, the implementation assumes +** If the nFin parameter is non-zero, this function assumes ** that the caller will keep calling incrVacuumStep() until ** it returns SQLITE_DONE or an error, and that nFin is the ** number of pages the database file will contain after this -** process is complete. +** process is complete. If nFin is zero, it is assumed that +** incrVacuumStep() will be called a finite amount of times +** which may or may not empty the freelist. A full autovacuum +** has nFin>0. A "PRAGMA incremental_vacuum" has nFin==0. */ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ Pgno nFreeList; /* Number of pages still on the free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); @@ -38675,11 +40317,11 @@ } } else { Pgno iFreePg; /* Index of free page to move pLastPg to */ MemPage *pLastPg; - rc = sqlite3BtreeGetPage(pBt, iLastPg, &pLastPg, 0); + rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); if( rc!=SQLITE_OK ){ return rc; } /* If nFin is zero, this loop runs exactly once and page pLastPg @@ -38714,11 +40356,11 @@ if( nFin==0 ){ iLastPg--; while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){ if( PTRMAP_ISPAGE(pBt, iLastPg) ){ MemPage *pPg; - int rc = sqlite3BtreeGetPage(pBt, iLastPg, &pPg, 0); + int rc = btreeGetPage(pBt, iLastPg, &pPg, 0); if( rc!=SQLITE_OK ){ return rc; } rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); @@ -38773,34 +40415,37 @@ assert( sqlite3_mutex_held(pBt->mutex) ); invalidateAllOverflowCache(pBt); assert(pBt->autoVacuum); if( !pBt->incrVacuum ){ - Pgno nFin; - Pgno nFree; - Pgno nPtrmap; - Pgno iFree; - const int pgsz = pBt->pageSize; - Pgno nOrig = pagerPagecount(pBt); - + Pgno nFin; /* Number of pages in database after autovacuuming */ + Pgno nFree; /* Number of pages on the freelist initially */ + Pgno nPtrmap; /* Number of PtrMap pages to be freed */ + Pgno iFree; /* The next page to be freed */ + int nEntry; /* Number of entries on one ptrmap page */ + Pgno nOrig; /* Database size before freeing */ + + nOrig = pagerPagecount(pBt); if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ /* It is not possible to create a database for which the final page ** is either a pointer-map page or the pending-byte page. If one ** is encountered, this indicates corruption. */ return SQLITE_CORRUPT_BKPT; } nFree = get4byte(&pBt->pPage1->aData[36]); - nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+pgsz/5)/(pgsz/5); + nEntry = pBt->usableSize/5; + nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; nFin = nOrig - nFree - nPtrmap; if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){ nFin--; } while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ nFin--; } + if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){ rc = incrVacuumStep(pBt, nFin, iFree); } if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ @@ -38817,11 +40462,13 @@ assert( nRef==sqlite3PagerRefcount(pPager) ); return rc; } -#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ +#else /* ifndef SQLITE_OMIT_AUTOVACUUM */ +# define setChildPtrmaps(x) SQLITE_OK +#endif /* ** This routine does the first phase of a two-phase commit. This routine ** causes a rollback journal to be created (if it does not already exist) ** and populated with enough information so that if a power loss occurs @@ -38829,11 +40476,11 @@ ** the journal. Then the contents of the journal are flushed out to ** the disk. After the journal is safely on oxide, the changes to the ** database are written into the database file and flushed to oxide. ** At the end of this call, the rollback journal still exists on the ** disk and we are still holding all locks, so the transaction has not -** committed. See sqlite3BtreeCommit() for the second phase of the +** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the ** commit process. ** ** This call is a no-op if no write-transaction is currently active on pBt. ** ** Otherwise, sync the database file for the btree pBt. zMaster points to @@ -38866,19 +40513,62 @@ } return rc; } /* +** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() +** at the conclusion of a transaction. +*/ +static void btreeEndTransaction(Btree *p){ + BtShared *pBt = p->pBt; + BtCursor *pCsr; + assert( sqlite3BtreeHoldsMutex(p) ); + + /* Search for a cursor held open by this b-tree connection. If one exists, + ** then the transaction will be downgraded to a read-only transaction + ** instead of actually concluded. A subsequent call to CommitPhaseTwo() + ** or Rollback() will finish the transaction and unlock the database. */ + for(pCsr=pBt->pCursor; pCsr && pCsr->pBtree!=p; pCsr=pCsr->pNext); + assert( pCsr==0 || p->inTrans>TRANS_NONE ); + + btreeClearHasContent(pBt); + if( pCsr ){ + downgradeAllSharedCacheTableLocks(p); + p->inTrans = TRANS_READ; + }else{ + /* If the handle had any kind of transaction open, decrement the + ** transaction count of the shared btree. If the transaction count + ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused() + ** call below will unlock the pager. */ + if( p->inTrans!=TRANS_NONE ){ + clearAllSharedCacheTableLocks(p); + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + /* Set the current transaction state to TRANS_NONE and unlock the + ** pager if this call closed the only read or write transaction. */ + p->inTrans = TRANS_NONE; + unlockBtreeIfUnused(pBt); + } + + btreeIntegrity(p); +} + +/* ** Commit the transaction currently in progress. ** ** This routine implements the second phase of a 2-phase commit. The -** sqlite3BtreeSync() routine does the first phase and should be invoked -** prior to calling this routine. The sqlite3BtreeSync() routine did -** all the work of writing information out to disk and flushing the +** sqlite3BtreeCommitPhaseOne() routine does the first phase and should +** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne() +** routine did all the work of writing information out to disk and flushing the ** contents so that they are written onto the disk platter. All this -** routine has to do is delete or truncate the rollback journal -** (which causes the transaction to commit) and drop locks. +** routine has to do is delete or truncate or zero the header in the +** the rollback journal (which causes the transaction to commit) and +** drop locks. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p){ @@ -38900,31 +40590,11 @@ return rc; } pBt->inTransaction = TRANS_READ; } - /* If the handle has any kind of transaction open, decrement the transaction - ** count of the shared btree. If the transaction count reaches 0, set - ** the shared state to TRANS_NONE. The unlockBtreeIfUnused() call below - ** will unlock the pager. - */ - if( p->inTrans!=TRANS_NONE ){ - clearAllSharedCacheTableLocks(p); - pBt->nTransaction--; - if( 0==pBt->nTransaction ){ - pBt->inTransaction = TRANS_NONE; - } - } - - /* Set the handles current transaction state to TRANS_NONE and unlock - ** the pager if this call closed the only read or write transaction. - */ - btreeClearHasContent(pBt); - p->inTrans = TRANS_NONE; - unlockBtreeIfUnused(pBt); - - btreeIntegrity(p); + btreeEndTransaction(p); sqlite3BtreeLeave(p); return SQLITE_OK; } /* @@ -38984,11 +40654,11 @@ sqlite3BtreeEnter(pBtree); for(p=pBtree->pBt->pCursor; p; p=p->pNext){ int i; sqlite3BtreeClearCursor(p); p->eState = CURSOR_FAULT; - p->skip = errCode; + p->skipNext = errCode; for(i=0; i<=p->iPage; i++){ releasePage(p->apPage[i]); p->apPage[i] = 0; } } @@ -39033,33 +40703,20 @@ if( rc2!=SQLITE_OK ){ rc = rc2; } /* The rollback may have destroyed the pPage1->aData value. So - ** call sqlite3BtreeGetPage() on page 1 again to make + ** call btreeGetPage() on page 1 again to make ** sure pPage1->aData is set correctly. */ - if( sqlite3BtreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ + if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ releasePage(pPage1); } assert( countWriteCursors(pBt)==0 ); pBt->inTransaction = TRANS_READ; } - if( p->inTrans!=TRANS_NONE ){ - clearAllSharedCacheTableLocks(p); - assert( pBt->nTransaction>0 ); - pBt->nTransaction--; - if( 0==pBt->nTransaction ){ - pBt->inTransaction = TRANS_NONE; - } - } - - btreeClearHasContent(pBt); - p->inTrans = TRANS_NONE; - unlockBtreeIfUnused(pBt); - - btreeIntegrity(p); + btreeEndTransaction(p); sqlite3BtreeLeave(p); return rc; } /* @@ -39131,12 +40788,14 @@ return rc; } /* ** Create a new cursor for the BTree whose root is on the page -** iTable. The act of acquiring a cursor gets a read lock on -** the database file. +** iTable. If a read-only cursor is requested, it is assumed that +** the caller already has at least a read-only transaction open +** on the database already. If a write-cursor is requested, then +** the caller is assumed to have an open write transaction. ** ** If wrFlag==0, then the cursor can only be used for reading. ** If wrFlag==1, then the cursor can be used for reading or for ** writing if other conditions for writing are also met. These ** are the conditions that must be met in order for writing to @@ -39166,52 +40825,38 @@ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ struct KeyInfo *pKeyInfo, /* First arg to comparison function */ BtCursor *pCur /* Space for new cursor */ ){ - int rc; - Pgno nPage; - BtShared *pBt = p->pBt; + BtShared *pBt = p->pBt; /* Shared b-tree handle */ assert( sqlite3BtreeHoldsMutex(p) ); assert( wrFlag==0 || wrFlag==1 ); - if( wrFlag ){ - assert( !pBt->readOnly ); - if( NEVER(pBt->readOnly) ){ - return SQLITE_READONLY; - } - rc = checkForReadConflicts(p, iTable, 0, 0); - if( rc!=SQLITE_OK ){ - assert( rc==SQLITE_LOCKED_SHAREDCACHE ); - return rc; - } - } - - if( pBt->pPage1==0 ){ - rc = lockBtreeWithRetry(p); - if( rc!=SQLITE_OK ){ - return rc; - } - } - pCur->pgnoRoot = (Pgno)iTable; - rc = sqlite3PagerPagecount(pBt->pPager, (int *)&nPage); - if( rc!=SQLITE_OK ){ - return rc; - } - if( iTable==1 && nPage==0 ){ - rc = SQLITE_EMPTY; - goto create_cursor_exception; - } - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]); - if( rc!=SQLITE_OK ){ - goto create_cursor_exception; + + /* The following assert statements verify that if this is a sharable + ** b-tree database, the connection is holding the required table locks, + ** and that no other connection has any open cursor that conflicts with + ** this lock. */ + assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) ); + assert( wrFlag==0 || !hasReadConflicts(p, iTable) ); + + /* Assert that the caller has opened the required transaction. */ + assert( p->inTrans>TRANS_NONE ); + assert( wrFlag==0 || p->inTrans==TRANS_WRITE ); + assert( pBt->pPage1 && pBt->pPage1->aData ); + + if( NEVER(wrFlag && pBt->readOnly) ){ + return SQLITE_READONLY; + } + if( iTable==1 && pagerPagecount(pBt)==0 ){ + return SQLITE_EMPTY; } /* Now that no other errors can occur, finish filling in the BtCursor - ** variables, link the cursor into the BtShared list and set *ppCur (the - ** output argument to this function). - */ + ** variables and link the cursor into the BtShared list. */ + pCur->pgnoRoot = (Pgno)iTable; + pCur->iPage = -1; pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; pCur->wrFlag = (u8)wrFlag; pCur->pNext = pBt->pCursor; @@ -39219,17 +40864,11 @@ pCur->pNext->pPrev = pCur; } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; pCur->cachedRowid = 0; - - return SQLITE_OK; - -create_cursor_exception: - releasePage(pCur->apPage[0]); - unlockBtreeIfUnused(pBt); - return rc; + return SQLITE_OK; } SQLITE_PRIVATE int sqlite3BtreeCursor( Btree *p, /* The btree */ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ @@ -39314,47 +40953,16 @@ } return SQLITE_OK; } /* -** Make a temporary cursor by filling in the fields of pTempCur. -** The temporary cursor is not on the cursor list for the Btree. -*/ -SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ - int i; - assert( cursorHoldsMutex(pCur) ); - memcpy(pTempCur, pCur, sizeof(BtCursor)); - pTempCur->pNext = 0; - pTempCur->pPrev = 0; - for(i=0; i<=pTempCur->iPage; i++){ - sqlite3PagerRef(pTempCur->apPage[i]->pDbPage); - } - assert( pTempCur->pKey==0 ); -} - -/* -** Delete a temporary cursor such as was made by the CreateTemporaryCursor() -** function above. -*/ -SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ - int i; - assert( cursorHoldsMutex(pCur) ); - for(i=0; i<=pCur->iPage; i++){ - sqlite3PagerUnref(pCur->apPage[i]->pDbPage); - } - sqlite3_free(pCur->pKey); -} - - - -/* ** Make sure the BtCursor* given in the argument has a valid ** BtCursor.info structure. If it is not already valid, call -** sqlite3BtreeParseCell() to fill it in. +** btreeParseCell() to fill it in. ** ** BtCursor.info is a cache of the information in the current cell. -** Using this cache reduces the number of calls to sqlite3BtreeParseCell(). +** Using this cache reduces the number of calls to btreeParseCell(). ** ** 2007-06-25: There is a bug in some versions of MSVC that cause the ** compiler to crash when getCellInfo() is implemented as a macro. ** But there is a measureable speed advantage to using the macro on gcc ** (when less compiler optimizations like -Os or -O0 are used and the @@ -39364,11 +40972,11 @@ #ifndef NDEBUG static void assertCellInfo(BtCursor *pCur){ CellInfo info; int iPage = pCur->iPage; memset(&info, 0, sizeof(info)); - sqlite3BtreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); + btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else #define assertCellInfo(x) #endif @@ -39375,11 +40983,11 @@ #ifdef _MSC_VER /* Use a real function in MSVC to work around bugs in that compiler. */ static void getCellInfo(BtCursor *pCur){ if( pCur->info.nSize==0 ){ int iPage = pCur->iPage; - sqlite3BtreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); + btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); pCur->validNKey = 1; }else{ assertCellInfo(pCur); } } @@ -39386,65 +40994,70 @@ #else /* if not _MSC_VER */ /* Use a macro in all other compilers so that the function is inlined */ #define getCellInfo(pCur) \ if( pCur->info.nSize==0 ){ \ int iPage = pCur->iPage; \ - sqlite3BtreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ + btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ pCur->validNKey = 1; \ }else{ \ assertCellInfo(pCur); \ } #endif /* _MSC_VER */ + +#ifndef NDEBUG /* The next routine used only within assert() statements */ +/* +** Return true if the given BtCursor is valid. A valid cursor is one +** that is currently pointing to a row in a (non-empty) table. +** This is a verification routine is used only within assert() statements. +*/ +SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ + return pCur && pCur->eState==CURSOR_VALID; +} +#endif /* NDEBUG */ /* ** Set *pSize to the size of the buffer needed to hold the value of ** the key for the current entry. If the cursor is not pointing ** to a valid entry, *pSize is set to 0. ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. +** +** The caller must position the cursor prior to invoking this routine. +** +** This routine cannot fail. It always returns SQLITE_OK. */ SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ - int rc; - - assert( cursorHoldsMutex(pCur) ); - rc = restoreCursorPosition(pCur); - if( rc==SQLITE_OK ){ - assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); - if( pCur->eState==CURSOR_INVALID ){ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nKey; - } - } - return rc; + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState!=CURSOR_VALID ){ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nKey; + } + return SQLITE_OK; } /* ** Set *pSize to the number of bytes of data in the entry the -** cursor currently points to. Always return SQLITE_OK. -** Failure is not possible. If the cursor is not currently -** pointing to an entry (which can happen, for example, if -** the database is empty) then *pSize is set to 0. +** cursor currently points to. +** +** The caller must guarantee that the cursor is pointing to a non-NULL +** valid entry. In other words, the calling procedure must guarantee +** that the cursor has Cursor.eState==CURSOR_VALID. +** +** Failure is not possible. This function always returns SQLITE_OK. +** It might just as well be a procedure (returning void) but we continue +** to return an integer result code for historical reasons. */ SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - int rc; - - assert( cursorHoldsMutex(pCur) ); - rc = restoreCursorPosition(pCur); - if( rc==SQLITE_OK ){ - assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); - if( pCur->eState==CURSOR_INVALID ){ - /* Not pointing at a valid entry - set *pSize to 0. */ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nData; - } - } - return rc; + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + getCellInfo(pCur); + *pSize = pCur->info.nData; + return SQLITE_OK; } /* ** Given the page number of an overflow page in the database (parameter ** ovfl), this function finds the page number of the next page in the @@ -39463,12 +41076,12 @@ ** on *ppPage to free the reference. In no reference was obtained (because ** the pointer-map was used to obtain the value for *pPgnoNext), then ** *ppPage is set to zero. */ static int getOverflowPage( - BtShared *pBt, - Pgno ovfl, /* Overflow page */ + BtShared *pBt, /* The database file */ + Pgno ovfl, /* Current overflow page number */ MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */ Pgno *pPgnoNext /* OUT: Next overflow page number */ ){ Pgno next = 0; MemPage *pPage = 0; @@ -39501,14 +41114,15 @@ } } } #endif - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeGetPage(pBt, ovfl, &pPage, 0); - assert(rc==SQLITE_OK || pPage==0); - if( next==0 && rc==SQLITE_OK ){ + assert( next==0 || rc==SQLITE_DONE ); + if( rc==SQLITE_OK ){ + rc = btreeGetPage(pBt, ovfl, &pPage, 0); + assert( rc==SQLITE_OK || pPage==0 ); + if( rc==SQLITE_OK ){ next = get4byte(pPage->aData); } } *pPgnoNext = next; @@ -39560,14 +41174,12 @@ ** buffer pBuf). ** ** A total of "amt" bytes are read or written beginning at "offset". ** Data is read to or from the buffer pBuf. ** -** This routine does not make a distinction between key and data. -** It just reads or writes bytes from the payload area. Data might -** appear on the main page or be scattered out on multiple overflow -** pages. +** The content being read or written might appear on the main page +** or be scattered out on multiple overflow pages. ** ** If the BtCursor.isIncrblobHandle flag is set, and the current ** cursor entry uses one or more overflow pages, this function ** allocates space for and lazily popluates the overflow page-list ** cache array (BtCursor.aOverflow). Subsequent calls use this @@ -39585,11 +41197,10 @@ static int accessPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 offset, /* Begin reading this far into payload */ u32 amt, /* Read this many bytes */ unsigned char *pBuf, /* Write the bytes into this buffer */ - int skipKey, /* offset begins at data if this is true */ int eOp /* zero to read. non-zero to write. */ ){ unsigned char *aPayload; int rc = SQLITE_OK; u32 nKey; @@ -39604,14 +41215,11 @@ getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey); - if( skipKey ){ - offset += nKey; - } - if( offset+amt > nKey+pCur->info.nData + if( NEVER(offset+amt > nKey+pCur->info.nData) || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ){ /* Trying to read or write past the end of the data is an error */ return SQLITE_CORRUPT_BKPT; } @@ -39645,11 +41253,13 @@ ** (the cache is lazily populated). */ if( pCur->isIncrblobHandle && !pCur->aOverflow ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl); - if( nOvfl && !pCur->aOverflow ){ + /* nOvfl is always positive. If it were zero, fetchPayload would have + ** been used instead of this routine. */ + if( ALWAYS(nOvfl) && !pCur->aOverflow ){ rc = SQLITE_NOMEM; } } /* If the overflow page-list cache has been allocated and the @@ -39719,29 +41329,23 @@ /* ** Read part of the key associated with cursor pCur. Exactly ** "amt" bytes will be transfered into pBuf[]. The transfer ** begins at "offset". ** +** The caller must ensure that pCur is pointing to a valid row +** in the table. +** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - int rc; - - assert( cursorHoldsMutex(pCur) ); - rc = restoreCursorPosition(pCur); - if( rc==SQLITE_OK ){ - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); - if( pCur->apPage[0]->intKey ){ - return SQLITE_CORRUPT_BKPT; - } - assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); - rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0); - } - return rc; + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); + assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); + return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } /* ** Read part of the data associated with cursor pCur. Exactly ** "amt" bytes will be transfered into pBuf[]. The transfer @@ -39764,11 +41368,11 @@ rc = restoreCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); - rc = accessPayload(pCur, offset, amt, pBuf, 1, 0); + rc = accessPayload(pCur, offset, amt, pBuf, 0); } return rc; } /* @@ -39803,11 +41407,14 @@ assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( cursorHoldsMutex(pCur) ); pPage = pCur->apPage[pCur->iPage]; assert( pCur->aiIdx[pCur->iPage]<pPage->nCell ); - getCellInfo(pCur); + if( NEVER(pCur->info.nSize==0) ){ + btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage], + &pCur->info); + } aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ @@ -39816,13 +41423,11 @@ if( skipKey ){ aPayload += nKey; nLocal = pCur->info.nLocal - nKey; }else{ nLocal = pCur->info.nLocal; - if( nLocal>nKey ){ - nLocal = nKey; - } + assert( nLocal<=nKey ); } *pAmt = nLocal; return aPayload; } @@ -39840,28 +41445,37 @@ ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ - assert( cursorHoldsMutex(pCur) ); - if( pCur->eState==CURSOR_VALID ){ - return (const void*)fetchPayload(pCur, pAmt, 0); - } - return 0; + const void *p = 0; + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert( cursorHoldsMutex(pCur) ); + if( ALWAYS(pCur->eState==CURSOR_VALID) ){ + p = (const void*)fetchPayload(pCur, pAmt, 0); + } + return p; } SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ - assert( cursorHoldsMutex(pCur) ); - if( pCur->eState==CURSOR_VALID ){ - return (const void*)fetchPayload(pCur, pAmt, 1); - } - return 0; + const void *p = 0; + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert( cursorHoldsMutex(pCur) ); + if( ALWAYS(pCur->eState==CURSOR_VALID) ){ + p = (const void*)fetchPayload(pCur, pAmt, 1); + } + return p; } /* ** Move the cursor down to a new child page. The newPgno argument is the ** page number of the child page to move to. +** +** This function returns SQLITE_CORRUPT if the page-header flags field of +** the new child page does not match the flags field of the parent (i.e. +** if an intkey page appears to be the parent of a non-intkey page, or +** vice-versa). */ static int moveToChild(BtCursor *pCur, u32 newPgno){ int rc; int i = pCur->iPage; MemPage *pNewPage; @@ -39879,11 +41493,11 @@ pCur->aiIdx[i+1] = 0; pCur->iPage++; pCur->info.nSize = 0; pCur->validNKey = 0; - if( pNewPage->nCell<1 ){ + if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){ return SQLITE_CORRUPT_BKPT; } return SQLITE_OK; } @@ -39913,11 +41527,11 @@ ** pCur->idx is set to the cell index that contains the pointer ** to the page we are coming from. If we are coming from the ** right-most child page then pCur->idx is set to one more than ** the largest cell index. */ -SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur){ +static void moveToParent(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>0 ); assert( pCur->apPage[pCur->iPage] ); assertParentIndex( @@ -39930,11 +41544,29 @@ pCur->info.nSize = 0; pCur->validNKey = 0; } /* -** Move the cursor to the root page +** Move the cursor to point to the root page of its b-tree structure. +** +** If the table has a virtual root page, then the cursor is moved to point +** to the virtual root page instead of the actual root page. A table has a +** virtual root page when the actual root page contains no cells and a +** single child page. This can only happen with the table rooted at page 1. +** +** If the b-tree structure is empty, the cursor state is set to +** CURSOR_INVALID. Otherwise, the cursor is set to point to the first +** cell located on the root (or virtual root) page and the cursor state +** is set to CURSOR_VALID. +** +** If this function returns successfully, it may be assumed that the +** page-header flags indicate that the [virtual] root-page is the expected +** kind of b-tree page (i.e. if when opening the cursor the caller did not +** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D, +** indicating a table b-tree, or if the caller did specify a KeyInfo +** structure the flags byte is set to 0x02 or 0x0A, indicating an index +** b-tree). */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; Btree *p = pCur->pBtree; @@ -39944,42 +41576,59 @@ assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); if( pCur->eState>=CURSOR_REQUIRESEEK ){ if( pCur->eState==CURSOR_FAULT ){ - return pCur->skip; + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; } sqlite3BtreeClearCursor(pCur); } if( pCur->iPage>=0 ){ int i; for(i=1; i<=pCur->iPage; i++){ releasePage(pCur->apPage[i]); } - }else{ - if( - SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0])) - ){ + pCur->iPage = 0; + }else{ + rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]); + if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; } - } - + pCur->iPage = 0; + + /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor + ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is + ** NULL, the caller expects a table b-tree. If this is not the case, + ** return an SQLITE_CORRUPT error. */ + assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 ); + if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){ + return SQLITE_CORRUPT_BKPT; + } + } + + /* Assert that the root page is of the correct type. This must be the + ** case as the call to this function that loaded the root-page (either + ** this call or a previous invocation) would have detected corruption + ** if the assumption were not true, and it is not possible for the flags + ** byte to have been modified while this cursor is holding a reference + ** to the page. */ pRoot = pCur->apPage[0]; assert( pRoot->pgno==pCur->pgnoRoot ); - pCur->iPage = 0; + assert( pRoot->isInit && (pCur->pKeyInfo==0)==pRoot->intKey ); + pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->atLast = 0; pCur->validNKey = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; - assert( pRoot->pgno==1 ); - subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); - assert( subpage>0 ); + if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; + subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); pCur->eState = CURSOR_VALID; rc = moveToChild(pCur, subpage); }else{ pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID); } @@ -40069,20 +41718,35 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + + /* If the cursor already points to the last entry, this is a no-op. */ + if( CURSOR_VALID==pCur->eState && pCur->atLast ){ +#ifdef SQLITE_DEBUG + /* This block serves to assert() that the cursor really does point + ** to the last entry in the b-tree. */ + int ii; + for(ii=0; ii<pCur->iPage; ii++){ + assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); + } + assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 ); + assert( pCur->apPage[pCur->iPage]->leaf ); +#endif + return SQLITE_OK; + } + rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( CURSOR_INVALID==pCur->eState ){ assert( pCur->apPage[pCur->iPage]->nCell==0 ); *pRes = 1; }else{ assert( pCur->eState==CURSOR_VALID ); *pRes = 0; rc = moveToRightmost(pCur); - getCellInfo(pCur); pCur->atLast = rc==SQLITE_OK ?1:0; } } return rc; } @@ -40124,10 +41788,12 @@ ){ int rc; assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert( pRes ); + assert( (pIdxKey==0)==(pCur->pKeyInfo==0) ); /* If the cursor is already positioned at the point we are trying ** to move to, then just return without doing any work */ if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->apPage[0]->intKey @@ -40146,10 +41812,11 @@ if( rc ){ return rc; } assert( pCur->apPage[pCur->iPage] ); assert( pCur->apPage[pCur->iPage]->isInit ); + assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID ); if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; assert( pCur->apPage[pCur->iPage]->nCell==0 ); return SQLITE_OK; } @@ -40156,31 +41823,35 @@ assert( pCur->apPage[0]->intKey || pIdxKey ); for(;;){ int lwr, upr; Pgno chldPg; MemPage *pPage = pCur->apPage[pCur->iPage]; - int c = -1; /* pRes return if table is empty must be -1 */ + int c; + + /* pPage->nCell must be greater than zero. If this is the root-page + ** the cursor would have been INVALID above and this for(;;) loop + ** not run. If this is not the root-page, then the moveToChild() routine + ** would have already detected db corruption. Similarly, pPage must + ** be the right kind (index or table) of b-tree page. Otherwise + ** a moveToChild() or moveToRoot() call would have detected corruption. */ + assert( pPage->nCell>0 ); + assert( pPage->intKey==(pIdxKey==0) ); lwr = 0; upr = pPage->nCell-1; - if( (!pPage->intKey && pIdxKey==0) || upr<0 ){ - rc = SQLITE_CORRUPT_BKPT; - goto moveto_finish; - } if( biasRight ){ pCur->aiIdx[pCur->iPage] = (u16)upr; }else{ pCur->aiIdx[pCur->iPage] = (u16)((upr+lwr)/2); } for(;;){ - void *pCellKey; - i64 nCellKey; - int idx = pCur->aiIdx[pCur->iPage]; + int idx = pCur->aiIdx[pCur->iPage]; /* Index of current cell in pPage */ + u8 *pCell; /* Pointer to current cell in pPage */ + pCur->info.nSize = 0; - pCur->validNKey = 1; + pCell = findCell(pPage, idx) + pPage->childPtrSize; if( pPage->intKey ){ - u8 *pCell; - pCell = findCell(pPage, idx) + pPage->childPtrSize; + i64 nCellKey; if( pPage->hasData ){ u32 dummy; pCell += getVarint32(pCell, dummy); } getVarint(pCell, (u64*)&nCellKey); @@ -40190,30 +41861,57 @@ c = -1; }else{ assert( nCellKey>intKey ); c = +1; } - }else{ - int available; - pCellKey = (void *)fetchPayload(pCur, &available, 0); - nCellKey = pCur->info.nKey; - if( available>=nCellKey ){ - c = sqlite3VdbeRecordCompare((int)nCellKey, pCellKey, pIdxKey); - }else{ - pCellKey = sqlite3Malloc( (int)nCellKey ); + pCur->validNKey = 1; + pCur->info.nKey = nCellKey; + }else{ + /* The maximum supported page-size is 32768 bytes. This means that + ** the maximum number of record bytes stored on an index B-Tree + ** page is at most 8198 bytes, which may be stored as a 2-byte + ** varint. This information is used to attempt to avoid parsing + ** the entire cell by checking for the cases where the record is + ** stored entirely within the b-tree page by inspecting the first + ** 2 bytes of the cell. + */ + int nCell = pCell[0]; + if( !(nCell & 0x80) && nCell<=pPage->maxLocal ){ + /* This branch runs if the record-size field of the cell is a + ** single byte varint and the record fits entirely on the main + ** b-tree page. */ + c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + }else if( !(pCell[1] & 0x80) + && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal + ){ + /* The record-size field is a 2 byte varint and the record + ** fits entirely on the main b-tree page. */ + c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + }else{ + /* The record flows over onto one or more overflow pages. In + ** this case the whole cell needs to be parsed, a buffer allocated + ** and accessPayload() used to retrieve the record into the + ** buffer before VdbeRecordCompare() can be called. */ + void *pCellKey; + u8 * const pCellBody = pCell - pPage->childPtrSize; + btreeParseCellPtr(pPage, pCellBody, &pCur->info); + nCell = (int)pCur->info.nKey; + pCellKey = sqlite3Malloc( nCell ); if( pCellKey==0 ){ rc = SQLITE_NOMEM; goto moveto_finish; } - rc = sqlite3BtreeKey(pCur, 0, (int)nCellKey, (void*)pCellKey); - c = sqlite3VdbeRecordCompare((int)nCellKey, pCellKey, pIdxKey); + rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); + if( rc ){ + sqlite3_free(pCellKey); + goto moveto_finish; + } + c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); sqlite3_free(pCellKey); - if( rc ) goto moveto_finish; - } - } - if( c==0 ){ - pCur->info.nKey = nCellKey; + } + } + if( c==0 ){ if( pPage->intKey && !pPage->leaf ){ lwr = idx; upr = lwr - 1; break; }else{ @@ -40226,11 +41924,10 @@ lwr = idx+1; }else{ upr = idx-1; } if( lwr>upr ){ - pCur->info.nKey = nCellKey; break; } pCur->aiIdx[pCur->iPage] = (u16)((lwr+upr)/2); } assert( lwr==upr+1 ); @@ -40242,11 +41939,11 @@ }else{ chldPg = get4byte(findCell(pPage, lwr)); } if( chldPg==0 ){ assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); - if( pRes ) *pRes = c; + *pRes = c; rc = SQLITE_OK; goto moveto_finish; } pCur->aiIdx[pCur->iPage] = (u16)lwr; pCur->info.nSize = 0; @@ -40253,42 +41950,10 @@ pCur->validNKey = 0; rc = moveToChild(pCur, chldPg); if( rc ) goto moveto_finish; } moveto_finish: - return rc; -} - -/* -** In this version of BtreeMoveto, pKey is a packed index record -** such as is generated by the OP_MakeRecord opcode. Unpack the -** record and then call BtreeMovetoUnpacked() to do the work. -*/ -SQLITE_PRIVATE int sqlite3BtreeMoveto( - BtCursor *pCur, /* Cursor open on the btree to be searched */ - const void *pKey, /* Packed key if the btree is an index */ - i64 nKey, /* Integer key for tables. Size of pKey for indices */ - int bias, /* Bias search to the high end */ - int *pRes /* Write search results here */ -){ - int rc; /* Status code */ - UnpackedRecord *pIdxKey; /* Unpacked index key */ - char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */ - - - if( pKey ){ - assert( nKey==(i64)(int)nKey ); - pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, - aSpace, sizeof(aSpace)); - if( pIdxKey==0 ) return SQLITE_NOMEM; - }else{ - pIdxKey = 0; - } - rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); - if( pKey ){ - sqlite3VdbeDeleteUnpackedRecord(pIdxKey); - } return rc; } /* @@ -40302,18 +41967,10 @@ /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries ** have been deleted? This API will need to change to return an error code ** as well as the boolean result value. */ return (CURSOR_VALID!=pCur->eState); -} - -/* -** Return the database connection handle for a cursor. -*/ -SQLITE_PRIVATE sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - return pCur->pBtree->db; } /* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor @@ -40333,16 +41990,16 @@ assert( pRes!=0 ); if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; } - if( pCur->skip>0 ){ - pCur->skip = 0; + if( pCur->skipNext>0 ){ + pCur->skipNext = 0; *pRes = 0; return SQLITE_OK; } - pCur->skip = 0; + pCur->skipNext = 0; pPage = pCur->apPage[pCur->iPage]; idx = ++pCur->aiIdx[pCur->iPage]; assert( pPage->isInit ); assert( idx<=pPage->nCell ); @@ -40361,11 +42018,11 @@ if( pCur->iPage==0 ){ *pRes = 1; pCur->eState = CURSOR_INVALID; return SQLITE_OK; } - sqlite3BtreeMoveToParent(pCur); + moveToParent(pCur); pPage = pCur->apPage[pCur->iPage]; }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell ); *pRes = 0; if( pPage->intKey ){ rc = sqlite3BtreeNext(pCur, pRes); @@ -40401,16 +42058,16 @@ pCur->atLast = 0; if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; } - if( pCur->skip<0 ){ - pCur->skip = 0; + if( pCur->skipNext<0 ){ + pCur->skipNext = 0; *pRes = 0; return SQLITE_OK; } - pCur->skip = 0; + pCur->skipNext = 0; pPage = pCur->apPage[pCur->iPage]; assert( pPage->isInit ); if( !pPage->leaf ){ int idx = pCur->aiIdx[pCur->iPage]; @@ -40424,11 +42081,11 @@ if( pCur->iPage==0 ){ pCur->eState = CURSOR_INVALID; *pRes = 1; return SQLITE_OK; } - sqlite3BtreeMoveToParent(pCur); + moveToParent(pCur); } pCur->info.nSize = 0; pCur->validNKey = 0; pCur->aiIdx[pCur->iPage]--; @@ -40471,18 +42128,24 @@ Pgno nearby, u8 exact ){ MemPage *pPage1; int rc; - int n; /* Number of pages on the freelist */ - int k; /* Number of leaves on the trunk of the freelist */ + u32 n; /* Number of pages on the freelist */ + u32 k; /* Number of leaves on the trunk of the freelist */ MemPage *pTrunk = 0; MemPage *pPrevTrunk = 0; + Pgno mxPage; /* Total size of the database file */ assert( sqlite3_mutex_held(pBt->mutex) ); pPage1 = pBt->pPage1; + mxPage = pagerPagecount(pBt); n = get4byte(&pPage1->aData[36]); + testcase( n==mxPage-1 ); + if( n>=mxPage ){ + return SQLITE_CORRUPT_BKPT; + } if( n>0 ){ /* There are pages on the freelist. Reuse one of those pages. */ Pgno iTrunk; u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ @@ -40489,11 +42152,11 @@ /* If the 'exact' parameter was true and a query of the pointer-map ** shows that the page 'nearby' is somewhere on the free-list, then ** the entire-list will be searched for that page. */ #ifndef SQLITE_OMIT_AUTOVACUUM - if( exact && nearby<=pagerPagecount(pBt) ){ + if( exact && nearby<=mxPage ){ u8 eType; assert( nearby>0 ); assert( pBt->autoVacuum ); rc = ptrmapGet(pBt, nearby, &eType, 0); if( rc ) return rc; @@ -40520,11 +42183,16 @@ if( pPrevTrunk ){ iTrunk = get4byte(&pPrevTrunk->aData[0]); }else{ iTrunk = get4byte(&pPage1->aData[32]); } - rc = sqlite3BtreeGetPage(pBt, iTrunk, &pTrunk, 0); + testcase( iTrunk==mxPage ); + if( iTrunk>mxPage ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); + } if( rc ){ pTrunk = 0; goto end_allocate_page; } @@ -40541,11 +42209,11 @@ *pPgno = iTrunk; memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); *ppPage = pTrunk; pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); - }else if( k>pBt->usableSize/4 - 2 ){ + }else if( k>(u32)(pBt->usableSize/4 - 2) ){ /* Value of k is out of range. Database corruption */ rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList && nearby==iTrunk ){ @@ -40570,11 +42238,16 @@ ** pointers to free-list leaves. The first leaf becomes a trunk ** page in this case. */ MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); - rc = sqlite3BtreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0); + if( iNewTrunk>mxPage ){ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; + } + testcase( iNewTrunk==mxPage ); + rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0); if( rc!=SQLITE_OK ){ goto end_allocate_page; } rc = sqlite3PagerWrite(pNewTrunk->pDbPage); if( rc!=SQLITE_OK ){ @@ -40597,21 +42270,22 @@ } } pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); #endif - }else{ + }else if( k>0 ){ /* Extract a leaf from the trunk */ - int closest; + u32 closest; Pgno iPage; unsigned char *aData = pTrunk->aData; rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ){ goto end_allocate_page; } if( nearby>0 ){ - int i, dist; + u32 i; + int dist; closest = 0; dist = get4byte(&aData[8]) - nearby; if( dist<0 ) dist = -dist; for(i=1; i<k; i++){ int d2 = get4byte(&aData[8+i*4]) - nearby; @@ -40624,30 +42298,29 @@ }else{ closest = 0; } iPage = get4byte(&aData[8+closest*4]); + testcase( iPage==mxPage ); + if( iPage>mxPage ){ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; + } + testcase( iPage==mxPage ); if( !searchList || iPage==nearby ){ int noContent; - Pgno nPage; - *pPgno = iPage; - nPage = pagerPagecount(pBt); - if( *pPgno>nPage ){ - /* Free page off the end of the file */ - rc = SQLITE_CORRUPT_BKPT; - goto end_allocate_page; - } + *pPgno = iPage; TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" ": %d more free pages\n", *pPgno, closest+1, k, pTrunk->pgno, n-1)); if( closest<k-1 ){ memcpy(&aData[8+closest*4], &aData[4+k*4], 4); } put4byte(&aData[4], k-1); assert( sqlite3PagerIswriteable(pTrunk->pDbPage) ); noContent = !btreeGetHasContent(pBt, *pPgno); - rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, noContent); + rc = btreeGetPage(pBt, *pPgno, ppPage, noContent); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } @@ -40675,11 +42348,11 @@ ** becomes a new pointer-map page, the second is used by the caller. */ MemPage *pPg = 0; TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno)); assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = sqlite3BtreeGetPage(pBt, *pPgno, &pPg, 0); + rc = btreeGetPage(pBt, *pPgno, &pPg, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); } if( rc ) return rc; @@ -40687,11 +42360,11 @@ if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ (*pPgno)++; } } #endif assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, 0); + rc = btreeGetPage(pBt, *pPgno, ppPage, 0); if( rc ) return rc; rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } @@ -40707,10 +42380,12 @@ if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ releasePage(*ppPage); return SQLITE_CORRUPT_BKPT; } (*ppPage)->isInit = 0; + }else{ + *ppPage = 0; } return rc; } /* @@ -40752,11 +42427,11 @@ #ifdef SQLITE_SECURE_DELETE /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then ** always fully overwrite deleted information with zeros. */ - if( (!pPage && (rc = sqlite3BtreeGetPage(pBt, iPage, &pPage, 0))) + if( (!pPage && (rc = btreeGetPage(pBt, iPage, &pPage, 0))) || (rc = sqlite3PagerWrite(pPage->pDbPage)) ){ goto freepage_out; } memset(pPage->aData, 0, pPage->pBt->pageSize); @@ -40764,11 +42439,11 @@ /* If the database supports auto-vacuum, write an entry in the pointer-map ** to indicate that the page is free. */ if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0); + ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc); if( rc ) goto freepage_out; } /* Now manipulate the actual database free-list structure. There are two ** possibilities. If the free-list is currently empty, or if the first @@ -40776,34 +42451,35 @@ ** new free-list trunk page. Otherwise, it will become a leaf of the ** first trunk page in the current free-list. This block tests if it ** is possible to add the page as a new free-list leaf. */ if( nFree!=0 ){ - int nLeaf; /* Initial number of leaf cells on trunk page */ + u32 nLeaf; /* Initial number of leaf cells on trunk page */ iTrunk = get4byte(&pPage1->aData[32]); - rc = sqlite3BtreeGetPage(pBt, iTrunk, &pTrunk, 0); + rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); if( rc!=SQLITE_OK ){ goto freepage_out; } nLeaf = get4byte(&pTrunk->aData[4]); - if( nLeaf<0 ){ + assert( pBt->usableSize>32 ); + if( nLeaf > (u32)pBt->usableSize/4 - 2 ){ rc = SQLITE_CORRUPT_BKPT; goto freepage_out; } - if( nLeaf<pBt->usableSize/4 - 8 ){ + if( nLeaf < (u32)pBt->usableSize/4 - 8 ){ /* In this case there is room on the trunk page to insert the page ** being freed as a new leaf. ** ** Note that the trunk page is not really full until it contains ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have ** coded. But due to a coding error in versions of SQLite prior to ** 3.6.0, databases with freelist trunk pages holding more than ** usableSize/4 - 8 entries will be reported as corrupt. In order ** to maintain backwards compatibility with older versions of SQLite, - ** we will contain to restrict the number of entries to usableSize/4 - 8 + ** we will continue to restrict the number of entries to usableSize/4 - 8 ** for now. At some point in the future (once everyone has upgraded ** to 3.6.0 or later) we should consider fixing the conditional above ** to read "usableSize/4-2" instead of "usableSize/4-8". */ rc = sqlite3PagerWrite(pTrunk->pDbPage); @@ -40826,13 +42502,15 @@ ** the page being freed as a leaf page of the first trunk in the free-list. ** Possibly because the free-list is empty, or possibly because the ** first trunk in the free-list is full. Either way, the page being freed ** will become the new first trunk page in the free-list. */ - if( ((!pPage) && (0 != (rc = sqlite3BtreeGetPage(pBt, iPage, &pPage, 0)))) - || (0 != (rc = sqlite3PagerWrite(pPage->pDbPage))) - ){ + if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){ + goto freepage_out; + } + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc!=SQLITE_OK ){ goto freepage_out; } put4byte(pPage->aData, iTrunk); put4byte(&pPage->aData[4], 0); put4byte(&pPage1->aData[32], iPage); @@ -40844,12 +42522,14 @@ } releasePage(pPage); releasePage(pTrunk); return rc; } -static int freePage(MemPage *pPage){ - return freePage2(pPage->pBt, pPage, pPage->pgno); +static void freePage(MemPage *pPage, int *pRC){ + if( (*pRC)==SQLITE_OK ){ + *pRC = freePage2(pPage->pBt, pPage, pPage->pgno); + } } /* ** Free any overflow pages associated with the given Cell. */ @@ -40860,11 +42540,11 @@ int rc; int nOvfl; u16 ovflPageSize; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - sqlite3BtreeParseCellPtr(pPage, pCell, &info); + btreeParseCellPtr(pPage, pCell, &info); if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } ovflPgno = get4byte(&pCell[info.iOverflow]); assert( pBt->usableSize > 4 ); @@ -40943,11 +42623,11 @@ nHeader += putVarint(&pCell[nHeader], nData+nZero); }else{ nData = nZero = 0; } nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); - sqlite3BtreeParseCellPtr(pPage, pCell, &info); + btreeParseCellPtr(pPage, pCell, &info); assert( info.nHeader==nHeader ); assert( info.nKey==nKey ); assert( info.nData==(u32)(nData+nZero) ); /* Fill in the payload */ @@ -40955,12 +42635,12 @@ if( pPage->intKey ){ pSrc = pData; nSrc = nData; nData = 0; }else{ - if( nKey>0x7fffffff || pKey==0 ){ - return SQLITE_CORRUPT; + if( NEVER(nKey>0x7fffffff || pKey==0) ){ + return SQLITE_CORRUPT_BKPT; } nPayload += (int)nKey; pSrc = pKey; nSrc = (int)nKey; } @@ -40993,11 +42673,11 @@ ** may misinterpret the uninitialised values and delete the ** wrong pages from the database. */ if( pBt->autoVacuum && rc==SQLITE_OK ){ u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); - rc = ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap); + ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc); if( rc ){ releasePage(pOvfl); } } #endif @@ -41062,40 +42742,46 @@ ** the cell content has been copied someplace else. This routine just ** removes the reference to the cell from pPage. ** ** "sz" must be the number of bytes in the cell. */ -static int dropCell(MemPage *pPage, int idx, int sz){ +static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ int i; /* Loop counter */ int pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ int rc; /* The return code */ + int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ + + if( *pRC ) return; assert( idx>=0 && idx<pPage->nCell ); assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); data = pPage->aData; ptr = &data[pPage->cellOffset + 2*idx]; pc = get2byte(ptr); - if( (pc<pPage->hdrOffset+6+(pPage->leaf?0:4)) - || (pc+sz>pPage->pBt->usableSize) ){ - return SQLITE_CORRUPT_BKPT; + hdr = pPage->hdrOffset; + testcase( pc==get2byte(&data[hdr+5]) ); + testcase( pc+sz==pPage->pBt->usableSize ); + if( pc < get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ + *pRC = SQLITE_CORRUPT_BKPT; + return; } rc = freeSpace(pPage, pc, sz); - if( rc!=SQLITE_OK ){ - return rc; + if( rc ){ + *pRC = rc; + return; } for(i=idx+1; i<pPage->nCell; i++, ptr+=2){ ptr[0] = ptr[2]; ptr[1] = ptr[3]; } pPage->nCell--; - put2byte(&data[pPage->hdrOffset+3], pPage->nCell); - pPage->nFree += 2; - return SQLITE_OK; + put2byte(&data[hdr+3], pPage->nCell); + pPage->nFree += 2; } /* ** Insert a new cell on pPage at cell index "i". pCell points to the ** content of the cell. @@ -41111,27 +42797,30 @@ ** If nSkip is non-zero, then do not copy the first nSkip bytes of the ** cell. The caller will overwrite them after this function returns. If ** nSkip is non-zero, then pCell may not point to an invalid memory location ** (but pCell+nSkip is always valid). */ -static int insertCell( +static void insertCell( MemPage *pPage, /* Page into which we are copying */ int i, /* New cell becomes the i-th cell of the page */ u8 *pCell, /* Content of the new cell */ int sz, /* Bytes of content in pCell */ u8 *pTemp, /* Temp storage space for pCell, if needed */ - u8 nSkip /* Do not write the first nSkip bytes of the cell */ + Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ + int *pRC /* Read and write return code from here */ ){ int idx; /* Where to write new cell content in data[] */ int j; /* Loop counter */ - int top; /* First byte of content for any cell in data[] */ int end; /* First byte past the last cell pointer in data[] */ int ins; /* Index in data[] where new cell pointer is inserted */ - int hdr; /* Offset into data[] of the page header */ int cellOffset; /* Address of first cell pointer in data[] */ u8 *data; /* The content of the whole page */ u8 *ptr; /* Used for moving information around in data[] */ + + int nSkip = (iChild ? 4 : 0); + + if( *pRC ) return; assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) ); assert( sz==cellSizePtr(pPage, pCell) ); @@ -41139,68 +42828,55 @@ if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); pCell = pTemp; } + if( iChild ){ + put4byte(pCell, iChild); + } j = pPage->nOverflow++; assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) ); pPage->aOvfl[j].pCell = pCell; pPage->aOvfl[j].idx = (u16)i; - pPage->nFree = 0; }else{ int rc = sqlite3PagerWrite(pPage->pDbPage); if( rc!=SQLITE_OK ){ - return rc; + *pRC = rc; + return; } assert( sqlite3PagerIswriteable(pPage->pDbPage) ); data = pPage->aData; - hdr = pPage->hdrOffset; - top = get2byte(&data[hdr+5]); cellOffset = pPage->cellOffset; - end = cellOffset + 2*pPage->nCell + 2; + end = cellOffset + 2*pPage->nCell; ins = cellOffset + 2*i; - if( end > top - sz ){ - rc = defragmentPage(pPage); - if( rc!=SQLITE_OK ){ - return rc; - } - top = get2byte(&data[hdr+5]); - assert( end + sz <= top ); - } - idx = allocateSpace(pPage, sz); - assert( idx>0 ); - assert( end <= get2byte(&data[hdr+5]) ); - if (idx+sz > pPage->pBt->usableSize) { - return SQLITE_CORRUPT_BKPT; - } + rc = allocateSpace(pPage, sz, &idx); + if( rc ){ *pRC = rc; return; } + /* The allocateSpace() routine guarantees the following two properties + ** if it returns success */ + assert( idx >= end+2 ); + assert( idx+sz <= pPage->pBt->usableSize ); pPage->nCell++; - pPage->nFree -= 2; + pPage->nFree -= (u16)(2 + sz); memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip); - for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){ + if( iChild ){ + put4byte(&data[idx], iChild); + } + for(j=end, ptr=&data[j]; j>ins; j-=2, ptr-=2){ ptr[0] = ptr[-2]; ptr[1] = ptr[-1]; } put2byte(&data[ins], idx); - put2byte(&data[hdr+3], pPage->nCell); + put2byte(&data[pPage->hdrOffset+3], pPage->nCell); #ifndef SQLITE_OMIT_AUTOVACUUM if( pPage->pBt->autoVacuum ){ /* The cell may contain a pointer to an overflow page. If so, write ** the entry for the overflow page into the pointer map. */ - CellInfo info; - sqlite3BtreeParseCellPtr(pPage, pCell, &info); - assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); - if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ - Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); - rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno); - if( rc!=SQLITE_OK ) return rc; - } - } -#endif - } - - return SQLITE_OK; + ptrmapPutOvflPtr(pPage, pCell, pRC); + } +#endif + } } /* ** Add a list of cells to a page. The page should be initially empty. ** The cells are guaranteed to fit on the page. @@ -41210,43 +42886,36 @@ int nCell, /* The number of cells to add to this page */ u8 **apCell, /* Pointers to cell bodies */ u16 *aSize /* Sizes of the cells */ ){ int i; /* Loop counter */ - int totalSize; /* Total size of all cells */ - int hdr; /* Index of page header */ - int cellptr; /* Address of next cell pointer */ + u8 *pCellptr; /* Address of next cell pointer */ int cellbody; /* Address of next cell body */ - u8 *data; /* Data for the page */ + u8 * const data = pPage->aData; /* Pointer to data for pPage */ + const int hdr = pPage->hdrOffset; /* Offset of header on pPage */ + const int nUsable = pPage->pBt->usableSize; /* Usable size of page */ assert( pPage->nOverflow==0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( nCell>=0 && nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); - totalSize = 0; - for(i=0; i<nCell; i++){ - totalSize += aSize[i]; - } - assert( totalSize+2*nCell<=pPage->nFree ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + + /* Check that the page has just been zeroed by zeroPage() */ assert( pPage->nCell==0 ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - cellptr = pPage->cellOffset; - data = pPage->aData; - hdr = pPage->hdrOffset; + assert( get2byte(&data[hdr+5])==nUsable ); + + pCellptr = &data[pPage->cellOffset + nCell*2]; + cellbody = nUsable; + for(i=nCell-1; i>=0; i--){ + pCellptr -= 2; + cellbody -= aSize[i]; + put2byte(pCellptr, cellbody); + memcpy(&data[cellbody], apCell[i], aSize[i]); + } put2byte(&data[hdr+3], nCell); - if( nCell ){ - cellbody = allocateSpace(pPage, totalSize); - assert( cellbody>0 ); - assert( pPage->nFree >= 2*nCell ); - pPage->nFree -= 2*nCell; - for(i=0; i<nCell; i++){ - put2byte(&data[cellptr], cellbody); - memcpy(&data[cellbody], apCell[i], aSize[i]); - cellptr += 2; - cellbody += aSize[i]; - } - assert( cellbody==pPage->pBt->usableSize ); - } + put2byte(&data[hdr+5], cellbody); + pPage->nFree -= (nCell*2 + nUsable - cellbody); pPage->nCell = (u16)nCell; } /* ** The following parameters determine how many adjacent pages get involved @@ -41261,336 +42930,401 @@ ** The value of NN appears to give the best results overall. */ #define NN 1 /* Number of neighbors on either side of pPage */ #define NB (NN*2+1) /* Total pages involved in the balance */ -/* Forward reference */ -static int balance(BtCursor*, int); #ifndef SQLITE_OMIT_QUICKBALANCE /* ** This version of balance() handles the common special case where ** a new entry is being inserted on the extreme right-end of the ** tree, in other words, when the new entry will become the largest ** entry in the tree. ** -** Instead of trying balance the 3 right-most leaf pages, just add +** Instead of trying to balance the 3 right-most leaf pages, just add ** a new page to the right-hand side and put the one new entry in ** that page. This leaves the right side of the tree somewhat ** unbalanced. But odds are that we will be inserting new entries ** at the end soon afterwards so the nearly empty page will quickly ** fill up. On average. ** ** pPage is the leaf page which is the right-most page in the tree. ** pParent is its parent. pPage must have a single overflow entry ** which is also the right-most entry on the page. -*/ -static int balance_quick(BtCursor *pCur){ - int rc; - MemPage *pNew = 0; - Pgno pgnoNew; - u8 *pCell; - u16 szCell; - CellInfo info; - MemPage *pPage = pCur->apPage[pCur->iPage]; - MemPage *pParent = pCur->apPage[pCur->iPage-1]; - BtShared *pBt = pPage->pBt; - int parentIdx = pParent->nCell; /* pParent new divider cell index */ - int parentSize; /* Size of new divider cell */ - u8 parentCell[64]; /* Space for the new divider cell */ +** +** The pSpace buffer is used to store a temporary copy of the divider +** cell that will be inserted into pParent. Such a cell consists of a 4 +** byte page number followed by a variable length integer. In other +** words, at most 13 bytes. Hence the pSpace buffer must be at +** least 13 bytes in size. +*/ +static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ + BtShared *const pBt = pPage->pBt; /* B-Tree Database */ + MemPage *pNew; /* Newly allocated page */ + int rc; /* Return Code */ + Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - - /* Allocate a new page. Insert the overflow cell from pPage - ** into it. Then remove the overflow cell from pPage. + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + assert( pPage->nOverflow==1 ); + + if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT; + + /* Allocate a new page. This page will become the right-sibling of + ** pPage. Make the parent page writable, so that the new divider cell + ** may be inserted. If both these operations are successful, proceed. */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); - if( rc==SQLITE_OK ){ - pCell = pPage->aOvfl[0].pCell; - szCell = cellSizePtr(pPage, pCell); + + if( rc==SQLITE_OK ){ + + u8 *pOut = &pSpace[4]; + u8 *pCell = pPage->aOvfl[0].pCell; + u16 szCell = cellSizePtr(pPage, pCell); + u8 *pStop; + assert( sqlite3PagerIswriteable(pNew->pDbPage) ); - zeroPage(pNew, pPage->aData[0]); - assemblePage(pNew, 1, &pCell, &szCell); - pPage->nOverflow = 0; - - /* pPage is currently the right-child of pParent. Change this - ** so that the right-child is the new page allocated above and - ** pPage is the next-to-right child. - ** - ** Ignore the return value of the call to fillInCell(). fillInCell() - ** may only return other than SQLITE_OK if it is required to allocate - ** one or more overflow pages. Since an internal table B-Tree cell - ** may never spill over onto an overflow page (it is a maximum of - ** 13 bytes in size), it is not neccessary to check the return code. - ** - ** Similarly, the insertCell() function cannot fail if the page - ** being inserted into is already writable and the cell does not - ** contain an overflow pointer. So ignore this return code too. - */ - assert( pPage->nCell>0 ); - pCell = findCell(pPage, pPage->nCell-1); - sqlite3BtreeParseCellPtr(pPage, pCell, &info); - fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize); - assert( parentSize<64 ); - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4); - put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno); - put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); + assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) ); + zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF); + assemblePage(pNew, 1, &pCell, &szCell); /* If this is an auto-vacuum database, update the pointer map ** with entries for the new page, and any pointer from the - ** cell on the page to an overflow page. + ** cell on the page to an overflow page. If either of these + ** operations fails, the return code is set, but the contents + ** of the parent page are still manipulated by thh code below. + ** That is Ok, at this point the parent page is guaranteed to + ** be marked as dirty. Returning an error code will cause a + ** rollback, undoing any changes made to the parent page. */ if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno); - if( rc==SQLITE_OK ){ - rc = ptrmapPutOvfl(pNew, 0); - } - } + ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc); + if( szCell>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, pCell, &rc); + } + } + + /* Create a divider cell to insert into pParent. The divider cell + ** consists of a 4-byte page number (the page number of pPage) and + ** a variable length key value (which must be the same value as the + ** largest key on pPage). + ** + ** To find the largest key value on pPage, first find the right-most + ** cell on pPage. The first two fields of this cell are the + ** record-length (a variable length integer at most 32-bits in size) + ** and the key value (a variable length integer, may have any value). + ** The first of the while(...) loops below skips over the record-length + ** field. The second while(...) loop copies the key value from the + ** cell on pPage into the pSpace buffer. + */ + pCell = findCell(pPage, pPage->nCell-1); + pStop = &pCell[9]; + while( (*(pCell++)&0x80) && pCell<pStop ); + pStop = &pCell[9]; + while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop ); + + /* Insert the new divider cell into pParent. */ + insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace), + 0, pPage->pgno, &rc); + + /* Set the right-child pointer of pParent to point to the new page. */ + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); /* Release the reference to the new page. */ releasePage(pNew); } - /* At this point the pPage->nFree variable is not set correctly with - ** respect to the content of the page (because it was set to 0 by - ** insertCell). So call sqlite3BtreeInitPage() to make sure it is - ** correct. - ** - ** This has to be done even if an error will be returned. Normally, if - ** an error occurs during tree balancing, the contents of MemPage are - ** not important, as they will be recalculated when the page is rolled - ** back. But here, in balance_quick(), it is possible that pPage has - ** not yet been marked dirty or written into the journal file. Therefore - ** it will not be rolled back and so it is important to make sure that - ** the page data and contents of MemPage are consistent. - */ - pPage->isInit = 0; - sqlite3BtreeInitPage(pPage); - assert( pPage->nOverflow==0 ); - - /* If everything else succeeded, balance the parent page, in - ** case the divider cell inserted caused it to become overfull. - */ - if( rc==SQLITE_OK ){ - releasePage(pPage); - pCur->iPage--; - rc = balance(pCur, 0); - } return rc; } #endif /* SQLITE_OMIT_QUICKBALANCE */ -/* -** This routine redistributes Cells on pPage and up to NN*2 siblings -** of pPage so that all pages have about the same amount of free space. -** Usually NN siblings on either side of pPage is used in the balancing, -** though more siblings might come from one side if pPage is the first -** or last child of its parent. If pPage has fewer than 2*NN siblings -** (something which can only happen if pPage is the root page or a -** child of root) then all available siblings participate in the balancing. -** -** The number of siblings of pPage might be increased or decreased by one or -** two in an effort to keep pages nearly full but not over full. The root page -** is special and is allowed to be nearly empty. If pPage is -** the root page, then the depth of the tree might be increased -** or decreased by one, as necessary, to keep the root page from being -** overfull or completely empty. -** -** Note that when this routine is called, some of the Cells on pPage -** might not actually be stored in pPage->aData[]. This can happen -** if the page is overfull. Part of the job of this routine is to -** make sure all Cells for pPage once again fit in pPage->aData[]. -** -** In the course of balancing the siblings of pPage, the parent of pPage -** might become overfull or underfull. If that happens, then this routine -** is called recursively on the parent. +#if 0 +/* +** This function does not contribute anything to the operation of SQLite. +** it is sometimes activated temporarily while debugging code responsible +** for setting pointer-map entries. +*/ +static int ptrmapCheckPages(MemPage **apPage, int nPage){ + int i, j; + for(i=0; i<nPage; i++){ + Pgno n; + u8 e; + MemPage *pPage = apPage[i]; + BtShared *pBt = pPage->pBt; + assert( pPage->isInit ); + + for(j=0; j<pPage->nCell; j++){ + CellInfo info; + u8 *z; + + z = findCell(pPage, j); + btreeParseCellPtr(pPage, z, &info); + if( info.iOverflow ){ + Pgno ovfl = get4byte(&z[info.iOverflow]); + ptrmapGet(pBt, ovfl, &e, &n); + assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 ); + } + if( !pPage->leaf ){ + Pgno child = get4byte(z); + ptrmapGet(pBt, child, &e, &n); + assert( n==pPage->pgno && e==PTRMAP_BTREE ); + } + } + if( !pPage->leaf ){ + Pgno child = get4byte(&pPage->aData[pPage->hdrOffset+8]); + ptrmapGet(pBt, child, &e, &n); + assert( n==pPage->pgno && e==PTRMAP_BTREE ); + } + } + return 1; +} +#endif + +/* +** This function is used to copy the contents of the b-tree node stored +** on page pFrom to page pTo. If page pFrom was not a leaf page, then +** the pointer-map entries for each child page are updated so that the +** parent page stored in the pointer map is page pTo. If pFrom contained +** any cells with overflow page pointers, then the corresponding pointer +** map entries are also updated so that the parent page is page pTo. +** +** If pFrom is currently carrying any overflow cells (entries in the +** MemPage.aOvfl[] array), they are not copied to pTo. +** +** Before returning, page pTo is reinitialized using btreeInitPage(). +** +** The performance of this function is not critical. It is only used by +** the balance_shallower() and balance_deeper() procedures, neither of +** which are called often under normal circumstances. +*/ +static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ + if( (*pRC)==SQLITE_OK ){ + BtShared * const pBt = pFrom->pBt; + u8 * const aFrom = pFrom->aData; + u8 * const aTo = pTo->aData; + int const iFromHdr = pFrom->hdrOffset; + int const iToHdr = ((pTo->pgno==1) ? 100 : 0); + TESTONLY(int rc;) + int iData; + + + assert( pFrom->isInit ); + assert( pFrom->nFree>=iToHdr ); + assert( get2byte(&aFrom[iFromHdr+5])<=pBt->usableSize ); + + /* Copy the b-tree node content from page pFrom to page pTo. */ + iData = get2byte(&aFrom[iFromHdr+5]); + memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); + memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); + + /* Reinitialize page pTo so that the contents of the MemPage structure + ** match the new data. The initialization of pTo "cannot" fail, as the + ** data copied from pFrom is known to be valid. */ + pTo->isInit = 0; + TESTONLY(rc = ) btreeInitPage(pTo); + assert( rc==SQLITE_OK ); + + /* If this is an auto-vacuum database, update the pointer-map entries + ** for any b-tree or overflow pages that pTo now contains the pointers to. + */ + if( ISAUTOVACUUM ){ + *pRC = setChildPtrmaps(pTo); + } + } +} + +/* +** This routine redistributes cells on the iParentIdx'th child of pParent +** (hereafter "the page") and up to 2 siblings so that all pages have about the +** same amount of free space. Usually a single sibling on either side of the +** page are used in the balancing, though both siblings might come from one +** side if the page is the first or last child of its parent. If the page +** has fewer than 2 siblings (something which can only happen if the page +** is a root page or a child of a root page) then all available siblings +** participate in the balancing. +** +** The number of siblings of the page might be increased or decreased by +** one or two in an effort to keep pages nearly full but not over full. +** +** Note that when this routine is called, some of the cells on the page +** might not actually be stored in MemPage.aData[]. This can happen +** if the page is overfull. This routine ensures that all cells allocated +** to the page and its siblings fit into MemPage.aData[] before returning. +** +** In the course of balancing the page and its siblings, cells may be +** inserted into or removed from the parent page (pParent). Doing so +** may cause the parent page to become overfull or underfull. If this +** happens, it is the responsibility of the caller to invoke the correct +** balancing routine to fix this problem (see the balance() routine). ** ** If this routine fails for any reason, it might leave the database -** in a corrupted state. So if this routine fails, the database should +** in a corrupted state. So if this routine fails, the database should ** be rolled back. -*/ -static int balance_nonroot(BtCursor *pCur){ - MemPage *pPage; /* The over or underfull page to balance */ - MemPage *pParent; /* The parent of pPage */ +** +** The third argument to this function, aOvflSpace, is a pointer to a +** buffer big enough to hold one page. If while inserting cells into the parent +** page (pParent) the parent page becomes overfull, this buffer is +** used to store the parent's overflow cells. Because this function inserts +** a maximum of four divider cells into the parent page, and the maximum +** size of a cell stored within an internal node is always less than 1/4 +** of the page-size, the aOvflSpace[] buffer is guaranteed to be large +** enough for all overflow cells. +** +** If aOvflSpace is set to a null pointer, this function returns +** SQLITE_NOMEM. +*/ +static int balance_nonroot( + MemPage *pParent, /* Parent page of siblings being balanced */ + int iParentIdx, /* Index of "the page" in pParent */ + u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */ + int isRoot /* True if pParent is a root-page */ +){ BtShared *pBt; /* The whole database */ int nCell = 0; /* Number of cells in apCell[] */ int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ - int nOld = 0; /* Number of pages in apOld[] */ int nNew = 0; /* Number of pages in apNew[] */ - int nDiv; /* Number of cells in apDiv[] */ + int nOld; /* Number of pages in apOld[] */ int i, j, k; /* Loop counters */ - int idx; /* Index of pPage in pParent->aCell[] */ int nxDiv; /* Next divider slot in pParent->aCell[] */ - int rc; /* The return code */ - int leafCorrection; /* 4 if pPage is a leaf. 0 if not */ + int rc = SQLITE_OK; /* The return code */ + u16 leafCorrection; /* 4 if pPage is a leaf. 0 if not */ int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ int usableSpace; /* Bytes in pPage beyond the header */ int pageFlags; /* Value of pPage->aData[0] */ int subtotal; /* Subtotal of bytes in cells on one page */ int iSpace1 = 0; /* First unused byte of aSpace1[] */ - int iSpace2 = 0; /* First unused byte of aSpace2[] */ + int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */ int szScratch; /* Size of scratch memory requested */ MemPage *apOld[NB]; /* pPage and up to two siblings */ - Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */ MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ - Pgno pgnoNew[NB+2]; /* Page numbers for each page in apNew[] */ - u8 *apDiv[NB]; /* Divider cells in pParent */ + u8 *pRight; /* Location in parent of right-sibling pointer */ + u8 *apDiv[NB-1]; /* Divider cells in pParent */ int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ int szNew[NB+2]; /* Combined size of cells place on i-th page */ u8 **apCell = 0; /* All cells begin balanced */ u16 *szCell; /* Local size of all cells in apCell[] */ - u8 *aCopy[NB]; /* Space for holding data of apCopy[] */ - u8 *aSpace1; /* Space for copies of dividers cells before balance */ - u8 *aSpace2 = 0; /* Space for overflow dividers cells after balance */ - u8 *aFrom = 0; - - pPage = pCur->apPage[pCur->iPage]; - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - VVA_ONLY( pCur->pagesShuffled = 1 ); - - /* - ** Find the parent page. - */ - assert( pCur->iPage>0 ); - assert( pPage->isInit ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 ); - pBt = pPage->pBt; - pParent = pCur->apPage[pCur->iPage-1]; - assert( pParent ); - if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){ - goto balance_cleanup; - } - + u8 *aSpace1; /* Space for copies of dividers cells */ + Pgno pgno; /* Temp var to store a page number in */ + + pBt = pParent->pBt; + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + +#if 0 TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); - -#ifndef SQLITE_OMIT_QUICKBALANCE - /* - ** A special case: If a new entry has just been inserted into a - ** table (that is, a btree with integer keys and all data at the leaves) - ** and the new entry is the right-most entry in the tree (it has the - ** largest key) then use the special balance_quick() routine for - ** balancing. balance_quick() is much faster and results in a tighter - ** packing of data in the common case. - */ - if( pPage->leaf && - pPage->intKey && - pPage->nOverflow==1 && - pPage->aOvfl[0].idx==pPage->nCell && - pParent->pgno!=1 && - get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno - ){ - assert( pPage->intKey ); - /* - ** TODO: Check the siblings to the left of pPage. It may be that - ** they are not full and no new page is required. - */ - return balance_quick(pCur); - } -#endif - - if( SQLITE_OK!=(rc = sqlite3PagerWrite(pPage->pDbPage)) ){ - goto balance_cleanup; - } - - /* - ** Find the cell in the parent page whose left child points back - ** to pPage. The "idx" variable is the index of that cell. If pPage - ** is the rightmost child of pParent then set idx to pParent->nCell - */ - idx = pCur->aiIdx[pCur->iPage-1]; - assertParentIndex(pParent, idx, pPage->pgno); - - /* - ** Find sibling pages to pPage and the cells in pParent that divide - ** the siblings. An attempt is made to find NN siblings on either - ** side of pPage. More siblings are taken from one side, however, if - ** pPage there are fewer than NN siblings on the other side. If pParent +#endif + + /* At this point pParent may have at most one overflow cell. And if + ** this overflow cell is present, it must be the cell with + ** index iParentIdx. This scenario comes about when this function + ** is called (indirectly) from sqlite3BtreeDelete(). + */ + assert( pParent->nOverflow==0 || pParent->nOverflow==1 ); + assert( pParent->nOverflow==0 || pParent->aOvfl[0].idx==iParentIdx ); + + if( !aOvflSpace ){ + return SQLITE_NOMEM; + } + + /* Find the sibling pages to balance. Also locate the cells in pParent + ** that divide the siblings. An attempt is made to find NN siblings on + ** either side of pPage. More siblings are taken from one side, however, + ** if there are fewer than NN siblings on the other side. If pParent ** has NB or fewer children then all children of pParent are taken. - */ - nxDiv = idx - NN; - if( nxDiv + NB > pParent->nCell ){ - nxDiv = pParent->nCell - NB + 1; - } - if( nxDiv<0 ){ + ** + ** This loop also drops the divider cells from the parent page. This + ** way, the remainder of the function does not have to deal with any + ** overflow cells in the parent page, since if any existed they will + ** have already been removed. + */ + i = pParent->nOverflow + pParent->nCell; + if( i<2 ){ nxDiv = 0; - } - nDiv = 0; - for(i=0, k=nxDiv; i<NB; i++, k++){ - if( k<pParent->nCell ){ - apDiv[i] = findCell(pParent, k); - nDiv++; - assert( !pParent->leaf ); - pgnoOld[i] = get4byte(apDiv[i]); - }else if( k==pParent->nCell ){ - pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]); - }else{ - break; - } - rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i]); - if( rc ) goto balance_cleanup; - /* apOld[i]->idxParent = k; */ - apCopy[i] = 0; - assert( i==nOld ); - nOld++; + nOld = i+1; + }else{ + nOld = 3; + if( iParentIdx==0 ){ + nxDiv = 0; + }else if( iParentIdx==i ){ + nxDiv = i-2; + }else{ + nxDiv = iParentIdx-1; + } + i = 2; + } + if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){ + pRight = &pParent->aData[pParent->hdrOffset+8]; + }else{ + pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); + } + pgno = get4byte(pRight); + while( 1 ){ + rc = getAndInitPage(pBt, pgno, &apOld[i]); + if( rc ){ + memset(apOld, 0, (i+1)*sizeof(MemPage*)); + goto balance_cleanup; + } nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; + if( (i--)==0 ) break; + + if( i+nxDiv==pParent->aOvfl[0].idx && pParent->nOverflow ){ + apDiv[i] = pParent->aOvfl[0].pCell; + pgno = get4byte(apDiv[i]); + szNew[i] = cellSizePtr(pParent, apDiv[i]); + pParent->nOverflow = 0; + }else{ + apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow); + pgno = get4byte(apDiv[i]); + szNew[i] = cellSizePtr(pParent, apDiv[i]); + + /* Drop the cell from the parent page. apDiv[i] still points to + ** the cell within the parent, even though it has been dropped. + ** This is safe because dropping a cell only overwrites the first + ** four bytes of it, and this function does not need the first + ** four bytes of the divider cell. So the pointer is safe to use + ** later on. + ** + ** Unless SQLite is compiled in secure-delete mode. In this case, + ** the dropCell() routine will overwrite the entire cell with zeroes. + ** In this case, temporarily copy the cell into the aOvflSpace[] + ** buffer. It will be copied out again as soon as the aSpace[] buffer + ** is allocated. */ +#ifdef SQLITE_SECURE_DELETE + memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]); + apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; +#endif + dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); + } } /* Make nMaxCells a multiple of 4 in order to preserve 8-byte ** alignment */ nMaxCells = (nMaxCells + 3)&~3; /* ** Allocate space for memory structures */ + k = pBt->pageSize + ROUND8(sizeof(MemPage)); szScratch = nMaxCells*sizeof(u8*) /* apCell */ + nMaxCells*sizeof(u16) /* szCell */ - + (ROUND8(sizeof(MemPage))+pBt->pageSize)*NB /* aCopy */ + pBt->pageSize /* aSpace1 */ - + (ISAUTOVACUUM ? nMaxCells : 0); /* aFrom */ + + k*nOld; /* Page copies (apCopy) */ apCell = sqlite3ScratchMalloc( szScratch ); if( apCell==0 ){ rc = SQLITE_NOMEM; goto balance_cleanup; } szCell = (u16*)&apCell[nMaxCells]; - aCopy[0] = (u8*)&szCell[nMaxCells]; - assert( EIGHT_BYTE_ALIGNMENT(aCopy[0]) ); - for(i=1; i<NB; i++){ - aCopy[i] = &aCopy[i-1][pBt->pageSize+ROUND8(sizeof(MemPage))]; - assert( ((aCopy[i] - (u8*)0) & 7)==0 ); /* 8-byte alignment required */ - } - aSpace1 = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))]; - assert( EIGHT_BYTE_ALIGNMENT(aSpace1) ); - if( ISAUTOVACUUM ){ - aFrom = &aSpace1[pBt->pageSize]; - } - aSpace2 = sqlite3PageMalloc(pBt->pageSize); - if( aSpace2==0 ){ - rc = SQLITE_NOMEM; - goto balance_cleanup; - } - - /* - ** Make copies of the content of pPage and its siblings into aOld[]. - ** The rest of this function will use data from the copies rather - ** that the original pages since the original pages will be in the - ** process of being overwritten. - */ - for(i=0; i<nOld; i++){ - MemPage *p = apCopy[i] = (MemPage*)aCopy[i]; - memcpy(p, apOld[i], sizeof(MemPage)); - p->aData = (void*)&p[1]; - memcpy(p->aData, apOld[i]->aData, pBt->pageSize); - } + aSpace1 = (u8*)&szCell[nMaxCells]; + assert( EIGHT_BYTE_ALIGNMENT(aSpace1) ); /* ** Load pointers to all cells on sibling pages and the divider cells ** into the local apCell[] array. Make copies of the divider cells - ** into space obtained form aSpace1[] and remove the the divider Cells + ** into space obtained from aSpace1[] and remove the the divider Cells ** from pParent. ** ** If the siblings are on leaf pages, then the child pointers of the ** divider cells are stripped from the cells before they are copied ** into aSpace1[]. In this way, all cells in apCell[] are without @@ -41599,72 +43333,58 @@ ** are alike. ** ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. ** leafData: 1 if pPage holds key+data and pParent holds only keys. */ - nCell = 0; - leafCorrection = pPage->leaf*4; - leafData = pPage->hasData; + leafCorrection = apOld[0]->leaf*4; + leafData = apOld[0]->hasData; for(i=0; i<nOld; i++){ - MemPage *pOld = apCopy[i]; - int limit = pOld->nCell+pOld->nOverflow; + int limit; + + /* Before doing anything else, take a copy of the i'th original sibling + ** The rest of this function will use data from the copies rather + ** that the original pages since the original pages will be in the + ** process of being overwritten. */ + MemPage *pOld = apCopy[i] = (MemPage*)&aSpace1[pBt->pageSize + k*i]; + memcpy(pOld, apOld[i], sizeof(MemPage)); + pOld->aData = (void*)&pOld[1]; + memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize); + + limit = pOld->nCell+pOld->nOverflow; for(j=0; j<limit; j++){ assert( nCell<nMaxCells ); apCell[nCell] = findOverflowCell(pOld, j); szCell[nCell] = cellSizePtr(pOld, apCell[nCell]); - if( ISAUTOVACUUM ){ - int a; - aFrom[nCell] = (u8)i; assert( i>=0 && i<6 ); - for(a=0; a<pOld->nOverflow; a++){ - if( pOld->aOvfl[a].pCell==apCell[nCell] ){ - aFrom[nCell] = 0xFF; - break; - } - } - } nCell++; } - if( i<nOld-1 ){ - u16 sz = cellSizePtr(pParent, apDiv[i]); - if( leafData ){ - /* With the LEAFDATA flag, pParent cells hold only INTKEYs that - ** are duplicates of keys on the child pages. We need to remove - ** the divider cells from pParent, but the dividers cells are not - ** added to apCell[] because they are duplicates of child cells. - */ - dropCell(pParent, nxDiv, sz); - }else{ - u8 *pTemp; - assert( nCell<nMaxCells ); - szCell[nCell] = sz; - pTemp = &aSpace1[iSpace1]; - iSpace1 += sz; - assert( sz<=pBt->pageSize/4 ); - assert( iSpace1<=pBt->pageSize ); - memcpy(pTemp, apDiv[i], sz); - apCell[nCell] = pTemp+leafCorrection; - if( ISAUTOVACUUM ){ - aFrom[nCell] = 0xFF; - } - dropCell(pParent, nxDiv, sz); - assert( leafCorrection==0 || leafCorrection==4 ); - szCell[nCell] -= (u16)leafCorrection; - assert( get4byte(pTemp)==pgnoOld[i] ); - if( !pOld->leaf ){ - assert( leafCorrection==0 ); - /* The right pointer of the child page pOld becomes the left - ** pointer of the divider cell */ - memcpy(apCell[nCell], &pOld->aData[pOld->hdrOffset+8], 4); - }else{ - assert( leafCorrection==4 ); - if( szCell[nCell]<4 ){ - /* Do not allow any cells smaller than 4 bytes. */ - szCell[nCell] = 4; - } - } - nCell++; - } + if( i<nOld-1 && !leafData){ + u16 sz = (u16)szNew[i]; + u8 *pTemp; + assert( nCell<nMaxCells ); + szCell[nCell] = sz; + pTemp = &aSpace1[iSpace1]; + iSpace1 += sz; + assert( sz<=pBt->pageSize/4 ); + assert( iSpace1<=pBt->pageSize ); + memcpy(pTemp, apDiv[i], sz); + apCell[nCell] = pTemp+leafCorrection; + assert( leafCorrection==0 || leafCorrection==4 ); + szCell[nCell] = szCell[nCell] - leafCorrection; + if( !pOld->leaf ){ + assert( leafCorrection==0 ); + assert( pOld->hdrOffset==0 ); + /* The right pointer of the child page pOld becomes the left + ** pointer of the divider cell */ + memcpy(apCell[nCell], &pOld->aData[8], 4); + }else{ + assert( leafCorrection==4 ); + if( szCell[nCell]<4 ){ + /* Do not allow any cells smaller than 4 bytes. */ + szCell[nCell] = 4; + } + } + nCell++; } } /* ** Figure out the number of pages needed to hold all nCell cells. @@ -41690,10 +43410,11 @@ szNew[k] = subtotal - szCell[i]; cntNew[k] = i; if( leafData ){ i--; } subtotal = 0; k++; + if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; } } } szNew[k] = subtotal; cntNew[k] = nCell; k++; @@ -41727,43 +43448,59 @@ } szNew[i] = szRight; szNew[i-1] = szLeft; } - /* Either we found one or more cells (cntnew[0])>0) or we are the + /* Either we found one or more cells (cntnew[0])>0) or pPage is ** a virtual root page. A virtual root page is when the real root ** page is page 1 and we are the only child of that page. */ assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) ); + TRACE(("BALANCE: old: %d %d %d ", + apOld[0]->pgno, + nOld>=2 ? apOld[1]->pgno : 0, + nOld>=3 ? apOld[2]->pgno : 0 + )); + /* ** Allocate k new pages. Reuse old pages where possible. */ - assert( pPage->pgno>1 ); - pageFlags = pPage->aData[0]; + if( apOld[0]->pgno<=1 ){ + rc = SQLITE_CORRUPT; + goto balance_cleanup; + } + pageFlags = apOld[0]->aData[0]; for(i=0; i<k; i++){ MemPage *pNew; if( i<nOld ){ pNew = apNew[i] = apOld[i]; - pgnoNew[i] = pgnoOld[i]; apOld[i] = 0; rc = sqlite3PagerWrite(pNew->pDbPage); nNew++; if( rc ) goto balance_cleanup; }else{ assert( i>0 ); - rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); + rc = allocateBtreePage(pBt, &pNew, &pgno, pgno, 0); if( rc ) goto balance_cleanup; apNew[i] = pNew; nNew++; + + /* Set the pointer-map entry for the new sibling page. */ + if( ISAUTOVACUUM ){ + ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } } } /* Free any old pages that were not reused as new pages. */ while( i<nOld ){ - rc = freePage(apOld[i]); + freePage(apOld[i], &rc); if( rc ) goto balance_cleanup; releasePage(apOld[i]); apOld[i] = 0; i++; } @@ -41781,38 +43518,36 @@ ** ** When NB==3, this one optimization makes the database ** about 25% faster for large insertions and deletions. */ for(i=0; i<k-1; i++){ - int minV = pgnoNew[i]; + int minV = apNew[i]->pgno; int minI = i; for(j=i+1; j<k; j++){ - if( pgnoNew[j]<(unsigned)minV ){ + if( apNew[j]->pgno<(unsigned)minV ){ minI = j; - minV = pgnoNew[j]; + minV = apNew[j]->pgno; } } if( minI>i ){ int t; MemPage *pT; - t = pgnoNew[i]; + t = apNew[i]->pgno; pT = apNew[i]; - pgnoNew[i] = pgnoNew[minI]; - apNew[i] = apNew[minI]; - pgnoNew[minI] = t; + apNew[i] = apNew[minI]; apNew[minI] = pT; } } - TRACE(("BALANCE: old: %d %d %d new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n", - pgnoOld[0], - nOld>=2 ? pgnoOld[1] : 0, - nOld>=3 ? pgnoOld[2] : 0, - pgnoNew[0], szNew[0], - nNew>=2 ? pgnoNew[1] : 0, nNew>=2 ? szNew[1] : 0, - nNew>=3 ? pgnoNew[2] : 0, nNew>=3 ? szNew[2] : 0, - nNew>=4 ? pgnoNew[3] : 0, nNew>=4 ? szNew[3] : 0, - nNew>=5 ? pgnoNew[4] : 0, nNew>=5 ? szNew[4] : 0)); + TRACE(("new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n", + apNew[0]->pgno, szNew[0], + nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0, + nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0, + nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0, + nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0)); + + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + put4byte(pRight, apNew[nNew-1]->pgno); /* ** Evenly distribute the data in apCell[] across the new pages. ** Insert divider cells into pParent as necessary. */ @@ -41819,81 +43554,50 @@ j = 0; for(i=0; i<nNew; i++){ /* Assemble the new sibling page. */ MemPage *pNew = apNew[i]; assert( j<nMaxCells ); - assert( pNew->pgno==pgnoNew[i] ); zeroPage(pNew, pageFlags); assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]); assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) ); assert( pNew->nOverflow==0 ); - - /* If this is an auto-vacuum database, update the pointer map entries - ** that point to the siblings that were rearranged. These can be: left - ** children of cells, the right-child of the page, or overflow pages - ** pointed to by cells. - */ - if( ISAUTOVACUUM ){ - for(k=j; k<cntNew[i]; k++){ - assert( k<nMaxCells ); - if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){ - rc = ptrmapPutOvfl(pNew, k-j); - if( rc==SQLITE_OK && leafCorrection==0 ){ - rc = ptrmapPut(pBt, get4byte(apCell[k]), PTRMAP_BTREE, pNew->pgno); - } - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } - } - } - } j = cntNew[i]; /* If the sibling page assembled above was not the right-most sibling, ** insert a divider cell into the parent page. */ - if( i<nNew-1 && j<nCell ){ + assert( i<nNew-1 || j==nCell ); + if( j<nCell ){ u8 *pCell; u8 *pTemp; int sz; assert( j<nMaxCells ); pCell = apCell[j]; sz = szCell[j] + leafCorrection; - pTemp = &aSpace2[iSpace2]; + pTemp = &aOvflSpace[iOvflSpace]; if( !pNew->leaf ){ memcpy(&pNew->aData[8], pCell, 4); - if( ISAUTOVACUUM - && (aFrom[j]==0xFF || apCopy[aFrom[j]]->pgno!=pNew->pgno) - ){ - rc = ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno); - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } - } }else if( leafData ){ /* If the tree is a leaf-data tree, and the siblings are leaves, ** then there is no divider cell in apCell[]. Instead, the divider ** cell consists of the integer key for the right-most cell of ** the sibling-page assembled above only. */ CellInfo info; j--; - sqlite3BtreeParseCellPtr(pNew, apCell[j], &info); + btreeParseCellPtr(pNew, apCell[j], &info); pCell = pTemp; - rc = fillInCell(pParent, pCell, 0, info.nKey, 0, 0, 0, &sz); - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } + sz = 4 + putVarint(&pCell[4], info.nKey); pTemp = 0; }else{ pCell -= 4; /* Obscure case for non-leaf-data trees: If the cell at pCell was ** previously stored on a leaf node, and its reported size was 4 ** bytes, then it may actually be smaller than this - ** (see sqlite3BtreeParseCellPtr(), 4 bytes is the minimum size of + ** (see btreeParseCellPtr(), 4 bytes is the minimum size of ** any cell). But it is important to pass the correct size to ** insertCell(), so reparse the cell now. ** ** Note that this can never happen in an SQLite data file, as all ** cells are at least 4 bytes. It only happens in b-trees used @@ -41902,426 +43606,447 @@ if( szCell[j]==4 ){ assert(leafCorrection==4); sz = cellSizePtr(pParent, pCell); } } - iSpace2 += sz; + iOvflSpace += sz; assert( sz<=pBt->pageSize/4 ); - assert( iSpace2<=pBt->pageSize ); - rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4); + assert( iOvflSpace<=pBt->pageSize ); + insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc); if( rc!=SQLITE_OK ) goto balance_cleanup; assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); - - /* If this is an auto-vacuum database, and not a leaf-data tree, - ** then update the pointer map with an entry for the overflow page - ** that the cell just inserted points to (if any). - */ - if( ISAUTOVACUUM && !leafData ){ - rc = ptrmapPutOvfl(pParent, nxDiv); - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } - } + j++; nxDiv++; - } - - /* Set the pointer-map entry for the new sibling page. */ - if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno); - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } } } assert( j==nCell ); assert( nOld>0 ); assert( nNew>0 ); if( (pageFlags & PTF_LEAF)==0 ){ u8 *zChild = &apCopy[nOld-1]->aData[8]; memcpy(&apNew[nNew-1]->aData[8], zChild, 4); - if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, get4byte(zChild), PTRMAP_BTREE, apNew[nNew-1]->pgno); - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } - } - } - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - if( nxDiv==pParent->nCell+pParent->nOverflow ){ - /* Right-most sibling is the right-most child of pParent */ - put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew[nNew-1]); - }else{ - /* Right-most sibling is the left child of the first entry in pParent - ** past the right-most divider entry */ - put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]); - } - - /* - ** Balance the parent page. Note that the current page (pPage) might - ** have been added to the freelist so it might no longer be initialized. - ** But the parent page will always be initialized. - */ + } + + if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){ + /* The root page of the b-tree now contains no cells. The only sibling + ** page is the right-child of the parent. Copy the contents of the + ** child page into the parent, decreasing the overall height of the + ** b-tree structure by one. This is described as the "balance-shallower" + ** sub-algorithm in some documentation. + ** + ** If this is an auto-vacuum database, the call to copyNodeContent() + ** sets all pointer-map entries corresponding to database image pages + ** for which the pointer is stored within the content being copied. + ** + ** The second assert below verifies that the child page is defragmented + ** (it must be, as it was just reconstructed using assemblePage()). This + ** is important if the parent page happens to be page 1 of the database + ** image. */ + assert( nNew==1 ); + assert( apNew[0]->nFree == + (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) + ); + copyNodeContent(apNew[0], pParent, &rc); + freePage(apNew[0], &rc); + }else if( ISAUTOVACUUM ){ + /* Fix the pointer-map entries for all the cells that were shifted around. + ** There are several different types of pointer-map entries that need to + ** be dealt with by this routine. Some of these have been set already, but + ** many have not. The following is a summary: + ** + ** 1) The entries associated with new sibling pages that were not + ** siblings when this function was called. These have already + ** been set. We don't need to worry about old siblings that were + ** moved to the free-list - the freePage() code has taken care + ** of those. + ** + ** 2) The pointer-map entries associated with the first overflow + ** page in any overflow chains used by new divider cells. These + ** have also already been taken care of by the insertCell() code. + ** + ** 3) If the sibling pages are not leaves, then the child pages of + ** cells stored on the sibling pages may need to be updated. + ** + ** 4) If the sibling pages are not internal intkey nodes, then any + ** overflow pages used by these cells may need to be updated + ** (internal intkey nodes never contain pointers to overflow pages). + ** + ** 5) If the sibling pages are not leaves, then the pointer-map + ** entries for the right-child pages of each sibling may need + ** to be updated. + ** + ** Cases 1 and 2 are dealt with above by other code. The next + ** block deals with cases 3 and 4 and the one after that, case 5. Since + ** setting a pointer map entry is a relatively expensive operation, this + ** code only sets pointer map entries for child or overflow pages that have + ** actually moved between pages. */ + MemPage *pNew = apNew[0]; + MemPage *pOld = apCopy[0]; + int nOverflow = pOld->nOverflow; + int iNextOld = pOld->nCell + nOverflow; + int iOverflow = (nOverflow ? pOld->aOvfl[0].idx : -1); + j = 0; /* Current 'old' sibling page */ + k = 0; /* Current 'new' sibling page */ + for(i=0; i<nCell; i++){ + int isDivider = 0; + while( i==iNextOld ){ + /* Cell i is the cell immediately following the last cell on old + ** sibling page j. If the siblings are not leaf pages of an + ** intkey b-tree, then cell i was a divider cell. */ + pOld = apCopy[++j]; + iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow; + if( pOld->nOverflow ){ + nOverflow = pOld->nOverflow; + iOverflow = i + !leafData + pOld->aOvfl[0].idx; + } + isDivider = !leafData; + } + + assert(nOverflow>0 || iOverflow<i ); + assert(nOverflow<2 || pOld->aOvfl[0].idx==pOld->aOvfl[1].idx-1); + assert(nOverflow<3 || pOld->aOvfl[1].idx==pOld->aOvfl[2].idx-1); + if( i==iOverflow ){ + isDivider = 1; + if( (--nOverflow)>0 ){ + iOverflow++; + } + } + + if( i==cntNew[k] ){ + /* Cell i is the cell immediately following the last cell on new + ** sibling page k. If the siblings are not leaf pages of an + ** intkey b-tree, then cell i is a divider cell. */ + pNew = apNew[++k]; + if( !leafData ) continue; + } + assert( j<nOld ); + assert( k<nNew ); + + /* If the cell was originally divider cell (and is not now) or + ** an overflow cell, or if the cell was located on a different sibling + ** page before the balancing, then the pointer map entries associated + ** with any child or overflow pages need to be updated. */ + if( isDivider || pOld->pgno!=pNew->pgno ){ + if( !leafCorrection ){ + ptrmapPut(pBt, get4byte(apCell[i]), PTRMAP_BTREE, pNew->pgno, &rc); + } + if( szCell[i]>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, apCell[i], &rc); + } + } + } + + if( !leafCorrection ){ + for(i=0; i<nNew; i++){ + u32 key = get4byte(&apNew[i]->aData[8]); + ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); + } + } + +#if 0 + /* The ptrmapCheckPages() contains assert() statements that verify that + ** all pointer map pages are set correctly. This is helpful while + ** debugging. This is usually disabled because a corrupt database may + ** cause an assert() statement to fail. */ + ptrmapCheckPages(apNew, nNew); + ptrmapCheckPages(&pParent, 1); +#endif + } + assert( pParent->isInit ); - sqlite3ScratchFree(apCell); - apCell = 0; - TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n", - pPage->pgno, nOld, nNew, nCell)); - pPage->nOverflow = 0; - releasePage(pPage); - pCur->iPage--; - rc = balance(pCur, 0); + TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", + nOld, nNew, nCell)); /* ** Cleanup before returning. */ balance_cleanup: - sqlite3PageFree(aSpace2); sqlite3ScratchFree(apCell); for(i=0; i<nOld; i++){ releasePage(apOld[i]); } for(i=0; i<nNew; i++){ releasePage(apNew[i]); } - pCur->apPage[pCur->iPage]->nOverflow = 0; - - return rc; -} - -/* -** This routine is called for the root page of a btree when the root -** page contains no cells. This is an opportunity to make the tree -** shallower by one level. -*/ -static int balance_shallower(BtCursor *pCur){ - MemPage *pPage; /* Root page of B-Tree */ - MemPage *pChild; /* The only child page of pPage */ - Pgno pgnoChild; /* Page number for pChild */ - int rc = SQLITE_OK; /* Return code from subprocedures */ - BtShared *pBt; /* The main BTree structure */ - int mxCellPerPage; /* Maximum number of cells per page */ - u8 **apCell; /* All cells from pages being balanced */ - u16 *szCell; /* Local size of all cells */ - - assert( pCur->iPage==0 ); - pPage = pCur->apPage[0]; - - assert( pPage->nCell==0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pBt = pPage->pBt; - mxCellPerPage = MX_CELL(pBt); - apCell = sqlite3Malloc( mxCellPerPage*(sizeof(u8*)+sizeof(u16)) ); - if( apCell==0 ) return SQLITE_NOMEM; - szCell = (u16*)&apCell[mxCellPerPage]; - if( pPage->leaf ){ - /* The table is completely empty */ - TRACE(("BALANCE: empty table %d\n", pPage->pgno)); - }else{ - /* The root page is empty but has one child. Transfer the - ** information from that one child into the root page if it - ** will fit. This reduces the depth of the tree by one. - ** - ** If the root page is page 1, it has less space available than - ** its child (due to the 100 byte header that occurs at the beginning - ** of the database fle), so it might not be able to hold all of the - ** information currently contained in the child. If this is the - ** case, then do not do the transfer. Leave page 1 empty except - ** for the right-pointer to the child page. The child page becomes - ** the virtual root of the tree. - */ - VVA_ONLY( pCur->pagesShuffled = 1 ); - pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]); - assert( pgnoChild>0 ); - assert( pgnoChild<=pagerPagecount(pPage->pBt) ); - rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0); - if( rc ) goto end_shallow_balance; - if( pPage->pgno==1 ){ - rc = sqlite3BtreeInitPage(pChild); - if( rc ) goto end_shallow_balance; - assert( pChild->nOverflow==0 ); - if( pChild->nFree>=100 ){ - /* The child information will fit on the root page, so do the - ** copy */ - int i; - zeroPage(pPage, pChild->aData[0]); - for(i=0; i<pChild->nCell; i++){ - apCell[i] = findCell(pChild,i); - szCell[i] = cellSizePtr(pChild, apCell[i]); - } - assemblePage(pPage, pChild->nCell, apCell, szCell); - /* Copy the right-pointer of the child to the parent. */ - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - put4byte(&pPage->aData[pPage->hdrOffset+8], - get4byte(&pChild->aData[pChild->hdrOffset+8])); - rc = freePage(pChild); - TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno)); - }else{ - /* The child has more information that will fit on the root. - ** The tree is already balanced. Do nothing. */ - TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno)); - } - }else{ - memcpy(pPage->aData, pChild->aData, pPage->pBt->usableSize); - pPage->isInit = 0; - rc = sqlite3BtreeInitPage(pPage); - assert( rc==SQLITE_OK ); - freePage(pChild); - TRACE(("BALANCE: transfer child %d into root %d\n", - pChild->pgno, pPage->pgno)); - } - assert( pPage->nOverflow==0 ); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( ISAUTOVACUUM && rc==SQLITE_OK ){ - rc = setChildPtrmaps(pPage); - } -#endif + + return rc; +} + + +/* +** This function is called when the root page of a b-tree structure is +** overfull (has one or more overflow pages). +** +** A new child page is allocated and the contents of the current root +** page, including overflow cells, are copied into the child. The root +** page is then overwritten to make it an empty page with the right-child +** pointer pointing to the new page. +** +** Before returning, all pointer-map entries corresponding to pages +** that the new child-page now contains pointers to are updated. The +** entry corresponding to the new right-child pointer of the root +** page is also updated. +** +** If successful, *ppChild is set to contain a reference to the child +** page and SQLITE_OK is returned. In this case the caller is required +** to call releasePage() on *ppChild exactly once. If an error occurs, +** an error code is returned and *ppChild is set to 0. +*/ +static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ + int rc; /* Return value from subprocedures */ + MemPage *pChild = 0; /* Pointer to a new child page */ + Pgno pgnoChild = 0; /* Page number of the new child page */ + BtShared *pBt = pRoot->pBt; /* The BTree */ + + assert( pRoot->nOverflow>0 ); + assert( sqlite3_mutex_held(pBt->mutex) ); + + /* Make pRoot, the root page of the b-tree, writable. Allocate a new + ** page that will become the new right-child of pPage. Copy the contents + ** of the node stored on pRoot into the new child page. + */ + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc==SQLITE_OK ){ + rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0); + copyNodeContent(pRoot, pChild, &rc); + if( ISAUTOVACUUM ){ + ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc); + } + } + if( rc ){ + *ppChild = 0; releasePage(pChild); - } -end_shallow_balance: - sqlite3_free(apCell); - return rc; -} - - -/* -** The root page is overfull -** -** When this happens, Create a new child page and copy the -** contents of the root into the child. Then make the root -** page an empty page with rightChild pointing to the new -** child. Finally, call balance_internal() on the new child -** to cause it to split. -*/ -static int balance_deeper(BtCursor *pCur){ - int rc; /* Return value from subprocedures */ - MemPage *pPage; /* Pointer to the root page */ - MemPage *pChild; /* Pointer to a new child page */ - Pgno pgnoChild; /* Page number of the new child page */ - BtShared *pBt; /* The BTree */ - int usableSize; /* Total usable size of a page */ - u8 *data; /* Content of the parent page */ - u8 *cdata; /* Content of the child page */ - int hdr; /* Offset to page header in parent */ - int cbrk; /* Offset to content of first cell in parent */ - - assert( pCur->iPage==0 ); - assert( pCur->apPage[0]->nOverflow>0 ); - - VVA_ONLY( pCur->pagesShuffled = 1 ); - pPage = pCur->apPage[0]; - pBt = pPage->pBt; - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); - if( rc ) return rc; + return rc; + } assert( sqlite3PagerIswriteable(pChild->pDbPage) ); - usableSize = pBt->usableSize; - data = pPage->aData; - hdr = pPage->hdrOffset; - cbrk = get2byte(&data[hdr+5]); - cdata = pChild->aData; - memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr); - memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk); - - assert( pChild->isInit==0 ); - rc = sqlite3BtreeInitPage(pChild); - if( rc==SQLITE_OK ){ - int nCopy = pPage->nOverflow*sizeof(pPage->aOvfl[0]); - memcpy(pChild->aOvfl, pPage->aOvfl, nCopy); - pChild->nOverflow = pPage->nOverflow; - if( pChild->nOverflow ){ - pChild->nFree = 0; - } - assert( pChild->nCell==pPage->nCell ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF); - put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild); - TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno)); - if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( rc==SQLITE_OK ){ - rc = setChildPtrmaps(pChild); - } - if( rc ){ - pChild->nOverflow = 0; - } -#endif - } - } - - if( rc==SQLITE_OK ){ - pCur->iPage++; - pCur->apPage[1] = pChild; - pCur->aiIdx[0] = 0; - rc = balance_nonroot(pCur); - }else{ - releasePage(pChild); - } - - return rc; + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); + assert( pChild->nCell==pRoot->nCell ); + + TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); + + /* Copy the overflow cells from pRoot to pChild */ + memcpy(pChild->aOvfl, pRoot->aOvfl, pRoot->nOverflow*sizeof(pRoot->aOvfl[0])); + pChild->nOverflow = pRoot->nOverflow; + + /* Zero the contents of pRoot. Then install pChild as the right-child. */ + zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF); + put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild); + + *ppChild = pChild; + return SQLITE_OK; } /* ** The page that pCur currently points to has just been modified in ** some way. This function figures out if this modification means the ** tree needs to be balanced, and if so calls the appropriate balancing -** routine. -** -** Parameter isInsert is true if a new cell was just inserted into the -** page, or false otherwise. -*/ -static int balance(BtCursor *pCur, int isInsert){ - int rc = SQLITE_OK; - MemPage *pPage = pCur->apPage[pCur->iPage]; - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - if( pCur->iPage==0 ){ - rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc==SQLITE_OK && pPage->nOverflow>0 ){ - rc = balance_deeper(pCur); - assert( pCur->apPage[0]==pPage ); - assert( pPage->nOverflow==0 || rc!=SQLITE_OK ); - } - if( rc==SQLITE_OK && pPage->nCell==0 ){ - rc = balance_shallower(pCur); - assert( pCur->apPage[0]==pPage ); - assert( pPage->nOverflow==0 || rc!=SQLITE_OK ); - } - }else{ - if( pPage->nOverflow>0 || - (!isInsert && pPage->nFree>pPage->pBt->usableSize*2/3) ){ - rc = balance_nonroot(pCur); - } - } - return rc; -} - -/* -** This routine checks all cursors that point to table pgnoRoot. -** If any of those cursors were opened with wrFlag==0 in a different -** database connection (a database connection that shares the pager -** cache with the current connection) and that other connection -** is not in the ReadUncommmitted state, then this routine returns -** SQLITE_LOCKED. -** -** As well as cursors with wrFlag==0, cursors with -** isIncrblobHandle==1 are also considered 'read' cursors because -** incremental blob cursors are used for both reading and writing. -** -** When pgnoRoot is the root page of an intkey table, this function is also -** responsible for invalidating incremental blob cursors when the table row -** on which they are opened is deleted or modified. Cursors are invalidated -** according to the following rules: -** -** 1) When BtreeClearTable() is called to completely delete the contents -** of a B-Tree table, pExclude is set to zero and parameter iRow is -** set to non-zero. In this case all incremental blob cursors open -** on the table rooted at pgnoRoot are invalidated. -** -** 2) When BtreeInsert(), BtreeDelete() or BtreePutData() is called to -** modify a table row via an SQL statement, pExclude is set to the -** write cursor used to do the modification and parameter iRow is set -** to the integer row id of the B-Tree entry being modified. Unless -** pExclude is itself an incremental blob cursor, then all incremental -** blob cursors open on row iRow of the B-Tree are invalidated. -** -** 3) If both pExclude and iRow are set to zero, no incremental blob -** cursors are invalidated. -*/ -static int checkForReadConflicts( - Btree *pBtree, /* The database file to check */ - Pgno pgnoRoot, /* Look for read cursors on this btree */ - BtCursor *pExclude, /* Ignore this cursor */ - i64 iRow /* The rowid that might be changing */ -){ - BtCursor *p; - BtShared *pBt = pBtree->pBt; - sqlite3 *db = pBtree->db; - assert( sqlite3BtreeHoldsMutex(pBtree) ); - for(p=pBt->pCursor; p; p=p->pNext){ - if( p==pExclude ) continue; - if( p->pgnoRoot!=pgnoRoot ) continue; -#ifndef SQLITE_OMIT_INCRBLOB - if( p->isIncrblobHandle && ( - (!pExclude && iRow) - || (pExclude && !pExclude->isIncrblobHandle && p->info.nKey==iRow) - )){ - p->eState = CURSOR_INVALID; - } -#endif - if( p->eState!=CURSOR_VALID ) continue; - if( p->wrFlag==0 -#ifndef SQLITE_OMIT_INCRBLOB - || p->isIncrblobHandle -#endif - ){ - sqlite3 *dbOther = p->pBtree->db; - assert(dbOther); - if( dbOther!=db && (dbOther->flags & SQLITE_ReadUncommitted)==0 ){ - sqlite3ConnectionBlocked(db, dbOther); - return SQLITE_LOCKED_SHAREDCACHE; - } - } - } - return SQLITE_OK; -} +** routine. Balancing routines are: +** +** balance_quick() +** balance_deeper() +** balance_nonroot() +*/ +static int balance(BtCursor *pCur){ + int rc = SQLITE_OK; + const int nMin = pCur->pBt->usableSize * 2 / 3; + u8 aBalanceQuickSpace[13]; + u8 *pFree = 0; + + TESTONLY( int balance_quick_called = 0 ); + TESTONLY( int balance_deeper_called = 0 ); + + do { + int iPage = pCur->iPage; + MemPage *pPage = pCur->apPage[iPage]; + + if( iPage==0 ){ + if( pPage->nOverflow ){ + /* The root page of the b-tree is overfull. In this case call the + ** balance_deeper() function to create a new child for the root-page + ** and copy the current contents of the root-page to it. The + ** next iteration of the do-loop will balance the child page. + */ + assert( (balance_deeper_called++)==0 ); + rc = balance_deeper(pPage, &pCur->apPage[1]); + if( rc==SQLITE_OK ){ + pCur->iPage = 1; + pCur->aiIdx[0] = 0; + pCur->aiIdx[1] = 0; + assert( pCur->apPage[1]->nOverflow ); + } + }else{ + break; + } + }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){ + break; + }else{ + MemPage * const pParent = pCur->apPage[iPage-1]; + int const iIdx = pCur->aiIdx[iPage-1]; + + rc = sqlite3PagerWrite(pParent->pDbPage); + if( rc==SQLITE_OK ){ +#ifndef SQLITE_OMIT_QUICKBALANCE + if( pPage->hasData + && pPage->nOverflow==1 + && pPage->aOvfl[0].idx==pPage->nCell + && pParent->pgno!=1 + && pParent->nCell==iIdx + ){ + /* Call balance_quick() to create a new sibling of pPage on which + ** to store the overflow cell. balance_quick() inserts a new cell + ** into pParent, which may cause pParent overflow. If this + ** happens, the next interation of the do-loop will balance pParent + ** use either balance_nonroot() or balance_deeper(). Until this + ** happens, the overflow cell is stored in the aBalanceQuickSpace[] + ** buffer. + ** + ** The purpose of the following assert() is to check that only a + ** single call to balance_quick() is made for each call to this + ** function. If this were not verified, a subtle bug involving reuse + ** of the aBalanceQuickSpace[] might sneak in. + */ + assert( (balance_quick_called++)==0 ); + rc = balance_quick(pParent, pPage, aBalanceQuickSpace); + }else +#endif + { + /* In this case, call balance_nonroot() to redistribute cells + ** between pPage and up to 2 of its sibling pages. This involves + ** modifying the contents of pParent, which may cause pParent to + ** become overfull or underfull. The next iteration of the do-loop + ** will balance the parent page to correct this. + ** + ** If the parent page becomes overfull, the overflow cell or cells + ** are stored in the pSpace buffer allocated immediately below. + ** A subsequent iteration of the do-loop will deal with this by + ** calling balance_nonroot() (balance_deeper() may be called first, + ** but it doesn't deal with overflow cells - just moves them to a + ** different page). Once this subsequent call to balance_nonroot() + ** has completed, it is safe to release the pSpace buffer used by + ** the previous call, as the overflow cell data will have been + ** copied either into the body of a database page or into the new + ** pSpace buffer passed to the latter call to balance_nonroot(). + */ + u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); + rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1); + if( pFree ){ + /* If pFree is not NULL, it points to the pSpace buffer used + ** by a previous call to balance_nonroot(). Its contents are + ** now stored either on real database pages or within the + ** new pSpace buffer, so it may be safely freed here. */ + sqlite3PageFree(pFree); + } + + /* The pSpace buffer will be freed after the next call to + ** balance_nonroot(), or just before this function returns, whichever + ** comes first. */ + pFree = pSpace; + } + } + + pPage->nOverflow = 0; + + /* The next iteration of the do-loop balances the parent page. */ + releasePage(pPage); + pCur->iPage--; + } + }while( rc==SQLITE_OK ); + + if( pFree ){ + sqlite3PageFree(pFree); + } + return rc; +} + /* ** Insert a new record into the BTree. The key is given by (pKey,nKey) ** and the data is given by (pData,nData). The cursor is used only to ** define what table the record should be inserted into. The cursor ** is left pointing at a random location. ** ** For an INTKEY table, only the nKey value of the key is used. pKey is ** ignored. For a ZERODATA table, the pData and nData are both ignored. +** +** If the seekResult parameter is non-zero, then a successful call to +** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already +** been performed. seekResult is the search result returned (a negative +** number if pCur points at an entry that is smaller than (pKey, nKey), or +** a positive value if pCur points at an etry that is larger than +** (pKey, nKey)). +** +** If the seekResult parameter is non-zero, then the caller guarantees that +** cursor pCur is pointing at the existing copy of a row that is to be +** overwritten. If the seekResult parameter is 0, then cursor pCur may +** point to any entry or to no entry at all and so this function has to seek +** the cursor before the new key can be inserted. */ SQLITE_PRIVATE int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ const void *pKey, i64 nKey, /* The key of the new record */ const void *pData, int nData, /* The data of the new record */ int nZero, /* Number of extra 0 bytes to append to data */ - int appendBias /* True if this is likely an append */ -){ - int rc; - int loc; + int appendBias, /* True if this is likely an append */ + int seekResult /* Result of prior MovetoUnpacked() call */ +){ + int rc; + int loc = seekResult; /* -1: before desired location +1: after */ int szNew; int idx; MemPage *pPage; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; unsigned char *oldCell; unsigned char *newCell = 0; - assert( cursorHoldsMutex(pCur) ); - assert( pBt->inTransaction==TRANS_WRITE ); - assert( !pBt->readOnly ); - assert( pCur->wrFlag ); - rc = checkForReadConflicts(pCur->pBtree, pCur->pgnoRoot, pCur, nKey); - if( rc ){ - /* The table pCur points to has a read lock */ - assert( rc==SQLITE_LOCKED_SHAREDCACHE ); - return rc; - } if( pCur->eState==CURSOR_FAULT ){ - return pCur->skip; - } - - /* Save the positions of any other cursors open on this table */ - sqlite3BtreeClearCursor(pCur); - if( - SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || - SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) - ){ - return rc; - } + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; + } + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE && !pBt->readOnly ); + assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); + + /* Assert that the caller has been consistent. If this cursor was opened + ** expecting an index b-tree, then the caller should be inserting blob + ** keys with no associated data. If the cursor was opened expecting an + ** intkey table, the caller should be inserting integer keys with a + ** blob of associated data. */ + assert( (pKey==0)==(pCur->pKeyInfo==0) ); + + /* If this is an insert into a table b-tree, invalidate any incrblob + ** cursors open on the row being replaced (assuming this is a replace + ** operation - if it is not, the following is a no-op). */ + if( pCur->pKeyInfo==0 ){ + invalidateIncrblobCursors(p, nKey, 0); + } + + /* Save the positions of any other cursors open on this table. + ** + ** In some cases, the call to btreeMoveto() below is a no-op. For + ** example, when inserting data into a table with auto-generated integer + ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the + ** integer key to use. It then calls this function to actually insert the + ** data into the intkey B-Tree. In this case btreeMoveto() recognizes + ** that the cursor is already where it needs to be and returns without + ** doing any work. To avoid thwarting these optimizations, it is important + ** not to clear the cursor here. + */ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; + if( !loc ){ + rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc); + if( rc ) return rc; + } + assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); pPage = pCur->apPage[pCur->iPage]; assert( pPage->intKey || nKey>=0 ); assert( pPage->leaf || !pPage->intKey ); + TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", pCur->pgnoRoot, nKey, nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); assert( pPage->isInit ); allocateTempSpace(pBt); @@ -42330,11 +44055,11 @@ rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); if( rc ) goto end_insert; assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew<=MX_CELL_SIZE(pBt) ); idx = pCur->aiIdx[pCur->iPage]; - if( loc==0 && CURSOR_VALID==pCur->eState ){ + if( loc==0 ){ u16 szOld; assert( idx<pPage->nCell ); rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ){ goto end_insert; @@ -42343,236 +44068,169 @@ if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } szOld = cellSizePtr(pPage, oldCell); rc = clearCell(pPage, oldCell); - if( rc ) goto end_insert; - rc = dropCell(pPage, idx, szOld); - if( rc!=SQLITE_OK ) { - goto end_insert; - } + dropCell(pPage, idx, szOld, &rc); + if( rc ) goto end_insert; }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->aiIdx[pCur->iPage]; - pCur->info.nSize = 0; - pCur->validNKey = 0; }else{ assert( pPage->leaf ); } - rc = insertCell(pPage, idx, newCell, szNew, 0, 0); - if( rc==SQLITE_OK ){ - rc = balance(pCur, 1); - } - - /* Must make sure nOverflow is reset to zero even if the balance() - ** fails. Internal data structure corruption will result otherwise. */ - pCur->apPage[pCur->iPage]->nOverflow = 0; - - if( rc==SQLITE_OK ){ - moveToRoot(pCur); - } + insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); + assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); + + /* If no error has occured and pPage has an overflow cell, call balance() + ** to redistribute the cells within the tree. Since balance() may move + ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey + ** variables. + ** + ** Previous versions of SQLite called moveToRoot() to move the cursor + ** back to the root page as balance() used to invalidate the contents + ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that, + ** set the cursor state to "invalid". This makes common insert operations + ** slightly faster. + ** + ** There is a subtle but important optimization here too. When inserting + ** multiple records into an intkey b-tree using a single cursor (as can + ** happen while processing an "INSERT INTO ... SELECT" statement), it + ** is advantageous to leave the cursor pointing to the last entry in + ** the b-tree if possible. If the cursor is left pointing to the last + ** entry in the table, and the next row inserted has an integer key + ** larger than the largest existing key, it is possible to insert the + ** row without seeking the cursor. This can be a big performance boost. + */ + pCur->info.nSize = 0; + pCur->validNKey = 0; + if( rc==SQLITE_OK && pPage->nOverflow ){ + rc = balance(pCur); + + /* Must make sure nOverflow is reset to zero even if the balance() + ** fails. Internal data structure corruption will result otherwise. + ** Also, set the cursor state to invalid. This stops saveCursorPosition() + ** from trying to save the current position of the cursor. */ + pCur->apPage[pCur->iPage]->nOverflow = 0; + pCur->eState = CURSOR_INVALID; + } + assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); + end_insert: return rc; } /* ** Delete the entry that the cursor is pointing to. The cursor ** is left pointing at a arbitrary location. */ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ - MemPage *pPage = pCur->apPage[pCur->iPage]; - int idx; - unsigned char *pCell; - int rc; - Pgno pgnoChild = 0; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; - - assert( cursorHoldsMutex(pCur) ); - assert( pPage->isInit ); + int rc; /* Return code */ + MemPage *pPage; /* Page to delete cell from */ + unsigned char *pCell; /* Pointer to cell to delete */ + int iCellIdx; /* Index of cell to delete */ + int iCellDepth; /* Depth of node containing pCell */ + + assert( cursorHoldsMutex(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); assert( !pBt->readOnly ); - if( pCur->eState==CURSOR_FAULT ){ - return pCur->skip; - } - if( NEVER(pCur->aiIdx[pCur->iPage]>=pPage->nCell) ){ - return SQLITE_ERROR; /* The cursor is not pointing to anything */ - } assert( pCur->wrFlag ); - rc = checkForReadConflicts(p, pCur->pgnoRoot, pCur, pCur->info.nKey); - if( rc!=SQLITE_OK ){ - /* The table pCur points to has a read lock */ - assert( rc==SQLITE_LOCKED_SHAREDCACHE ); - return rc; - } - - /* Restore the current cursor position (a no-op if the cursor is not in - ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors - ** open on the same table. Then call sqlite3PagerWrite() on the page - ** that the entry will be deleted from. - */ - if( - (rc = restoreCursorPosition(pCur))!=0 || - (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || - (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 - ){ - return rc; - } - - /* Locate the cell within its page and leave pCell pointing to the - ** data. The clearCell() call frees any overflow pages associated with the - ** cell. The cell itself is still intact. - */ - idx = pCur->aiIdx[pCur->iPage]; - pCell = findCell(pPage, idx); + assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); + assert( !hasReadConflicts(p, pCur->pgnoRoot) ); + + if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell) + || NEVER(pCur->eState!=CURSOR_VALID) + ){ + return SQLITE_ERROR; /* Something has gone awry. */ + } + + /* If this is a delete operation to remove a row from a table b-tree, + ** invalidate any incrblob cursors open on the row being deleted. */ + if( pCur->pKeyInfo==0 ){ + invalidateIncrblobCursors(p, pCur->info.nKey, 0); + } + + iCellDepth = pCur->iPage; + iCellIdx = pCur->aiIdx[iCellDepth]; + pPage = pCur->apPage[iCellDepth]; + pCell = findCell(pPage, iCellIdx); + + /* If the page containing the entry to delete is not a leaf page, move + ** the cursor to the largest entry in the tree that is smaller than + ** the entry being deleted. This cell will replace the cell being deleted + ** from the internal node. The 'previous' entry is used for this instead + ** of the 'next' entry, as the previous entry is always a part of the + ** sub-tree headed by the child page of the cell being deleted. This makes + ** balancing the tree following the delete operation easier. */ if( !pPage->leaf ){ - pgnoChild = get4byte(pCell); - } + int notUsed; + rc = sqlite3BtreePrevious(pCur, ¬Used); + if( rc ) return rc; + } + + /* Save the positions of any other cursors open on this table before + ** making any modifications. Make the page containing the entry to be + ** deleted writable. Then free any overflow pages associated with the + ** entry and finally remove the cell itself from within the page. + */ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; rc = clearCell(pPage, pCell); - if( rc ){ - return rc; - } - + dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc); + if( rc ) return rc; + + /* If the cell deleted was not located on a leaf page, then the cursor + ** is currently pointing to the largest entry in the sub-tree headed + ** by the child-page of the cell that was just deleted from an internal + ** node. The cell from the leaf node needs to be moved to the internal + ** node to replace the deleted cell. */ if( !pPage->leaf ){ - /* - ** The entry we are about to delete is not a leaf so if we do not - ** do something we will leave a hole on an internal page. - ** We have to fill the hole by moving in a cell from a leaf. The - ** next Cell after the one to be deleted is guaranteed to exist and - ** to be a leaf so we can use it. - */ - BtCursor leafCur; - MemPage *pLeafPage = 0; - - unsigned char *pNext; - int notUsed; - unsigned char *tempCell = 0; - assert( !pPage->intKey ); - sqlite3BtreeGetTempCursor(pCur, &leafCur); - rc = sqlite3BtreeNext(&leafCur, ¬Used); - if( rc==SQLITE_OK ){ - assert( leafCur.aiIdx[leafCur.iPage]==0 ); - pLeafPage = leafCur.apPage[leafCur.iPage]; - rc = sqlite3PagerWrite(pLeafPage->pDbPage); - } - if( rc==SQLITE_OK ){ - int leafCursorInvalid = 0; - u16 szNext; - TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", - pCur->pgnoRoot, pPage->pgno, pLeafPage->pgno)); - dropCell(pPage, idx, cellSizePtr(pPage, pCell)); - pNext = findCell(pLeafPage, 0); - szNext = cellSizePtr(pLeafPage, pNext); - assert( MX_CELL_SIZE(pBt)>=szNext+4 ); - allocateTempSpace(pBt); - tempCell = pBt->pTmpSpace; - if( tempCell==0 ){ - rc = SQLITE_NOMEM; - } - if( rc==SQLITE_OK ){ - rc = insertCell(pPage, idx, pNext-4, szNext+4, tempCell, 0); - } - - - /* The "if" statement in the next code block is critical. The - ** slightest error in that statement would allow SQLite to operate - ** correctly most of the time but produce very rare failures. To - ** guard against this, the following macros help to verify that - ** the "if" statement is well tested. - */ - testcase( pPage->nOverflow==0 && pPage->nFree<pBt->usableSize*2/3 - && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 ); - testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3 - && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 ); - testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3+1 - && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 ); - testcase( pPage->nOverflow>0 && pPage->nFree<=pBt->usableSize*2/3 - && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 ); - testcase( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3)) - && pLeafPage->nFree+2+szNext == pBt->usableSize*2/3 ); - - - if( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3)) && - (pLeafPage->nFree+2+szNext > pBt->usableSize*2/3) - ){ - /* This branch is taken if the internal node is now either overflowing - ** or underfull and the leaf node will be underfull after the just cell - ** copied to the internal node is deleted from it. This is a special - ** case because the call to balance() to correct the internal node - ** may change the tree structure and invalidate the contents of - ** the leafCur.apPage[] and leafCur.aiIdx[] arrays, which will be - ** used by the balance() required to correct the underfull leaf - ** node. - ** - ** The formula used in the expression above are based on facets of - ** the SQLite file-format that do not change over time. - */ - testcase( pPage->nFree==pBt->usableSize*2/3+1 ); - testcase( pLeafPage->nFree+2+szNext==pBt->usableSize*2/3+1 ); - leafCursorInvalid = 1; - } - - if( rc==SQLITE_OK ){ - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - put4byte(findOverflowCell(pPage, idx), pgnoChild); - VVA_ONLY( pCur->pagesShuffled = 0 ); - rc = balance(pCur, 0); - } - - if( rc==SQLITE_OK && leafCursorInvalid ){ - /* The leaf-node is now underfull and so the tree needs to be - ** rebalanced. However, the balance() operation on the internal - ** node above may have modified the structure of the B-Tree and - ** so the current contents of leafCur.apPage[] and leafCur.aiIdx[] - ** may not be trusted. - ** - ** It is not possible to copy the ancestry from pCur, as the same - ** balance() call has invalidated the pCur->apPage[] and aiIdx[] - ** arrays. - ** - ** The call to saveCursorPosition() below internally saves the - ** key that leafCur is currently pointing to. Currently, there - ** are two copies of that key in the tree - one here on the leaf - ** page and one on some internal node in the tree. The copy on - ** the leaf node is always the next key in tree-order after the - ** copy on the internal node. So, the call to sqlite3BtreeNext() - ** calls restoreCursorPosition() to point the cursor to the copy - ** stored on the internal node, then advances to the next entry, - ** which happens to be the copy of the key on the internal node. - ** Net effect: leafCur is pointing back to the duplicate cell - ** that needs to be removed, and the leafCur.apPage[] and - ** leafCur.aiIdx[] arrays are correct. - */ - VVA_ONLY( Pgno leafPgno = pLeafPage->pgno ); - rc = saveCursorPosition(&leafCur); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeNext(&leafCur, ¬Used); - } - pLeafPage = leafCur.apPage[leafCur.iPage]; - assert( rc!=SQLITE_OK || pLeafPage->pgno==leafPgno ); - assert( rc!=SQLITE_OK || leafCur.aiIdx[leafCur.iPage]==0 ); - } - - if( SQLITE_OK==rc - && SQLITE_OK==(rc = sqlite3PagerWrite(pLeafPage->pDbPage)) - ){ - dropCell(pLeafPage, 0, szNext); - VVA_ONLY( leafCur.pagesShuffled = 0 ); - rc = balance(&leafCur, 0); - assert( leafCursorInvalid || !leafCur.pagesShuffled - || !pCur->pagesShuffled ); - } - } - sqlite3BtreeReleaseTempCursor(&leafCur); - }else{ - TRACE(("DELETE: table=%d delete from leaf %d\n", - pCur->pgnoRoot, pPage->pgno)); - rc = dropCell(pPage, idx, cellSizePtr(pPage, pCell)); - if( rc==SQLITE_OK ){ - rc = balance(pCur, 0); - } - } + MemPage *pLeaf = pCur->apPage[pCur->iPage]; + int nCell; + Pgno n = pCur->apPage[iCellDepth+1]->pgno; + unsigned char *pTmp; + + pCell = findCell(pLeaf, pLeaf->nCell-1); + nCell = cellSizePtr(pLeaf, pCell); + assert( MX_CELL_SIZE(pBt)>=nCell ); + + allocateTempSpace(pBt); + pTmp = pBt->pTmpSpace; + + rc = sqlite3PagerWrite(pLeaf->pDbPage); + insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); + dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); + if( rc ) return rc; + } + + /* Balance the tree. If the entry deleted was located on a leaf page, + ** then the cursor still points to that page. In this case the first + ** call to balance() repairs the tree, and the if(...) condition is + ** never true. + ** + ** Otherwise, if the entry deleted was on an internal node page, then + ** pCur is pointing to the leaf page from which a cell was removed to + ** replace the cell deleted from the internal node. This is slightly + ** tricky as the leaf node may be underfull, and the internal node may + ** be either under or overfull. In this case run the balancing algorithm + ** on the leaf node first. If the balance proceeds far enough up the + ** tree that we can be sure that any problem in the internal node has + ** been corrected, so be it. Otherwise, after balancing the leaf node, + ** walk the cursor up the tree to the internal node and balance it as + ** well. */ + rc = balance(pCur); + if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){ + while( pCur->iPage>iCellDepth ){ + releasePage(pCur->apPage[pCur->iPage--]); + } + rc = balance(pCur); + } + if( rc==SQLITE_OK ){ moveToRoot(pCur); } return rc; } @@ -42617,14 +44275,11 @@ /* Read the value of meta[3] from the database to determine where the ** root page of the new table should go. meta[3] is the largest root-page ** created so far, so the new root-page is (meta[3]+1). */ - rc = sqlite3BtreeGetMeta(p, 4, &pgnoRoot); - if( rc!=SQLITE_OK ){ - return rc; - } + sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot); pgnoRoot++; /* The new root-page may not be allocated on a pointer-map page, or the ** PENDING_BYTE page. */ @@ -42648,22 +44303,25 @@ ** the new table (assuming an error did not occur). But we were ** allocated pgnoMove. If required (i.e. if it was not allocated ** by extending the file), the current page at position pgnoMove ** is already journaled. */ - u8 eType; - Pgno iPtrPage; + u8 eType = 0; + Pgno iPtrPage = 0; releasePage(pPageMove); /* Move the page currently at pgnoRoot to pgnoMove. */ - rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); if( rc!=SQLITE_OK ){ return rc; } rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); - if( rc!=SQLITE_OK || eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ + if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ + rc = SQLITE_CORRUPT_BKPT; + } + if( rc!=SQLITE_OK ){ releasePage(pRoot); return rc; } assert( eType!=PTRMAP_ROOTPAGE ); assert( eType!=PTRMAP_FREEPAGE ); @@ -42672,11 +44330,11 @@ /* Obtain the page at pgnoRoot */ if( rc!=SQLITE_OK ){ return rc; } - rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); if( rc!=SQLITE_OK ){ return rc; } rc = sqlite3PagerWrite(pRoot->pDbPage); if( rc!=SQLITE_OK ){ @@ -42686,11 +44344,11 @@ }else{ pRoot = pPageMove; } /* Update the pointer-map and meta-data with the new root-page number. */ - rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); + ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc); if( rc ){ releasePage(pRoot); return rc; } rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); @@ -42726,11 +44384,11 @@ BtShared *pBt, /* The BTree that contains the table */ Pgno pgno, /* Page number to clear */ int freePageFlag, /* Deallocate page if true */ int *pnChange ){ - MemPage *pPage = 0; + MemPage *pPage; int rc; unsigned char *pCell; int i; assert( sqlite3_mutex_held(pBt->mutex) ); @@ -42737,11 +44395,11 @@ if( pgno>pagerPagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage); - if( rc ) goto cleardatabasepage_out; + if( rc ) return rc; for(i=0; i<pPage->nCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; @@ -42755,11 +44413,11 @@ }else if( pnChange ){ assert( pPage->intKey ); *pnChange += pPage->nCell; } if( freePageFlag ){ - rc = freePage(pPage); + freePage(pPage, &rc); }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ zeroPage(pPage, pPage->aData[0] | PTF_LEAF); } cleardatabasepage_out: @@ -42783,15 +44441,18 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){ int rc; BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); assert( p->inTrans==TRANS_WRITE ); - if( (rc = checkForReadConflicts(p, iTable, 0, 1))!=SQLITE_OK ){ - /* nothing to do */ - }else if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){ - /* nothing to do */ - }else{ + + /* Invalidate all incrblob cursors open on table iTable (assuming iTable + ** is the root of a table b-tree - if it is not, the following call is + ** a no-op). */ + invalidateIncrblobCursors(p, 0, 1); + + rc = saveAllCursors(pBt, (Pgno)iTable, 0); + if( SQLITE_OK==rc ){ rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange); } sqlite3BtreeLeave(p); return rc; } @@ -42827,17 +44488,19 @@ /* It is illegal to drop a table if any cursors are open on the ** database. This is because in auto-vacuum mode the backend may ** need to move another root-page to fill a gap left by the deleted ** root page. If an open cursor was using this page a problem would ** occur. - */ - if( pBt->pCursor ){ + ** + ** This error is caught long before control reaches this point. + */ + if( NEVER(pBt->pCursor) ){ sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db); return SQLITE_LOCKED_SHAREDCACHE; } - rc = sqlite3BtreeGetPage(pBt, (Pgno)iTable, &pPage, 0); + rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; rc = sqlite3BtreeClearTable(p, iTable, 0); if( rc ){ releasePage(pPage); return rc; @@ -42845,26 +44508,22 @@ *piMoved = 0; if( iTable>1 ){ #ifdef SQLITE_OMIT_AUTOVACUUM - rc = freePage(pPage); + freePage(pPage, &rc); releasePage(pPage); #else if( pBt->autoVacuum ){ Pgno maxRootPgno; - rc = sqlite3BtreeGetMeta(p, 4, &maxRootPgno); - if( rc!=SQLITE_OK ){ - releasePage(pPage); - return rc; - } + sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno); if( iTable==maxRootPgno ){ /* If the table being dropped is the table with the largest root-page ** number in the database, put the root page on the free list. */ - rc = freePage(pPage); + freePage(pPage, &rc); releasePage(pPage); if( rc!=SQLITE_OK ){ return rc; } }else{ @@ -42872,24 +44531,22 @@ ** number in the database. So move the page that does into the ** gap left by the deleted root-page. */ MemPage *pMove; releasePage(pPage); - rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); + rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); if( rc!=SQLITE_OK ){ return rc; } rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0); releasePage(pMove); if( rc!=SQLITE_OK ){ return rc; } - rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = freePage(pMove); + pMove = 0; + rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); + freePage(pMove, &rc); releasePage(pMove); if( rc!=SQLITE_OK ){ return rc; } *piMoved = maxRootPgno; @@ -42899,26 +44556,27 @@ ** is the old value less one, less one more if that happens to ** be a root-page number, less one again if that is the ** PENDING_BYTE_PAGE. */ maxRootPgno--; - if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){ - maxRootPgno--; - } - if( maxRootPgno==PTRMAP_PAGENO(pBt, maxRootPgno) ){ + while( maxRootPgno==PENDING_BYTE_PAGE(pBt) + || PTRMAP_ISPAGE(pBt, maxRootPgno) ){ maxRootPgno--; } assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); }else{ - rc = freePage(pPage); + freePage(pPage, &rc); releasePage(pPage); } #endif }else{ - /* If sqlite3BtreeDropTable was called on page 1. */ + /* If sqlite3BtreeDropTable was called on page 1. + ** This really never should happen except in a corrupt + ** database. + */ zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); releasePage(pPage); } return rc; } @@ -42930,84 +44588,40 @@ return rc; } /* +** This function may only be called if the b-tree connection already +** has a read or write transaction open on the database. +** ** Read the meta-information out of a database file. Meta[0] ** is the number of free pages currently in the database. Meta[1] ** through meta[15] are available for use by higher layers. Meta[0] ** is read-only, the others are read/write. ** ** The schema layer numbers meta values differently. At the schema ** layer (and the SetCookie and ReadCookie opcodes) the number of ** free pages is not visible. So Cookie[0] is the same as Meta[1]. */ -SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ - DbPage *pDbPage = 0; - int rc; - unsigned char *pP1; +SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); - - /* Reading a meta-data value requires a read-lock on page 1 (and hence - ** the sqlite_master table. We grab this lock regardless of whether or - ** not the SQLITE_ReadUncommitted flag is set (the table rooted at page - ** 1 is treated as a special case by querySharedCacheTableLock() - ** and setSharedCacheTableLock()). - */ - rc = querySharedCacheTableLock(p, 1, READ_LOCK); - if( rc!=SQLITE_OK ){ - sqlite3BtreeLeave(p); - return rc; - } - + assert( p->inTrans>TRANS_NONE ); + assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); + assert( pBt->pPage1 ); assert( idx>=0 && idx<=15 ); - if( pBt->pPage1 ){ - /* The b-tree is already holding a reference to page 1 of the database - ** file. In this case the required meta-data value can be read directly - ** from the page data of this reference. This is slightly faster than - ** requesting a new reference from the pager layer. - */ - pP1 = (unsigned char *)pBt->pPage1->aData; - }else{ - /* The b-tree does not have a reference to page 1 of the database file. - ** Obtain one from the pager layer. - */ - rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage); - if( rc ){ - sqlite3BtreeLeave(p); - return rc; - } - pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage); - } - *pMeta = get4byte(&pP1[36 + idx*4]); - - /* If the b-tree is not holding a reference to page 1, then one was - ** requested from the pager layer in the above block. Release it now. - */ - if( !pBt->pPage1 ){ - sqlite3PagerUnref(pDbPage); - } - - /* If autovacuumed is disabled in this build but we are trying to - ** access an autovacuumed database, then make the database readonly. - */ + + *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); + + /* If auto-vacuum is disabled in this build and this is an auto-vacuum + ** database, mark the database as read-only. */ #ifdef SQLITE_OMIT_AUTOVACUUM - if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; -#endif - - /* If there is currently an open transaction, grab a read-lock - ** on page 1 of the database file. This is done to make sure that - ** no other connection can modify the meta value just read from - ** the database until the transaction is concluded. - */ - if( p->inTrans>0 ){ - rc = setSharedCacheTableLock(p, 1, READ_LOCK); - } - sqlite3BtreeLeave(p); - return rc; + if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ) pBt->readOnly = 1; +#endif + + sqlite3BtreeLeave(p); } /* ** Write meta-information back into the database. Meta[0] is ** read-only and may not be written. @@ -43023,36 +44637,19 @@ pP1 = pBt->pPage1->aData; rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc==SQLITE_OK ){ put4byte(&pP1[36 + idx*4], iMeta); #ifndef SQLITE_OMIT_AUTOVACUUM - if( idx==7 ){ + if( idx==BTREE_INCR_VACUUM ){ assert( pBt->autoVacuum || iMeta==0 ); assert( iMeta==0 || iMeta==1 ); pBt->incrVacuum = (u8)iMeta; } #endif } sqlite3BtreeLeave(p); return rc; -} - -/* -** Return the flag byte at the beginning of the page that the cursor -** is currently pointing to. -*/ -SQLITE_PRIVATE int sqlite3BtreeFlags(BtCursor *pCur){ - /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call - ** restoreCursorPosition() here. - */ - MemPage *pPage; - restoreCursorPosition(pCur); - pPage = pCur->apPage[pCur->iPage]; - assert( cursorHoldsMutex(pCur) ); - assert( pPage!=0 ); - assert( pPage->pBt==pCur->pBt ); - return pPage->aData[pPage->hdrOffset]; } #ifndef SQLITE_OMIT_BTREECOUNT /* ** The first argument, pCur, is a cursor opened on some b-tree. Count the @@ -43098,11 +44695,11 @@ if( pCur->iPage==0 ){ /* All pages of the b-tree have been visited. Return successfully. */ *pnEntry = nEntry; return SQLITE_OK; } - sqlite3BtreeMoveToParent(pCur); + moveToParent(pCur); }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); pCur->aiIdx[pCur->iPage]++; pPage = pCur->apPage[pCur->iPage]; } @@ -43199,11 +44796,11 @@ u8 ePtrmapType; Pgno iPtrmapParent; rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) pCheck->mallocFailed = 1; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1; checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild); return; } if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ @@ -43325,20 +44922,23 @@ */ pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; - if( (rc = sqlite3BtreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ - if( rc==SQLITE_NOMEM ) pCheck->mallocFailed = 1; + if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, zContext, "unable to get the page. error code=%d", rc); return 0; } - if( (rc = sqlite3BtreeInitPage(pPage))!=0 ){ + + /* Clear MemPage.isInit to make sure the corruption detection code in + ** btreeInitPage() is executed. */ + pPage->isInit = 0; + if( (rc = btreeInitPage(pPage))!=0 ){ assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ checkAppendMsg(pCheck, zContext, - "sqlite3BtreeInitPage() returns error code %d", rc); + "btreeInitPage() returns error code %d", rc); releasePage(pPage); return 0; } /* Check out all the cells. @@ -43352,11 +44952,11 @@ /* Check payload overflow pages */ sqlite3_snprintf(sizeof(zContext), zContext, "On tree page %d cell %d: ", iPage, i); pCell = findCell(pPage,i); - sqlite3BtreeParseCellPtr(pPage, pCell, &info); + btreeParseCellPtr(pPage, pCell, &info); sz = info.nData; if( !pPage->intKey ) sz += (int)info.nKey; assert( sz==info.nPayload ); if( (sz>info.nLocal) && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize]) @@ -43406,44 +45006,40 @@ hit = sqlite3PageMalloc( pBt->pageSize ); if( hit==0 ){ pCheck->mallocFailed = 1; }else{ u16 contentOffset = get2byte(&data[hdr+5]); - if (contentOffset > usableSize) { - checkAppendMsg(pCheck, 0, - "Corruption detected in header on page %d",iPage,0); - goto check_page_abort; - } + assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ memset(hit+contentOffset, 0, usableSize-contentOffset); memset(hit, 1, contentOffset); nCell = get2byte(&data[hdr+3]); cellStart = hdr + 12 - 4*pPage->leaf; for(i=0; i<nCell; i++){ int pc = get2byte(&data[cellStart+i*2]); u16 size = 1024; int j; - if( pc<=usableSize ){ + if( pc<=usableSize-4 ){ size = cellSizePtr(pPage, &data[pc]); } - if( (pc+size-1)>=usableSize || pc<0 ){ + if( (pc+size-1)>=usableSize ){ checkAppendMsg(pCheck, 0, "Corruption detected in cell %d on page %d",i,iPage,0); }else{ for(j=pc+size-1; j>=pc; j--) hit[j]++; } } - for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000; - cnt++){ - int size = get2byte(&data[i+2]); - int j; - if( (i+size-1)>=usableSize || i<0 ){ - checkAppendMsg(pCheck, 0, - "Corruption detected in cell %d on page %d",i,iPage,0); - }else{ - for(j=i+size-1; j>=i; j--) hit[j]++; - } - i = get2byte(&data[i]); + i = get2byte(&data[hdr+1]); + while( i>0 ){ + int size, j; + assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */ + size = get2byte(&data[i+2]); + assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */ + for(j=i+size-1; j>=i; j--) hit[j]++; + j = get2byte(&data[i]); + assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */ + assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */ + i = j; } for(i=cnt=0; i<usableSize; i++){ if( hit[i]==0 ){ cnt++; }else if( hit[i]>1 ){ @@ -43452,17 +45048,15 @@ break; } } if( cnt!=data[hdr+7] ){ checkAppendMsg(pCheck, 0, - "Fragmented space is %d byte reported as %d on page %d", + "Fragmentation of %d bytes reported as %d on page %d", cnt, data[hdr+7], iPage); } } -check_page_abort: - if (hit) sqlite3PageFree(hit); - + sqlite3PageFree(hit); releasePage(pPage); return depth+1; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ @@ -43469,10 +45063,13 @@ #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** This routine does a complete check of the given BTree file. aRoot[] is ** an array of pages numbers were each page number is the root page of ** a table. nRoot is the number of entries in aRoot. +** +** A read-only or read-write transaction must be opened before calling +** this function. ** ** Write the number of error seen in *pnErr. Except for some memory ** allocation errors, an error message held in memory obtained from ** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is ** returned. If a memory allocation error occurs, NULL is returned. @@ -43489,31 +45086,25 @@ IntegrityCk sCheck; BtShared *pBt = p->pBt; char zErr[100]; sqlite3BtreeEnter(p); - nRef = sqlite3PagerRefcount(pBt->pPager); - if( lockBtreeWithRetry(p)!=SQLITE_OK ){ - *pnErr = 1; - sqlite3BtreeLeave(p); - return sqlite3DbStrDup(0, "cannot acquire a read lock on the database"); - } + assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); + nRef = sqlite3PagerRefcount(pBt->pPager); sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = pagerPagecount(sCheck.pBt); sCheck.mxErr = mxErr; sCheck.nErr = 0; sCheck.mallocFailed = 0; *pnErr = 0; if( sCheck.nPage==0 ){ - unlockBtreeIfUnused(pBt); sqlite3BtreeLeave(p); return 0; } sCheck.anRef = sqlite3Malloc( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); if( !sCheck.anRef ){ - unlockBtreeIfUnused(pBt); *pnErr = 1; sqlite3BtreeLeave(p); return 0; } for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } @@ -43564,11 +45155,10 @@ /* Make sure this analysis did not leave any unref() pages. ** This is an internal consistency check; an integrity check ** of the integrity check. */ - unlockBtreeIfUnused(pBt); if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){ checkAppendMsg(&sCheck, 0, "Outstanding page count goes from %d to %d during this analysis", nRef, sqlite3PagerRefcount(pBt->pPager) ); @@ -43689,14 +45279,16 @@ ** lock is a write lock if isWritelock is true or a read lock ** if it is false. */ SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ int rc = SQLITE_OK; + assert( p->inTrans!=TRANS_NONE ); if( p->sharable ){ u8 lockType = READ_LOCK + isWriteLock; assert( READ_LOCK+1==WRITE_LOCK ); assert( isWriteLock==0 || isWriteLock==1 ); + sqlite3BtreeEnter(p); rc = querySharedCacheTableLock(p, iTab, lockType); if( rc==SQLITE_OK ){ rc = setSharedCacheTableLock(p, iTab, lockType); } @@ -43709,47 +45301,47 @@ #ifndef SQLITE_OMIT_INCRBLOB /* ** Argument pCsr must be a cursor opened for writing on an ** INTKEY table currently pointing at a valid table entry. ** This function modifies the data stored as part of that entry. -** Only the data content may only be modified, it is not possible -** to change the length of the data stored. +** +** Only the data content may only be modified, it is not possible to +** change the length of the data stored. If this function is called with +** parameters that attempt to write past the end of the existing data, +** no modifications are made and SQLITE_CORRUPT is returned. */ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ int rc; - assert( cursorHoldsMutex(pCsr) ); assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); - assert(pCsr->isIncrblobHandle); - - restoreCursorPosition(pCsr); + assert( pCsr->isIncrblobHandle ); + + rc = restoreCursorPosition(pCsr); + if( rc!=SQLITE_OK ){ + return rc; + } assert( pCsr->eState!=CURSOR_REQUIRESEEK ); if( pCsr->eState!=CURSOR_VALID ){ return SQLITE_ABORT; } - /* Check some preconditions: + /* Check some assumptions: ** (a) the cursor is open for writing, - ** (b) there is no read-lock on the table being modified and - ** (c) the cursor points at a valid row of an intKey table. + ** (b) there is a read/write transaction open, + ** (c) the connection holds a write-lock on the table (if required), + ** (d) there are no conflicting read-locks, and + ** (e) the cursor points at a valid row of an intKey table. */ if( !pCsr->wrFlag ){ return SQLITE_READONLY; } - assert( !pCsr->pBt->readOnly - && pCsr->pBt->inTransaction==TRANS_WRITE ); - rc = checkForReadConflicts(pCsr->pBtree, pCsr->pgnoRoot, pCsr, 0); - if( rc!=SQLITE_OK ){ - /* The table pCur points to has a read lock */ - assert( rc==SQLITE_LOCKED_SHAREDCACHE ); - return rc; - } - if( pCsr->eState==CURSOR_INVALID || !pCsr->apPage[pCsr->iPage]->intKey ){ - return SQLITE_ERROR; - } - - return accessPayload(pCsr, offset, amt, (unsigned char *)z, 0, 1); + assert( !pCsr->pBt->readOnly && pCsr->pBt->inTransaction==TRANS_WRITE ); + assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); + assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); + assert( pCsr->apPage[pCsr->iPage]->intKey ); + + return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); } /* ** Set a flag on this cursor to cache the locations of pages from the ** overflow list for the current row. This is used by cursors opened @@ -43783,11 +45375,11 @@ ** ************************************************************************* ** This file contains the implementation of the sqlite3_backup_XXX() ** API functions and the related features. ** -** $Id: backup.c,v 1.13 2009/03/16 13:19:36 danielk1977 Exp $ +** $Id: backup.c,v 1.19 2009/07/06 19:03:13 drh Exp $ */ /* Macro to find the minimum of two numeric values. */ #ifndef MIN @@ -43813,10 +45405,11 @@ ** read by calls to backup_remaining() and backup_pagecount(). */ Pgno nRemaining; /* Number of pages left to copy */ Pgno nPagecount; /* Total number of pages to copy */ + int isAttached; /* True once backup has been registered with pager */ sqlite3_backup *pNext; /* Next backup associated with source pager */ }; /* ** THREAD SAFETY NOTES: @@ -43859,19 +45452,28 @@ */ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int i = sqlite3FindDbName(pDb, zDb); if( i==1 ){ - Parse sParse; - memset(&sParse, 0, sizeof(sParse)); - sParse.db = pDb; - if( sqlite3OpenTempDatabase(&sParse) ){ - sqlite3ErrorClear(&sParse); - sqlite3Error(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); - return 0; - } - assert( sParse.zErrMsg==0 ); + Parse *pParse; + int rc = 0; + pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); + if( pParse==0 ){ + sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); + rc = SQLITE_NOMEM; + }else{ + pParse->db = pDb; + if( sqlite3OpenTempDatabase(pParse) ){ + sqlite3ErrorClear(pParse); + sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); + rc = SQLITE_ERROR; + } + sqlite3StackFree(pErrorDb, pParse); + } + if( rc ){ + return 0; + } } if( i<0 ){ sqlite3Error(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); return 0; @@ -43926,10 +45528,11 @@ p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); p->pDest = findBtree(pDestDb, pDestDb, zDestDb); p->pDestDb = pDestDb; p->pSrcDb = pSrcDb; p->iNext = 1; + p->isAttached = 0; if( 0==p->pSrc || 0==p->pDest ){ /* One (or both) of the named databases did not exist. An error has ** already been written into the pDestDb handle. All that is left ** to do here is free the sqlite3_backup structure. @@ -43936,22 +45539,11 @@ */ sqlite3_free(p); p = 0; } } - - /* If everything has gone as planned, attach the backup object to the - ** source pager. The source pager calls BackupUpdate() and BackupRestart() - ** to notify this module if the source file is modified mid-backup. - */ - if( p ){ - sqlite3_backup **pp; /* Pointer to head of pagers backup list */ - sqlite3BtreeEnter(p->pSrc); - pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); - p->pNext = *pp; - *pp = p; - sqlite3BtreeLeave(p->pSrc); + if( p ){ p->pSrc->nBackup++; } sqlite3_mutex_leave(pDestDb->mutex); sqlite3_mutex_leave(pSrcDb->mutex); @@ -43962,11 +45554,11 @@ ** Argument rc is an SQLite error code. Return true if this error is ** considered fatal if encountered during a backup operation. All errors ** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. */ static int isFatalError(int rc){ - return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED); + return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED)); } /* ** Parameter zSrcData points to a buffer containing the data for ** page iSrcPg from the source database. Copy this data into the @@ -44041,10 +45633,23 @@ } return rc; } /* +** Register this backup object with the associated source pager for +** callbacks when pages are changed or the cache invalidated. +*/ +static void attachBackupObject(sqlite3_backup *p){ + sqlite3_backup **pp; + assert( sqlite3BtreeHoldsMutex(p->pSrc) ); + pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); + p->pNext = *pp; + *pp = p; + p->isAttached = 1; +} + +/* ** Copy nPage pages from the source b-tree to the destination. */ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ int rc; @@ -44074,11 +45679,11 @@ /* Lock the destination database, if it is not locked already. */ if( SQLITE_OK==rc && p->bDestLocked==0 && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) ){ p->bDestLocked = 1; - rc = sqlite3BtreeGetMeta(p->pDest, 1, &p->iDestSchema); + sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); } /* If there is no open read-transaction on the source database, open ** one now. If a transaction is opened here, then it will be closed ** before this function exits. @@ -44109,24 +45714,27 @@ if( rc==SQLITE_OK ){ p->nPagecount = nSrcPage; p->nRemaining = nSrcPage+1-p->iNext; if( p->iNext>(Pgno)nSrcPage ){ rc = SQLITE_DONE; - } - } - - if( rc==SQLITE_DONE ){ + }else if( !p->isAttached ){ + attachBackupObject(p); + } + } + + /* Update the schema version field in the destination database. This + ** is to make sure that the schema-version really does change in + ** the case where the source and destination databases have the + ** same schema version. + */ + if( rc==SQLITE_DONE + && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK + ){ const int nSrcPagesize = sqlite3BtreeGetPageSize(p->pSrc); const int nDestPagesize = sqlite3BtreeGetPageSize(p->pDest); int nDestTruncate; - /* Update the schema version field in the destination database. This - ** is to make sure that the schema-version really does change in - ** the case where the source and destination databases have the - ** same schema version. - */ - sqlite3BtreeUpdateMeta(p->pDest, 1, p->iDestSchema+1); if( p->pDestDb ){ sqlite3ResetInternalSchema(p->pDestDb, 0); } /* Set nDestTruncate to the final number of pages in the destination @@ -44232,25 +45840,28 @@ sqlite3_backup **pp; /* Ptr to head of pagers backup list */ sqlite3_mutex *mutex; /* Mutex to protect source database */ int rc; /* Value to return */ /* Enter the mutexes */ + if( p==0 ) return SQLITE_OK; sqlite3_mutex_enter(p->pSrcDb->mutex); sqlite3BtreeEnter(p->pSrc); mutex = p->pSrcDb->mutex; if( p->pDestDb ){ sqlite3_mutex_enter(p->pDestDb->mutex); } /* Detach this backup from the source pager. */ if( p->pDestDb ){ + p->pSrc->nBackup--; + } + if( p->isAttached ){ pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); while( *pp!=p ){ pp = &(*pp)->pNext; } *pp = p->pNext; - p->pSrc->nBackup--; } /* If a transaction is still open on the Btree, roll it back. */ sqlite3BtreeRollback(p->pDest); @@ -44398,11 +46009,11 @@ ** This file contains code use to manipulate "Mem" structure. A "Mem" ** stores a single value in the VDBE. Mem is an opaque structure visible ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value ** -** $Id: vdbemem.c,v 1.140 2009/04/05 12:22:09 drh Exp $ +** $Id: vdbemem.c,v 1.152 2009/07/22 18:07:41 drh Exp $ */ /* ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*) ** P if required. @@ -44477,11 +46088,11 @@ sqlite3DbFree(pMem->db, pMem->zMalloc); pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } } - if( preserve && pMem->z && pMem->zMalloc && pMem->z!=pMem->zMalloc ){ + if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){ memcpy(pMem->zMalloc, pMem->z, pMem->n); } if( pMem->flags&MEM_Dyn && pMem->xDel ){ pMem->xDel((void *)(pMem->z)); } @@ -44626,11 +46237,11 @@ ** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK ** otherwise. */ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ int rc = SQLITE_OK; - if( pFunc && pFunc->xFinalize ){ + if( ALWAYS(pFunc && pFunc->xFinalize) ){ sqlite3_context ctx; assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); memset(&ctx, 0, sizeof(ctx)); ctx.s.flags = MEM_Null; @@ -44639,11 +46250,11 @@ ctx.pFunc = pFunc; pFunc->xFinalize(&ctx); assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel ); sqlite3DbFree(pMem->db, pMem->zMalloc); memcpy(pMem, &ctx.s, sizeof(ctx.s)); - rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK); + rc = ctx.isError; } return rc; } /* @@ -44651,20 +46262,28 @@ ** invoking an external callback, free it now. Calling this function ** does not free any Mem.zMalloc buffer. */ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); - if( p->flags&MEM_Agg ){ - sqlite3VdbeMemFinalize(p, p->u.pDef); - assert( (p->flags & MEM_Agg)==0 ); - sqlite3VdbeMemRelease(p); - }else if( p->flags&MEM_Dyn && p->xDel ){ - assert( (p->flags&MEM_RowSet)==0 ); - p->xDel((void *)p->z); - p->xDel = 0; - }else if( p->flags&MEM_RowSet ){ - sqlite3RowSetClear(p->u.pRowSet); + testcase( p->flags & MEM_Agg ); + testcase( p->flags & MEM_Dyn ); + testcase( p->flags & MEM_RowSet ); + testcase( p->flags & MEM_Frame ); + if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){ + if( p->flags&MEM_Agg ){ + sqlite3VdbeMemFinalize(p, p->u.pDef); + assert( (p->flags & MEM_Agg)==0 ); + sqlite3VdbeMemRelease(p); + }else if( p->flags&MEM_Dyn && p->xDel ){ + assert( (p->flags&MEM_RowSet)==0 ); + p->xDel((void *)p->z); + p->xDel = 0; + }else if( p->flags&MEM_RowSet ){ + sqlite3RowSetClear(p->u.pRowSet); + }else if( p->flags&MEM_Frame ){ + sqlite3VdbeMemSetNull(p); + } } } /* ** Release any memory held by the Mem. This may leave the Mem in an @@ -44790,11 +46409,25 @@ assert( (pMem->flags & MEM_RowSet)==0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); pMem->u.i = doubleToInt64(pMem->r); - if( pMem->r==(double)pMem->u.i ){ + + /* Only mark the value as an integer if + ** + ** (1) the round-trip conversion real->int->real is a no-op, and + ** (2) The integer is neither the largest nor the smallest + ** possible integer (ticket #3922) + ** + ** The second and third terms in the following conditional enforces + ** the second condition under the assumption that addition overflow causes + ** values to wrap around. On x86 hardware, the third term is always + ** true and could be omitted. But we leave it in because other + ** architectures might behave differently. + */ + if( pMem->r==(double)pMem->u.i && pMem->u.i>SMALLEST_INT64 + && ALWAYS(pMem->u.i<LARGEST_INT64) ){ pMem->flags |= MEM_Int; } } /* @@ -44847,10 +46480,13 @@ /* ** Delete any previous value and set the value stored in *pMem to NULL. */ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ + if( pMem->flags & MEM_Frame ){ + sqlite3VdbeFrameDelete(pMem->u.pFrame); + } if( pMem->flags & MEM_RowSet ){ sqlite3RowSetClear(pMem->u.pRowSet); } MemSetTypeFlag(pMem, MEM_Null); pMem->type = SQLITE_NULL; @@ -44866,10 +46502,18 @@ pMem->type = SQLITE_BLOB; pMem->n = 0; if( n<0 ) n = 0; pMem->u.nZero = n; pMem->enc = SQLITE_UTF8; + +#ifdef SQLITE_OMIT_INCRBLOB + sqlite3VdbeMemGrow(pMem, n, 0); + if( pMem->z ){ + pMem->n = n; + memset(pMem->z, 0, n); + } +#endif } /* ** Delete any previous value and set the value stored in *pMem to val, ** manifest type INTEGER. @@ -44901,16 +46545,13 @@ ** empty boolean index. */ SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ sqlite3 *db = pMem->db; assert( db!=0 ); - if( pMem->flags & MEM_RowSet ){ - sqlite3RowSetClear(pMem->u.pRowSet); - }else{ - sqlite3VdbeMemRelease(pMem); - pMem->zMalloc = sqlite3DbMallocRaw(db, 64); - } + assert( (pMem->flags & MEM_RowSet)==0 ); + sqlite3VdbeMemRelease(pMem); + pMem->zMalloc = sqlite3DbMallocRaw(db, 64); if( db->mallocFailed ){ pMem->flags = MEM_Null; }else{ assert( pMem->zMalloc ); pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, @@ -45005,10 +46646,16 @@ ** The memory management strategy depends on the value of the xDel ** parameter. If the value passed is SQLITE_TRANSIENT, then the ** string is copied into a (possibly existing) buffer managed by the ** Mem structure. Otherwise, any existing buffer is freed and the ** pointer copied. +** +** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH +** size limit) then no memory allocation occurs. If the string can be +** stored without allocating memory, then it is. If a memory allocation +** is required to store the string, then value of pMem is unchanged. In +** either case, SQLITE_TOOBIG is returned. */ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( Mem *pMem, /* Memory cell to set to string value */ const char *z, /* String pointer */ int n, /* Bytes in string, or negative */ @@ -45068,13 +46715,10 @@ sqlite3VdbeMemRelease(pMem); pMem->z = (char *)z; pMem->xDel = xDel; flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); } - if( nByte>iLimit ){ - return SQLITE_TOOBIG; - } pMem->n = nByte; pMem->flags = flags; pMem->enc = (enc==0 ? SQLITE_UTF8 : enc); pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT); @@ -45082,10 +46726,14 @@ #ifndef SQLITE_OMIT_UTF16 if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ return SQLITE_NOMEM; } #endif + + if( nByte>iLimit ){ + return SQLITE_TOOBIG; + } return SQLITE_OK; } /* @@ -45227,26 +46875,27 @@ int offset, /* Offset from the start of data to return bytes from. */ int amt, /* Number of bytes to return. */ int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ - char *zData; /* Data from the btree layer */ - int available = 0; /* Number of bytes available on the local btree page */ - sqlite3 *db; /* Database connection */ - int rc = SQLITE_OK; - - db = sqlite3BtreeCursorDb(pCur); - assert( sqlite3_mutex_held(db->mutex) ); + char *zData; /* Data from the btree layer */ + int available = 0; /* Number of bytes available on the local btree page */ + int rc = SQLITE_OK; /* Return code */ + + assert( sqlite3BtreeCursorIsValid(pCur) ); + + /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() + ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } assert( zData!=0 ); - if( offset+amt<=available && ((pMem->flags&MEM_Dyn)==0 || pMem->xDel) ){ + if( offset+amt<=available && (pMem->flags&MEM_Dyn)==0 ){ sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; @@ -45351,21 +47000,32 @@ if( !pExpr ){ *ppVal = 0; return SQLITE_OK; } op = pExpr->op; + if( op==TK_REGISTER ){ + op = pExpr->op2; + } if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ - zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n); pVal = sqlite3ValueNew(db); - if( !zVal || !pVal ) goto no_mem; - sqlite3Dequote(zVal); - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + if( pVal==0 ) goto no_mem; + if( ExprHasProperty(pExpr, EP_IntValue) ){ + sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue); + }else{ + zVal = sqlite3DbStrDup(db, pExpr->u.zToken); + if( zVal==0 ) goto no_mem; + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT; + } if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ - sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc); - }else{ - sqlite3ValueApplyAffinity(pVal, affinity, enc); + sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); + }else{ + sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); + } + if( enc!=SQLITE_UTF8 ){ + sqlite3VdbeChangeEncoding(pVal, enc); } }else if( op==TK_UMINUS ) { if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){ pVal->u.i = -1 * pVal->u.i; /* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */ @@ -45373,18 +47033,17 @@ } } #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; - assert( pExpr->token.n>=3 ); - assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); - assert( pExpr->token.z[1]=='\'' ); - assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); pVal = sqlite3ValueNew(db); if( !pVal ) goto no_mem; - nVal = pExpr->token.n - 3; - zVal = (char*)pExpr->token.z + 2; + zVal = &pExpr->u.zToken[2]; + nVal = sqlite3Strlen30(zVal)-1; + assert( zVal[nVal]=='\'' ); sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, 0, SQLITE_DYNAMIC); } #endif @@ -45453,11 +47112,11 @@ ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** -** $Id: vdbeaux.c,v 1.451 2009/04/10 15:42:36 shane Exp $ +** $Id: vdbeaux.c,v 1.480 2009/08/08 18:01:08 drh Exp $ */ /* @@ -45582,11 +47241,11 @@ i = p->nOp; assert( p->magic==VDBE_MAGIC_INIT ); assert( op>0 && op<0xff ); if( p->nOpAlloc<=i ){ if( growOpArray(p) ){ - return 0; + return 1; } } p->nOp++; pOp = &p->aOp[i]; pOp->opcode = (u8)op; @@ -45677,10 +47336,127 @@ if( p->aLabel ){ p->aLabel[j] = p->nOp; } } +#ifdef SQLITE_DEBUG + +/* +** The following type and function are used to iterate through all opcodes +** in a Vdbe main program and each of the sub-programs (triggers) it may +** invoke directly or indirectly. It should be used as follows: +** +** Op *pOp; +** VdbeOpIter sIter; +** +** memset(&sIter, 0, sizeof(sIter)); +** sIter.v = v; // v is of type Vdbe* +** while( (pOp = opIterNext(&sIter)) ){ +** // Do something with pOp +** } +** sqlite3DbFree(v->db, sIter.apSub); +** +*/ +typedef struct VdbeOpIter VdbeOpIter; +struct VdbeOpIter { + Vdbe *v; /* Vdbe to iterate through the opcodes of */ + SubProgram **apSub; /* Array of subprograms */ + int nSub; /* Number of entries in apSub */ + int iAddr; /* Address of next instruction to return */ + int iSub; /* 0 = main program, 1 = first sub-program etc. */ +}; +static Op *opIterNext(VdbeOpIter *p){ + Vdbe *v = p->v; + Op *pRet = 0; + Op *aOp; + int nOp; + + if( p->iSub<=p->nSub ){ + + if( p->iSub==0 ){ + aOp = v->aOp; + nOp = v->nOp; + }else{ + aOp = p->apSub[p->iSub-1]->aOp; + nOp = p->apSub[p->iSub-1]->nOp; + } + assert( p->iAddr<nOp ); + + pRet = &aOp[p->iAddr]; + p->iAddr++; + if( p->iAddr==nOp ){ + p->iSub++; + p->iAddr = 0; + } + + if( pRet->p4type==P4_SUBPROGRAM ){ + int nByte = (p->nSub+1)*sizeof(SubProgram*); + int j; + for(j=0; j<p->nSub; j++){ + if( p->apSub[j]==pRet->p4.pProgram ) break; + } + if( j==p->nSub ){ + p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte); + if( !p->apSub ){ + pRet = 0; + }else{ + p->apSub[p->nSub++] = pRet->p4.pProgram; + } + } + } + } + + return pRet; +} + +/* +** Check if the program stored in the VM associated with pParse may +** throw an ABORT exception (causing the statement, but not transaction +** to be rolled back). This condition is true if the main program or any +** sub-programs contains any of the following: +** +** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. +** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort. +** * OP_Destroy +** * OP_VUpdate +** * OP_VRename +** +** Then check that the value of Parse.mayAbort is true if an +** ABORT may be thrown, or false otherwise. Return true if it does +** match, or false otherwise. This function is intended to be used as +** part of an assert statement in the compiler. Similar to: +** +** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); +*/ +SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ + int hasAbort = 0; + Op *pOp; + VdbeOpIter sIter; + memset(&sIter, 0, sizeof(sIter)); + sIter.v = v; + + while( (pOp = opIterNext(&sIter))!=0 ){ + int opcode = pOp->opcode; + if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename + || ((opcode==OP_Halt || opcode==OP_HaltIfNull) + && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) + ){ + hasAbort = 1; + break; + } + } + sqlite3DbFree(v->db, sIter.apSub); + + /* Return true if hasAbort==mayAbort. Or if a malloc failure occured. + ** If malloc failed, then the while() loop above may not have iterated + ** through all opcodes and hasAbort may be set incorrectly. Return + ** true for this case to prevent the assert() in the callers frame + ** from failing. */ + return ( v->db->mallocFailed || hasAbort==mayAbort ); +} +#endif + /* ** Loop through the program looking for P2 values that are negative ** on jump instructions. Each such value is a label. Resolve the ** label by setting the P2 value to its correct non-zero value. ** @@ -45687,57 +47463,29 @@ ** This routine is called once after all opcodes have been inserted. ** ** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument ** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by ** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. -** -** This routine also does the following optimization: It scans for -** instructions that might cause a statement rollback. Such instructions -** are: -** -** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. -** * OP_Destroy -** * OP_VUpdate -** * OP_VRename -** -** If no such instruction is found, then every Statement instruction -** is changed to a Noop. In this way, we avoid creating the statement -** journal file unnecessarily. */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; - int nMaxArgs = 0; + int nMaxArgs = *pMaxFuncArgs; Op *pOp; int *aLabel = p->aLabel; - int doesStatementRollback = 0; - int hasStatementBegin = 0; - p->readOnly = 1; - p->usesStmtJournal = 0; + p->readOnly = 1; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; if( opcode==OP_Function || opcode==OP_AggStep ){ if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( opcode==OP_VUpdate ){ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; #endif - } - if( opcode==OP_Halt ){ - if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){ - doesStatementRollback = 1; - } - }else if( opcode==OP_Statement ){ - hasStatementBegin = 1; - p->usesStmtJournal = 1; - }else if( opcode==OP_Destroy ){ - doesStatementRollback = 1; }else if( opcode==OP_Transaction && pOp->p2!=0 ){ p->readOnly = 0; #ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( opcode==OP_VUpdate || opcode==OP_VRename ){ - doesStatementRollback = 1; }else if( opcode==OP_VFilter ){ int n; assert( p->nOp - i >= 3 ); assert( pOp[-1].opcode==OP_Integer ); n = pOp[-1].p1; @@ -45752,32 +47500,42 @@ } sqlite3DbFree(p->db, p->aLabel); p->aLabel = 0; *pMaxFuncArgs = nMaxArgs; - - /* If we never rollback a statement transaction, then statement - ** transactions are not needed. So change every OP_Statement - ** opcode into an OP_Noop. This avoid a call to sqlite3OsOpenExclusive() - ** which can be expensive on some platforms. - */ - if( hasStatementBegin && !doesStatementRollback ){ - p->usesStmtJournal = 0; - for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ - if( pOp->opcode==OP_Statement ){ - pOp->opcode = OP_Noop; - } - } - } } /* ** Return the address of the next instruction to be inserted. */ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){ assert( p->magic==VDBE_MAGIC_INIT ); return p->nOp; +} + +/* +** This function returns a pointer to the array of opcodes associated with +** the Vdbe passed as the first argument. It is the callers responsibility +** to arrange for the returned array to be eventually freed using the +** vdbeFreeOpArray() function. +** +** Before returning, *pnOp is set to the number of entries in the returned +** array. Also, *pnMaxArg is set to the larger of its current value and +** the number of entries in the Vdbe.apArg[] array required to execute the +** returned program. +*/ +SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ + VdbeOp *aOp = p->aOp; + assert( aOp && !p->db->mallocFailed ); + + /* Check that sqlite3VdbeUsesBtree() was not called on this VM */ + assert( p->aMutex.nMutex==0 ); + + resolveP2Values(p, pnMaxArg); + *pnOp = p->nOp; + p->aOp = 0; + return aOp; } /* ** Add a whole list of operations to the operation stack. Return the ** address of the first operation added. @@ -45787,11 +47545,11 @@ assert( p->magic==VDBE_MAGIC_INIT ); if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){ return 0; } addr = p->nOp; - if( nOp>0 ){ + if( ALWAYS(nOp>0) ){ int i; VdbeOpList const *pIn = aOp; for(i=0; i<nOp; i++, pIn++){ int p2 = pIn->p2; VdbeOp *pOut = &p->aOp[i+addr]; @@ -45823,44 +47581,47 @@ ** This routine is useful when a large program is loaded from a ** static array using sqlite3VdbeAddOpList but we want to make a ** few minor changes to the program. */ SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){ - assert( p==0 || p->magic==VDBE_MAGIC_INIT ); - if( p && addr>=0 && p->nOp>addr && p->aOp ){ + assert( p!=0 ); + assert( addr>=0 ); + if( p->nOp>addr ){ p->aOp[addr].p1 = val; } } /* ** Change the value of the P2 operand for a specific instruction. ** This routine is useful for setting a jump destination. */ SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ - assert( p==0 || p->magic==VDBE_MAGIC_INIT ); - if( p && addr>=0 && p->nOp>addr && p->aOp ){ + assert( p!=0 ); + assert( addr>=0 ); + if( p->nOp>addr ){ p->aOp[addr].p2 = val; } } /* ** Change the value of the P3 operand for a specific instruction. */ SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){ - assert( p==0 || p->magic==VDBE_MAGIC_INIT ); - if( p && addr>=0 && p->nOp>addr && p->aOp ){ + assert( p!=0 ); + assert( addr>=0 ); + if( p->nOp>addr ){ p->aOp[addr].p3 = val; } } /* ** Change the value of the P5 operand for the most recently ** added operation. */ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ - assert( p==0 || p->magic==VDBE_MAGIC_INIT ); - if( p && p->aOp ){ + assert( p!=0 ); + if( p->aOp ){ assert( p->nOp>0 ); p->aOp[p->nOp-1].p5 = val; } } @@ -45876,11 +47637,11 @@ /* ** If the input FuncDef structure is ephemeral, then free it. If ** the FuncDef is not ephermal, then do nothing. */ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ - if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){ + if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){ sqlite3DbFree(db, pDef); } } /* @@ -45912,20 +47673,75 @@ } case P4_MEM: { sqlite3ValueFree((sqlite3_value*)p4); break; } + case P4_VTAB : { + sqlite3VtabUnlock((VTable *)p4); + break; + } + case P4_SUBPROGRAM : { + sqlite3VdbeProgramDelete(db, (SubProgram *)p4, 1); + break; + } + } + } +} + +/* +** Free the space allocated for aOp and any p4 values allocated for the +** opcodes contained within. If aOp is not NULL it is assumed to contain +** nOp entries. +*/ +static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ + if( aOp ){ + Op *pOp; + for(pOp=aOp; pOp<&aOp[nOp]; pOp++){ + freeP4(db, pOp->p4type, pOp->p4.p); +#ifdef SQLITE_DEBUG + sqlite3DbFree(db, pOp->zComment); +#endif + } + } + sqlite3DbFree(db, aOp); +} + +/* +** Decrement the ref-count on the SubProgram structure passed as the +** second argument. If the ref-count reaches zero, free the structure. +** +** The array of VDBE opcodes stored as SubProgram.aOp is freed if +** either the ref-count reaches zero or parameter freeop is non-zero. +** +** Since the array of opcodes pointed to by SubProgram.aOp may directly +** or indirectly contain a reference to the SubProgram structure itself. +** By passing a non-zero freeop parameter, the caller may ensure that all +** SubProgram structures and their aOp arrays are freed, even when there +** are such circular references. +*/ +SQLITE_PRIVATE void sqlite3VdbeProgramDelete(sqlite3 *db, SubProgram *p, int freeop){ + if( p ){ + assert( p->nRef>0 ); + if( freeop || p->nRef==1 ){ + Op *aOp = p->aOp; + p->aOp = 0; + vdbeFreeOpArray(db, aOp, p->nOp); + p->nOp = 0; + } + p->nRef--; + if( p->nRef==0 ){ + sqlite3DbFree(db, p); } } } /* ** Change N opcodes starting at addr to No-ops. */ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){ - if( p && p->aOp ){ + if( p->aOp ){ VdbeOp *pOp = &p->aOp[addr]; sqlite3 *db = p->db; while( N-- ){ freeP4(db, pOp->p4type, pOp->p4.p); memset(pOp, 0, sizeof(pOp[0])); @@ -45965,19 +47781,19 @@ sqlite3 *db; assert( p!=0 ); db = p->db; assert( p->magic==VDBE_MAGIC_INIT ); if( p->aOp==0 || db->mallocFailed ){ - if (n != P4_KEYINFO) { + if ( n!=P4_KEYINFO && n!=P4_VTAB ) { freeP4(db, n, (void*)*(char**)&zP4); } return; } + assert( p->nOp>0 ); assert( addr<p->nOp ); if( addr<0 ){ addr = p->nOp - 1; - if( addr<0 ) return; } pOp = &p->aOp[addr]; freeP4(db, pOp->p4type, pOp->p4.p); pOp->p4.p = 0; if( n==P4_INT32 ){ @@ -46010,10 +47826,15 @@ pOp->p4type = P4_NOTUSED; } }else if( n==P4_KEYINFO_HANDOFF ){ pOp->p4.p = (void*)zP4; pOp->p4type = P4_KEYINFO; + }else if( n==P4_VTAB ){ + pOp->p4.p = (void*)zP4; + pOp->p4type = P4_VTAB; + sqlite3VtabLock((VTable *)zP4); + assert( ((VTable *)zP4)->db==p->db ); }else if( n<0 ){ pOp->p4.p = (void*)zP4; pOp->p4type = (signed char)n; }else{ if( n==0 ) n = sqlite3Strlen30(zP4); @@ -46029,10 +47850,11 @@ ** makes the code easier to read during debugging. None of this happens ** in a production build. */ SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; + if( !p ) return; assert( p->nOp>0 || p->aOp==0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; va_start(ap, zFormat); @@ -46041,10 +47863,11 @@ va_end(ap); } } SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ va_list ap; + if( !p ) return; sqlite3VdbeAddOp0(p, OP_Noop); assert( p->nOp>0 || p->aOp==0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; @@ -46055,16 +47878,42 @@ } } #endif /* NDEBUG */ /* -** Return the opcode for a given address. +** Return the opcode for a given address. If the address is -1, then +** return the most recently inserted opcode. +** +** If a memory allocation error has occurred prior to the calling of this +** routine, then a pointer to a dummy VdbeOp will be returned. That opcode +** is readable and writable, but it has no effect. The return of a dummy +** opcode allows the call to continue functioning after a OOM fault without +** having to check to see if the return from this routine is a valid pointer. +** +** About the #ifdef SQLITE_OMIT_TRACE: Normally, this routine is never called +** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE, +** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as +** a new VDBE is created. So we are free to set addr to p->nOp-1 without +** having to double-check to make sure that the result is non-negative. But +** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to +** check the value of p->nOp-1 before continuing. */ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ + static VdbeOp dummy; assert( p->magic==VDBE_MAGIC_INIT ); + if( addr<0 ){ +#ifdef SQLITE_OMIT_TRACE + if( p->nOp==0 ) return &dummy; +#endif + addr = p->nOp - 1; + } assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed ); - return ((addr>=0 && addr<p->nOp)?(&p->aOp[addr]):0); + if( p->db->mallocFailed ){ + return &dummy; + }else{ + return &p->aOp[addr]; + } } #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* @@ -46134,22 +47983,29 @@ zP4 = pMem->z; }else if( pMem->flags & MEM_Int ){ sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); + }else{ + assert( pMem->flags & MEM_Blob ); + zP4 = "(blob)"; } break; } #ifndef SQLITE_OMIT_VIRTUALTABLE case P4_VTAB: { - sqlite3_vtab *pVtab = pOp->p4.pVtab; + sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); break; } #endif case P4_INTARRAY: { sqlite3_snprintf(nTemp, zTemp, "intarray"); + break; + } + case P4_SUBPROGRAM: { + sqlite3_snprintf(nTemp, zTemp, "program"); break; } default: { zP4 = pOp->p4.z; if( zP4==0 ){ @@ -46163,17 +48019,16 @@ } #endif /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. -** */ SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){ int mask; - assert( i>=0 && i<p->db->nDb ); + assert( i>=0 && i<p->db->nDb && i<sizeof(u32)*8 ); assert( i<(int)sizeof(p->btreeMask)*8 ); - mask = 1<<i; + mask = ((u32)1)<<i; if( (p->btreeMask & mask)==0 ){ p->btreeMask |= mask; sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); } } @@ -46222,11 +48077,11 @@ ** sqlite3MemRelease() were called from here. With -O2, this jumps ** to 6.6 percent. The test case is inserting 1000 rows into a table ** with no indexes using a single prepared INSERT statement, bind() ** and reset(). Inserts are grouped into a transaction. */ - if( p->flags&(MEM_Agg|MEM_Dyn) ){ + if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); }else if( p->zMalloc ){ sqlite3DbFree(db, p->zMalloc); p->zMalloc = 0; } @@ -46234,10 +48089,26 @@ p->flags = MEM_Null; } db->mallocFailed = malloc_failed; } } + +/* +** Delete a VdbeFrame object and its contents. VdbeFrame objects are +** allocated by the OP_Program opcode in sqlite3VdbeExec(). +*/ +SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){ + int i; + Mem *aMem = VdbeFrameMem(p); + VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; + for(i=0; i<p->nChildCsr; i++){ + sqlite3VdbeFreeCursor(p->v, apCsr[i]); + } + releaseMemArray(aMem, p->nChildMem); + sqlite3DbFree(p->v->db, p); +} + #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT SQLITE_PRIVATE int sqlite3VdbeReleaseBuffers(Vdbe *p){ int ii; int nFree = 0; @@ -46271,46 +48142,74 @@ ** EXPLAIN QUERY PLAN. */ SQLITE_PRIVATE int sqlite3VdbeList( Vdbe *p /* The VDBE */ ){ + int nRow; /* Total number of rows to return */ + int nSub = 0; /* Number of sub-vdbes seen so far */ + SubProgram **apSub = 0; /* Array of sub-vdbes */ + Mem *pSub = 0; sqlite3 *db = p->db; int i; int rc = SQLITE_OK; Mem *pMem = p->pResultSet = &p->aMem[1]; assert( p->explain ); - if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; + assert( p->magic==VDBE_MAGIC_RUN ); assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); /* Even though this opcode does not use dynamic strings for ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ - releaseMemArray(pMem, p->nMem); + releaseMemArray(pMem, 8); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ db->mallocFailed = 1; return SQLITE_ERROR; } + /* Figure out total number of rows that will be returned by this + ** EXPLAIN program. */ + nRow = p->nOp; + if( p->explain==1 ){ + pSub = &p->aMem[9]; + if( pSub->flags&MEM_Blob ){ + nSub = pSub->n/sizeof(Vdbe*); + apSub = (SubProgram **)pSub->z; + } + for(i=0; i<nSub; i++){ + nRow += apSub[i]->nOp; + } + } + do{ i = p->pc++; - }while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain ); - if( i>=p->nOp ){ + }while( i<nRow && p->explain==2 && p->aOp[i].opcode!=OP_Explain ); + if( i>=nRow ){ p->rc = SQLITE_OK; rc = SQLITE_DONE; }else if( db->u1.isInterrupted ){ p->rc = SQLITE_INTERRUPT; rc = SQLITE_ERROR; sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc)); }else{ char *z; - Op *pOp = &p->aOp[i]; + Op *pOp; + if( i<p->nOp ){ + pOp = &p->aOp[i]; + }else{ + int j; + i -= p->nOp; + for(j=0; i>=apSub[j]->nOp; j++){ + i -= apSub[j]->nOp; + } + pOp = &apSub[j]->aOp[i]; + } if( p->explain==1 ){ pMem->flags = MEM_Int; pMem->type = SQLITE_INTEGER; pMem->u.i = i; /* Program counter */ pMem++; @@ -46320,10 +48219,24 @@ assert( pMem->z!=0 ); pMem->n = sqlite3Strlen30(pMem->z); pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; pMem++; + + if( pOp->p4type==P4_SUBPROGRAM ){ + int nByte = (nSub+1)*sizeof(SubProgram*); + int j; + for(j=0; j<nSub; j++){ + if( apSub[j]==pOp->p4.pProgram ) break; + } + if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, 1) ){ + apSub = (SubProgram **)pSub->z; + apSub[nSub++] = pOp->p4.pProgram; + pSub->flags |= MEM_Blob; + pSub->n = nSub*sizeof(SubProgram*); + } + } } pMem->flags = MEM_Int; pMem->u.i = pOp->p1; /* P1 */ pMem->type = SQLITE_INTEGER; @@ -46463,11 +48376,11 @@ int *pnByte /* If allocation cannot be made, increment *pnByte */ ){ assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) ); if( (*(void**)pp)==0 ){ nByte = ROUND8(nByte); - if( (pEnd - *ppFrom)>=nByte ){ + if( &(*ppFrom)[nByte] <= pEnd ){ *(void**)pp = (void *)*ppFrom; *ppFrom += nByte; }else{ *pnByte += nByte; } @@ -46494,11 +48407,13 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ - int isExplain /* True if the EXPLAIN keywords is present */ + int nArg, /* Maximum number of args in SubPrograms */ + int isExplain, /* True if the EXPLAIN keywords is present */ + int usesStmtJournal /* True to set Vdbe.usesStmtJournal */ ){ int n; sqlite3 *db = p->db; assert( p!=0 ); @@ -46525,43 +48440,42 @@ /* Allocate space for memory registers, SQL variables, VDBE cursors and ** an array to marshal SQL function arguments in. This is only done the ** first time this function is called for a given VDBE, not when it is ** being called from sqlite3_reset() to reset the virtual machine. */ - if( nVar>=0 && !db->mallocFailed ){ + if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){ u8 *zCsr = (u8 *)&p->aOp[p->nOp]; u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; int nByte; - int nArg; /* Maximum number of args passed to a user function. */ resolveP2Values(p, &nArg); + p->usesStmtJournal = (u8)usesStmtJournal; if( isExplain && nMem<10 ){ nMem = 10; } + memset(zCsr, 0, zEnd-zCsr); zCsr += (zCsr - (u8*)0)&7; assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); - if( zEnd<zCsr ) zEnd = zCsr; - - do { - memset(zCsr, 0, zEnd-zCsr); + + do { nByte = 0; allocSpace((char*)&p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); allocSpace((char*)&p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); allocSpace((char*)&p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); allocSpace((char*)&p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); allocSpace((char*)&p->apCsr, nCursor*sizeof(VdbeCursor*), &zCsr, zEnd, &nByte ); if( nByte ){ - p->pFree = sqlite3DbMallocRaw(db, nByte); + p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); - p->nCursor = nCursor; + p->nCursor = (u16)nCursor; if( p->aVar ){ - p->nVar = nVar; + p->nVar = (u16)nVar; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; p->aVar[n].db = db; } } @@ -46624,28 +48538,59 @@ pModule->xClose(pVtabCursor); (void)sqlite3SafetyOn(p->db); p->inVtabMethod = 0; } #endif - if( !pCx->ephemPseudoTable ){ - sqlite3DbFree(p->db, pCx->pData); - } -} - -/* -** Close all cursors except for VTab cursors that are currently -** in use. -*/ -static void closeAllCursorsExceptActiveVtabs(Vdbe *p){ - int i; - if( p->apCsr==0 ) return; - for(i=0; i<p->nCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC && (!p->inVtabMethod || !pC->pVtabCursor) ){ - sqlite3VdbeFreeCursor(p, pC); - p->apCsr[i] = 0; - } +} + +/* +** Copy the values stored in the VdbeFrame structure to its Vdbe. This +** is used, for example, when a trigger sub-program is halted to restore +** control to the main program. +*/ +SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ + Vdbe *v = pFrame->v; + v->aOp = pFrame->aOp; + v->nOp = pFrame->nOp; + v->aMem = pFrame->aMem; + v->nMem = pFrame->nMem; + v->apCsr = pFrame->apCsr; + v->nCursor = pFrame->nCursor; + v->db->lastRowid = pFrame->lastRowid; + v->nChange = pFrame->nChange; + return pFrame->pc; +} + +/* +** Close all cursors. +** +** Also release any dynamic memory held by the VM in the Vdbe.aMem memory +** cell array. This is necessary as the memory cell array may contain +** pointers to VdbeFrame objects, which may in turn contain pointers to +** open cursors. +*/ +static void closeAllCursors(Vdbe *p){ + if( p->pFrame ){ + VdbeFrame *pFrame = p->pFrame; + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); + sqlite3VdbeFrameRestore(pFrame); + } + p->pFrame = 0; + p->nFrame = 0; + + if( p->apCsr ){ + int i; + for(i=0; i<p->nCursor; i++){ + VdbeCursor *pC = p->apCsr[i]; + if( pC ){ + sqlite3VdbeFreeCursor(p, pC); + p->apCsr[i] = 0; + } + } + } + if( p->aMem ){ + releaseMemArray(&p->aMem[1], p->nMem); } } /* ** Clean up the VM after execution. @@ -46653,27 +48598,20 @@ ** This routine will automatically close any cursors, lists, and/or ** sorters that were left open. It also deletes the values of ** variables in the aVar[] array. */ static void Cleanup(Vdbe *p){ - int i; sqlite3 *db = p->db; - Mem *pMem; - closeAllCursorsExceptActiveVtabs(p); - for(pMem=&p->aMem[1], i=1; i<=p->nMem; i++, pMem++){ - if( pMem->flags & MEM_RowSet ){ - sqlite3RowSetClear(pMem->u.pRowSet); - } - MemSetTypeFlag(pMem, MEM_Null); - } - releaseMemArray(&p->aMem[1], p->nMem); - if( p->contextStack ){ - sqlite3DbFree(db, p->contextStack); - } - p->contextStack = 0; - p->contextStackDepth = 0; - p->contextStackTop = 0; + +#ifdef SQLITE_DEBUG + /* Execute assert() statements to ensure that the Vdbe.apCsr[] and + ** Vdbe.aMem[] arrays have already been cleaned up. */ + int i; + for(i=0; i<p->nCursor; i++) assert( p->apCsr==0 || p->apCsr[i]==0 ); + for(i=1; i<=p->nMem; i++) assert( p->aMem==0 || p->aMem[i].flags==MEM_Null ); +#endif + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; p->pResultSet = 0; } @@ -46689,11 +48627,11 @@ sqlite3 *db = p->db; releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); sqlite3DbFree(db, p->aColName); n = nResColumn*COLNAME_N; - p->nResColumn = nResColumn; + p->nResColumn = (u16)nResColumn; p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; while( n-- > 0 ){ pColName->flags = MEM_Null; pColName->db = p->db; @@ -46743,10 +48681,17 @@ int i; int nTrans = 0; /* Number of databases with an active write-transaction */ int rc = SQLITE_OK; int needXcommit = 0; +#ifdef SQLITE_OMIT_VIRTUALTABLE + /* With this option, sqlite3VtabSync() is defined to be simply + ** SQLITE_OK so p is not used. + */ + UNUSED_PARAMETER(p); +#endif + /* Before doing anything else, call the xSync() callback for any ** virtual module tables written in this transaction. This has to ** be done before determining whether a master journal file is ** required, as an xSync() callback may add an attached database ** to the transaction. @@ -46770,16 +48715,13 @@ } } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ - assert( (db->flags & SQLITE_CommitBusy)==0 ); - db->flags |= SQLITE_CommitBusy; (void)sqlite3SafetyOff(db); rc = db->xCommitCallback(db->pCommitArg); (void)sqlite3SafetyOn(db); - db->flags &= ~SQLITE_CommitBusy; if( rc ){ return SQLITE_CONSTRAINT; } } @@ -47018,11 +48960,17 @@ ** Otherwise SQLITE_OK. */ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ sqlite3 *const db = p->db; int rc = SQLITE_OK; - if( p->iStatement && db->nStatement ){ + + /* If p->iStatement is greater than zero, then this Vdbe opened a + ** statement transaction that should be closed here. The only exception + ** is that an IO error may have occured, causing an emergency rollback. + ** In this case (db->nStatement==0), and there is nothing to do. + */ + if( db->nStatement && p->iStatement ){ int i; const int iSavepoint = p->iStatement-1; assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); assert( db->nStatement>0 ); @@ -47110,11 +49058,11 @@ */ if( p->db->mallocFailed ){ p->rc = SQLITE_NOMEM; } - closeAllCursorsExceptActiveVtabs(p); + closeAllCursors(p); if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_OK; } checkActiveVdbeCnt(db); @@ -47127,22 +49075,19 @@ /* Lock all btrees used by the statement */ sqlite3VdbeMutexArrayEnter(p); /* Check for one of the special errors */ mrc = p->rc & 0xff; + assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */ isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; if( isSpecialError ){ /* If the query was read-only, we need do no rollback at all. Otherwise, ** proceed with the special handling. */ if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ - if( p->rc==SQLITE_IOERR_BLOCKED && p->usesStmtJournal ){ - eStatementOp = SAVEPOINT_ROLLBACK; - p->rc = SQLITE_BUSY; - }else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) - && p->usesStmtJournal ){ + if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ eStatementOp = SAVEPOINT_ROLLBACK; }else{ /* We are forced to roll back the active transaction. Before doing ** so, abort any other statements this handle currently has active. */ @@ -47161,11 +49106,10 @@ ** above has occurred. */ if( !sqlite3VtabInSync(db) && db->autoCommit && db->writeVdbeCnt==(p->readOnly==0) - && (db->flags & SQLITE_CommitBusy)==0 ){ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ /* The auto-commit flag is true, and the vdbe program was ** successful or hit an 'OR FAIL' constraint. This means a commit ** is required. @@ -47213,11 +49157,11 @@ } /* If this was an INSERT, UPDATE or DELETE and no statement transaction ** has been rolled back, update the database connection change-counter. */ - if( p->changeCntOn && p->pc>=0 ){ + if( p->changeCntOn ){ if( eStatementOp!=SAVEPOINT_ROLLBACK ){ sqlite3VdbeSetChanges(db, p->nChange); }else{ sqlite3VdbeSetChanges(db, 0); } @@ -47360,12 +49304,10 @@ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ int rc = SQLITE_OK; if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ rc = sqlite3VdbeReset(p); assert( (rc & p->db->errMask)==rc ); - }else if( p->magic!=VDBE_MAGIC_INIT ){ - return SQLITE_MISUSE; } sqlite3VdbeDelete(p); return rc; } @@ -47377,11 +49319,11 @@ */ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){ int i; for(i=0; i<pVdbeFunc->nAux; i++){ struct AuxData *pAux = &pVdbeFunc->apAux[i]; - if( (i>31 || !(mask&(1<<i))) && pAux->pAux ){ + if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){ if( pAux->xDelete ){ pAux->xDelete(pAux->pAux); } pAux->pAux = 0; } @@ -47390,14 +49332,13 @@ /* ** Delete an entire VDBE. */ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ - int i; - sqlite3 *db; - - if( p==0 ) return; + sqlite3 *db; + + if( NEVER(p==0) ) return; db = p->db; if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ assert( db->pVdbe==p ); @@ -47404,34 +49345,33 @@ db->pVdbe = p->pNext; } if( p->pNext ){ p->pNext->pPrev = p->pPrev; } - if( p->aOp ){ - Op *pOp = p->aOp; - for(i=0; i<p->nOp; i++, pOp++){ - freeP4(db, pOp->p4type, pOp->p4.p); -#ifdef SQLITE_DEBUG - sqlite3DbFree(db, pOp->zComment); -#endif - } - } releaseMemArray(p->aVar, p->nVar); - sqlite3DbFree(db, p->aLabel); releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + vdbeFreeOpArray(db, p->aOp, p->nOp); + sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); p->magic = VDBE_MAGIC_DEAD; - sqlite3DbFree(db, p->aOp); sqlite3DbFree(db, p->pFree); sqlite3DbFree(db, p); } /* +** 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 +** prevents us from positioning the cursor to its correct position. +** ** If a MoveTo operation is pending on the given cursor, then do that -** MoveTo now. Return an error code. If no MoveTo is pending, this -** routine does nothing and returns SQLITE_OK. +** MoveTo now. If no move is pending, check to see if the row has been +** deleted out from under the cursor and if it has, mark the row as +** a NULL row. +** +** If the cursor is already pointing to the correct row and that row has +** not been deleted out from under the cursor, then this routine is a no-op. */ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ if( p->deferredMoveto ){ int res, rc; #ifdef SQLITE_TEST @@ -47438,22 +49378,22 @@ extern int sqlite3_search_count; #endif assert( p->isTable ); rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); if( rc ) return rc; - p->lastRowid = keyToInt(p->movetoTarget); - p->rowidIsValid = res==0 ?1:0; - if( res<0 ){ + p->lastRowid = p->movetoTarget; + p->rowidIsValid = ALWAYS(res==0) ?1:0; + if( NEVER(res<0) ){ rc = sqlite3BtreeNext(p->pCursor, &res); if( rc ) return rc; } #ifdef SQLITE_TEST sqlite3_search_count++; #endif p->deferredMoveto = 0; p->cacheStatus = CACHE_STALE; - }else if( p->pCursor ){ + }else if( ALWAYS(p->pCursor) ){ int hasMoved; int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved); if( rc ) return rc; if( hasMoved ){ p->cacheStatus = CACHE_STALE; @@ -47544,11 +49484,11 @@ } /* ** Return the length of the data corresponding to the supplied serial-type. */ -SQLITE_PRIVATE int sqlite3VdbeSerialTypeLen(u32 serial_type){ +SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){ if( serial_type>=12 ){ return (serial_type-12)/2; }else{ static const u8 aSize[] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 }; return aSize[serial_type]; @@ -47624,27 +49564,27 @@ ** ** Return the number of bytes actually written into buf[]. The number ** of bytes in the zero-filled tail is included in the return value only ** if those bytes were zeroed in buf[]. */ -SQLITE_PRIVATE int sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){ +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){ u32 serial_type = sqlite3VdbeSerialType(pMem, file_format); - int len; + u32 len; /* Integer and Real */ if( serial_type<=7 && serial_type>0 ){ u64 v; - int i; + u32 i; if( serial_type==7 ){ assert( sizeof(v)==sizeof(pMem->r) ); memcpy(&v, &pMem->r, sizeof(v)); swapMixedEndianFloat(v); }else{ v = pMem->u.i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); - assert( len<=nBuf ); + assert( len<=(u32)nBuf ); while( i-- ){ buf[i] = (u8)(v&0xFF); v >>= 8; } return len; @@ -47651,18 +49591,19 @@ } /* String or blob */ if( serial_type>=12 ){ assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) - == sqlite3VdbeSerialTypeLen(serial_type) ); + == (int)sqlite3VdbeSerialTypeLen(serial_type) ); assert( pMem->n<=nBuf ); len = pMem->n; memcpy(buf, pMem->z, len); if( pMem->flags & MEM_Zero ){ len += pMem->u.nZero; - if( len>nBuf ){ - len = nBuf; + assert( nBuf>=0 ); + if( len > (u32)nBuf ){ + len = (u32)nBuf; } memset(&buf[pMem->n], 0, len-pMem->n); } return len; } @@ -47673,11 +49614,11 @@ /* ** 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. */ -SQLITE_PRIVATE int sqlite3VdbeSerialGet( +SQLITE_PRIVATE 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 ){ @@ -47751,11 +49692,11 @@ pMem->u.i = serial_type-8; pMem->flags = MEM_Int; return 0; } default: { - int len = (serial_type-12)/2; + u32 len = (serial_type-12)/2; pMem->z = (char *)buf; pMem->n = len; pMem->xDel = 0; if( serial_type&0x01 ){ pMem->flags = MEM_Str | MEM_Ephem; @@ -47821,15 +49762,14 @@ p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; assert( EIGHT_BYTE_ALIGNMENT(pMem) ); idx = getVarint32(aKey, szHdr); d = szHdr; u = 0; - while( idx<szHdr && u<p->nField ){ + while( idx<szHdr && u<p->nField && d<=nKey ){ u32 serial_type; idx += getVarint32(&aKey[idx], serial_type); - if( d>=nKey && sqlite3VdbeSerialTypeLen(serial_type)>0 ) break; pMem->enc = pKeyInfo->enc; pMem->db = pKeyInfo->db; pMem->flags = 0; pMem->zMalloc = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); @@ -47840,26 +49780,28 @@ p->nField = u; return (void*)p; } /* -** This routine destroys a UnpackedRecord object +** This routine destroys a UnpackedRecord object. */ SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){ - if( p ){ - if( p->flags & UNPACKED_NEED_DESTROY ){ - int i; - Mem *pMem; - for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){ - if( pMem->zMalloc ){ - sqlite3VdbeMemRelease(pMem); - } - } - } - if( p->flags & UNPACKED_NEED_FREE ){ - sqlite3DbFree(p->pKeyInfo->db, p); - } + int i; + Mem *pMem; + + assert( p!=0 ); + assert( p->flags & UNPACKED_NEED_DESTROY ); + for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){ + /* The unpacked record is always constructed by the + ** sqlite3VdbeUnpackRecord() function above, which makes all + ** strings and blobs static. And none of the elements are + ** ever transformed, so there is never anything to delete. + */ + if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem); + } + if( p->flags & UNPACKED_NEED_FREE ){ + sqlite3DbFree(p->pKeyInfo->db, p); } } /* ** This function compares the two table rows or index records @@ -47903,10 +49845,11 @@ pKeyInfo = pPKey2->pKeyInfo; mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; mem1.flags = 0; + mem1.u.i = 0; /* not needed, here to silence compiler warning */ mem1.zMalloc = 0; idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){ @@ -47931,11 +49874,25 @@ if( rc!=0 ){ break; } i++; } - if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1); + + /* No memory allocation is ever used on mem1. */ + if( NEVER(mem1.zMalloc) ) sqlite3VdbeMemRelease(&mem1); + + /* If the PREFIX_SEARCH flag is set and all fields except the final + ** rowid field were equal, then clear the PREFIX_SEARCH flag and set + ** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1). + ** This is used by the OP_IsUnique opcode. + */ + if( (pPKey2->flags & UNPACKED_PREFIX_SEARCH) && i==(pPKey2->nField-1) ){ + assert( idx1==szHdr1 && rc ); + assert( mem1.flags & MEM_Int ); + pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH; + pPKey2->rowid = mem1.u.i; + } if( rc==0 ){ /* rc==0 here means that one of the keys ran out of fields and ** all the fields up to that point were equal. If the UNPACKED_INCRKEY ** flag is set, then break the tie by treating key2 as larger. @@ -47966,39 +49923,42 @@ ** Return SQLITE_OK if everything works, or an error code otherwise. ** ** pCur might be pointing to text obtained from a corrupt database file. ** So the content cannot be trusted. Do appropriate checks on the content. */ -SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ +SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ i64 nCellKey = 0; int rc; u32 szHdr; /* Size of the header */ u32 typeRowid; /* Serial type of the rowid */ u32 lenRowid; /* Size of the rowid */ Mem m, v; + UNUSED_PARAMETER(db); + /* Get the size of the index entry. Only indices entries of less - ** than 2GiB are support - anything large must be database corruption */ - sqlite3BtreeKeySize(pCur, &nCellKey); - if( unlikely(nCellKey<=0 || nCellKey>0x7fffffff) ){ - return SQLITE_CORRUPT_BKPT; - } + ** than 2GiB are support - anything large must be database corruption. + ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so + ** this code can safely assume that nCellKey is 32-bits + */ + assert( sqlite3BtreeCursorIsValid(pCur) ); + rc = sqlite3BtreeKeySize(pCur, &nCellKey); + assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ + assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); /* Read in the complete content of the index entry */ - m.flags = 0; - m.db = 0; - m.zMalloc = 0; + memset(&m, 0, sizeof(m)); rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m); if( rc ){ return rc; } /* The index entry must begin with a header size */ (void)getVarint32((u8*)m.z, szHdr); - testcase( szHdr==2 ); + testcase( szHdr==3 ); testcase( szHdr==m.n ); - if( unlikely(szHdr<2 || (int)szHdr>m.n) ){ + if( unlikely(szHdr<3 || (int)szHdr>m.n) ){ goto idx_rowid_corruption; } /* The last field of the index should be an integer - the ROWID. ** Verify that the last entry really is an integer. */ @@ -48013,12 +49973,12 @@ testcase( typeRowid==9 ); if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){ goto idx_rowid_corruption; } lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); - testcase( m.n-lenRowid==szHdr ); - if( unlikely(m.n-lenRowid<szHdr) ){ + testcase( (u32)m.n==szHdr+lenRowid ); + if( unlikely((u32)m.n<szHdr+lenRowid) ){ goto idx_rowid_corruption; } /* Fetch the integer off the end of the index record */ sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v); @@ -48033,41 +49993,40 @@ sqlite3VdbeMemRelease(&m); return SQLITE_CORRUPT_BKPT; } /* -** Compare the key of the index entry that cursor pC is point to against -** the key string in pKey (of length nKey). Write into *pRes a number +** Compare the key of the index entry that cursor pC is pointing to against +** the key string in pUnpacked. Write into *pRes a number ** that is negative, zero, or positive if pC is less than, equal to, -** or greater than pKey. Return SQLITE_OK on success. -** -** pKey is either created without a rowid or is truncated so that it +** or greater than pUnpacked. Return SQLITE_OK on success. +** +** pUnpacked is either created without a rowid or is truncated so that it ** omits the rowid at the end. The rowid at the end of the index entry ** is ignored as well. Hence, this routine only compares the prefixes ** of the keys prior to the final rowid, not the entire key. -** -** pUnpacked may be an unpacked version of pKey,nKey. If pUnpacked is -** supplied it is used in place of pKey,nKey. */ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( VdbeCursor *pC, /* The cursor to compare against */ - UnpackedRecord *pUnpacked, /* Unpacked version of pKey and nKey */ + UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */ int *res /* Write the comparison result here */ ){ i64 nCellKey = 0; int rc; BtCursor *pCur = pC->pCursor; Mem m; - sqlite3BtreeKeySize(pCur, &nCellKey); + assert( sqlite3BtreeCursorIsValid(pCur) ); + rc = sqlite3BtreeKeySize(pCur, &nCellKey); + assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ + /* nCellKey will always be between 0 and 0xffffffff because of the say + ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ if( nCellKey<=0 || nCellKey>0x7fffffff ){ *res = 0; - return SQLITE_OK; - } - m.db = 0; - m.flags = 0; - m.zMalloc = 0; + return SQLITE_CORRUPT; + } + memset(&m, 0, sizeof(m)); rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m); if( rc ){ return rc; } assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID ); @@ -48133,168 +50092,12 @@ ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. ** -** $Id: vdbeapi.c,v 1.161 2009/04/10 23:11:31 drh Exp $ -*/ - -#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) -/* -** The following structure contains pointers to the end points of a -** doubly-linked list of all compiled SQL statements that may be holding -** buffers eligible for release when the sqlite3_release_memory() interface is -** invoked. Access to this list is protected by the SQLITE_MUTEX_STATIC_LRU2 -** mutex. -** -** Statements are added to the end of this list when sqlite3_reset() is -** called. They are removed either when sqlite3_step() or sqlite3_finalize() -** is called. When statements are added to this list, the associated -** register array (p->aMem[1..p->nMem]) may contain dynamic buffers that -** can be freed using sqlite3VdbeReleaseMemory(). -** -** When statements are added or removed from this list, the mutex -** associated with the Vdbe being added or removed (Vdbe.db->mutex) is -** already held. The LRU2 mutex is then obtained, blocking if necessary, -** the linked-list pointers manipulated and the LRU2 mutex relinquished. -*/ -struct StatementLruList { - Vdbe *pFirst; - Vdbe *pLast; -}; -static struct StatementLruList sqlite3LruStatements; - -/* -** Check that the list looks to be internally consistent. This is used -** as part of an assert() statement as follows: -** -** assert( stmtLruCheck() ); -*/ -#ifndef NDEBUG -static int stmtLruCheck(){ - Vdbe *p; - for(p=sqlite3LruStatements.pFirst; p; p=p->pLruNext){ - assert(p->pLruNext || p==sqlite3LruStatements.pLast); - assert(!p->pLruNext || p->pLruNext->pLruPrev==p); - assert(p->pLruPrev || p==sqlite3LruStatements.pFirst); - assert(!p->pLruPrev || p->pLruPrev->pLruNext==p); - } - return 1; -} -#endif - -/* -** Add vdbe p to the end of the statement lru list. It is assumed that -** p is not already part of the list when this is called. The lru list -** is protected by the SQLITE_MUTEX_STATIC_LRU mutex. -*/ -static void stmtLruAdd(Vdbe *p){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); - - if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); - return; - } - - assert( stmtLruCheck() ); - - if( !sqlite3LruStatements.pFirst ){ - assert( !sqlite3LruStatements.pLast ); - sqlite3LruStatements.pFirst = p; - sqlite3LruStatements.pLast = p; - }else{ - assert( !sqlite3LruStatements.pLast->pLruNext ); - p->pLruPrev = sqlite3LruStatements.pLast; - sqlite3LruStatements.pLast->pLruNext = p; - sqlite3LruStatements.pLast = p; - } - - assert( stmtLruCheck() ); - - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); -} - -/* -** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove -** statement p from the least-recently-used statement list. If the -** statement is not currently part of the list, this call is a no-op. -*/ -static void stmtLruRemoveNomutex(Vdbe *p){ - if( p->pLruPrev || p->pLruNext || p==sqlite3LruStatements.pFirst ){ - assert( stmtLruCheck() ); - if( p->pLruNext ){ - p->pLruNext->pLruPrev = p->pLruPrev; - }else{ - sqlite3LruStatements.pLast = p->pLruPrev; - } - if( p->pLruPrev ){ - p->pLruPrev->pLruNext = p->pLruNext; - }else{ - sqlite3LruStatements.pFirst = p->pLruNext; - } - p->pLruNext = 0; - p->pLruPrev = 0; - assert( stmtLruCheck() ); - } -} - -/* -** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove -** statement p from the least-recently-used statement list. If the -** statement is not currently part of the list, this call is a no-op. -*/ -static void stmtLruRemove(Vdbe *p){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); - stmtLruRemoveNomutex(p); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); -} - -/* -** Try to release n bytes of memory by freeing buffers associated -** with the memory registers of currently unused vdbes. -*/ -SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int n){ - Vdbe *p; - Vdbe *pNext; - int nFree = 0; - - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); - for(p=sqlite3LruStatements.pFirst; p && nFree<n; p=pNext){ - pNext = p->pLruNext; - - /* For each statement handle in the lru list, attempt to obtain the - ** associated database mutex. If it cannot be obtained, continue - ** to the next statement handle. It is not possible to block on - ** the database mutex - that could cause deadlock. - */ - if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){ - nFree += sqlite3VdbeReleaseBuffers(p); - stmtLruRemoveNomutex(p); - sqlite3_mutex_leave(p->db->mutex); - } - } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); - - return nFree; -} - -/* -** Call sqlite3Reprepare() on the statement. Remove it from the -** lru list before doing so, as Reprepare() will free all the -** memory register buffers anyway. -*/ -int vdbeReprepare(Vdbe *p){ - stmtLruRemove(p); - return sqlite3Reprepare(p); -} - -#else /* !SQLITE_ENABLE_MEMORY_MANAGEMENT */ - #define stmtLruRemove(x) - #define stmtLruAdd(x) - #define vdbeReprepare(x) sqlite3Reprepare(x) -#endif - +** $Id: vdbeapi.c,v 1.167 2009/06/25 01:47:12 drh Exp $ +*/ #ifndef SQLITE_OMIT_DEPRECATED /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the @@ -48327,11 +50130,10 @@ sqlite3 *db = v->db; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = v->db->mutex; #endif sqlite3_mutex_enter(mutex); - stmtLruRemove(v); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(mutex); } return rc; @@ -48351,12 +50153,11 @@ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3_mutex_enter(v->db->mutex); rc = sqlite3VdbeReset(v); - stmtLruAdd(v); - sqlite3VdbeMakeReady(v, -1, 0, 0, 0); + sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0, 0); assert( (rc & (v->db->errMask))==rc ); rc = sqlite3ApiExit(v->db, rc); sqlite3_mutex_leave(v->db->mutex); } return rc; @@ -48431,20 +50232,35 @@ } /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify ** the function result. -*/ +** +** The setStrOrError() funtion calls sqlite3VdbeMemSetStr() to store the +** result as a string or blob but if the string or blob is too large, it +** then sets the error code to SQLITE_TOOBIG +*/ +static void setResultStrOrError( + sqlite3_context *pCtx, /* Function context */ + const char *z, /* String pointer */ + int n, /* Bytes in string, or negative */ + u8 enc, /* Encoding of z. 0 for BLOBs */ + void (*xDel)(void*) /* Destructor function */ +){ + if( sqlite3VdbeMemSetStr(&pCtx->s, z, n, enc, xDel)==SQLITE_TOOBIG ){ + sqlite3_result_error_toobig(pCtx); + } +} SQLITE_API void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ assert( n>=0 ); assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel); + setResultStrOrError(pCtx, z, n, 0, xDel); } SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetDouble(&pCtx->s, rVal); } @@ -48477,39 +50293,39 @@ const char *z, int n, void (*xDel)(void *) ){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel); + setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API void sqlite3_result_text16( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); } SQLITE_API void sqlite3_result_text16be( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16BE, xDel); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); } SQLITE_API void sqlite3_result_text16le( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemCopy(&pCtx->s, pValue); @@ -48518,10 +50334,14 @@ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetZeroBlob(&pCtx->s, n); } SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; + if( pCtx->s.flags & MEM_Null ){ + sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1, + SQLITE_UTF8, SQLITE_STATIC); + } } /* Force an SQLITE_TOOBIG error. */ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); @@ -48591,11 +50411,10 @@ #endif db->activeVdbeCnt++; if( p->readOnly==0 ) db->writeVdbeCnt++; p->pc = 0; - stmtLruRemove(p); } #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); }else @@ -48651,33 +50470,20 @@ /* ** This is the top-level implementation of sqlite3_step(). Call ** sqlite3Step() to do most of the work. If a schema error occurs, ** call sqlite3Reprepare() and try again. */ -#ifdef SQLITE_OMIT_PARSER -SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ - int rc = SQLITE_MISUSE; - if( pStmt ){ - Vdbe *v; - v = (Vdbe*)pStmt; - sqlite3_mutex_enter(v->db->mutex); - rc = sqlite3Step(v); - sqlite3_mutex_leave(v->db->mutex); - } - return rc; -} -#else SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_MISUSE; if( pStmt ){ int cnt = 0; Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; sqlite3_mutex_enter(db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < 5 - && (rc = vdbeReprepare(v))==SQLITE_OK ){ + && (rc = sqlite3Reprepare(v))==SQLITE_OK ){ sqlite3_reset(pStmt); v->expired = 0; } if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ /* This case occurs after failing to recompile an sql statement. @@ -48700,11 +50506,10 @@ rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); } return rc; } -#endif /* ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ @@ -48880,12 +50685,27 @@ if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){ sqlite3_mutex_enter(pVm->db->mutex); vals = sqlite3_data_count(pStmt); pOut = &pVm->pResultSet[i]; }else{ - /* ((double)0) In case of SQLITE_OMIT_FLOATING_POINT... */ - static const Mem nullMem = {{0}, (double)0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 }; + /* If the value passed as the second argument is out of range, return + ** a pointer to the following static Mem object which contains the + ** value SQL NULL. Even though the Mem structure contains an element + ** of type i64, on certain architecture (x86) with certain compiler + ** switches (-Os), gcc may align this Mem object on a 4-byte boundary + ** instead of an 8-byte one. This all works fine, except that when + ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s + ** that a Mem structure is located on an 8-byte boundary. To prevent + ** this assert() from failing, when building with SQLITE_DEBUG defined + ** using gcc, force nullMem to be 8-byte aligned using the magical + ** __attribute__((aligned(8))) macro. */ + static const Mem nullMem +#if defined(SQLITE_DEBUG) && defined(__GNUC__) + __attribute__((aligned(8))) +#endif + = {{0}, (double)0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 }; + if( pVm && ALWAYS(pVm->db) ){ sqlite3_mutex_enter(pVm->db->mutex); sqlite3Error(pVm->db, SQLITE_RANGE, 0); } pOut = (Mem*)&nullMem; @@ -49270,19 +51090,36 @@ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; - Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, i); - if( rc==SQLITE_OK ){ - rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue); - if( rc==SQLITE_OK ){ - rc = sqlite3VdbeChangeEncoding(&p->aVar[i-1], ENC(p->db)); - } - sqlite3_mutex_leave(p->db->mutex); - rc = sqlite3ApiExit(p->db, rc); + switch( pValue->type ){ + case SQLITE_INTEGER: { + rc = sqlite3_bind_int64(pStmt, i, pValue->u.i); + break; + } + case SQLITE_FLOAT: { + rc = sqlite3_bind_double(pStmt, i, pValue->r); + break; + } + case SQLITE_BLOB: { + if( pValue->flags & MEM_Zero ){ + rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero); + }else{ + rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT); + } + break; + } + case SQLITE_TEXT: { + rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT, + pValue->enc); + break; + } + default: { + rc = sqlite3_bind_null(pStmt, i); + break; + } } return rc; } SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; @@ -49491,11 +51328,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.832 2009/04/10 12:55:17 danielk1977 Exp $ +** $Id: vdbe.c,v 1.874 2009/07/24 17:58:53 danielk1977 Exp $ */ /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test @@ -49635,11 +51472,11 @@ static VdbeCursor *allocateCursor( Vdbe *p, /* The virtual machine */ int iCur, /* Index of the new VdbeCursor */ int nField, /* Number of fields in the table or index */ int iDb, /* When database the cursor belongs to, or -1 */ - int isBtreeCursor /* */ + int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */ ){ /* Find the memory cell that will be used to store the blob of memory ** required for this VdbeCursor structure. It is convenient to use a ** vdbe memory cell to manage the memory allocation required for a ** VdbeCursor structure for the following reasons: @@ -49872,12 +51709,16 @@ fprintf(out, " NULL"); }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ fprintf(out, " si:%lld", p->u.i); }else if( p->flags & MEM_Int ){ fprintf(out, " i:%lld", p->u.i); +#ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ fprintf(out, " r:%g", p->r); +#endif + }else if( p->flags & MEM_RowSet ){ + fprintf(out, " (rowset)"); }else{ char zBuf[200]; sqlite3VdbeMemPrettyPrint(p, zBuf); fprintf(out, " "); fprintf(out, "%s", zBuf); @@ -50099,13 +51940,416 @@ int origPc; /* Program counter at start of opcode */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif - - /* Temporary space into which to unpack a record. */ - char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; + /******************************************************************** + ** Automatically generated code + ** + ** The following union is automatically generated by the + ** vdbe-compress.tcl script. The purpose of this union is to + ** reduce the amount of stack space required by this function. + ** See comments in the vdbe-compress.tcl script for details. + */ + union vdbeExecUnion { + struct OP_Yield_stack_vars { + int pcDest; + } aa; + struct OP_Variable_stack_vars { + int p1; /* Variable to copy from */ + int p2; /* Register to copy to */ + int n; /* Number of values left to copy */ + Mem *pVar; /* Value being transferred */ + } ab; + struct OP_Move_stack_vars { + char *zMalloc; /* Holding variable for allocated memory */ + int n; /* Number of registers left to copy */ + int p1; /* Register to copy from */ + int p2; /* Register to copy to */ + } ac; + struct OP_ResultRow_stack_vars { + Mem *pMem; + int i; + } ad; + struct OP_Concat_stack_vars { + i64 nByte; + } ae; + struct OP_Remainder_stack_vars { + int flags; /* Combined MEM_* flags from both inputs */ + i64 iA; /* Integer value of left operand */ + i64 iB; /* Integer value of right operand */ + double rA; /* Real value of left operand */ + double rB; /* Real value of right operand */ + } af; + struct OP_Function_stack_vars { + int i; + Mem *pArg; + sqlite3_context ctx; + sqlite3_value **apVal; + int n; + } ag; + struct OP_ShiftRight_stack_vars { + i64 a; + i64 b; + } ah; + struct OP_Ge_stack_vars { + int flags; + int res; + char affinity; + } ai; + struct OP_Compare_stack_vars { + int n; + int i; + int p1; + int p2; + const KeyInfo *pKeyInfo; + int idx; + CollSeq *pColl; /* Collating sequence to use on this term */ + int bRev; /* True for DESCENDING sort order */ + } aj; + struct OP_Or_stack_vars { + int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + } ak; + struct OP_IfNot_stack_vars { + int c; + } al; + struct OP_Column_stack_vars { + u32 payloadSize; /* Number of bytes in the record */ + i64 payloadSize64; /* Number of bytes in the record */ + int p1; /* P1 value of the opcode */ + int p2; /* column number to retrieve */ + VdbeCursor *pC; /* The VDBE cursor */ + char *zRec; /* Pointer to complete record-data */ + BtCursor *pCrsr; /* The BTree cursor */ + u32 *aType; /* aType[i] holds the numeric type of the i-th column */ + u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ + int nField; /* number of fields in the record */ + int len; /* The length of the serialized data for the column */ + int i; /* Loop counter */ + char *zData; /* Part of the record being decoded */ + Mem *pDest; /* Where to write the extracted value */ + Mem sMem; /* For storing the record being decoded */ + u8 *zIdx; /* Index into header */ + u8 *zEndHdr; /* Pointer to first byte after the header */ + u32 offset; /* Offset into the data */ + u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ + int szHdr; /* Size of the header size field at start of record */ + int avail; /* Number of bytes of available data */ + Mem *pReg; /* PseudoTable input register */ + } am; + struct OP_Affinity_stack_vars { + char *zAffinity; /* The affinity to be applied */ + Mem *pData0; /* First register to which to apply affinity */ + Mem *pLast; /* Last register to which to apply affinity */ + Mem *pRec; /* Current register */ + } an; + struct OP_MakeRecord_stack_vars { + u8 *zNewRecord; /* A buffer to hold the data for the new record */ + Mem *pRec; /* The new record */ + u64 nData; /* Number of bytes of data space */ + int nHdr; /* Number of bytes of header space */ + i64 nByte; /* Data space required for this record */ + int nZero; /* Number of zero bytes at the end of the record */ + int nVarint; /* Number of bytes in a varint */ + u32 serial_type; /* Type field */ + Mem *pData0; /* First field to be combined into the record */ + Mem *pLast; /* Last field of the record */ + int nField; /* Number of fields in the record */ + char *zAffinity; /* The affinity string for the record */ + int file_format; /* File format to use for encoding */ + int i; /* Space used in zNewRecord[] */ + int len; /* Length of a field */ + } ao; + struct OP_Count_stack_vars { + i64 nEntry; + BtCursor *pCrsr; + } ap; + struct OP_Savepoint_stack_vars { + int p1; /* Value of P1 operand */ + char *zName; /* Name of savepoint */ + int nName; + Savepoint *pNew; + Savepoint *pSavepoint; + Savepoint *pTmp; + int iSavepoint; + int ii; + } aq; + struct OP_AutoCommit_stack_vars { + int desiredAutoCommit; + int iRollback; + int turnOnAC; + } ar; + struct OP_Transaction_stack_vars { + Btree *pBt; + } as; + struct OP_ReadCookie_stack_vars { + int iMeta; + int iDb; + int iCookie; + } at; + struct OP_SetCookie_stack_vars { + Db *pDb; + } au; + struct OP_VerifyCookie_stack_vars { + int iMeta; + Btree *pBt; + } av; + struct OP_OpenWrite_stack_vars { + int nField; + KeyInfo *pKeyInfo; + int p2; + int iDb; + int wrFlag; + Btree *pX; + VdbeCursor *pCur; + Db *pDb; + } aw; + struct OP_OpenEphemeral_stack_vars { + VdbeCursor *pCx; + } ax; + struct OP_OpenPseudo_stack_vars { + VdbeCursor *pCx; + } ay; + struct OP_SeekGt_stack_vars { + int res; + int oc; + VdbeCursor *pC; + UnpackedRecord r; + int nField; + i64 iKey; /* The rowid we are to seek to */ + } az; + struct OP_Seek_stack_vars { + VdbeCursor *pC; + } ba; + struct OP_Found_stack_vars { + int alreadyExists; + VdbeCursor *pC; + int res; + UnpackedRecord *pIdxKey; + char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; + } bb; + struct OP_IsUnique_stack_vars { + u16 ii; + VdbeCursor *pCx; + BtCursor *pCrsr; + u16 nField; + Mem *aMem; + UnpackedRecord r; /* B-Tree index search key */ + i64 R; /* Rowid stored in register P3 */ + } bc; + struct OP_NotExists_stack_vars { + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + u64 iKey; + } bd; + struct OP_NewRowid_stack_vars { + i64 v; /* The new rowid */ + VdbeCursor *pC; /* Cursor of table to get the new rowid */ + int res; /* Result of an sqlite3BtreeLast() */ + int cnt; /* Counter to limit the number of searches */ + Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ + VdbeFrame *pFrame; /* Root frame of VDBE */ + } be; + struct OP_Insert_stack_vars { + Mem *pData; /* MEM cell holding data for the record to be inserted */ + Mem *pKey; /* MEM cell holding key for the record */ + i64 iKey; /* The integer ROWID or key for the record to be inserted */ + VdbeCursor *pC; /* Cursor to table into which insert is written */ + int nZero; /* Number of zero-bytes to append */ + int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ + const char *zDb; /* database name - used by the update hook */ + const char *zTbl; /* Table name - used by the opdate hook */ + int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ + } bf; + struct OP_Delete_stack_vars { + i64 iKey; + VdbeCursor *pC; + } bg; + struct OP_RowData_stack_vars { + VdbeCursor *pC; + BtCursor *pCrsr; + u32 n; + i64 n64; + } bh; + struct OP_Rowid_stack_vars { + VdbeCursor *pC; + i64 v; + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + } bi; + struct OP_NullRow_stack_vars { + VdbeCursor *pC; + } bj; + struct OP_Last_stack_vars { + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + } bk; + struct OP_Rewind_stack_vars { + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + } bl; + struct OP_Next_stack_vars { + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + } bm; + struct OP_IdxInsert_stack_vars { + VdbeCursor *pC; + BtCursor *pCrsr; + int nKey; + const char *zKey; + } bn; + struct OP_IdxDelete_stack_vars { + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + UnpackedRecord r; + } bo; + struct OP_IdxRowid_stack_vars { + BtCursor *pCrsr; + VdbeCursor *pC; + i64 rowid; + } bp; + struct OP_IdxGE_stack_vars { + VdbeCursor *pC; + int res; + UnpackedRecord r; + } bq; + struct OP_Destroy_stack_vars { + int iMoved; + int iCnt; + Vdbe *pVdbe; + int iDb; + } br; + struct OP_Clear_stack_vars { + int nChange; + } bs; + struct OP_CreateTable_stack_vars { + int pgno; + int flags; + Db *pDb; + } bt; + struct OP_ParseSchema_stack_vars { + int iDb; + const char *zMaster; + char *zSql; + InitData initData; + } bu; + struct OP_IntegrityCk_stack_vars { + int nRoot; /* Number of tables to check. (Number of root pages.) */ + int *aRoot; /* Array of rootpage numbers for tables to be checked */ + int j; /* Loop counter */ + int nErr; /* Number of errors reported */ + char *z; /* Text of the error report */ + Mem *pnErr; /* Register keeping track of errors remaining */ + } bv; + struct OP_RowSetAdd_stack_vars { + Mem *pIdx; + Mem *pVal; + } bw; + struct OP_RowSetRead_stack_vars { + Mem *pIdx; + i64 val; + } bx; + struct OP_RowSetTest_stack_vars { + int iSet; + int exists; + } by; + struct OP_Program_stack_vars { + int nMem; /* Number of memory registers for sub-program */ + int nByte; /* Bytes of runtime space required for sub-program */ + Mem *pRt; /* Register to allocate runtime space */ + Mem *pMem; /* Used to iterate through memory cells */ + Mem *pEnd; /* Last memory cell in new array */ + VdbeFrame *pFrame; /* New vdbe frame to execute in */ + SubProgram *pProgram; /* Sub-program to execute */ + void *t; /* Token identifying trigger */ + } bz; + struct OP_Param_stack_vars { + VdbeFrame *pFrame; + Mem *pIn; + } ca; + struct OP_MemMax_stack_vars { + Mem *pIn1; + VdbeFrame *pFrame; + } cb; + struct OP_AggStep_stack_vars { + int n; + int i; + Mem *pMem; + Mem *pRec; + sqlite3_context ctx; + sqlite3_value **apVal; + } cc; + struct OP_AggFinal_stack_vars { + Mem *pMem; + } cd; + struct OP_IncrVacuum_stack_vars { + Btree *pBt; + } ce; + struct OP_VBegin_stack_vars { + VTable *pVTab; + } cf; + struct OP_VOpen_stack_vars { + VdbeCursor *pCur; + sqlite3_vtab_cursor *pVtabCursor; + sqlite3_vtab *pVtab; + sqlite3_module *pModule; + } cg; + struct OP_VFilter_stack_vars { + int nArg; + int iQuery; + const sqlite3_module *pModule; + Mem *pQuery; + Mem *pArgc; + sqlite3_vtab_cursor *pVtabCursor; + sqlite3_vtab *pVtab; + VdbeCursor *pCur; + int res; + int i; + Mem **apArg; + } ch; + struct OP_VColumn_stack_vars { + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + Mem *pDest; + sqlite3_context sContext; + } ci; + struct OP_VNext_stack_vars { + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + int res; + VdbeCursor *pCur; + } cj; + struct OP_VRename_stack_vars { + sqlite3_vtab *pVtab; + Mem *pName; + } ck; + struct OP_VUpdate_stack_vars { + sqlite3_vtab *pVtab; + sqlite3_module *pModule; + int nArg; + int i; + sqlite_int64 rowid; + Mem **apArg; + Mem *pX; + } cl; + struct OP_Pagecount_stack_vars { + int p1; + int nPage; + Pager *pPager; + } cm; + struct OP_Trace_stack_vars { + char *zTrace; + } cn; + } u; + /* End automatically generated code + ********************************************************************/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ assert( db->magic==SQLITE_MAGIC_BUSY ); sqlite3VdbeMutexArrayEnter(p); if( p->rc==SQLITE_NOMEM ){ @@ -50211,10 +52455,11 @@ assert( pOp->p2>0 ); assert( pOp->p2<=p->nMem ); pOut = &p->aMem[pOp->p2]; sqlite3VdbeMemReleaseExternal(pOut); pOut->flags = MEM_Null; + pOut->n = 0; }else /* Do common setup for opcodes marked with one of the following ** combinations of properties. ** @@ -50234,15 +52479,16 @@ if( (opProperty & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); assert( pOp->p2<=p->nMem ); pIn2 = &p->aMem[pOp->p2]; REGISTER_TRACE(pOp->p2, pIn2); - if( (opProperty & OPFLG_OUT3)!=0 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=p->nMem ); - pOut = &p->aMem[pOp->p3]; - } + /* As currently implemented, in2 implies out3. There is no reason + ** why this has to be, it just worked out that way. */ + assert( (opProperty & OPFLG_OUT3)!=0 ); + assert( pOp->p3>0 ); + assert( pOp->p3<=p->nMem ); + pOut = &p->aMem[pOp->p3]; }else if( (opProperty & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); assert( pOp->p3<=p->nMem ); pIn3 = &p->aMem[pOp->p3]; REGISTER_TRACE(pOp->p3, pIn3); @@ -50339,17 +52585,19 @@ /* Opcode: Yield P1 * * * * ** ** Swap the program counter with the value in register P1. */ case OP_Yield: { /* in1 */ +#if 0 /* local variables moved into u.aa */ int pcDest; +#endif /* local variables moved into u.aa */ assert( (pIn1->flags & MEM_Dyn)==0 ); pIn1->flags = MEM_Int; - pcDest = (int)pIn1->u.i; + u.aa.pcDest = (int)pIn1->u.i; pIn1->u.i = pc; REGISTER_TRACE(pOp->p1, pIn1); - pc = pcDest; + pc = u.aa.pcDest; break; } /* Opcode: HaltIfNull P1 P2 P3 P4 * ** @@ -50380,13 +52628,31 @@ ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ case OP_Halt: { + if( pOp->p1==SQLITE_OK && p->pFrame ){ + /* Halt the sub-program. Return control to the parent frame. */ + VdbeFrame *pFrame = p->pFrame; + p->pFrame = pFrame->pParent; + p->nFrame--; + sqlite3VdbeSetChanges(db, p->nChange); + pc = sqlite3VdbeFrameRestore(pFrame); + if( pOp->p2==OE_Ignore ){ + /* Instruction pc is the OP_Program that invoked the sub-program + ** currently being halted. If the p2 instruction of this OP_Halt + ** instruction is set to OE_Ignore, then the sub-program is throwing + ** an IGNORE exception. In this case jump to the address specified + ** as the p2 of the calling OP_Program. */ + pc = p->aOp[pc].p2-1; + } + break; + } + p->rc = pOp->p1; - p->pc = pc; - p->errorAction = pOp->p2; + p->errorAction = (u8)pOp->p2; + p->pc = pc; if( pOp->p4.z ){ sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); @@ -50442,27 +52708,24 @@ pOp->opcode = OP_String; pOp->p1 = sqlite3Strlen30(pOp->p4.z); #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ - sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); + rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); + if( rc==SQLITE_TOOBIG ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; - if( SQLITE_OK!=sqlite3VdbeMemMakeWriteable(pOut) ) goto no_mem; + assert( pOut->zMalloc==pOut->z ); + assert( pOut->flags & MEM_Dyn ); pOut->zMalloc = 0; pOut->flags |= MEM_Static; pOut->flags &= ~MEM_Dyn; if( pOp->p4type==P4_DYNAMIC ){ sqlite3DbFree(db, pOp->p4.z); } pOp->p4type = P4_DYNAMIC; pOp->p4.z = pOut->z; pOp->p1 = pOut->n; - if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - UPDATE_MAX_BLOBSIZE(pOut); - break; } #endif if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } @@ -50516,27 +52779,33 @@ ** ** If the parameter is named, then its name appears in P4 and P3==1. ** The P4 value is used by sqlite3_bind_parameter_name(). */ case OP_Variable: { - int j = pOp->p1 - 1; - int k = pOp->p2; - Mem *pVar; - int n = pOp->p3; - assert( j>=0 && j+n<=p->nVar ); - assert( k>=1 && k+n-1<=p->nMem ); +#if 0 /* local variables moved into u.ab */ + int p1; /* Variable to copy from */ + int p2; /* Register to copy to */ + int n; /* Number of values left to copy */ + Mem *pVar; /* Value being transferred */ +#endif /* local variables moved into u.ab */ + + u.ab.p1 = pOp->p1 - 1; + u.ab.p2 = pOp->p2; + u.ab.n = pOp->p3; + assert( u.ab.p1>=0 && u.ab.p1+u.ab.n<=p->nVar ); + assert( u.ab.p2>=1 && u.ab.p2+u.ab.n-1<=p->nMem ); assert( pOp->p4.z==0 || pOp->p3==1 ); - while( n-- > 0 ){ - pVar = &p->aVar[j++]; - if( sqlite3VdbeMemTooBig(pVar) ){ + while( u.ab.n-- > 0 ){ + u.ab.pVar = &p->aVar[u.ab.p1++]; + if( sqlite3VdbeMemTooBig(u.ab.pVar) ){ goto too_big; } - pOut = &p->aMem[k++]; + pOut = &p->aMem[u.ab.p2++]; sqlite3VdbeMemReleaseExternal(pOut); pOut->flags = MEM_Null; - sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); + sqlite3VdbeMemShallowCopy(pOut, u.ab.pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); } break; } @@ -50546,27 +52815,33 @@ ** registers P2..P2+P3-1. Registers P1..P1+P1-1 are ** left holding a NULL. It is an error for register ranges ** P1..P1+P3-1 and P2..P2+P3-1 to overlap. */ case OP_Move: { - char *zMalloc; - int n = pOp->p3; - int p1 = pOp->p1; - int p2 = pOp->p2; - assert( n>0 && p1>0 && p2>0 ); - assert( p1+n<=p2 || p2+n<=p1 ); - - pIn1 = &p->aMem[p1]; - pOut = &p->aMem[p2]; - while( n-- ){ +#if 0 /* local variables moved into u.ac */ + char *zMalloc; /* Holding variable for allocated memory */ + int n; /* Number of registers left to copy */ + int p1; /* Register to copy from */ + int p2; /* Register to copy to */ +#endif /* local variables moved into u.ac */ + + u.ac.n = pOp->p3; + u.ac.p1 = pOp->p1; + u.ac.p2 = pOp->p2; + assert( u.ac.n>0 && u.ac.p1>0 && u.ac.p2>0 ); + assert( u.ac.p1+u.ac.n<=u.ac.p2 || u.ac.p2+u.ac.n<=u.ac.p1 ); + + pIn1 = &p->aMem[u.ac.p1]; + pOut = &p->aMem[u.ac.p2]; + while( u.ac.n-- ){ assert( pOut<=&p->aMem[p->nMem] ); assert( pIn1<=&p->aMem[p->nMem] ); - zMalloc = pOut->zMalloc; + u.ac.zMalloc = pOut->zMalloc; pOut->zMalloc = 0; sqlite3VdbeMemMove(pOut, pIn1); - pIn1->zMalloc = zMalloc; - REGISTER_TRACE(p2++, pOut); + pIn1->zMalloc = u.ac.zMalloc; + REGISTER_TRACE(u.ac.p2++, pOut); pIn1++; pOut++; } break; } @@ -50619,12 +52894,14 @@ ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt ** structure to provide access to the top P1 values as the result ** row. */ case OP_ResultRow: { +#if 0 /* local variables moved into u.ad */ Mem *pMem; int i; +#endif /* local variables moved into u.ad */ assert( p->nResColumn==pOp->p2 ); assert( pOp->p1>0 ); assert( pOp->p1+pOp->p2<=p->nMem+1 ); /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then @@ -50636,13 +52913,17 @@ ** opened by this VM before returning control to the user. This is to ** ensure that statement-transactions are always nested, not overlapping. ** If the open statement-transaction is not closed here, then the user ** may step another VM that opens its own statement transaction. This ** may lead to overlapping statement transactions. + ** + ** The statement transaction is never a top-level transaction. Hence + ** the RELEASE call below can never fail. */ assert( p->iStatement==0 || db->flags&SQLITE_CountRows ); - if( SQLITE_OK!=(rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE)) ){ + rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE); + if( NEVER(rc!=SQLITE_OK) ){ break; } /* Invalidate all ephemeral cursor row caches */ p->cacheCtr = (p->cacheCtr + 2)|1; @@ -50649,15 +52930,15 @@ /* Make sure the results of the current row are \000 terminated ** and have an assigned type. The results are de-ephemeralized as ** as side effect. */ - pMem = p->pResultSet = &p->aMem[pOp->p1]; - for(i=0; i<pOp->p2; i++){ - sqlite3VdbeMemNulTerminate(&pMem[i]); - storeTypeInfo(&pMem[i], encoding); - REGISTER_TRACE(pOp->p1+i, &pMem[i]); + u.ad.pMem = p->pResultSet = &p->aMem[pOp->p1]; + for(u.ad.i=0; u.ad.i<pOp->p2; u.ad.i++){ + sqlite3VdbeMemNulTerminate(&u.ad.pMem[u.ad.i]); + storeTypeInfo(&u.ad.pMem[u.ad.i], encoding); + REGISTER_TRACE(pOp->p1+u.ad.i, &u.ad.pMem[u.ad.i]); } if( db->mallocFailed ) goto no_mem; /* Return SQLITE_ROW */ @@ -50677,37 +52958,38 @@ ** It is illegal for P1 and P3 to be the same register. Sometimes, ** if P3 is the same register as P2, the implementation is able ** to avoid a memcpy(). */ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ +#if 0 /* local variables moved into u.ae */ i64 nByte; +#endif /* local variables moved into u.ae */ assert( pIn1!=pOut ); if( (pIn1->flags | pIn2->flags) & MEM_Null ){ sqlite3VdbeMemSetNull(pOut); break; } - ExpandBlob(pIn1); - Stringify(pIn1, encoding); - ExpandBlob(pIn2); + if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem; + Stringify(pIn1, encoding); Stringify(pIn2, encoding); - nByte = pIn1->n + pIn2->n; - if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + u.ae.nByte = pIn1->n + pIn2->n; + if( u.ae.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } MemSetTypeFlag(pOut, MEM_Str); - if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ + if( sqlite3VdbeMemGrow(pOut, (int)u.ae.nByte+2, pOut==pIn2) ){ goto no_mem; } if( pOut!=pIn2 ){ memcpy(pOut->z, pIn2->z, pIn2->n); } memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); - pOut->z[nByte] = 0; - pOut->z[nByte+1] = 0; + pOut->z[u.ae.nByte] = 0; + pOut->z[u.ae.nByte+1] = 0; pOut->flags |= MEM_Term; - pOut->n = (int)nByte; + pOut->n = (int)u.ae.nByte; pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; } @@ -50731,13 +53013,13 @@ ** If either input is NULL, the result is NULL. */ /* Opcode: Divide P1 P2 P3 * * ** ** Divide the value in register P1 by the value in register P2 -** and store the result in register P3. If the value in register P2 -** is zero, then the result is NULL. -** If either input is NULL, the result is NULL. +** and store the result in register P3 (P3=P2/P1). If the value in +** register P1 is zero, then the result is NULL. If either input is +** NULL, the result is NULL. */ /* Opcode: Remainder P1 P2 P3 * * ** ** Compute the remainder after integer division of the value in ** register P1 by the value in register P2 and store the result in P3. @@ -50747,74 +53029,79 @@ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ - int flags; +#if 0 /* local variables moved into u.af */ + int flags; /* Combined MEM_* flags from both inputs */ + i64 iA; /* Integer value of left operand */ + i64 iB; /* Integer value of right operand */ + double rA; /* Real value of left operand */ + double rB; /* Real value of right operand */ +#endif /* local variables moved into u.af */ + applyNumericAffinity(pIn1); applyNumericAffinity(pIn2); - flags = pIn1->flags | pIn2->flags; - if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; + u.af.flags = pIn1->flags | pIn2->flags; + if( (u.af.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ - i64 a, b; - a = pIn1->u.i; - b = pIn2->u.i; + u.af.iA = pIn1->u.i; + u.af.iB = pIn2->u.i; switch( pOp->opcode ){ - case OP_Add: b += a; break; - case OP_Subtract: b -= a; break; - case OP_Multiply: b *= a; break; + case OP_Add: u.af.iB += u.af.iA; break; + case OP_Subtract: u.af.iB -= u.af.iA; break; + case OP_Multiply: u.af.iB *= u.af.iA; break; case OP_Divide: { - if( a==0 ) goto arithmetic_result_is_null; + if( u.af.iA==0 ) goto arithmetic_result_is_null; /* Dividing the largest possible negative 64-bit integer (1<<63) by ** -1 returns an integer too large to store in a 64-bit data-type. On ** some architectures, the value overflows to (1<<63). On others, ** a SIGFPE is issued. The following statement normalizes this ** behavior so that all architectures behave as if integer ** overflow occurred. */ - if( a==-1 && b==SMALLEST_INT64 ) a = 1; - b /= a; + if( u.af.iA==-1 && u.af.iB==SMALLEST_INT64 ) u.af.iA = 1; + u.af.iB /= u.af.iA; break; } default: { - if( a==0 ) goto arithmetic_result_is_null; - if( a==-1 ) a = 1; - b %= a; - break; - } - } - pOut->u.i = b; + if( u.af.iA==0 ) goto arithmetic_result_is_null; + if( u.af.iA==-1 ) u.af.iA = 1; + u.af.iB %= u.af.iA; + break; + } + } + pOut->u.i = u.af.iB; MemSetTypeFlag(pOut, MEM_Int); }else{ - double a, b; - a = sqlite3VdbeRealValue(pIn1); - b = sqlite3VdbeRealValue(pIn2); + u.af.rA = sqlite3VdbeRealValue(pIn1); + u.af.rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ - case OP_Add: b += a; break; - case OP_Subtract: b -= a; break; - case OP_Multiply: b *= a; break; + case OP_Add: u.af.rB += u.af.rA; break; + case OP_Subtract: u.af.rB -= u.af.rA; break; + case OP_Multiply: u.af.rB *= u.af.rA; break; case OP_Divide: { /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - if( a==(double)0 ) goto arithmetic_result_is_null; - b /= a; + if( u.af.rA==(double)0 ) goto arithmetic_result_is_null; + u.af.rB /= u.af.rA; break; } default: { - i64 ia = (i64)a; - i64 ib = (i64)b; - if( ia==0 ) goto arithmetic_result_is_null; - if( ia==-1 ) ia = 1; - b = (double)(ib % ia); - break; - } - } - if( sqlite3IsNaN(b) ){ + u.af.iA = (i64)u.af.rA; + u.af.iB = (i64)u.af.rB; + if( u.af.iA==0 ) goto arithmetic_result_is_null; + if( u.af.iA==-1 ) u.af.iA = 1; + u.af.rB = (double)(u.af.iB % u.af.iA); + break; + } + } + if( sqlite3IsNaN(u.af.rB) ){ goto arithmetic_result_is_null; } - pOut->r = b; + pOut->r = u.af.rB; MemSetTypeFlag(pOut, MEM_Real); - if( (flags & MEM_Real)==0 ){ + if( (u.af.flags & MEM_Real)==0 ){ sqlite3VdbeIntegerAffinity(pOut); } } break; @@ -50854,62 +53141,65 @@ ** invocation of this opcode. ** ** See also: AggStep and AggFinal */ case OP_Function: { +#if 0 /* local variables moved into u.ag */ int i; Mem *pArg; sqlite3_context ctx; sqlite3_value **apVal; - int n = pOp->p5; - - apVal = p->apArg; - assert( apVal || n==0 ); - - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem+1) ); - assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); - pArg = &p->aMem[pOp->p2]; - for(i=0; i<n; i++, pArg++){ - apVal[i] = pArg; - storeTypeInfo(pArg, encoding); - REGISTER_TRACE(pOp->p2, pArg); + int n; +#endif /* local variables moved into u.ag */ + + u.ag.n = pOp->p5; + u.ag.apVal = p->apArg; + assert( u.ag.apVal || u.ag.n==0 ); + + assert( u.ag.n==0 || (pOp->p2>0 && pOp->p2+u.ag.n<=p->nMem+1) ); + assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ag.n ); + u.ag.pArg = &p->aMem[pOp->p2]; + for(u.ag.i=0; u.ag.i<u.ag.n; u.ag.i++, u.ag.pArg++){ + u.ag.apVal[u.ag.i] = u.ag.pArg; + storeTypeInfo(u.ag.pArg, encoding); + REGISTER_TRACE(pOp->p2, u.ag.pArg); } assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC ); if( pOp->p4type==P4_FUNCDEF ){ - ctx.pFunc = pOp->p4.pFunc; - ctx.pVdbeFunc = 0; - }else{ - ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc; - ctx.pFunc = ctx.pVdbeFunc->pFunc; + u.ag.ctx.pFunc = pOp->p4.pFunc; + u.ag.ctx.pVdbeFunc = 0; + }else{ + u.ag.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc; + u.ag.ctx.pFunc = u.ag.ctx.pVdbeFunc->pFunc; } assert( pOp->p3>0 && pOp->p3<=p->nMem ); pOut = &p->aMem[pOp->p3]; - ctx.s.flags = MEM_Null; - ctx.s.db = db; - ctx.s.xDel = 0; - ctx.s.zMalloc = 0; + u.ag.ctx.s.flags = MEM_Null; + u.ag.ctx.s.db = db; + u.ag.ctx.s.xDel = 0; + u.ag.ctx.s.zMalloc = 0; /* The output cell may already have a buffer allocated. Move - ** the pointer to ctx.s so in case the user-function can use + ** the pointer to u.ag.ctx.s so in case the user-function can use ** the already allocated buffer instead of allocating a new one. */ - sqlite3VdbeMemMove(&ctx.s, pOut); - MemSetTypeFlag(&ctx.s, MEM_Null); - - ctx.isError = 0; - if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ + sqlite3VdbeMemMove(&u.ag.ctx.s, pOut); + MemSetTypeFlag(&u.ag.ctx.s, MEM_Null); + + u.ag.ctx.isError = 0; + if( u.ag.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); - ctx.pColl = pOp[-1].p4.pColl; + u.ag.ctx.pColl = pOp[-1].p4.pColl; } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - (*ctx.pFunc->xFunc)(&ctx, n, apVal); + (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); if( sqlite3SafetyOn(db) ){ - sqlite3VdbeMemRelease(&ctx.s); + sqlite3VdbeMemRelease(&u.ag.ctx.s); goto abort_due_to_misuse; } if( db->mallocFailed ){ /* Even though a malloc() has failed, the implementation of the ** user function may have called an sqlite3_result_XXX() function @@ -50918,32 +53208,32 @@ ** ** Note: Maybe MemRelease() should be called if sqlite3SafetyOn() ** fails also (the if(...) statement above). But if people are ** misusing sqlite, they have bigger problems than a leaked value. */ - sqlite3VdbeMemRelease(&ctx.s); + sqlite3VdbeMemRelease(&u.ag.ctx.s); goto no_mem; } /* If any auxiliary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ - if( ctx.pVdbeFunc ){ - sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1); - pOp->p4.pVdbeFunc = ctx.pVdbeFunc; + if( u.ag.ctx.pVdbeFunc ){ + sqlite3VdbeDeleteAuxData(u.ag.ctx.pVdbeFunc, pOp->p1); + pOp->p4.pVdbeFunc = u.ag.ctx.pVdbeFunc; pOp->p4type = P4_VDBEFUNC; } /* If the function returned an error, throw an exception */ - if( ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); - rc = ctx.isError; + if( u.ag.ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ag.ctx.s)); + rc = u.ag.ctx.isError; } /* Copy the result of the function into register P3 */ - sqlite3VdbeChangeEncoding(&ctx.s, encoding); - sqlite3VdbeMemMove(pOut, &ctx.s); + sqlite3VdbeChangeEncoding(&u.ag.ctx.s, encoding); + sqlite3VdbeMemMove(pOut, &u.ag.ctx.s); if( sqlite3VdbeMemTooBig(pOut) ){ goto too_big; } REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); @@ -50978,26 +53268,29 @@ */ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ - i64 a, b; +#if 0 /* local variables moved into u.ah */ + i64 a; + i64 b; +#endif /* local variables moved into u.ah */ if( (pIn1->flags | pIn2->flags) & MEM_Null ){ sqlite3VdbeMemSetNull(pOut); break; } - a = sqlite3VdbeIntValue(pIn2); - b = sqlite3VdbeIntValue(pIn1); + u.ah.a = sqlite3VdbeIntValue(pIn2); + u.ah.b = sqlite3VdbeIntValue(pIn1); switch( pOp->opcode ){ - case OP_BitAnd: a &= b; break; - case OP_BitOr: a |= b; break; - case OP_ShiftLeft: a <<= b; break; + case OP_BitAnd: u.ah.a &= u.ah.b; break; + case OP_BitOr: u.ah.a |= u.ah.b; break; + case OP_ShiftLeft: u.ah.a <<= u.ah.b; break; default: assert( pOp->opcode==OP_ShiftRight ); - a >>= b; break; - } - pOut->u.i = a; + u.ah.a >>= u.ah.b; break; + } + pOut->u.i = u.ah.a; MemSetTypeFlag(pOut, MEM_Int); break; } /* Opcode: AddImm P1 P2 * * * @@ -51211,17 +53504,19 @@ case OP_Ne: /* same as TK_NE, jump, in1, in3 */ case OP_Lt: /* same as TK_LT, jump, in1, in3 */ case OP_Le: /* same as TK_LE, jump, in1, in3 */ case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ +#if 0 /* local variables moved into u.ai */ int flags; int res; char affinity; - - flags = pIn1->flags|pIn3->flags; - - if( flags&MEM_Null ){ +#endif /* local variables moved into u.ai */ + + u.ai.flags = pIn1->flags|pIn3->flags; + + if( u.ai.flags&MEM_Null ){ /* If either operand is NULL then the result is always NULL. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. */ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &p->aMem[pOp->p2]; @@ -51231,36 +53526,36 @@ pc = pOp->p2-1; } break; } - affinity = pOp->p5 & SQLITE_AFF_MASK; - if( affinity ){ - applyAffinity(pIn1, affinity, encoding); - applyAffinity(pIn3, affinity, encoding); + u.ai.affinity = pOp->p5 & SQLITE_AFF_MASK; + if( u.ai.affinity ){ + applyAffinity(pIn1, u.ai.affinity, encoding); + applyAffinity(pIn3, u.ai.affinity, encoding); if( db->mallocFailed ) goto no_mem; } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); ExpandBlob(pIn1); ExpandBlob(pIn3); - res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); + u.ai.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); switch( pOp->opcode ){ - case OP_Eq: res = res==0; break; - case OP_Ne: res = res!=0; break; - case OP_Lt: res = res<0; break; - case OP_Le: res = res<=0; break; - case OP_Gt: res = res>0; break; - default: res = res>=0; break; + case OP_Eq: u.ai.res = u.ai.res==0; break; + case OP_Ne: u.ai.res = u.ai.res!=0; break; + case OP_Lt: u.ai.res = u.ai.res<0; break; + case OP_Le: u.ai.res = u.ai.res<=0; break; + case OP_Gt: u.ai.res = u.ai.res>0; break; + default: u.ai.res = u.ai.res>=0; break; } if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &p->aMem[pOp->p2]; MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = res; + pOut->u.i = u.ai.res; REGISTER_TRACE(pOp->p2, pOut); - }else if( res ){ + }else if( u.ai.res ){ pc = pOp->p2-1; } break; } @@ -51293,31 +53588,39 @@ ** The comparison is a sort comparison, so NULLs compare equal, ** NULLs are less than numbers, numbers are less than strings, ** and strings are less than blobs. */ case OP_Compare: { - int n = pOp->p3; - int i, p1, p2; - const KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; - assert( n>0 ); - assert( pKeyInfo!=0 ); - p1 = pOp->p1; - assert( p1>0 && p1+n<=p->nMem+1 ); - p2 = pOp->p2; - assert( p2>0 && p2+n<=p->nMem+1 ); - for(i=0; i<n; i++){ - int idx = aPermute ? aPermute[i] : i; - CollSeq *pColl; /* Collating sequence to use on this term */ - int bRev; /* True for DESCENDING sort order */ - REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]); - REGISTER_TRACE(p2+idx, &p->aMem[p2+idx]); - assert( i<pKeyInfo->nField ); - pColl = pKeyInfo->aColl[i]; - bRev = pKeyInfo->aSortOrder[i]; - iCompare = sqlite3MemCompare(&p->aMem[p1+idx], &p->aMem[p2+idx], pColl); +#if 0 /* local variables moved into u.aj */ + int n; + int i; + int p1; + int p2; + const KeyInfo *pKeyInfo; + int idx; + CollSeq *pColl; /* Collating sequence to use on this term */ + int bRev; /* True for DESCENDING sort order */ +#endif /* local variables moved into u.aj */ + + u.aj.n = pOp->p3; + u.aj.pKeyInfo = pOp->p4.pKeyInfo; + assert( u.aj.n>0 ); + assert( u.aj.pKeyInfo!=0 ); + u.aj.p1 = pOp->p1; + assert( u.aj.p1>0 && u.aj.p1+u.aj.n<=p->nMem+1 ); + u.aj.p2 = pOp->p2; + assert( u.aj.p2>0 && u.aj.p2+u.aj.n<=p->nMem+1 ); + for(u.aj.i=0; u.aj.i<u.aj.n; u.aj.i++){ + u.aj.idx = aPermute ? aPermute[u.aj.i] : u.aj.i; + REGISTER_TRACE(u.aj.p1+u.aj.idx, &p->aMem[u.aj.p1+u.aj.idx]); + REGISTER_TRACE(u.aj.p2+u.aj.idx, &p->aMem[u.aj.p2+u.aj.idx]); + assert( u.aj.i<u.aj.pKeyInfo->nField ); + u.aj.pColl = u.aj.pKeyInfo->aColl[u.aj.i]; + u.aj.bRev = u.aj.pKeyInfo->aSortOrder[u.aj.i]; + iCompare = sqlite3MemCompare(&p->aMem[u.aj.p1+u.aj.idx], &p->aMem[u.aj.p2+u.aj.idx], u.aj.pColl); if( iCompare ){ - if( bRev ) iCompare = -iCompare; + if( u.aj.bRev ) iCompare = -iCompare; break; } } aPermute = 0; break; @@ -51358,33 +53661,36 @@ ** even if the other input is NULL. A NULL and false or two NULLs ** give a NULL output. */ case OP_And: /* same as TK_AND, in1, in2, out3 */ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ - int v1, v2; /* 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ +#if 0 /* local variables moved into u.ak */ + int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ +#endif /* local variables moved into u.ak */ if( pIn1->flags & MEM_Null ){ - v1 = 2; - }else{ - v1 = sqlite3VdbeIntValue(pIn1)!=0; + u.ak.v1 = 2; + }else{ + u.ak.v1 = sqlite3VdbeIntValue(pIn1)!=0; } if( pIn2->flags & MEM_Null ){ - v2 = 2; - }else{ - v2 = sqlite3VdbeIntValue(pIn2)!=0; + u.ak.v2 = 2; + }else{ + u.ak.v2 = sqlite3VdbeIntValue(pIn2)!=0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; - v1 = and_logic[v1*3+v2]; + u.ak.v1 = and_logic[u.ak.v1*3+u.ak.v2]; }else{ static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; - v1 = or_logic[v1*3+v2]; - } - if( v1==2 ){ + u.ak.v1 = or_logic[u.ak.v1*3+u.ak.v2]; + } + if( u.ak.v1==2 ){ MemSetTypeFlag(pOut, MEM_Null); }else{ - pOut->u.i = v1; + pOut->u.i = u.ak.v1; MemSetTypeFlag(pOut, MEM_Int); } break; } @@ -51432,43 +53738,37 @@ ** is considered true if it has a numeric value of zero. If the value ** in P1 is NULL then take the jump if P3 is true. */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ +#if 0 /* local variables moved into u.al */ int c; +#endif /* local variables moved into u.al */ if( pIn1->flags & MEM_Null ){ - c = pOp->p3; + u.al.c = pOp->p3; }else{ #ifdef SQLITE_OMIT_FLOATING_POINT - c = sqlite3VdbeIntValue(pIn1)!=0; -#else - c = sqlite3VdbeRealValue(pIn1)!=0.0; -#endif - if( pOp->opcode==OP_IfNot ) c = !c; - } - if( c ){ + u.al.c = sqlite3VdbeIntValue(pIn1)!=0; +#else + u.al.c = sqlite3VdbeRealValue(pIn1)!=0.0; +#endif + if( pOp->opcode==OP_IfNot ) u.al.c = !u.al.c; + } + if( u.al.c ){ pc = pOp->p2-1; } break; } -/* Opcode: IsNull P1 P2 P3 * * -** -** Jump to P2 if the value in register P1 is NULL. If P3 is greater -** than zero, then check all values reg(P1), reg(P1+1), -** reg(P1+2), ..., reg(P1+P3-1). +/* Opcode: IsNull P1 P2 * * * +** +** Jump to P2 if the value in register P1 is NULL. */ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ - int n = pOp->p3; - assert( pOp->p3==0 || pOp->p1>0 ); - do{ - if( (pIn1->flags & MEM_Null)!=0 ){ - pc = pOp->p2 - 1; - break; - } - pIn1++; - }while( --n > 0 ); + if( (pIn1->flags & MEM_Null)!=0 ){ + pc = pOp->p2 - 1; + } break; } /* Opcode: NotNull P1 P2 * * * ** @@ -51479,33 +53779,11 @@ pc = pOp->p2 - 1; } break; } -/* Opcode: SetNumColumns * P2 * * * -** -** This opcode sets the number of columns for the cursor opened by the -** following instruction to P2. -** -** An OP_SetNumColumns is only useful if it occurs immediately before -** one of the following opcodes: -** -** OpenRead -** OpenWrite -** OpenPseudo -** -** If the OP_Column opcode is to be executed on a cursor, then -** this opcode must be present immediately before the opcode that -** opens the cursor. -*/ -#if 0 -case OP_SetNumColumns: { - break; -} -#endif - -/* Opcode: Column P1 P2 P3 P4 * +/* Opcode: Column P1 P2 P3 P4 P5 ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional ** information about the format of the data.) Extract the P2-th column ** from this record. If there are less that (P2+1) @@ -51514,16 +53792,23 @@ ** The value extracted is stored in register P3. ** ** If the column contains fewer than P2 fields, then extract a NULL. Or, ** if the P4 argument is a P4_MEM use the value of the P4 argument as ** the result. +** +** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor, +** then the cache of the cursor is reset prior to extracting the column. +** The first OP_Column against a pseudo-table after the value of the content +** register has changed should have this bit set. */ case OP_Column: { - int payloadSize; /* Number of bytes in the record */ - int p1 = pOp->p1; /* P1 value of the opcode */ - int p2 = pOp->p2; /* column number to retrieve */ - VdbeCursor *pC = 0;/* The VDBE cursor */ +#if 0 /* local variables moved into u.am */ + u32 payloadSize; /* Number of bytes in the record */ + i64 payloadSize64; /* Number of bytes in the record */ + int p1; /* P1 value of the opcode */ + int p2; /* column number to retrieve */ + VdbeCursor *pC; /* The VDBE cursor */ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ int nField; /* number of fields in the record */ @@ -51530,223 +53815,271 @@ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ - - memset(&sMem, 0, sizeof(sMem)); - assert( p1<p->nCursor ); + u8 *zIdx; /* Index into header */ + u8 *zEndHdr; /* Pointer to first byte after the header */ + u32 offset; /* Offset into the data */ + u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ + int szHdr; /* Size of the header size field at start of record */ + int avail; /* Number of bytes of available data */ + Mem *pReg; /* PseudoTable input register */ +#endif /* local variables moved into u.am */ + + + u.am.p1 = pOp->p1; + u.am.p2 = pOp->p2; + u.am.pC = 0; + memset(&u.am.sMem, 0, sizeof(u.am.sMem)); + assert( u.am.p1<p->nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); - pDest = &p->aMem[pOp->p3]; - MemSetTypeFlag(pDest, MEM_Null); - - /* This block sets the variable payloadSize to be the total number of + u.am.pDest = &p->aMem[pOp->p3]; + MemSetTypeFlag(u.am.pDest, MEM_Null); + u.am.zRec = 0; + + /* This block sets the variable u.am.payloadSize to be the total number of ** bytes in the record. ** - ** zRec is set to be the complete text of the record if it is available. + ** u.am.zRec is set to be the complete text of the record if it is available. ** The complete record text is always available for pseudo-tables ** If the record is stored in a cursor, the complete record text - ** might be available in the pC->aRow cache. Or it might not be. - ** If the data is unavailable, zRec is set to NULL. + ** might be available in the u.am.pC->aRow cache. Or it might not be. + ** If the data is unavailable, u.am.zRec is set to NULL. ** ** We also compute the number of columns in the record. For cursors, ** the number of columns is stored in the VdbeCursor.nField element. */ - pC = p->apCsr[p1]; - assert( pC!=0 ); -#ifndef SQLITE_OMIT_VIRTUALTABLE - assert( pC->pVtabCursor==0 ); -#endif - if( pC->pCursor!=0 ){ + u.am.pC = p->apCsr[u.am.p1]; + assert( u.am.pC!=0 ); +#ifndef SQLITE_OMIT_VIRTUALTABLE + assert( u.am.pC->pVtabCursor==0 ); +#endif + u.am.pCrsr = u.am.pC->pCursor; + if( u.am.pCrsr!=0 ){ /* The record is stored in a B-Tree */ - rc = sqlite3VdbeCursorMoveto(pC); + rc = sqlite3VdbeCursorMoveto(u.am.pC); if( rc ) goto abort_due_to_error; - zRec = 0; - pCrsr = pC->pCursor; - if( pC->nullRow ){ - payloadSize = 0; - }else if( pC->cacheStatus==p->cacheCtr ){ - payloadSize = pC->payloadSize; - zRec = (char*)pC->aRow; - }else if( pC->isIndex ){ - i64 payloadSize64; - sqlite3BtreeKeySize(pCrsr, &payloadSize64); - payloadSize = (int)payloadSize64; - }else{ - sqlite3BtreeDataSize(pCrsr, (u32 *)&payloadSize); - } - nField = pC->nField; - }else{ - assert( pC->pseudoTable ); - /* The record is the sole entry of a pseudo-table */ - payloadSize = pC->nData; - zRec = pC->pData; - pC->cacheStatus = CACHE_STALE; - assert( payloadSize==0 || zRec!=0 ); - nField = pC->nField; - pCrsr = 0; - } - - /* If payloadSize is 0, then just store a NULL */ - if( payloadSize==0 ){ - assert( pDest->flags&MEM_Null ); + if( u.am.pC->nullRow ){ + u.am.payloadSize = 0; + }else if( u.am.pC->cacheStatus==p->cacheCtr ){ + u.am.payloadSize = u.am.pC->payloadSize; + u.am.zRec = (char*)u.am.pC->aRow; + }else if( u.am.pC->isIndex ){ + assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) ); + rc = sqlite3BtreeKeySize(u.am.pCrsr, &u.am.payloadSize64); + assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ + /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the + ** payload size, so it is impossible for u.am.payloadSize64 to be + ** larger than 32 bits. */ + assert( (u.am.payloadSize64 & SQLITE_MAX_U32)==(u64)u.am.payloadSize64 ); + u.am.payloadSize = (u32)u.am.payloadSize64; + }else{ + assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) ); + rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize); + assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ + } + }else if( u.am.pC->pseudoTableReg>0 ){ + u.am.pReg = &p->aMem[u.am.pC->pseudoTableReg]; + assert( u.am.pReg->flags & MEM_Blob ); + u.am.payloadSize = u.am.pReg->n; + u.am.zRec = u.am.pReg->z; + u.am.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr; + assert( u.am.payloadSize==0 || u.am.zRec!=0 ); + }else{ + /* Consider the row to be NULL */ + u.am.payloadSize = 0; + } + + /* If u.am.payloadSize is 0, then just store a NULL */ + if( u.am.payloadSize==0 ){ + assert( u.am.pDest->flags&MEM_Null ); goto op_column_out; } - if( payloadSize>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 ); + if( u.am.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - assert( p2<nField ); + u.am.nField = u.am.pC->nField; + assert( u.am.p2<u.am.nField ); /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ - aType = pC->aType; - if( pC->cacheStatus==p->cacheCtr ){ - aOffset = pC->aOffset; - }else{ - u8 *zIdx; /* Index into header */ - u8 *zEndHdr; /* Pointer to first byte after the header */ - int offset; /* Offset into the data */ - int szHdrSz; /* Size of the header size field at start of record */ - int avail = 0; /* Number of bytes of available data */ - - assert(aType); - pC->aOffset = aOffset = &aType[nField]; - pC->payloadSize = payloadSize; - pC->cacheStatus = p->cacheCtr; + u.am.aType = u.am.pC->aType; + if( u.am.pC->cacheStatus==p->cacheCtr ){ + u.am.aOffset = u.am.pC->aOffset; + }else{ + assert(u.am.aType); + u.am.avail = 0; + u.am.pC->aOffset = u.am.aOffset = &u.am.aType[u.am.nField]; + u.am.pC->payloadSize = u.am.payloadSize; + u.am.pC->cacheStatus = p->cacheCtr; /* Figure out how many bytes are in the header */ - if( zRec ){ - zData = zRec; - }else{ - if( pC->isIndex ){ - zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail); - }else{ - zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail); + if( u.am.zRec ){ + u.am.zData = u.am.zRec; + }else{ + if( u.am.pC->isIndex ){ + u.am.zData = (char*)sqlite3BtreeKeyFetch(u.am.pCrsr, &u.am.avail); + }else{ + u.am.zData = (char*)sqlite3BtreeDataFetch(u.am.pCrsr, &u.am.avail); } /* If KeyFetch()/DataFetch() managed to get the entire payload, - ** save the payload in the pC->aRow cache. That will save us from + ** save the payload in the u.am.pC->aRow cache. That will save us from ** having to make additional calls to fetch the content portion of ** the record. */ - if( avail>=payloadSize ){ - zRec = zData; - pC->aRow = (u8*)zData; - }else{ - pC->aRow = 0; + assert( u.am.avail>=0 ); + if( u.am.payloadSize <= (u32)u.am.avail ){ + u.am.zRec = u.am.zData; + u.am.pC->aRow = (u8*)u.am.zData; + }else{ + u.am.pC->aRow = 0; } } /* The following assert is true in all cases accept when ** the database file has been corrupted externally. - ** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */ - szHdrSz = getVarint32((u8*)zData, offset); + ** assert( u.am.zRec!=0 || u.am.avail>=u.am.payloadSize || u.am.avail>=9 ); */ + u.am.szHdr = getVarint32((u8*)u.am.zData, u.am.offset); + + /* Make sure a corrupt database has not given us an oversize header. + ** Do this now to avoid an oversize memory allocation. + ** + ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte + ** types use so much data space that there can only be 4096 and 32 of + ** them, respectively. So the maximum header length results from a + ** 3-byte type for each of the maximum of 32768 columns plus three + ** extra bytes for the header length itself. 32768*3 + 3 = 98307. + */ + if( u.am.offset > 98307 ){ + rc = SQLITE_CORRUPT_BKPT; + goto op_column_out; + } + + /* Compute in u.am.len the number of bytes of data we need to read in order + ** to get u.am.nField type values. u.am.offset is an upper bound on this. But + ** u.am.nField might be significantly less than the true number of columns + ** in the table, and in that case, 5*u.am.nField+3 might be smaller than u.am.offset. + ** We want to minimize u.am.len in order to limit the size of the memory + ** allocation, especially if a corrupt database file has caused u.am.offset + ** to be oversized. Offset is limited to 98307 above. But 98307 might + ** still exceed Robson memory allocation limits on some configurations. + ** On systems that cannot tolerate large memory allocations, u.am.nField*5+3 + ** will likely be much smaller since u.am.nField will likely be less than + ** 20 or so. This insures that Robson memory allocation limits are + ** not exceeded even for corrupt database files. + */ + u.am.len = u.am.nField*5 + 3; + if( u.am.len > (int)u.am.offset ) u.am.len = (int)u.am.offset; /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete ** record header if the record header does not fit on a single page ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to ** acquire the complete header text. */ - if( !zRec && avail<offset ){ - sMem.flags = 0; - sMem.db = 0; - rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem); + if( !u.am.zRec && u.am.avail<u.am.len ){ + u.am.sMem.flags = 0; + u.am.sMem.db = 0; + rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, 0, u.am.len, u.am.pC->isIndex, &u.am.sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } - zData = sMem.z; - } - zEndHdr = (u8 *)&zData[offset]; - zIdx = (u8 *)&zData[szHdrSz]; - - /* Scan the header and use it to fill in the aType[] and aOffset[] - ** arrays. aType[i] will contain the type integer for the i-th - ** column and aOffset[i] will contain the offset from the beginning - ** of the record to the start of the data for the i-th column - */ - for(i=0; i<nField; i++){ - if( zIdx<zEndHdr ){ - aOffset[i] = offset; - zIdx += getVarint32(zIdx, aType[i]); - offset += sqlite3VdbeSerialTypeLen(aType[i]); - }else{ - /* If i is less that nField, then there are less fields in this + u.am.zData = u.am.sMem.z; + } + u.am.zEndHdr = (u8 *)&u.am.zData[u.am.len]; + u.am.zIdx = (u8 *)&u.am.zData[u.am.szHdr]; + + /* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[] + ** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th + ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning + ** of the record to the start of the data for the u.am.i-th column + */ + u.am.offset64 = u.am.offset; + for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){ + if( u.am.zIdx<u.am.zEndHdr ){ + u.am.aOffset[u.am.i] = (u32)u.am.offset64; + u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]); + u.am.offset64 += sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]); + }else{ + /* If u.am.i is less that u.am.nField, then there are less fields in this ** record than SetNumColumns indicated there are columns in the - ** table. Set the offset for any extra columns not present in + ** table. Set the u.am.offset for any extra columns not present in ** the record to 0. This tells code below to store a NULL ** instead of deserializing a value from the record. */ - aOffset[i] = 0; - } - } - sqlite3VdbeMemRelease(&sMem); - sMem.flags = MEM_Null; + u.am.aOffset[u.am.i] = 0; + } + } + sqlite3VdbeMemRelease(&u.am.sMem); + u.am.sMem.flags = MEM_Null; /* If we have read more header data than was contained in the header, ** or if the end of the last field appears to be past the end of the ** record, or if the end of the last field appears to be before the end ** of the record (when all fields present), then we must be dealing ** with a corrupt database. */ - if( zIdx>zEndHdr || offset>payloadSize - || (zIdx==zEndHdr && offset!=payloadSize) ){ + if( (u.am.zIdx > u.am.zEndHdr)|| (u.am.offset64 > u.am.payloadSize) + || (u.am.zIdx==u.am.zEndHdr && u.am.offset64!=(u64)u.am.payloadSize) ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_out; } } - /* Get the column information. If aOffset[p2] is non-zero, then - ** deserialize the value from the record. If aOffset[p2] is zero, + /* Get the column information. If u.am.aOffset[u.am.p2] is non-zero, then + ** deserialize the value from the record. If u.am.aOffset[u.am.p2] is zero, ** then there are not enough fields in the record to satisfy the ** request. In this case, set the value NULL or to P4 if P4 is ** a pointer to a Mem object. */ - if( aOffset[p2] ){ + if( u.am.aOffset[u.am.p2] ){ assert( rc==SQLITE_OK ); - if( zRec ){ - sqlite3VdbeMemReleaseExternal(pDest); - sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest); - }else{ - len = sqlite3VdbeSerialTypeLen(aType[p2]); - sqlite3VdbeMemMove(&sMem, pDest); - rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem); + if( u.am.zRec ){ + sqlite3VdbeMemReleaseExternal(u.am.pDest); + sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest); + }else{ + u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]); + sqlite3VdbeMemMove(&u.am.sMem, u.am.pDest); + rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, u.am.aOffset[u.am.p2], u.am.len, u.am.pC->isIndex, &u.am.sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } - zData = sMem.z; - sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest); - } - pDest->enc = encoding; + u.am.zData = u.am.sMem.z; + sqlite3VdbeSerialGet((u8*)u.am.zData, u.am.aType[u.am.p2], u.am.pDest); + } + u.am.pDest->enc = encoding; }else{ if( pOp->p4type==P4_MEM ){ - sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); - }else{ - assert( pDest->flags&MEM_Null ); + sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static); + }else{ + assert( u.am.pDest->flags&MEM_Null ); } } /* If we dynamically allocated space to hold the data (in the ** sqlite3VdbeMemFromBtree() call above) then transfer control of that - ** dynamically allocated space over to the pDest structure. + ** dynamically allocated space over to the u.am.pDest structure. ** This prevents a memory copy. */ - if( sMem.zMalloc ){ - assert( sMem.z==sMem.zMalloc ); - assert( !(pDest->flags & MEM_Dyn) ); - assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z ); - pDest->flags &= ~(MEM_Ephem|MEM_Static); - pDest->flags |= MEM_Term; - pDest->z = sMem.z; - pDest->zMalloc = sMem.zMalloc; - } - - rc = sqlite3VdbeMemMakeWriteable(pDest); + if( u.am.sMem.zMalloc ){ + assert( u.am.sMem.z==u.am.sMem.zMalloc ); + assert( !(u.am.pDest->flags & MEM_Dyn) ); + assert( !(u.am.pDest->flags & (MEM_Blob|MEM_Str)) || u.am.pDest->z==u.am.sMem.z ); + u.am.pDest->flags &= ~(MEM_Ephem|MEM_Static); + u.am.pDest->flags |= MEM_Term; + u.am.pDest->z = u.am.sMem.z; + u.am.pDest->zMalloc = u.am.sMem.zMalloc; + } + + rc = sqlite3VdbeMemMakeWriteable(u.am.pDest); op_column_out: - UPDATE_MAX_BLOBSIZE(pDest); - REGISTER_TRACE(pOp->p3, pDest); + UPDATE_MAX_BLOBSIZE(u.am.pDest); + REGISTER_TRACE(pOp->p3, u.am.pDest); break; } /* Opcode: Affinity P1 P2 * P4 * ** @@ -51755,18 +54088,23 @@ ** P4 is a string that is P2 characters long. The nth character of the ** string indicates the column affinity that should be used for the nth ** memory cell in the range. */ case OP_Affinity: { - char *zAffinity = pOp->p4.z; - Mem *pData0 = &p->aMem[pOp->p1]; - Mem *pLast = &pData0[pOp->p2-1]; - Mem *pRec; - - for(pRec=pData0; pRec<=pLast; pRec++){ - ExpandBlob(pRec); - applyAffinity(pRec, zAffinity[pRec-pData0], encoding); +#if 0 /* local variables moved into u.an */ + char *zAffinity; /* The affinity to be applied */ + Mem *pData0; /* First register to which to apply affinity */ + Mem *pLast; /* Last register to which to apply affinity */ + Mem *pRec; /* Current register */ +#endif /* local variables moved into u.an */ + + u.an.zAffinity = pOp->p4.z; + u.an.pData0 = &p->aMem[pOp->p1]; + u.an.pLast = &u.an.pData0[pOp->p2-1]; + for(u.an.pRec=u.an.pData0; u.an.pRec<=u.an.pLast; u.an.pRec++){ + ExpandBlob(u.an.pRec); + applyAffinity(u.an.pRec, u.an.zAffinity[u.an.pRec-u.an.pData0], encoding); } break; } /* Opcode: MakeRecord P1 P2 P3 P4 * @@ -51786,10 +54124,28 @@ ** macros defined in sqliteInt.h. ** ** If P4 is NULL then all index fields have the affinity NONE. */ case OP_MakeRecord: { +#if 0 /* local variables moved into u.ao */ + u8 *zNewRecord; /* A buffer to hold the data for the new record */ + Mem *pRec; /* The new record */ + u64 nData; /* Number of bytes of data space */ + int nHdr; /* Number of bytes of header space */ + i64 nByte; /* Data space required for this record */ + int nZero; /* Number of zero bytes at the end of the record */ + int nVarint; /* Number of bytes in a varint */ + u32 serial_type; /* Type field */ + Mem *pData0; /* First field to be combined into the record */ + Mem *pLast; /* Last field of the record */ + int nField; /* Number of fields in the record */ + char *zAffinity; /* The affinity string for the record */ + int file_format; /* File format to use for encoding */ + int i; /* Space used in zNewRecord[] */ + int len; /* Length of a field */ +#endif /* local variables moved into u.ao */ + /* Assuming the record contains N fields, the record format looks ** like this: ** ** ------------------------------------------------------------------------ ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | @@ -51801,64 +54157,52 @@ ** Each type field is a varint representing the serial type of the ** corresponding data element (see sqlite3VdbeSerialType()). The ** hdr-size field is also a varint which is the offset from the beginning ** of the record to data0. */ - u8 *zNewRecord; /* A buffer to hold the data for the new record */ - Mem *pRec; /* The new record */ - u64 nData = 0; /* Number of bytes of data space */ - int nHdr = 0; /* Number of bytes of header space */ - i64 nByte = 0; /* Data space required for this record */ - int nZero = 0; /* Number of zero bytes at the end of the record */ - int nVarint; /* Number of bytes in a varint */ - u32 serial_type; /* Type field */ - Mem *pData0; /* First field to be combined into the record */ - Mem *pLast; /* Last field of the record */ - int nField; /* Number of fields in the record */ - char *zAffinity; /* The affinity string for the record */ - int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ - - nField = pOp->p1; - zAffinity = pOp->p4.z; - assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem+1 ); - pData0 = &p->aMem[nField]; - nField = pOp->p2; - pLast = &pData0[nField-1]; - file_format = p->minWriteFileFormat; + u.ao.nData = 0; /* Number of bytes of data space */ + u.ao.nHdr = 0; /* Number of bytes of header space */ + u.ao.nByte = 0; /* Data space required for this record */ + u.ao.nZero = 0; /* Number of zero bytes at the end of the record */ + u.ao.nField = pOp->p1; + u.ao.zAffinity = pOp->p4.z; + assert( u.ao.nField>0 && pOp->p2>0 && pOp->p2+u.ao.nField<=p->nMem+1 ); + u.ao.pData0 = &p->aMem[u.ao.nField]; + u.ao.nField = pOp->p2; + u.ao.pLast = &u.ao.pData0[u.ao.nField-1]; + u.ao.file_format = p->minWriteFileFormat; /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ - for(pRec=pData0; pRec<=pLast; pRec++){ - int len; - if( zAffinity ){ - applyAffinity(pRec, zAffinity[pRec-pData0], encoding); - } - if( pRec->flags&MEM_Zero && pRec->n>0 ){ - sqlite3VdbeMemExpandBlob(pRec); - } - serial_type = sqlite3VdbeSerialType(pRec, file_format); - len = sqlite3VdbeSerialTypeLen(serial_type); - nData += len; - nHdr += sqlite3VarintLen(serial_type); - if( pRec->flags & MEM_Zero ){ + for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){ + if( u.ao.zAffinity ){ + applyAffinity(u.ao.pRec, u.ao.zAffinity[u.ao.pRec-u.ao.pData0], encoding); + } + if( u.ao.pRec->flags&MEM_Zero && u.ao.pRec->n>0 ){ + sqlite3VdbeMemExpandBlob(u.ao.pRec); + } + u.ao.serial_type = sqlite3VdbeSerialType(u.ao.pRec, u.ao.file_format); + u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.serial_type); + u.ao.nData += u.ao.len; + u.ao.nHdr += sqlite3VarintLen(u.ao.serial_type); + if( u.ao.pRec->flags & MEM_Zero ){ /* Only pure zero-filled BLOBs can be input to this Opcode. ** We do not allow blobs with a prefix and a zero-filled tail. */ - nZero += pRec->u.nZero; - }else if( len ){ - nZero = 0; + u.ao.nZero += u.ao.pRec->u.nZero; + }else if( u.ao.len ){ + u.ao.nZero = 0; } } /* Add the initial header varint and total the size */ - nHdr += nVarint = sqlite3VarintLen(nHdr); - if( nVarint<sqlite3VarintLen(nHdr) ){ - nHdr++; - } - nByte = nHdr+nData-nZero; - if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + u.ao.nHdr += u.ao.nVarint = sqlite3VarintLen(u.ao.nHdr); + if( u.ao.nVarint<sqlite3VarintLen(u.ao.nHdr) ){ + u.ao.nHdr++; + } + u.ao.nByte = u.ao.nHdr+u.ao.nData-u.ao.nZero; + if( u.ao.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } /* Make sure the output register has a buffer large enough to store ** the new record. The output register (pOp->p3) is not allowed to @@ -51865,32 +54209,32 @@ ** be one of the input registers (because the following call to ** sqlite3VdbeMemGrow() could clobber the value before it is used). */ assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 ); pOut = &p->aMem[pOp->p3]; - if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){ + if( sqlite3VdbeMemGrow(pOut, (int)u.ao.nByte, 0) ){ goto no_mem; } - zNewRecord = (u8 *)pOut->z; + u.ao.zNewRecord = (u8 *)pOut->z; /* Write the record */ - i = putVarint32(zNewRecord, nHdr); - for(pRec=pData0; pRec<=pLast; pRec++){ - serial_type = sqlite3VdbeSerialType(pRec, file_format); - i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ - } - for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */ - i += sqlite3VdbeSerialPut(&zNewRecord[i], (int)(nByte-i), pRec,file_format); - } - assert( i==nByte ); + u.ao.i = putVarint32(u.ao.zNewRecord, u.ao.nHdr); + for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){ + u.ao.serial_type = sqlite3VdbeSerialType(u.ao.pRec, u.ao.file_format); + u.ao.i += putVarint32(&u.ao.zNewRecord[u.ao.i], u.ao.serial_type); /* serial type */ + } + for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){ /* serial data */ + u.ao.i += sqlite3VdbeSerialPut(&u.ao.zNewRecord[u.ao.i], (int)(u.ao.nByte-u.ao.i), u.ao.pRec,u.ao.file_format); + } + assert( u.ao.i==u.ao.nByte ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); - pOut->n = (int)nByte; + pOut->n = (int)u.ao.nByte; pOut->flags = MEM_Blob | MEM_Dyn; pOut->xDel = 0; - if( nZero ){ - pOut->u.nZero = nZero; + if( u.ao.nZero ){ + pOut->u.nZero = u.ao.nZero; pOut->flags |= MEM_Zero; } pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); @@ -51902,150 +54246,122 @@ ** Store the number of entries (an integer value) in the table or index ** opened by cursor P1 in register P2 */ #ifndef SQLITE_OMIT_BTREECOUNT case OP_Count: { /* out2-prerelease */ +#if 0 /* local variables moved into u.ap */ i64 nEntry; - BtCursor *pCrsr = p->apCsr[pOp->p1]->pCursor; - if( pCrsr ){ - rc = sqlite3BtreeCount(pCrsr, &nEntry); - }else{ - nEntry = 0; + BtCursor *pCrsr; +#endif /* local variables moved into u.ap */ + + u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor; + if( u.ap.pCrsr ){ + rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry); + }else{ + u.ap.nEntry = 0; } pOut->flags = MEM_Int; - pOut->u.i = nEntry; - break; -} -#endif - -/* Opcode: Statement P1 * * * * -** -** Begin an individual statement transaction which is part of a larger -** transaction. This is needed so that the statement -** can be rolled back after an error without having to roll back the -** entire transaction. The statement transaction will automatically -** commit when the VDBE halts. -** -** If the database connection is currently in autocommit mode (that -** is to say, if it is in between BEGIN and COMMIT) -** and if there are no other active statements on the same database -** connection, then this operation is a no-op. No statement transaction -** is needed since any error can use the normal ROLLBACK process to -** undo changes. -** -** If a statement transaction is started, then a statement journal file -** will be allocated and initialized. -** -** The statement is begun on the database file with index P1. The main -** database file has an index of 0 and the file used for temporary tables -** has an index of 1. -*/ -case OP_Statement: { - if( db->autoCommit==0 || db->activeVdbeCnt>1 ){ - int i = pOp->p1; - Btree *pBt; - assert( i>=0 && i<db->nDb ); - assert( db->aDb[i].pBt!=0 ); - pBt = db->aDb[i].pBt; - assert( sqlite3BtreeIsInTrans(pBt) ); - assert( (p->btreeMask & (1<<i))!=0 ); - if( p->iStatement==0 ){ - assert( db->nStatement>=0 && db->nSavepoint>=0 ); - db->nStatement++; - p->iStatement = db->nSavepoint + db->nStatement; - } - rc = sqlite3BtreeBeginStmt(pBt, p->iStatement); - } - break; -} + pOut->u.i = u.ap.nEntry; + break; +} +#endif /* Opcode: Savepoint P1 * * P4 * ** ** Open, release or rollback the savepoint named by parameter P4, depending ** on the value of P1. To open a new savepoint, P1==0. To release (commit) an ** existing savepoint, P1==1, or to rollback an existing savepoint P1==2. */ case OP_Savepoint: { - int p1 = pOp->p1; - char *zName = pOp->p4.z; /* Name of savepoint */ - - /* Assert that the p1 parameter is valid. Also that if there is no open +#if 0 /* local variables moved into u.aq */ + int p1; /* Value of P1 operand */ + char *zName; /* Name of savepoint */ + int nName; + Savepoint *pNew; + Savepoint *pSavepoint; + Savepoint *pTmp; + int iSavepoint; + int ii; +#endif /* local variables moved into u.aq */ + + u.aq.p1 = pOp->p1; + u.aq.zName = pOp->p4.z; + + /* Assert that the u.aq.p1 parameter is valid. Also that if there is no open ** transaction, then there cannot be any savepoints. */ assert( db->pSavepoint==0 || db->autoCommit==0 ); - assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); + assert( u.aq.p1==SAVEPOINT_BEGIN||u.aq.p1==SAVEPOINT_RELEASE||u.aq.p1==SAVEPOINT_ROLLBACK ); assert( db->pSavepoint || db->isTransactionSavepoint==0 ); assert( checkSavepointCount(db) ); - if( p1==SAVEPOINT_BEGIN ){ + if( u.aq.p1==SAVEPOINT_BEGIN ){ if( db->writeVdbeCnt>0 ){ /* A new savepoint cannot be created if there are active write ** statements (i.e. open read/write incremental blob handles). */ sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - " "SQL statements in progress"); rc = SQLITE_BUSY; }else{ - int nName = sqlite3Strlen30(zName); - Savepoint *pNew; + u.aq.nName = sqlite3Strlen30(u.aq.zName); /* Create a new savepoint structure. */ - pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); - if( pNew ){ - pNew->zName = (char *)&pNew[1]; - memcpy(pNew->zName, zName, nName+1); + u.aq.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.aq.nName+1); + if( u.aq.pNew ){ + u.aq.pNew->zName = (char *)&u.aq.pNew[1]; + memcpy(u.aq.pNew->zName, u.aq.zName, u.aq.nName+1); /* If there is no open transaction, then mark this as a special ** "transaction savepoint". */ if( db->autoCommit ){ db->autoCommit = 0; db->isTransactionSavepoint = 1; }else{ db->nSavepoint++; - } + } /* Link the new savepoint into the database handle's list. */ - pNew->pNext = db->pSavepoint; - db->pSavepoint = pNew; - } - } - }else{ - Savepoint *pSavepoint; - int iSavepoint = 0; + u.aq.pNew->pNext = db->pSavepoint; + db->pSavepoint = u.aq.pNew; + } + } + }else{ + u.aq.iSavepoint = 0; /* Find the named savepoint. If there is no such savepoint, then an ** an error is returned to the user. */ for( - pSavepoint=db->pSavepoint; - pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName); - pSavepoint=pSavepoint->pNext - ){ - iSavepoint++; - } - if( !pSavepoint ){ - sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName); + u.aq.pSavepoint = db->pSavepoint; + u.aq.pSavepoint && sqlite3StrICmp(u.aq.pSavepoint->zName, u.aq.zName); + u.aq.pSavepoint = u.aq.pSavepoint->pNext + ){ + u.aq.iSavepoint++; + } + if( !u.aq.pSavepoint ){ + sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.aq.zName); rc = SQLITE_ERROR; }else if( - db->writeVdbeCnt>0 || (p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1) + db->writeVdbeCnt>0 || (u.aq.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1) ){ /* It is not possible to release (commit) a savepoint if there are ** active write statements. It is not possible to rollback a savepoint ** if there are any active statements at all. */ sqlite3SetString(&p->zErrMsg, db, "cannot %s savepoint - SQL statements in progress", - (p1==SAVEPOINT_ROLLBACK ? "rollback": "release") + (u.aq.p1==SAVEPOINT_ROLLBACK ? "rollback": "release") ); rc = SQLITE_BUSY; }else{ /* Determine whether or not this is a transaction savepoint. If so, ** and this is a RELEASE command, then the current transaction ** is committed. */ - int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint; - if( isTransaction && p1==SAVEPOINT_RELEASE ){ + int isTransaction = u.aq.pSavepoint->pNext==0 && db->isTransactionSavepoint; + if( isTransaction && u.aq.p1==SAVEPOINT_RELEASE ){ db->autoCommit = 1; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = pc; db->autoCommit = 0; p->rc = rc = SQLITE_BUSY; @@ -52052,38 +54368,37 @@ goto vdbe_return; } db->isTransactionSavepoint = 0; rc = p->rc; }else{ - int ii; - iSavepoint = db->nSavepoint - iSavepoint - 1; - for(ii=0; ii<db->nDb; ii++){ - rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); + u.aq.iSavepoint = db->nSavepoint - u.aq.iSavepoint - 1; + for(u.aq.ii=0; u.aq.ii<db->nDb; u.aq.ii++){ + rc = sqlite3BtreeSavepoint(db->aDb[u.aq.ii].pBt, u.aq.p1, u.aq.iSavepoint); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } } - if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ + if( u.aq.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetInternalSchema(db, 0); } } /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all ** savepoints nested inside of the savepoint being operated on. */ - while( db->pSavepoint!=pSavepoint ){ - Savepoint *pTmp = db->pSavepoint; - db->pSavepoint = pTmp->pNext; - sqlite3DbFree(db, pTmp); + while( db->pSavepoint!=u.aq.pSavepoint ){ + u.aq.pTmp = db->pSavepoint; + db->pSavepoint = u.aq.pTmp->pNext; + sqlite3DbFree(db, u.aq.pTmp); db->nSavepoint--; } /* If it is a RELEASE, then destroy the savepoint being operated on too */ - if( p1==SAVEPOINT_RELEASE ){ - assert( pSavepoint==db->pSavepoint ); - db->pSavepoint = pSavepoint->pNext; - sqlite3DbFree(db, pSavepoint); + if( u.aq.p1==SAVEPOINT_RELEASE ){ + assert( u.aq.pSavepoint==db->pSavepoint ); + db->pSavepoint = u.aq.pSavepoint->pNext; + sqlite3DbFree(db, u.aq.pSavepoint); if( !isTransaction ){ db->nSavepoint--; } } } @@ -52100,44 +54415,48 @@ ** there are active writing VMs or active VMs that use shared cache. ** ** This instruction causes the VM to halt. */ case OP_AutoCommit: { - int desiredAutoCommit = pOp->p1; - int rollback = pOp->p2; - int turnOnAC = desiredAutoCommit && !db->autoCommit; - - assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); - assert( desiredAutoCommit==1 || rollback==0 ); - +#if 0 /* local variables moved into u.ar */ + int desiredAutoCommit; + int iRollback; + int turnOnAC; +#endif /* local variables moved into u.ar */ + + u.ar.desiredAutoCommit = pOp->p1; + u.ar.iRollback = pOp->p2; + u.ar.turnOnAC = u.ar.desiredAutoCommit && !db->autoCommit; + assert( u.ar.desiredAutoCommit==1 || u.ar.desiredAutoCommit==0 ); + assert( u.ar.desiredAutoCommit==1 || u.ar.iRollback==0 ); assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ - if( turnOnAC && rollback && db->activeVdbeCnt>1 ){ + if( u.ar.turnOnAC && u.ar.iRollback && db->activeVdbeCnt>1 ){ /* If this instruction implements a ROLLBACK and other VMs are ** still running, and a transaction is active, return an error indicating ** that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; - }else if( turnOnAC && !rollback && db->writeVdbeCnt>1 ){ + }else if( u.ar.turnOnAC && !u.ar.iRollback && db->writeVdbeCnt>0 ){ /* If this instruction implements a COMMIT and other VMs are writing ** return an error indicating that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; - }else if( desiredAutoCommit!=db->autoCommit ){ - if( rollback ){ - assert( desiredAutoCommit==1 ); + }else if( u.ar.desiredAutoCommit!=db->autoCommit ){ + if( u.ar.iRollback ){ + assert( u.ar.desiredAutoCommit==1 ); sqlite3RollbackAll(db); db->autoCommit = 1; }else{ - db->autoCommit = (u8)desiredAutoCommit; + db->autoCommit = (u8)u.ar.desiredAutoCommit; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = pc; - db->autoCommit = (u8)(1-desiredAutoCommit); + db->autoCommit = (u8)(1-u.ar.desiredAutoCommit); p->rc = rc = SQLITE_BUSY; goto vdbe_return; } } assert( db->nStatement==0 ); @@ -52148,12 +54467,12 @@ rc = SQLITE_ERROR; } goto vdbe_return; }else{ sqlite3SetString(&p->zErrMsg, db, - (!desiredAutoCommit)?"cannot start a transaction within a transaction":( - (rollback)?"cannot rollback - no transaction is active": + (!u.ar.desiredAutoCommit)?"cannot start a transaction within a transaction":( + (u.ar.iRollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active")); rc = SQLITE_ERROR; } break; @@ -52176,105 +54495,118 @@ ** underway. Starting a write transaction also creates a rollback journal. A ** write transaction must be started before any changes can be made to the ** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained ** on the file. ** +** If a write-transaction is started and the Vdbe.usesStmtJournal flag is +** true (this flag is set if the Vdbe may modify more than one row and may +** throw an ABORT exception), a statement transaction may also be opened. +** More specifically, a statement transaction is opened iff the database +** connection is currently not in autocommit mode, or if there are other +** active statements. A statement transaction allows the affects of this +** VDBE to be rolled back after an error without having to roll back the +** entire transaction. If no error is encountered, the statement transaction +** will automatically commit when the VDBE halts. +** ** If P2 is zero, then a read-lock is obtained on the database file. */ case OP_Transaction: { - int i = pOp->p1; +#if 0 /* local variables moved into u.as */ Btree *pBt; - - assert( i>=0 && i<db->nDb ); - assert( (p->btreeMask & (1<<i))!=0 ); - pBt = db->aDb[i].pBt; - - if( pBt ){ - rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); +#endif /* local variables moved into u.as */ + + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( (p->btreeMask & (1<<pOp->p1))!=0 ); + u.as.pBt = db->aDb[pOp->p1].pBt; + + if( u.as.pBt ){ + rc = sqlite3BtreeBeginTrans(u.as.pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){ goto abort_due_to_error; } + + if( pOp->p2 && p->usesStmtJournal + && (db->autoCommit==0 || db->activeVdbeCnt>1) + ){ + assert( sqlite3BtreeIsInTrans(u.as.pBt) ); + if( p->iStatement==0 ){ + assert( db->nStatement>=0 && db->nSavepoint>=0 ); + db->nStatement++; + p->iStatement = db->nSavepoint + db->nStatement; + } + rc = sqlite3BtreeBeginStmt(u.as.pBt, p->iStatement); + } } break; } /* Opcode: ReadCookie P1 P2 P3 * * ** ** Read cookie number P3 from database P1 and write it into register P2. -** P3==0 is the schema version. P3==1 is the database format. -** P3==2 is the recommended pager cache size, and so forth. P1==0 is +** P3==1 is the schema version. P3==2 is the database format. +** P3==3 is the recommended pager cache size, and so forth. P1==0 is ** the main database file and P1==1 is the database file used to store ** temporary tables. -** -** If P1 is negative, then this is a request to read the size of a -** databases free-list. P3 must be set to 1 in this case. The actual -** database accessed is ((P1+1)*-1). For example, a P1 parameter of -1 -** corresponds to database 0 ("main"), a P1 of -2 is database 1 ("temp"). ** ** There must be a read-lock on the database (either a transaction ** must be started or there must be an open cursor) before ** executing this instruction. */ case OP_ReadCookie: { /* out2-prerelease */ +#if 0 /* local variables moved into u.at */ int iMeta; - int iDb = pOp->p1; - int iCookie = pOp->p3; - + int iDb; + int iCookie; +#endif /* local variables moved into u.at */ + + u.at.iDb = pOp->p1; + u.at.iCookie = pOp->p3; assert( pOp->p3<SQLITE_N_BTREE_META ); - if( iDb<0 ){ - iDb = (-1*(iDb+1)); - iCookie *= -1; - } - assert( iDb>=0 && iDb<db->nDb ); - assert( db->aDb[iDb].pBt!=0 ); - assert( (p->btreeMask & (1<<iDb))!=0 ); - /* The indexing of meta values at the schema layer is off by one from - ** the indexing in the btree layer. The btree considers meta[0] to - ** be the number of free pages in the database (a read-only value) - ** and meta[1] to be the schema cookie. The schema layer considers - ** meta[1] to be the schema cookie. So we have to shift the index - ** by one in the following statement. - */ - rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, 1 + iCookie, (u32 *)&iMeta); - pOut->u.i = iMeta; + assert( u.at.iDb>=0 && u.at.iDb<db->nDb ); + assert( db->aDb[u.at.iDb].pBt!=0 ); + assert( (p->btreeMask & (1<<u.at.iDb))!=0 ); + + sqlite3BtreeGetMeta(db->aDb[u.at.iDb].pBt, u.at.iCookie, (u32 *)&u.at.iMeta); + pOut->u.i = u.at.iMeta; MemSetTypeFlag(pOut, MEM_Int); break; } /* Opcode: SetCookie P1 P2 P3 * * ** ** Write the content of register P3 (interpreted as an integer) -** into cookie number P2 of database P1. -** P2==0 is the schema version. P2==1 is the database format. -** P2==2 is the recommended pager cache size, and so forth. P1==0 is -** the main database file and P1==1 is the database file used to store -** temporary tables. +** into cookie number P2 of database P1. P2==1 is the schema version. +** P2==2 is the database format. P2==3 is the recommended pager cache +** size, and so forth. P1==0 is the main database file and P1==1 is the +** database file used to store temporary tables. ** ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { /* in3 */ +#if 0 /* local variables moved into u.au */ Db *pDb; +#endif /* local variables moved into u.au */ assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); - pDb = &db->aDb[pOp->p1]; - assert( pDb->pBt!=0 ); + u.au.pDb = &db->aDb[pOp->p1]; + assert( u.au.pDb->pBt!=0 ); sqlite3VdbeMemIntegerify(pIn3); /* See note about index shifting on OP_ReadCookie */ - rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pIn3->u.i); - if( pOp->p2==0 ){ + rc = sqlite3BtreeUpdateMeta(u.au.pDb->pBt, pOp->p2, (int)pIn3->u.i); + if( pOp->p2==BTREE_SCHEMA_VERSION ){ /* When the schema cookie changes, record the new cookie internally */ - pDb->pSchema->schema_cookie = (int)pIn3->u.i; + u.au.pDb->pSchema->schema_cookie = (int)pIn3->u.i; db->flags |= SQLITE_InternChanges; - }else if( pOp->p2==1 ){ + }else if( pOp->p2==BTREE_FILE_FORMAT ){ /* Record changes in the file format */ - pDb->pSchema->file_format = (u8)pIn3->u.i; + u.au.pDb->pSchema->file_format = (u8)pIn3->u.i; } if( pOp->p1==1 ){ /* Invalidate all prepared statements whenever the TEMP database ** schema is changed. Ticket #1644 */ sqlite3ExpirePreparedStatements(db); @@ -52297,22 +54629,23 @@ ** Either a transaction needs to have been started or an OP_Open needs ** to be executed (to establish a read lock) before this opcode is ** invoked. */ case OP_VerifyCookie: { +#if 0 /* local variables moved into u.av */ int iMeta; Btree *pBt; +#endif /* local variables moved into u.av */ assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); - pBt = db->aDb[pOp->p1].pBt; - if( pBt ){ - rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta); - }else{ - rc = SQLITE_OK; - iMeta = 0; - } - if( rc==SQLITE_OK && iMeta!=pOp->p2 ){ + u.av.pBt = db->aDb[pOp->p1].pBt; + if( u.av.pBt ){ + sqlite3BtreeGetMeta(u.av.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.av.iMeta); + }else{ + u.av.iMeta = 0; + } + if( u.av.iMeta!=pOp->p2 ){ sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); /* If the schema-cookie from the database file matches the cookie ** stored with the in-memory representation of the schema, do ** not reload the schema from the database file. @@ -52324,11 +54657,11 @@ ** discard the database schema, as the user code implementing the ** v-table would have to be ready for the sqlite3_vtab structure itself ** to be invalidated whenever sqlite3_step() is called from within ** a v-table method. */ - if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ + if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.av.iMeta ){ sqlite3ResetInternalSchema(db, pOp->p1); } sqlite3ExpirePreparedStatements(db); rc = SQLITE_SCHEMA; @@ -52374,110 +54707,94 @@ ** ** The P4 value may be either an integer (P4_INT32) or a pointer to ** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo ** structure, then said structure defines the content and collating ** sequence of the index being opened. Otherwise, if P4 is an integer -** value, it is set to the number of columns in the table. +** value, it is set to the number of columns in the table, or to the +** largest index of any column of the table that is actually used. ** ** This instruction works just like OpenRead except that it opens the cursor ** in read/write mode. For a given table, there can be one or more read-only ** cursors or a single read/write cursor but not both. ** ** See also OpenRead. */ case OP_OpenRead: case OP_OpenWrite: { - int nField = 0; - KeyInfo *pKeyInfo = 0; - int i = pOp->p1; - int p2 = pOp->p2; - int iDb = pOp->p3; +#if 0 /* local variables moved into u.aw */ + int nField; + KeyInfo *pKeyInfo; + int p2; + int iDb; int wrFlag; Btree *pX; VdbeCursor *pCur; Db *pDb; - - assert( iDb>=0 && iDb<db->nDb ); - assert( (p->btreeMask & (1<<iDb))!=0 ); - pDb = &db->aDb[iDb]; - pX = pDb->pBt; - assert( pX!=0 ); +#endif /* local variables moved into u.aw */ + + u.aw.nField = 0; + u.aw.pKeyInfo = 0; + u.aw.p2 = pOp->p2; + u.aw.iDb = pOp->p3; + assert( u.aw.iDb>=0 && u.aw.iDb<db->nDb ); + assert( (p->btreeMask & (1<<u.aw.iDb))!=0 ); + u.aw.pDb = &db->aDb[u.aw.iDb]; + u.aw.pX = u.aw.pDb->pBt; + assert( u.aw.pX!=0 ); if( pOp->opcode==OP_OpenWrite ){ - wrFlag = 1; - if( pDb->pSchema->file_format < p->minWriteFileFormat ){ - p->minWriteFileFormat = pDb->pSchema->file_format; - } - }else{ - wrFlag = 0; + u.aw.wrFlag = 1; + if( u.aw.pDb->pSchema->file_format < p->minWriteFileFormat ){ + p->minWriteFileFormat = u.aw.pDb->pSchema->file_format; + } + }else{ + u.aw.wrFlag = 0; } if( pOp->p5 ){ - assert( p2>0 ); - assert( p2<=p->nMem ); - pIn2 = &p->aMem[p2]; + assert( u.aw.p2>0 ); + assert( u.aw.p2<=p->nMem ); + pIn2 = &p->aMem[u.aw.p2]; sqlite3VdbeMemIntegerify(pIn2); - p2 = (int)pIn2->u.i; - if( p2<2 ) { + u.aw.p2 = (int)pIn2->u.i; + /* The u.aw.p2 value always comes from a prior OP_CreateTable opcode and + ** that opcode will always set the u.aw.p2 value to 2 or more or else fail. + ** If there were a failure, the prepared statement would have halted + ** before reaching this instruction. */ + if( NEVER(u.aw.p2<2) ) { rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } } - assert( i>=0 ); if( pOp->p4type==P4_KEYINFO ){ - pKeyInfo = pOp->p4.pKeyInfo; - pKeyInfo->enc = ENC(p->db); - nField = pKeyInfo->nField+1; + u.aw.pKeyInfo = pOp->p4.pKeyInfo; + u.aw.pKeyInfo->enc = ENC(p->db); + u.aw.nField = u.aw.pKeyInfo->nField+1; }else if( pOp->p4type==P4_INT32 ){ - nField = pOp->p4.i; - } - pCur = allocateCursor(p, i, nField, iDb, 1); - if( pCur==0 ) goto no_mem; - pCur->nullRow = 1; - rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); - pCur->pKeyInfo = pKeyInfo; - - switch( rc ){ - case SQLITE_BUSY: { - p->pc = pc; - p->rc = rc = SQLITE_BUSY; - goto vdbe_return; - } - case SQLITE_OK: { - int flags = sqlite3BtreeFlags(pCur->pCursor); - /* Sanity checking. Only the lower four bits of the flags byte should - ** be used. Bit 3 (mask 0x08) is unpredictable. The lower 3 bits - ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or - ** 2 (zerodata for indices). If these conditions are not met it can - ** only mean that we are dealing with a corrupt database file - */ - if( (flags & 0xf0)!=0 || ((flags & 0x07)!=5 && (flags & 0x07)!=2) ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } - pCur->isTable = (flags & BTREE_INTKEY)!=0 ?1:0; - pCur->isIndex = (flags & BTREE_ZERODATA)!=0 ?1:0; - /* If P4==0 it means we are expected to open a table. If P4!=0 then - ** we expect to be opening an index. If this is not what happened, - ** then the database is corrupt - */ - if( (pCur->isTable && pOp->p4type==P4_KEYINFO) - || (pCur->isIndex && pOp->p4type!=P4_KEYINFO) ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } - break; - } - case SQLITE_EMPTY: { - pCur->isTable = pOp->p4type!=P4_KEYINFO; - pCur->isIndex = !pCur->isTable; - pCur->pCursor = 0; - rc = SQLITE_OK; - break; - } - default: { - goto abort_due_to_error; - } - } + u.aw.nField = pOp->p4.i; + } + assert( pOp->p1>=0 ); + u.aw.pCur = allocateCursor(p, pOp->p1, u.aw.nField, u.aw.iDb, 1); + if( u.aw.pCur==0 ) goto no_mem; + u.aw.pCur->nullRow = 1; + rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor); + u.aw.pCur->pKeyInfo = u.aw.pKeyInfo; + + /* Since it performs no memory allocation or IO, the only values that + ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK. + ** SQLITE_EMPTY is only returned when attempting to open the table + ** rooted at page 1 of a zero-byte database. */ + assert( rc==SQLITE_EMPTY || rc==SQLITE_OK ); + if( rc==SQLITE_EMPTY ){ + u.aw.pCur->pCursor = 0; + rc = SQLITE_OK; + } + + /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of + ** SQLite used to check if the root-page flags were sane at this point + ** and report database corruption if they were not, but this check has + ** since moved into the btree layer. */ + u.aw.pCur->isTable = pOp->p4type!=P4_KEYINFO; + u.aw.pCur->isIndex = !u.aw.pCur->isTable; break; } /* Opcode: OpenEphemeral P1 P2 * P4 * ** @@ -52496,27 +54813,28 @@ ** to a TEMP table at the SQL level, or to a table opened by ** this opcode. Then this opcode was call OpenVirtual. But ** that created confusion with the whole virtual-table idea. */ case OP_OpenEphemeral: { - int i = pOp->p1; +#if 0 /* local variables moved into u.ax */ VdbeCursor *pCx; +#endif /* local variables moved into u.ax */ static const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TRANSIENT_DB; - assert( i>=0 ); - pCx = allocateCursor(p, i, pOp->p2, -1, 1); - if( pCx==0 ) goto no_mem; - pCx->nullRow = 1; + assert( pOp->p1>=0 ); + u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); + if( u.ax.pCx==0 ) goto no_mem; + u.ax.pCx->nullRow = 1; rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags, - &pCx->pBt); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); + &u.ax.pCx->pBt); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeBeginTrans(u.ax.pCx->pBt, 1); } if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling ** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before ** opening it. If a transient table is required, just use the @@ -52523,75 +54841,67 @@ ** automatically created table with root-page 1 (an INTKEY table). */ if( pOp->p4.pKeyInfo ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); + rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_ZERODATA); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); - rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, - (KeyInfo*)pOp->p4.z, pCx->pCursor); - pCx->pKeyInfo = pOp->p4.pKeyInfo; - pCx->pKeyInfo->enc = ENC(p->db); - } - pCx->isTable = 0; - }else{ - rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor); - pCx->isTable = 1; - } - } - pCx->isIndex = !pCx->isTable; + rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1, + (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor); + u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo; + u.ax.pCx->pKeyInfo->enc = ENC(p->db); + } + u.ax.pCx->isTable = 0; + }else{ + rc = sqlite3BtreeCursor(u.ax.pCx->pBt, MASTER_ROOT, 1, 0, u.ax.pCx->pCursor); + u.ax.pCx->isTable = 1; + } + } + u.ax.pCx->isIndex = !u.ax.pCx->isTable; break; } /* Opcode: OpenPseudo P1 P2 P3 * * ** ** Open a new cursor that points to a fake table that contains a single -** row of data. Any attempt to write a second row of data causes the -** first row to be deleted. All data is deleted when the cursor is -** closed. -** -** A pseudo-table created by this opcode is useful for holding the -** NEW or OLD tables in a trigger. Also used to hold the a single +** row of data. The content of that one row in the content of memory +** register P2. In other words, cursor P1 becomes an alias for the +** MEM_Blob content contained in register P2. +** +** A pseudo-table created by this opcode is used to hold the a single ** row output from the sorter so that the row can be decomposed into -** individual columns using the OP_Column opcode. -** -** When OP_Insert is executed to insert a row in to the pseudo table, -** the pseudo-table cursor may or may not make it's own copy of the -** original row data. If P2 is 0, then the pseudo-table will copy the -** original row data. Otherwise, a pointer to the original memory cell -** is stored. In this case, the vdbe program must ensure that the -** memory cell containing the row data is not overwritten until the -** pseudo table is closed (or a new row is inserted into it). +** individual columns using the OP_Column opcode. The OP_Column opcode +** is the only cursor opcode that works with a pseudo-table. ** ** P3 is the number of fields in the records that will be stored by ** the pseudo-table. */ case OP_OpenPseudo: { - int i = pOp->p1; +#if 0 /* local variables moved into u.ay */ VdbeCursor *pCx; - assert( i>=0 ); - pCx = allocateCursor(p, i, pOp->p3, -1, 0); - if( pCx==0 ) goto no_mem; - pCx->nullRow = 1; - pCx->pseudoTable = 1; - pCx->ephemPseudoTable = (u8)pOp->p2; - pCx->isTable = 1; - pCx->isIndex = 0; +#endif /* local variables moved into u.ay */ + + assert( pOp->p1>=0 ); + u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); + if( u.ay.pCx==0 ) goto no_mem; + u.ay.pCx->nullRow = 1; + u.ay.pCx->pseudoTableReg = pOp->p2; + u.ay.pCx->isTable = 1; + u.ay.pCx->isIndex = 0; break; } /* Opcode: Close P1 * * * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ case OP_Close: { - int i = pOp->p1; - assert( i>=0 && i<p->nCursor ); - sqlite3VdbeFreeCursor(p, p->apCsr[i]); - p->apCsr[i] = 0; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]); + p->apCsr[pOp->p1] = 0; break; } /* Opcode: SeekGe P1 P2 P3 P4 * ** @@ -52647,30 +54957,34 @@ */ case OP_SeekLt: /* jump, in3 */ case OP_SeekLe: /* jump, in3 */ case OP_SeekGe: /* jump, in3 */ case OP_SeekGt: { /* jump, in3 */ - int i = pOp->p1; - VdbeCursor *pC; - - assert( i>=0 && i<p->nCursor ); +#if 0 /* local variables moved into u.az */ + int res; + int oc; + VdbeCursor *pC; + UnpackedRecord r; + int nField; + i64 iKey; /* The rowid we are to seek to */ +#endif /* local variables moved into u.az */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p2!=0 ); - pC = p->apCsr[i]; - assert( pC!=0 ); - if( pC->pCursor!=0 ){ - int res, oc; - oc = pOp->opcode; - pC->nullRow = 0; - if( pC->isTable ){ - i64 iKey; /* The rowid we are to seek to */ - + u.az.pC = p->apCsr[pOp->p1]; + assert( u.az.pC!=0 ); + assert( u.az.pC->pseudoTableReg==0 ); + if( u.az.pC->pCursor!=0 ){ + u.az.oc = pOp->opcode; + u.az.pC->nullRow = 0; + if( u.az.pC->isTable ){ /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so covert it. */ applyNumericAffinity(pIn3); - iKey = sqlite3VdbeIntValue(pIn3); - pC->rowidIsValid = 0; + u.az.iKey = sqlite3VdbeIntValue(pIn3); + u.az.pC->rowidIsValid = 0; /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ if( (pIn3->flags & MEM_Int)==0 ){ if( (pIn3->flags & MEM_Real)==0 ){ @@ -52681,96 +54995,95 @@ } /* If we reach this point, then the P3 value must be a floating ** point number. */ assert( (pIn3->flags & MEM_Real)!=0 ); - if( iKey==SMALLEST_INT64 && (pIn3->r<(double)iKey || pIn3->r>0) ){ - /* The P3 value is to large in magnitude to be expressed as an + if( u.az.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.az.iKey || pIn3->r>0) ){ + /* The P3 value is too large in magnitude to be expressed as an ** integer. */ - res = 1; + u.az.res = 1; if( pIn3->r<0 ){ - if( oc==OP_SeekGt || oc==OP_SeekGe ){ - rc = sqlite3BtreeFirst(pC->pCursor, &res); + if( u.az.oc==OP_SeekGt || u.az.oc==OP_SeekGe ){ + rc = sqlite3BtreeFirst(u.az.pC->pCursor, &u.az.res); if( rc!=SQLITE_OK ) goto abort_due_to_error; } }else{ - if( oc==OP_SeekLt || oc==OP_SeekLe ){ - rc = sqlite3BtreeLast(pC->pCursor, &res); + if( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe ){ + rc = sqlite3BtreeLast(u.az.pC->pCursor, &u.az.res); if( rc!=SQLITE_OK ) goto abort_due_to_error; } } - if( res ){ + if( u.az.res ){ pc = pOp->p2 - 1; } break; - }else if( oc==OP_SeekLt || oc==OP_SeekGe ){ + }else if( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekGe ){ /* Use the ceiling() function to convert real->int */ - if( pIn3->r > (double)iKey ) iKey++; + if( pIn3->r > (double)u.az.iKey ) u.az.iKey++; }else{ /* Use the floor() function to convert real->int */ - assert( oc==OP_SeekLe || oc==OP_SeekGt ); - if( pIn3->r < (double)iKey ) iKey--; - } - } - rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res); + assert( u.az.oc==OP_SeekLe || u.az.oc==OP_SeekGt ); + if( pIn3->r < (double)u.az.iKey ) u.az.iKey--; + } + } + rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, 0, (u64)u.az.iKey, 0, &u.az.res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - if( res==0 ){ - pC->rowidIsValid = 1; - pC->lastRowid = iKey; - } - }else{ - UnpackedRecord r; - int nField = pOp->p4.i; + if( u.az.res==0 ){ + u.az.pC->rowidIsValid = 1; + u.az.pC->lastRowid = u.az.iKey; + } + }else{ + u.az.nField = pOp->p4.i; assert( pOp->p4type==P4_INT32 ); - assert( nField>0 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)nField; - if( oc==OP_SeekGt || oc==OP_SeekLe ){ - r.flags = UNPACKED_INCRKEY; - }else{ - r.flags = 0; - } - r.aMem = &p->aMem[pOp->p3]; - rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res); + assert( u.az.nField>0 ); + u.az.r.pKeyInfo = u.az.pC->pKeyInfo; + u.az.r.nField = (u16)u.az.nField; + if( u.az.oc==OP_SeekGt || u.az.oc==OP_SeekLe ){ + u.az.r.flags = UNPACKED_INCRKEY; + }else{ + u.az.r.flags = 0; + } + u.az.r.aMem = &p->aMem[pOp->p3]; + rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, &u.az.r, 0, 0, &u.az.res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - pC->rowidIsValid = 0; - } - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; + u.az.pC->rowidIsValid = 0; + } + u.az.pC->deferredMoveto = 0; + u.az.pC->cacheStatus = CACHE_STALE; #ifdef SQLITE_TEST sqlite3_search_count++; #endif - if( oc==OP_SeekGe || oc==OP_SeekGt ){ - if( res<0 || (res==0 && oc==OP_SeekGt) ){ - rc = sqlite3BtreeNext(pC->pCursor, &res); + if( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt ){ + if( u.az.res<0 || (u.az.res==0 && u.az.oc==OP_SeekGt) ){ + rc = sqlite3BtreeNext(u.az.pC->pCursor, &u.az.res); if( rc!=SQLITE_OK ) goto abort_due_to_error; - pC->rowidIsValid = 0; - }else{ - res = 0; - } - }else{ - assert( oc==OP_SeekLt || oc==OP_SeekLe ); - if( res>0 || (res==0 && oc==OP_SeekLt) ){ - rc = sqlite3BtreePrevious(pC->pCursor, &res); + u.az.pC->rowidIsValid = 0; + }else{ + u.az.res = 0; + } + }else{ + assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe ); + if( u.az.res>0 || (u.az.res==0 && u.az.oc==OP_SeekLt) ){ + rc = sqlite3BtreePrevious(u.az.pC->pCursor, &u.az.res); if( rc!=SQLITE_OK ) goto abort_due_to_error; - pC->rowidIsValid = 0; - }else{ - /* res might be negative because the table is empty. Check to + u.az.pC->rowidIsValid = 0; + }else{ + /* u.az.res might be negative because the table is empty. Check to ** see if this is the case. */ - res = sqlite3BtreeEof(pC->pCursor); + u.az.res = sqlite3BtreeEof(u.az.pC->pCursor); } } assert( pOp->p2>0 ); - if( res ){ + if( u.az.res ){ pc = pOp->p2 - 1; } - }else if( !pC->pseudoTable ){ + }else{ /* This happens when attempting to open the sqlite3_master table ** for read access returns SQLITE_EMPTY. In this case always ** take the jump (since there are no records in the table). */ pc = pOp->p2 - 1; @@ -52786,22 +55099,23 @@ ** This is actually a deferred seek. Nothing actually happens until ** the cursor is used to read a record. That way, if no reads ** occur, no unnecessary I/O happens. */ case OP_Seek: { /* in2 */ - int i = pOp->p1; - VdbeCursor *pC; - - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC!=0 ); - if( pC->pCursor!=0 ){ - assert( pC->isTable ); - pC->nullRow = 0; - pC->movetoTarget = sqlite3VdbeIntValue(pIn2); - pC->rowidIsValid = 0; - pC->deferredMoveto = 1; +#if 0 /* local variables moved into u.ba */ + VdbeCursor *pC; +#endif /* local variables moved into u.ba */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.ba.pC = p->apCsr[pOp->p1]; + assert( u.ba.pC!=0 ); + if( ALWAYS(u.ba.pC->pCursor!=0) ){ + assert( u.ba.pC->isTable ); + u.ba.pC->nullRow = 0; + u.ba.pC->movetoTarget = sqlite3VdbeIntValue(pIn2); + u.ba.pC->rowidIsValid = 0; + u.ba.pC->deferredMoveto = 1; } break; } @@ -52835,145 +55149,132 @@ ** ** See also: Found, NotExists, IsUnique */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ - int i = pOp->p1; - int alreadyExists = 0; - VdbeCursor *pC; - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); - if( (pC = p->apCsr[i])->pCursor!=0 ){ - int res; - UnpackedRecord *pIdxKey; - - assert( pC->isTable==0 ); +#if 0 /* local variables moved into u.bb */ + int alreadyExists; + VdbeCursor *pC; + int res; + UnpackedRecord *pIdxKey; + char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; +#endif /* local variables moved into u.bb */ + + u.bb.alreadyExists = 0; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bb.pC = p->apCsr[pOp->p1]; + assert( u.bb.pC!=0 ); + if( ALWAYS(u.bb.pC->pCursor!=0) ){ + + assert( u.bb.pC->isTable==0 ); assert( pIn3->flags & MEM_Blob ); - pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, - aTempRec, sizeof(aTempRec)); - if( pIdxKey==0 ){ + ExpandBlob(pIn3); + u.bb.pIdxKey = sqlite3VdbeRecordUnpack(u.bb.pC->pKeyInfo, pIn3->n, pIn3->z, + u.bb.aTempRec, sizeof(u.bb.aTempRec)); + if( u.bb.pIdxKey==0 ){ goto no_mem; } if( pOp->opcode==OP_Found ){ - pIdxKey->flags |= UNPACKED_PREFIX_MATCH; - } - rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); - sqlite3VdbeDeleteUnpackedRecord(pIdxKey); + u.bb.pIdxKey->flags |= UNPACKED_PREFIX_MATCH; + } + rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, u.bb.pIdxKey, 0, 0, &u.bb.res); + sqlite3VdbeDeleteUnpackedRecord(u.bb.pIdxKey); if( rc!=SQLITE_OK ){ break; } - alreadyExists = (res==0); - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; + u.bb.alreadyExists = (u.bb.res==0); + u.bb.pC->deferredMoveto = 0; + u.bb.pC->cacheStatus = CACHE_STALE; } if( pOp->opcode==OP_Found ){ - if( alreadyExists ) pc = pOp->p2 - 1; - }else{ - if( !alreadyExists ) pc = pOp->p2 - 1; + if( u.bb.alreadyExists ) pc = pOp->p2 - 1; + }else{ + if( !u.bb.alreadyExists ) pc = pOp->p2 - 1; } break; } /* Opcode: IsUnique P1 P2 P3 P4 * ** -** The P3 register contains an integer record number. Call this -** record number R. The P4 register contains an index key created -** using MakeRecord. Call it K. -** -** P1 is an index. So it has no data and its key consists of a -** record generated by OP_MakeRecord where the last field is the +** Cursor P1 is open on an index. So it has no data and its key consists +** of a record generated by OP_MakeRecord where the last field is the ** rowid of the entry that the index refers to. ** -** This instruction asks if there is an entry in P1 where the -** fields matches K but the rowid is different from R. -** If there is no such entry, then there is an immediate -** jump to P2. If any entry does exist where the index string -** matches K but the record number is not R, then the record -** number for that entry is written into P3 and control -** falls through to the next instruction. +** The P3 register contains an integer record number. Call this record +** number R. Register P4 is the first in a set of N contiguous registers +** that make up an unpacked index key that can be used with cursor P1. +** The value of N can be inferred from the cursor. N includes the rowid +** value appended to the end of the index record. This rowid value may +** or may not be the same as R. +** +** If any of the N registers beginning with register P4 contains a NULL +** value, jump immediately to P2. +** +** Otherwise, this instruction checks if cursor P1 contains an entry +** where the first (N-1) fields match but the rowid value at the end +** of the index entry is not R. If there is no such entry, control jumps +** to instruction P2. Otherwise, the rowid of the conflicting index +** entry is copied to register P3 and control falls through to the next +** instruction. ** ** See also: NotFound, NotExists, Found */ case OP_IsUnique: { /* jump, in3 */ - int i = pOp->p1; +#if 0 /* local variables moved into u.bc */ + u16 ii; VdbeCursor *pCx; BtCursor *pCrsr; - Mem *pK; - i64 R; - - /* Pop the value R off the top of the stack - */ + u16 nField; + Mem *aMem; + UnpackedRecord r; /* B-Tree index search key */ + i64 R; /* Rowid stored in register P3 */ +#endif /* local variables moved into u.bc */ + + u.bc.aMem = &p->aMem[pOp->p4.i]; + /* Assert that the values of parameters P1 and P4 are in range. */ assert( pOp->p4type==P4_INT32 ); assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem ); - pK = &p->aMem[pOp->p4.i]; - sqlite3VdbeMemIntegerify(pIn3); - R = pIn3->u.i; - assert( i>=0 && i<p->nCursor ); - pCx = p->apCsr[i]; - assert( pCx!=0 ); - pCrsr = pCx->pCursor; - if( pCrsr!=0 ){ - int res; - i64 v; /* The record number that matches K */ - UnpackedRecord *pIdxKey; /* Unpacked version of P4 */ - - /* Make sure K is a string and make zKey point to K - */ - assert( pK->flags & MEM_Blob ); - pIdxKey = sqlite3VdbeRecordUnpack(pCx->pKeyInfo, pK->n, pK->z, - aTempRec, sizeof(aTempRec)); - if( pIdxKey==0 ){ - goto no_mem; - } - pIdxKey->flags |= UNPACKED_IGNORE_ROWID; - - /* Search for an entry in P1 where all but the last rowid match K - ** If there is no such entry, jump immediately to P2. - */ - assert( pCx->deferredMoveto==0 ); - pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeMovetoUnpacked(pCrsr, pIdxKey, 0, 0, &res); - if( rc!=SQLITE_OK ){ - sqlite3VdbeDeleteUnpackedRecord(pIdxKey); - goto abort_due_to_error; - } - if( res<0 ){ - rc = sqlite3BtreeNext(pCrsr, &res); - if( res ){ - pc = pOp->p2 - 1; - sqlite3VdbeDeleteUnpackedRecord(pIdxKey); - break; - } - } - rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res); - sqlite3VdbeDeleteUnpackedRecord(pIdxKey); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - if( res>0 ){ + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + + /* Find the index cursor. */ + u.bc.pCx = p->apCsr[pOp->p1]; + assert( u.bc.pCx->deferredMoveto==0 ); + u.bc.pCx->seekResult = 0; + u.bc.pCx->cacheStatus = CACHE_STALE; + u.bc.pCrsr = u.bc.pCx->pCursor; + + /* If any of the values are NULL, take the jump. */ + u.bc.nField = u.bc.pCx->pKeyInfo->nField; + for(u.bc.ii=0; u.bc.ii<u.bc.nField; u.bc.ii++){ + if( u.bc.aMem[u.bc.ii].flags & MEM_Null ){ + pc = pOp->p2 - 1; + u.bc.pCrsr = 0; + break; + } + } + assert( (u.bc.aMem[u.bc.nField].flags & MEM_Null)==0 ); + + if( u.bc.pCrsr!=0 ){ + /* Populate the index search key. */ + u.bc.r.pKeyInfo = u.bc.pCx->pKeyInfo; + u.bc.r.nField = u.bc.nField + 1; + u.bc.r.flags = UNPACKED_PREFIX_SEARCH; + u.bc.r.aMem = u.bc.aMem; + + /* Extract the value of u.bc.R from register P3. */ + sqlite3VdbeMemIntegerify(pIn3); + u.bc.R = pIn3->u.i; + + /* Search the B-Tree index. If no conflicting record is found, jump + ** to P2. Otherwise, copy the rowid of the conflicting record to + ** register P3 and fall through to the next instruction. */ + rc = sqlite3BtreeMovetoUnpacked(u.bc.pCrsr, &u.bc.r, 0, 0, &u.bc.pCx->seekResult); + if( (u.bc.r.flags & UNPACKED_PREFIX_SEARCH) || u.bc.r.rowid==u.bc.R ){ pc = pOp->p2 - 1; - break; - } - - /* At this point, pCrsr is pointing to an entry in P1 where all but - ** the final entry (the rowid) matches K. Check to see if the - ** final rowid column is different from R. If it equals R then jump - ** immediately to P2. - */ - rc = sqlite3VdbeIdxRowid(pCrsr, &v); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( v==R ){ - pc = pOp->p2 - 1; - break; - } - - /* The final varint of the key is different from R. Store it back - ** into register R3. (The record number of an entry that violates - ** a UNIQUE constraint.) - */ - pIn3->u.i = v; - assert( pIn3->flags&MEM_Int ); + }else{ + pIn3->u.i = u.bc.r.rowid; + } } break; } /* Opcode: NotExists P1 P2 P3 * * @@ -52989,37 +55290,45 @@ ** P1 is an index. ** ** See also: Found, NotFound, IsUnique */ case OP_NotExists: { /* jump, in3 */ - int i = pOp->p1; +#if 0 /* local variables moved into u.bd */ VdbeCursor *pC; BtCursor *pCrsr; - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); - if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ - int res = 0; - u64 iKey; - assert( pIn3->flags & MEM_Int ); - assert( p->apCsr[i]->isTable ); - iKey = intToKey(pIn3->u.i); - rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res); - pC->lastRowid = pIn3->u.i; - pC->rowidIsValid = res==0 ?1:0; - pC->nullRow = 0; - pC->cacheStatus = CACHE_STALE; - if( res!=0 ){ + int res; + u64 iKey; +#endif /* local variables moved into u.bd */ + + assert( pIn3->flags & MEM_Int ); + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bd.pC = p->apCsr[pOp->p1]; + assert( u.bd.pC!=0 ); + assert( u.bd.pC->isTable ); + assert( u.bd.pC->pseudoTableReg==0 ); + u.bd.pCrsr = u.bd.pC->pCursor; + if( u.bd.pCrsr!=0 ){ + u.bd.res = 0; + u.bd.iKey = pIn3->u.i; + rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res); + u.bd.pC->lastRowid = pIn3->u.i; + u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0; + u.bd.pC->nullRow = 0; + u.bd.pC->cacheStatus = CACHE_STALE; + u.bd.pC->deferredMoveto = 0; + if( u.bd.res!=0 ){ pc = pOp->p2 - 1; - assert( pC->rowidIsValid==0 ); - } - }else if( !pC->pseudoTable ){ + assert( u.bd.pC->rowidIsValid==0 ); + } + u.bd.pC->seekResult = u.bd.res; + }else{ /* This happens when an attempt to open a read cursor on the ** sqlite_master table returns SQLITE_EMPTY. */ - assert( pC->isTable ); pc = pOp->p2 - 1; - assert( pC->rowidIsValid==0 ); + assert( u.bd.pC->rowidIsValid==0 ); + u.bd.pC->seekResult = 0; } break; } /* Opcode: Sequence P1 P2 * * * @@ -53028,14 +55337,13 @@ ** Write the sequence number into register P2. ** The sequence number on the cursor is incremented after this ** instruction. */ case OP_Sequence: { /* out2-prerelease */ - int i = pOp->p1; - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); - pOut->u.i = p->apCsr[i]->seqCount++; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + assert( p->apCsr[pOp->p1]!=0 ); + pOut->u.i = p->apCsr[pOp->p1]->seqCount++; MemSetTypeFlag(pOut, MEM_Int); break; } @@ -53044,24 +55352,33 @@ ** Get a new integer record number (a.k.a "rowid") used as the key to a table. ** The record number is not previously used as a key in the database ** table that cursor P1 points to. The new record number is written ** written to register P2. ** -** If P3>0 then P3 is a register that holds the largest previously -** generated record number. No new record numbers are allowed to be less -** than this value. When this value reaches its maximum, a SQLITE_FULL -** error is generated. The P3 register is updated with the generated -** record number. This P3 mechanism is used to help implement the +** If P3>0 then P3 is a register in the root frame of this VDBE that holds +** the largest previously generated record number. No new record numbers are +** allowed to be less than this value. When this value reaches its maximum, +** a SQLITE_FULL error is generated. The P3 register is updated with the ' +** generated record number. This P3 mechanism is used to help implement the ** AUTOINCREMENT feature. */ case OP_NewRowid: { /* out2-prerelease */ - int i = pOp->p1; - i64 v = 0; - VdbeCursor *pC; - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); - if( (pC = p->apCsr[i])->pCursor==0 ){ +#if 0 /* local variables moved into u.be */ + i64 v; /* The new rowid */ + VdbeCursor *pC; /* Cursor of table to get the new rowid */ + int res; /* Result of an sqlite3BtreeLast() */ + int cnt; /* Counter to limit the number of searches */ + Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ + VdbeFrame *pFrame; /* Root frame of VDBE */ +#endif /* local variables moved into u.be */ + + u.be.v = 0; + u.be.res = 0; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.be.pC = p->apCsr[pOp->p1]; + assert( u.be.pC!=0 ); + if( NEVER(u.be.pC->pCursor==0) ){ /* The zero initialization above is all that is needed */ }else{ /* The next rowid or record number (different terms for the same ** thing) is obtained in a two-step algorithm. ** @@ -53071,40 +55388,14 @@ ** probabilistic algorithm ** ** The second algorithm is to select a rowid at random and see if ** it already exists in the table. If it does not exist, we have ** succeeded. If the random rowid does exist, we select a new one - ** and try again, up to 1000 times. - ** - ** For a table with less than 2 billion entries, the probability - ** of not finding a unused rowid is about 1.0e-300. This is a - ** non-zero probability, but it is still vanishingly small and should - ** never cause a problem. You are much, much more likely to have a - ** hardware failure than for this algorithm to fail. - ** - ** The analysis in the previous paragraph assumes that you have a good - ** source of random numbers. Is a library function like lrand48() - ** good enough? Maybe. Maybe not. It's hard to know whether there - ** might be subtle bugs is some implementations of lrand48() that - ** could cause problems. To avoid uncertainty, SQLite uses its own - ** random number generator based on the RC4 algorithm. - ** - ** To promote locality of reference for repetitive inserts, the - ** first few attempts at choosing a random rowid pick values just a little - ** larger than the previous rowid. This has been shown experimentally - ** to double the speed of the COPY operation. - */ - int res=0, rx=SQLITE_OK, cnt; - i64 x; - cnt = 0; - if( (sqlite3BtreeFlags(pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) != - BTREE_INTKEY ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } - assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_INTKEY)!=0 ); - assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_ZERODATA)==0 ); + ** and try again, up to 100 times. + */ + assert( u.be.pC->isTable ); + u.be.cnt = 0; #ifdef SQLITE_32BIT_ROWID # define MAX_ROWID 0x7fffffff #else /* Some compilers complain about constants of the form 0x7fffffffffffffff. @@ -53112,94 +55403,116 @@ ** to provide the constant while making all compilers happy. */ # define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) #endif - if( !pC->useRandomRowid ){ - v = sqlite3BtreeGetCachedRowid(pC->pCursor); - if( v==0 ){ - rc = sqlite3BtreeLast(pC->pCursor, &res); + if( !u.be.pC->useRandomRowid ){ + u.be.v = sqlite3BtreeGetCachedRowid(u.be.pC->pCursor); + if( u.be.v==0 ){ + rc = sqlite3BtreeLast(u.be.pC->pCursor, &u.be.res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - if( res ){ - v = 1; - }else{ - sqlite3BtreeKeySize(pC->pCursor, &v); - v = keyToInt(v); - if( v==MAX_ROWID ){ - pC->useRandomRowid = 1; + if( u.be.res ){ + u.be.v = 1; + }else{ + assert( sqlite3BtreeCursorIsValid(u.be.pC->pCursor) ); + rc = sqlite3BtreeKeySize(u.be.pC->pCursor, &u.be.v); + assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ + if( u.be.v==MAX_ROWID ){ + u.be.pC->useRandomRowid = 1; }else{ - v++; + u.be.v++; } } } #ifndef SQLITE_OMIT_AUTOINCREMENT if( pOp->p3 ){ - Mem *pMem; - assert( pOp->p3>0 && pOp->p3<=p->nMem ); /* P3 is a valid memory cell */ - pMem = &p->aMem[pOp->p3]; - REGISTER_TRACE(pOp->p3, pMem); - sqlite3VdbeMemIntegerify(pMem); - assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ - if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3>0 ); + if( p->pFrame ){ + for(u.be.pFrame=p->pFrame; u.be.pFrame->pParent; u.be.pFrame=u.be.pFrame->pParent); + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3<=u.be.pFrame->nMem ); + u.be.pMem = &u.be.pFrame->aMem[pOp->p3]; + }else{ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3<=p->nMem ); + u.be.pMem = &p->aMem[pOp->p3]; + } + + REGISTER_TRACE(pOp->p3, u.be.pMem); + sqlite3VdbeMemIntegerify(u.be.pMem); + assert( (u.be.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ + if( u.be.pMem->u.i==MAX_ROWID || u.be.pC->useRandomRowid ){ rc = SQLITE_FULL; goto abort_due_to_error; } - if( v<pMem->u.i+1 ){ - v = pMem->u.i + 1; - } - pMem->u.i = v; - } -#endif - - sqlite3BtreeSetCachedRowid(pC->pCursor, v<MAX_ROWID ? v+1 : 0); - } - if( pC->useRandomRowid ){ - assert( pOp->p3==0 ); /* SQLITE_FULL must have occurred prior to this */ - v = db->priorNewRowid; - cnt = 0; + if( u.be.v<u.be.pMem->u.i+1 ){ + u.be.v = u.be.pMem->u.i + 1; + } + u.be.pMem->u.i = u.be.v; + } +#endif + + sqlite3BtreeSetCachedRowid(u.be.pC->pCursor, u.be.v<MAX_ROWID ? u.be.v+1 : 0); + } + if( u.be.pC->useRandomRowid ){ + assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is + ** an AUTOINCREMENT table. */ + u.be.v = db->lastRowid; + u.be.cnt = 0; do{ - if( cnt==0 && (v&0xffffff)==v ){ - v++; - }else{ - sqlite3_randomness(sizeof(v), &v); - if( cnt<5 ) v &= 0xffffff; - } - if( v==0 ) continue; - x = intToKey(v); - rx = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)x, 0, &res); - cnt++; - }while( cnt<100 && rx==SQLITE_OK && res==0 ); - db->priorNewRowid = v; - if( rx==SQLITE_OK && res==0 ){ + if( u.be.cnt==0 && (u.be.v&0xffffff)==u.be.v ){ + u.be.v++; + }else{ + sqlite3_randomness(sizeof(u.be.v), &u.be.v); + if( u.be.cnt<5 ) u.be.v &= 0xffffff; + } + rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v, 0, &u.be.res); + u.be.cnt++; + }while( u.be.cnt<100 && rc==SQLITE_OK && u.be.res==0 ); + if( rc==SQLITE_OK && u.be.res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } } - pC->rowidIsValid = 0; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; + u.be.pC->rowidIsValid = 0; + u.be.pC->deferredMoveto = 0; + u.be.pC->cacheStatus = CACHE_STALE; } MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = v; + pOut->u.i = u.be.v; break; } /* Opcode: Insert P1 P2 P3 P4 P5 ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing -** entry is overwritten. The data is the value stored register +** entry is overwritten. The data is the value MEM_Blob stored in register ** number P2. The key is stored in register P3. The key must -** be an integer. +** be a MEM_Int. ** ** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is ** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, ** then rowid is stored for subsequent return by the ** sqlite3_last_insert_rowid() function (otherwise it is unmodified). +** +** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of +** the last seek operation (OP_NotExists) was a success, then this +** operation will not attempt to find the appropriate row before doing +** the insert but will instead overwrite the row that the cursor is +** currently pointing to. Presumably, the prior OP_NotExists opcode +** has already positioned the cursor correctly. This is an optimization +** that boosts performance by avoiding redundant seeks. +** +** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an +** UPDATE operation. Otherwise (if the flag is clear) then this opcode +** is part of an INSERT operation. The difference is only important to +** the update hook. ** ** Parameter P4 may point to a string containing the table-name, or ** may be NULL. If it is not NULL, then the update-hook ** (sqlite3.xUpdateCallback) is invoked following a successful insert. ** @@ -53211,80 +55524,66 @@ ** ** This instruction only works on tables. The equivalent instruction ** for indices is OP_IdxInsert. */ case OP_Insert: { - Mem *pData = &p->aMem[pOp->p2]; - Mem *pKey = &p->aMem[pOp->p3]; - - i64 iKey; /* The integer ROWID or key for the record to be inserted */ - int i = pOp->p1; - VdbeCursor *pC; - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC!=0 ); - assert( pC->pCursor!=0 || pC->pseudoTable ); - assert( pKey->flags & MEM_Int ); - assert( pC->isTable ); - REGISTER_TRACE(pOp->p2, pData); - REGISTER_TRACE(pOp->p3, pKey); - - iKey = intToKey(pKey->u.i); +#if 0 /* local variables moved into u.bf */ + Mem *pData; /* MEM cell holding data for the record to be inserted */ + Mem *pKey; /* MEM cell holding key for the record */ + i64 iKey; /* The integer ROWID or key for the record to be inserted */ + VdbeCursor *pC; /* Cursor to table into which insert is written */ + int nZero; /* Number of zero-bytes to append */ + int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ + const char *zDb; /* database name - used by the update hook */ + const char *zTbl; /* Table name - used by the opdate hook */ + int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ +#endif /* local variables moved into u.bf */ + + u.bf.pData = &p->aMem[pOp->p2]; + u.bf.pKey = &p->aMem[pOp->p3]; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bf.pC = p->apCsr[pOp->p1]; + assert( u.bf.pC!=0 ); + assert( u.bf.pC->pCursor!=0 ); + assert( u.bf.pC->pseudoTableReg==0 ); + assert( u.bf.pKey->flags & MEM_Int ); + assert( u.bf.pC->isTable ); + REGISTER_TRACE(pOp->p2, u.bf.pData); + REGISTER_TRACE(pOp->p3, u.bf.pKey); + + u.bf.iKey = u.bf.pKey->u.i; if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i; - if( pData->flags & MEM_Null ){ - pData->z = 0; - pData->n = 0; - }else{ - assert( pData->flags & (MEM_Blob|MEM_Str) ); - } - if( pC->pseudoTable ){ - if( !pC->ephemPseudoTable ){ - sqlite3DbFree(db, pC->pData); - } - pC->iKey = iKey; - pC->nData = pData->n; - if( pData->z==pData->zMalloc || pC->ephemPseudoTable ){ - pC->pData = pData->z; - if( !pC->ephemPseudoTable ){ - pData->flags &= ~MEM_Dyn; - pData->flags |= MEM_Ephem; - pData->zMalloc = 0; - } - }else{ - pC->pData = sqlite3Malloc( pC->nData+2 ); - if( !pC->pData ) goto no_mem; - memcpy(pC->pData, pData->z, pC->nData); - pC->pData[pC->nData] = 0; - pC->pData[pC->nData+1] = 0; - } - pC->nullRow = 0; - }else{ - int nZero; - if( pData->flags & MEM_Zero ){ - nZero = pData->u.nZero; - }else{ - nZero = 0; - } - sqlite3BtreeSetCachedRowid(pC->pCursor, 0); - rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, - pData->z, pData->n, nZero, - pOp->p5 & OPFLAG_APPEND); - } - - pC->rowidIsValid = 0; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = u.bf.pKey->u.i; + if( u.bf.pData->flags & MEM_Null ){ + u.bf.pData->z = 0; + u.bf.pData->n = 0; + }else{ + assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) ); + } + u.bf.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bf.pC->seekResult : 0); + if( u.bf.pData->flags & MEM_Zero ){ + u.bf.nZero = u.bf.pData->u.nZero; + }else{ + u.bf.nZero = 0; + } + sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, 0); + rc = sqlite3BtreeInsert(u.bf.pC->pCursor, 0, u.bf.iKey, + u.bf.pData->z, u.bf.pData->n, u.bf.nZero, + pOp->p5 & OPFLAG_APPEND, u.bf.seekResult + ); + u.bf.pC->rowidIsValid = 0; + u.bf.pC->deferredMoveto = 0; + u.bf.pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - const char *zDb = db->aDb[pC->iDb].zName; - const char *zTbl = pOp->p4.z; - int op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); - assert( pC->isTable ); - db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); - assert( pC->iDb>=0 ); + u.bf.zDb = db->aDb[u.bf.pC->iDb].zName; + u.bf.zTbl = pOp->p4.z; + u.bf.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + assert( u.bf.pC->isTable ); + db->xUpdateCallback(db->pUpdateArg, u.bf.op, u.bf.zDb, u.bf.zTbl, u.bf.iKey); + assert( u.bf.pC->iDb>=0 ); } break; } /* Opcode: Delete P1 P2 * P4 * @@ -53306,56 +55605,64 @@ ** pointing to. The update hook will be invoked, if it exists. ** If P4 is not NULL then the P1 cursor must have been positioned ** using OP_NotFound prior to invoking this opcode. */ case OP_Delete: { - int i = pOp->p1; - i64 iKey = 0; +#if 0 /* local variables moved into u.bg */ + i64 iKey; VdbeCursor *pC; - - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC!=0 ); - assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ - - /* If the update-hook will be invoked, set iKey to the rowid of the +#endif /* local variables moved into u.bg */ + + u.bg.iKey = 0; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bg.pC = p->apCsr[pOp->p1]; + assert( u.bg.pC!=0 ); + assert( u.bg.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ + + /* If the update-hook will be invoked, set u.bg.iKey to the rowid of the ** row being deleted. */ if( db->xUpdateCallback && pOp->p4.z ){ - assert( pC->isTable ); - assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ - iKey = pC->lastRowid; - } - - rc = sqlite3VdbeCursorMoveto(pC); - if( rc ) goto abort_due_to_error; - sqlite3BtreeSetCachedRowid(pC->pCursor, 0); - rc = sqlite3BtreeDelete(pC->pCursor); - pC->cacheStatus = CACHE_STALE; + assert( u.bg.pC->isTable ); + assert( u.bg.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ + u.bg.iKey = u.bg.pC->lastRowid; + } + + /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or + ** OP_Column on the same table without any intervening operations that + ** might move or invalidate the cursor. Hence cursor u.bg.pC is always pointing + ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation + ** below is always a no-op and cannot fail. We will run it anyhow, though, + ** to guard against future changes to the code generator. + **/ + assert( u.bg.pC->deferredMoveto==0 ); + rc = sqlite3VdbeCursorMoveto(u.bg.pC); + if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; + + sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0); + rc = sqlite3BtreeDelete(u.bg.pC->pCursor); + u.bg.pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - const char *zDb = db->aDb[pC->iDb].zName; + const char *zDb = db->aDb[u.bg.pC->iDb].zName; const char *zTbl = pOp->p4.z; - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); - assert( pC->iDb>=0 ); + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bg.iKey); + assert( u.bg.pC->iDb>=0 ); } if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; } - -/* Opcode: ResetCount P1 * * -** -** This opcode resets the VMs internal change counter to 0. If P1 is true, -** then the value of the change counter is copied to the database handle -** change counter (returned by subsequent calls to sqlite3_changes()) -** before it is reset. This is used by trigger programs. +/* Opcode: ResetCount * * * * * +** +** The value of the change counter is copied to the database handle +** change counter (returned by subsequent calls to sqlite3_changes()). +** Then the VMs internal change counter resets to 0. +** This is used by trigger programs. */ case OP_ResetCount: { - if( pOp->p1 ){ - sqlite3VdbeSetChanges(db, p->nChange); - } + sqlite3VdbeSetChanges(db, p->nChange); p->nChange = 0; break; } /* Opcode: RowData P1 P2 * * * @@ -53378,52 +55685,64 @@ ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. */ case OP_RowKey: case OP_RowData: { - int i = pOp->p1; +#if 0 /* local variables moved into u.bh */ VdbeCursor *pC; BtCursor *pCrsr; u32 n; + i64 n64; +#endif /* local variables moved into u.bh */ pOut = &p->aMem[pOp->p2]; /* Note that RowKey and RowData are really exactly the same instruction */ - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC->isTable || pOp->opcode==OP_RowKey ); - assert( pC->isIndex || pOp->opcode==OP_RowData ); - assert( pC!=0 ); - assert( pC->nullRow==0 ); - assert( pC->pseudoTable==0 ); - assert( pC->pCursor!=0 ); - pCrsr = pC->pCursor; - rc = sqlite3VdbeCursorMoveto(pC); - if( rc ) goto abort_due_to_error; - if( pC->isIndex ){ - i64 n64; - assert( !pC->isTable ); - sqlite3BtreeKeySize(pCrsr, &n64); - if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bh.pC = p->apCsr[pOp->p1]; + assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey ); + assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData ); + assert( u.bh.pC!=0 ); + assert( u.bh.pC->nullRow==0 ); + assert( u.bh.pC->pseudoTableReg==0 ); + assert( u.bh.pC->pCursor!=0 ); + u.bh.pCrsr = u.bh.pC->pCursor; + assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) ); + + /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or + ** OP_Rewind/Op_Next with no intervening instructions that might invalidate + ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always + ** a no-op and can never fail. But we leave it in place as a safety. + */ + assert( u.bh.pC->deferredMoveto==0 ); + rc = sqlite3VdbeCursorMoveto(u.bh.pC); + if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; + + if( u.bh.pC->isIndex ){ + assert( !u.bh.pC->isTable ); + rc = sqlite3BtreeKeySize(u.bh.pCrsr, &u.bh.n64); + assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ + if( u.bh.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - n = (int)n64; - }else{ - sqlite3BtreeDataSize(pCrsr, &n); - if( (int)n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + u.bh.n = (u32)u.bh.n64; + }else{ + rc = sqlite3BtreeDataSize(u.bh.pCrsr, &u.bh.n); + assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ + if( u.bh.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } } - if( sqlite3VdbeMemGrow(pOut, n, 0) ){ + if( sqlite3VdbeMemGrow(pOut, u.bh.n, 0) ){ goto no_mem; } - pOut->n = n; + pOut->n = u.bh.n; MemSetTypeFlag(pOut, MEM_Blob); - if( pC->isIndex ){ - rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); - }else{ - rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); + if( u.bh.pC->isIndex ){ + rc = sqlite3BtreeKey(u.bh.pCrsr, 0, u.bh.n, pOut->z); + }else{ + rc = sqlite3BtreeData(u.bh.pCrsr, 0, u.bh.n, pOut->z); } pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); break; } @@ -53430,34 +55749,56 @@ /* Opcode: Rowid P1 P2 * * * ** ** Store in register P2 an integer which is the key of the table entry that ** P1 is currently point to. +** +** P1 can be either an ordinary table or a virtual table. There used to +** be a separate OP_VRowid opcode for use with virtual tables, but this +** one opcode now works for both table types. */ case OP_Rowid: { /* out2-prerelease */ - int i = pOp->p1; +#if 0 /* local variables moved into u.bi */ VdbeCursor *pC; i64 v; - - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC!=0 ); - rc = sqlite3VdbeCursorMoveto(pC); - if( rc ) goto abort_due_to_error; - if( pC->rowidIsValid ){ - v = pC->lastRowid; - }else if( pC->pseudoTable ){ - v = keyToInt(pC->iKey); - }else if( pC->nullRow ){ - /* Leave the rowid set to a NULL */ + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; +#endif /* local variables moved into u.bi */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bi.pC = p->apCsr[pOp->p1]; + assert( u.bi.pC!=0 ); + assert( u.bi.pC->pseudoTableReg==0 ); + if( u.bi.pC->nullRow ){ + /* Do nothing so that reg[P2] remains NULL */ break; - }else{ - assert( pC->pCursor!=0 ); - sqlite3BtreeKeySize(pC->pCursor, &v); - v = keyToInt(v); - } - pOut->u.i = v; + }else if( u.bi.pC->deferredMoveto ){ + u.bi.v = u.bi.pC->movetoTarget; +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( u.bi.pC->pVtabCursor ){ + u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab; + u.bi.pModule = u.bi.pVtab->pModule; + assert( u.bi.pModule->xRowid ); + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = u.bi.pVtab->zErrMsg; + u.bi.pVtab->zErrMsg = 0; + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + }else{ + assert( u.bi.pC->pCursor!=0 ); + rc = sqlite3VdbeCursorMoveto(u.bi.pC); + if( rc ) goto abort_due_to_error; + if( u.bi.pC->rowidIsValid ){ + u.bi.v = u.bi.pC->lastRowid; + }else{ + rc = sqlite3BtreeKeySize(u.bi.pC->pCursor, &u.bi.v); + assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */ + } + } + pOut->u.i = u.bi.v; MemSetTypeFlag(pOut, MEM_Int); break; } /* Opcode: NullRow P1 * * * * @@ -53465,20 +55806,21 @@ ** Move the cursor P1 to a null row. Any OP_Column operations ** that occur while the cursor is on the null row will always ** write a NULL. */ case OP_NullRow: { - int i = pOp->p1; +#if 0 /* local variables moved into u.bj */ VdbeCursor *pC; - - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC!=0 ); - pC->nullRow = 1; - pC->rowidIsValid = 0; - if( pC->pCursor ){ - sqlite3BtreeClearCursor(pC->pCursor); +#endif /* local variables moved into u.bj */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bj.pC = p->apCsr[pOp->p1]; + assert( u.bj.pC!=0 ); + u.bj.pC->nullRow = 1; + u.bj.pC->rowidIsValid = 0; + if( u.bj.pC->pCursor ){ + sqlite3BtreeClearCursor(u.bj.pC->pCursor); } break; } /* Opcode: Last P1 P2 * * * @@ -53488,26 +55830,30 @@ ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ case OP_Last: { /* jump */ - int i = pOp->p1; +#if 0 /* local variables moved into u.bk */ VdbeCursor *pC; BtCursor *pCrsr; int res; - - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC!=0 ); - pCrsr = pC->pCursor; - assert( pCrsr!=0 ); - rc = sqlite3BtreeLast(pCrsr, &res); - pC->nullRow = (u8)res; - pC->deferredMoveto = 0; - pC->rowidIsValid = 0; - pC->cacheStatus = CACHE_STALE; - if( res && pOp->p2>0 ){ +#endif /* local variables moved into u.bk */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bk.pC = p->apCsr[pOp->p1]; + assert( u.bk.pC!=0 ); + u.bk.pCrsr = u.bk.pC->pCursor; + if( u.bk.pCrsr==0 ){ + u.bk.res = 1; + }else{ + rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res); + } + u.bk.pC->nullRow = (u8)u.bk.res; + u.bk.pC->deferredMoveto = 0; + u.bk.pC->rowidIsValid = 0; + u.bk.pC->cacheStatus = CACHE_STALE; + if( pOp->p2>0 && u.bk.res ){ pc = pOp->p2 - 1; } break; } @@ -53539,30 +55885,31 @@ ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ case OP_Rewind: { /* jump */ - int i = pOp->p1; +#if 0 /* local variables moved into u.bl */ VdbeCursor *pC; BtCursor *pCrsr; int res; - - assert( i>=0 && i<p->nCursor ); - pC = p->apCsr[i]; - assert( pC!=0 ); - if( (pCrsr = pC->pCursor)!=0 ){ - rc = sqlite3BtreeFirst(pCrsr, &res); - pC->atFirst = res==0 ?1:0; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - pC->rowidIsValid = 0; - }else{ - res = 1; - } - pC->nullRow = (u8)res; +#endif /* local variables moved into u.bl */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bl.pC = p->apCsr[pOp->p1]; + assert( u.bl.pC!=0 ); + if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){ + rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res); + u.bl.pC->atFirst = u.bl.res==0 ?1:0; + u.bl.pC->deferredMoveto = 0; + u.bl.pC->cacheStatus = CACHE_STALE; + u.bl.pC->rowidIsValid = 0; + }else{ + u.bl.res = 1; + } + u.bl.pC->nullRow = (u8)u.bl.res; assert( pOp->p2>0 && pOp->p2<p->nOp ); - if( res ){ + if( u.bl.res ){ pc = pOp->p2 - 1; } break; } @@ -53586,40 +55933,45 @@ ** ** The P1 cursor must be for a real table, not a pseudo-table. */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ +#if 0 /* local variables moved into u.bm */ VdbeCursor *pC; BtCursor *pCrsr; int res; +#endif /* local variables moved into u.bm */ CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); - pC = p->apCsr[pOp->p1]; - if( pC==0 ){ + u.bm.pC = p->apCsr[pOp->p1]; + if( u.bm.pC==0 ){ break; /* See ticket #2273 */ } - pCrsr = pC->pCursor; - assert( pCrsr ); - res = 1; - assert( pC->deferredMoveto==0 ); - rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : - sqlite3BtreePrevious(pCrsr, &res); - pC->nullRow = (u8)res; - pC->cacheStatus = CACHE_STALE; - if( res==0 ){ + u.bm.pCrsr = u.bm.pC->pCursor; + if( u.bm.pCrsr==0 ){ + u.bm.pC->nullRow = 1; + break; + } + u.bm.res = 1; + assert( u.bm.pC->deferredMoveto==0 ); + rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(u.bm.pCrsr, &u.bm.res) : + sqlite3BtreePrevious(u.bm.pCrsr, &u.bm.res); + u.bm.pC->nullRow = (u8)u.bm.res; + u.bm.pC->cacheStatus = CACHE_STALE; + if( u.bm.res==0 ){ pc = pOp->p2 - 1; if( pOp->p5 ) p->aCounter[pOp->p5-1]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif } - pC->rowidIsValid = 0; - break; -} - -/* Opcode: IdxInsert P1 P2 P3 * * + u.bm.pC->rowidIsValid = 0; + break; +} + +/* Opcode: IdxInsert P1 P2 P3 * P5 ** ** Register P2 holds a SQL index key made using the ** MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. ** @@ -53628,25 +55980,33 @@ ** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ case OP_IdxInsert: { /* in2 */ - int i = pOp->p1; +#if 0 /* local variables moved into u.bn */ VdbeCursor *pC; BtCursor *pCrsr; - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); + int nKey; + const char *zKey; +#endif /* local variables moved into u.bn */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bn.pC = p->apCsr[pOp->p1]; + assert( u.bn.pC!=0 ); assert( pIn2->flags & MEM_Blob ); - if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ - assert( pC->isTable==0 ); + u.bn.pCrsr = u.bn.pC->pCursor; + if( ALWAYS(u.bn.pCrsr!=0) ){ + assert( u.bn.pC->isTable==0 ); rc = ExpandBlob(pIn2); if( rc==SQLITE_OK ){ - int nKey = pIn2->n; - const char *zKey = pIn2->z; - rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3); - assert( pC->deferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; + u.bn.nKey = pIn2->n; + u.bn.zKey = pIn2->z; + rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3, + ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0) + ); + assert( u.bn.pC->deferredMoveto==0 ); + u.bn.pC->cacheStatus = CACHE_STALE; } } break; } @@ -53655,30 +56015,34 @@ ** The content of P3 registers starting at register P2 form ** an unpacked index key. This opcode removes that entry from the ** index opened by cursor P1. */ case OP_IdxDelete: { - int i = pOp->p1; +#if 0 /* local variables moved into u.bo */ VdbeCursor *pC; BtCursor *pCrsr; + int res; + UnpackedRecord r; +#endif /* local variables moved into u.bo */ + assert( pOp->p3>0 ); assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 ); - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); - if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ - int res; - UnpackedRecord r; - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p3; - r.flags = 0; - r.aMem = &p->aMem[pOp->p2]; - rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); - if( rc==SQLITE_OK && res==0 ){ - rc = sqlite3BtreeDelete(pCrsr); - } - assert( pC->deferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bo.pC = p->apCsr[pOp->p1]; + assert( u.bo.pC!=0 ); + u.bo.pCrsr = u.bo.pC->pCursor; + if( ALWAYS(u.bo.pCrsr!=0) ){ + u.bo.r.pKeyInfo = u.bo.pC->pKeyInfo; + u.bo.r.nField = (u16)pOp->p3; + u.bo.r.flags = 0; + u.bo.r.aMem = &p->aMem[pOp->p2]; + rc = sqlite3BtreeMovetoUnpacked(u.bo.pCrsr, &u.bo.r, 0, 0, &u.bo.res); + if( rc==SQLITE_OK && u.bo.res==0 ){ + rc = sqlite3BtreeDelete(u.bo.pCrsr); + } + assert( u.bo.pC->deferredMoveto==0 ); + u.bo.pC->cacheStatus = CACHE_STALE; } break; } /* Opcode: IdxRowid P1 P2 * * * @@ -53688,30 +56052,32 @@ ** the rowid of the table entry to which this index entry points. ** ** See also: Rowid, MakeRecord. */ case OP_IdxRowid: { /* out2-prerelease */ - int i = pOp->p1; +#if 0 /* local variables moved into u.bp */ BtCursor *pCrsr; VdbeCursor *pC; - - - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); - if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ - i64 rowid; - rc = sqlite3VdbeCursorMoveto(pC); - if( rc ) goto abort_due_to_error; - assert( pC->deferredMoveto==0 ); - assert( pC->isTable==0 ); - if( !pC->nullRow ){ - rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); + i64 rowid; +#endif /* local variables moved into u.bp */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bp.pC = p->apCsr[pOp->p1]; + assert( u.bp.pC!=0 ); + u.bp.pCrsr = u.bp.pC->pCursor; + if( ALWAYS(u.bp.pCrsr!=0) ){ + rc = sqlite3VdbeCursorMoveto(u.bp.pC); + if( NEVER(rc) ) goto abort_due_to_error; + assert( u.bp.pC->deferredMoveto==0 ); + assert( u.bp.pC->isTable==0 ); + if( !u.bp.pC->nullRow ){ + rc = sqlite3VdbeIdxRowid(db, u.bp.pCrsr, &u.bp.rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = rowid; + pOut->u.i = u.bp.rowid; } } break; } @@ -53741,37 +56107,39 @@ ** If P5 is non-zero then the key value is increased by an epsilon prior ** to the comparison. This makes the opcode work like IdxLE. */ case OP_IdxLT: /* jump, in3 */ case OP_IdxGE: { /* jump, in3 */ - int i= pOp->p1; +#if 0 /* local variables moved into u.bq */ VdbeCursor *pC; - - assert( i>=0 && i<p->nCursor ); - assert( p->apCsr[i]!=0 ); - if( (pC = p->apCsr[i])->pCursor!=0 ){ - int res; - UnpackedRecord r; - assert( pC->deferredMoveto==0 ); + int res; + UnpackedRecord r; +#endif /* local variables moved into u.bq */ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + u.bq.pC = p->apCsr[pOp->p1]; + assert( u.bq.pC!=0 ); + if( ALWAYS(u.bq.pC->pCursor!=0) ){ + assert( u.bq.pC->deferredMoveto==0 ); assert( pOp->p5==0 || pOp->p5==1 ); assert( pOp->p4type==P4_INT32 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p4.i; + u.bq.r.pKeyInfo = u.bq.pC->pKeyInfo; + u.bq.r.nField = (u16)pOp->p4.i; if( pOp->p5 ){ - r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID; - }else{ - r.flags = UNPACKED_IGNORE_ROWID; - } - r.aMem = &p->aMem[pOp->p3]; - rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res); + u.bq.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID; + }else{ + u.bq.r.flags = UNPACKED_IGNORE_ROWID; + } + u.bq.r.aMem = &p->aMem[pOp->p3]; + rc = sqlite3VdbeIdxKeyCompare(u.bq.pC, &u.bq.r, &u.bq.res); if( pOp->opcode==OP_IdxLT ){ - res = -res; + u.bq.res = -u.bq.res; }else{ assert( pOp->opcode==OP_IdxGE ); - res++; - } - if( res>0 ){ + u.bq.res++; + } + if( u.bq.res>0 ){ pc = pOp->p2 - 1 ; } } break; } @@ -53795,36 +56163,39 @@ ** If AUTOVACUUM is disabled then a zero is stored in register P2. ** ** See also: Clear */ case OP_Destroy: { /* out2-prerelease */ +#if 0 /* local variables moved into u.br */ int iMoved; int iCnt; -#ifndef SQLITE_OMIT_VIRTUALTABLE Vdbe *pVdbe; - iCnt = 0; - for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ - if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ - iCnt++; - } - } -#else - iCnt = db->activeVdbeCnt; -#endif - if( iCnt>1 ){ + int iDb; +#endif /* local variables moved into u.br */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u.br.iCnt = 0; + for(u.br.pVdbe=db->pVdbe; u.br.pVdbe; u.br.pVdbe = u.br.pVdbe->pNext){ + if( u.br.pVdbe->magic==VDBE_MAGIC_RUN && u.br.pVdbe->inVtabMethod<2 && u.br.pVdbe->pc>=0 ){ + u.br.iCnt++; + } + } +#else + u.br.iCnt = db->activeVdbeCnt; +#endif + if( u.br.iCnt>1 ){ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; }else{ - int iDb = pOp->p3; - assert( iCnt==1 ); - assert( (p->btreeMask & (1<<iDb))!=0 ); - rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); + u.br.iDb = pOp->p3; + assert( u.br.iCnt==1 ); + assert( (p->btreeMask & (1<<u.br.iDb))!=0 ); + rc = sqlite3BtreeDropTable(db->aDb[u.br.iDb].pBt, pOp->p1, &u.br.iMoved); MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = iMoved; + pOut->u.i = u.br.iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM - if( rc==SQLITE_OK && iMoved!=0 ){ - sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1); + if( rc==SQLITE_OK && u.br.iMoved!=0 ){ + sqlite3RootPageMoved(&db->aDb[u.br.iDb], u.br.iMoved, pOp->p1); } #endif } break; } @@ -53846,19 +56217,23 @@ ** also incremented by the number of rows in the table being cleared. ** ** See also: Destroy */ case OP_Clear: { - int nChange = 0; +#if 0 /* local variables moved into u.bs */ + int nChange; +#endif /* local variables moved into u.bs */ + + u.bs.nChange = 0; assert( (p->btreeMask & (1<<pOp->p2))!=0 ); rc = sqlite3BtreeClearTable( - db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) + db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bs.nChange : 0) ); if( pOp->p3 ){ - p->nChange += nChange; + p->nChange += u.bs.nChange; if( pOp->p3>0 ){ - p->aMem[pOp->p3].u.i += nChange; + p->aMem[pOp->p3].u.i += u.bs.nChange; } } break; } @@ -53884,25 +56259,29 @@ ** ** See documentation on OP_CreateTable for additional information. */ case OP_CreateIndex: /* out2-prerelease */ case OP_CreateTable: { /* out2-prerelease */ - int pgno = 0; +#if 0 /* local variables moved into u.bt */ + int pgno; int flags; Db *pDb; +#endif /* local variables moved into u.bt */ + + u.bt.pgno = 0; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); - pDb = &db->aDb[pOp->p1]; - assert( pDb->pBt!=0 ); + u.bt.pDb = &db->aDb[pOp->p1]; + assert( u.bt.pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ - /* flags = BTREE_INTKEY; */ - flags = BTREE_LEAFDATA|BTREE_INTKEY; - }else{ - flags = BTREE_ZERODATA; - } - rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); - pOut->u.i = pgno; + /* u.bt.flags = BTREE_INTKEY; */ + u.bt.flags = BTREE_LEAFDATA|BTREE_INTKEY; + }else{ + u.bt.flags = BTREE_ZERODATA; + } + rc = sqlite3BtreeCreateTable(u.bt.pDb->pBt, &u.bt.pgno, u.bt.flags); + pOut->u.i = u.bt.pgno; MemSetTypeFlag(pOut, MEM_Int); break; } /* Opcode: ParseSchema P1 P2 * P4 * @@ -53916,57 +56295,62 @@ ** ** This opcode invokes the parser to create a new virtual machine, ** then runs the new virtual machine. It is thus a re-entrant opcode. */ case OP_ParseSchema: { - int iDb = pOp->p1; - assert( iDb>=0 && iDb<db->nDb ); +#if 0 /* local variables moved into u.bu */ + int iDb; + const char *zMaster; + char *zSql; + InitData initData; +#endif /* local variables moved into u.bu */ + + u.bu.iDb = pOp->p1; + assert( u.bu.iDb>=0 && u.bu.iDb<db->nDb ); /* If pOp->p2 is 0, then this opcode is being executed to read a ** single row, for example the row corresponding to a new index ** created by this VDBE, from the sqlite_master table. It only ** does this if the corresponding in-memory schema is currently ** loaded. Otherwise, the new index definition can be loaded along ** with the rest of the schema when it is required. ** ** Although the mutex on the BtShared object that corresponds to - ** database iDb (the database containing the sqlite_master table + ** database u.bu.iDb (the database containing the sqlite_master table ** read by this instruction) is currently held, it is necessary to ** obtain the mutexes on all attached databases before checking if - ** the schema of iDb is loaded. This is because, at the start of + ** the schema of u.bu.iDb is loaded. This is because, at the start of ** the sqlite3_exec() call below, SQLite will invoke ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the - ** iDb mutex may be temporarily released to avoid deadlock. If + ** u.bu.iDb mutex may be temporarily released to avoid deadlock. If ** this happens, then some other thread may delete the in-memory - ** schema of database iDb before the SQL statement runs. The schema + ** schema of database u.bu.iDb before the SQL statement runs. The schema ** will not be reloaded becuase the db->init.busy flag is set. This ** can result in a "no such table: sqlite_master" or "malformed ** database schema" error being returned to the user. */ - assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + assert( sqlite3BtreeHoldsMutex(db->aDb[u.bu.iDb].pBt) ); sqlite3BtreeEnterAll(db); - if( pOp->p2 || DbHasProperty(db, iDb, DB_SchemaLoaded) ){ - const char *zMaster = SCHEMA_TABLE(iDb); - char *zSql; - InitData initData; - initData.db = db; - initData.iDb = pOp->p1; - initData.pzErrMsg = &p->zErrMsg; - zSql = sqlite3MPrintf(db, + if( pOp->p2 || DbHasProperty(db, u.bu.iDb, DB_SchemaLoaded) ){ + u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb); + u.bu.initData.db = db; + u.bu.initData.iDb = pOp->p1; + u.bu.initData.pzErrMsg = &p->zErrMsg; + u.bu.zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s", - db->aDb[iDb].zName, zMaster, pOp->p4.z); - if( zSql==0 ){ + db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z); + if( u.bu.zSql==0 ){ rc = SQLITE_NOMEM; }else{ (void)sqlite3SafetyOff(db); assert( db->init.busy==0 ); db->init.busy = 1; - initData.rc = SQLITE_OK; + u.bu.initData.rc = SQLITE_OK; assert( !db->mallocFailed ); - rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); - if( rc==SQLITE_OK ) rc = initData.rc; - sqlite3DbFree(db, zSql); + rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0); + if( rc==SQLITE_OK ) rc = u.bu.initData.rc; + sqlite3DbFree(db, u.bu.zSql); db->init.busy = 0; (void)sqlite3SafetyOn(db); } } sqlite3BtreeLeaveAll(db); @@ -53974,24 +56358,23 @@ goto no_mem; } break; } -#if !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER) +#if !defined(SQLITE_OMIT_ANALYZE) /* Opcode: LoadAnalysis P1 * * * * ** ** Read the sqlite_stat1 table for database P1 and load the content ** of that table into the internal index hash table. This will cause ** the analysis to be used when preparing all subsequent queries. */ case OP_LoadAnalysis: { - int iDb = pOp->p1; - assert( iDb>=0 && iDb<db->nDb ); - rc = sqlite3AnalysisLoad(db, iDb); - break; -} -#endif /* !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER) */ + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + rc = sqlite3AnalysisLoad(db, pOp->p1); + break; +} +#endif /* !defined(SQLITE_OMIT_ANALYZE) */ /* Opcode: DropTable P1 * * P4 * ** ** Remove the internal (in-memory) data structures that describe ** the table named P4 in database P1. This is called after a table @@ -54048,43 +56431,45 @@ ** file, not the main database file. ** ** This opcode is used to implement the integrity_check pragma. */ case OP_IntegrityCk: { +#if 0 /* local variables moved into u.bv */ int nRoot; /* Number of tables to check. (Number of root pages.) */ int *aRoot; /* Array of rootpage numbers for tables to be checked */ int j; /* Loop counter */ int nErr; /* Number of errors reported */ char *z; /* Text of the error report */ Mem *pnErr; /* Register keeping track of errors remaining */ - - nRoot = pOp->p2; - assert( nRoot>0 ); - aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); - if( aRoot==0 ) goto no_mem; +#endif /* local variables moved into u.bv */ + + u.bv.nRoot = pOp->p2; + assert( u.bv.nRoot>0 ); + u.bv.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bv.nRoot+1) ); + if( u.bv.aRoot==0 ) goto no_mem; assert( pOp->p3>0 && pOp->p3<=p->nMem ); - pnErr = &p->aMem[pOp->p3]; - assert( (pnErr->flags & MEM_Int)!=0 ); - assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); + u.bv.pnErr = &p->aMem[pOp->p3]; + assert( (u.bv.pnErr->flags & MEM_Int)!=0 ); + assert( (u.bv.pnErr->flags & (MEM_Str|MEM_Blob))==0 ); pIn1 = &p->aMem[pOp->p1]; - for(j=0; j<nRoot; j++){ - aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]); - } - aRoot[j] = 0; + for(u.bv.j=0; u.bv.j<u.bv.nRoot; u.bv.j++){ + u.bv.aRoot[u.bv.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bv.j]); + } + u.bv.aRoot[u.bv.j] = 0; assert( pOp->p5<db->nDb ); assert( (p->btreeMask & (1<<pOp->p5))!=0 ); - z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, - (int)pnErr->u.i, &nErr); - sqlite3DbFree(db, aRoot); - pnErr->u.i -= nErr; + u.bv.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bv.aRoot, u.bv.nRoot, + (int)u.bv.pnErr->u.i, &u.bv.nErr); + sqlite3DbFree(db, u.bv.aRoot); + u.bv.pnErr->u.i -= u.bv.nErr; sqlite3VdbeMemSetNull(pIn1); - if( nErr==0 ){ - assert( z==0 ); - }else if( z==0 ){ + if( u.bv.nErr==0 ){ + assert( u.bv.z==0 ); + }else if( u.bv.z==0 ){ goto no_mem; }else{ - sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); + sqlite3VdbeMemSetStr(pIn1, u.bv.z, -1, SQLITE_UTF8, sqlite3_free); } UPDATE_MAX_BLOBSIZE(pIn1); sqlite3VdbeChangeEncoding(pIn1, encoding); break; } @@ -54096,22 +56481,24 @@ ** held in register P1. ** ** An assertion fails if P2 is not an integer. */ case OP_RowSetAdd: { /* in2 */ +#if 0 /* local variables moved into u.bw */ Mem *pIdx; Mem *pVal; +#endif /* local variables moved into u.bw */ assert( pOp->p1>0 && pOp->p1<=p->nMem ); - pIdx = &p->aMem[pOp->p1]; + u.bw.pIdx = &p->aMem[pOp->p1]; assert( pOp->p2>0 && pOp->p2<=p->nMem ); - pVal = &p->aMem[pOp->p2]; - assert( (pVal->flags & MEM_Int)!=0 ); - if( (pIdx->flags & MEM_RowSet)==0 ){ - sqlite3VdbeMemSetRowSet(pIdx); - if( (pIdx->flags & MEM_RowSet)==0 ) goto no_mem; - } - sqlite3RowSetInsert(pIdx->u.pRowSet, pVal->u.i); + u.bw.pVal = &p->aMem[pOp->p2]; + assert( (u.bw.pVal->flags & MEM_Int)!=0 ); + if( (u.bw.pIdx->flags & MEM_RowSet)==0 ){ + sqlite3VdbeMemSetRowSet(u.bw.pIdx); + if( (u.bw.pIdx->flags & MEM_RowSet)==0 ) goto no_mem; + } + sqlite3RowSetInsert(u.bw.pIdx->u.pRowSet, u.bw.pVal->u.i); break; } /* Opcode: RowSetRead P1 P2 P3 * * ** @@ -54118,85 +56505,258 @@ ** Extract the smallest value from boolean index P1 and put that value into ** register P3. Or, if boolean index P1 is initially empty, leave P3 ** unchanged and jump to instruction P2. */ case OP_RowSetRead: { /* jump, out3 */ +#if 0 /* local variables moved into u.bx */ Mem *pIdx; i64 val; +#endif /* local variables moved into u.bx */ assert( pOp->p1>0 && pOp->p1<=p->nMem ); CHECK_FOR_INTERRUPT; - pIdx = &p->aMem[pOp->p1]; + u.bx.pIdx = &p->aMem[pOp->p1]; pOut = &p->aMem[pOp->p3]; - if( (pIdx->flags & MEM_RowSet)==0 - || sqlite3RowSetNext(pIdx->u.pRowSet, &val)==0 + if( (u.bx.pIdx->flags & MEM_RowSet)==0 + || sqlite3RowSetNext(u.bx.pIdx->u.pRowSet, &u.bx.val)==0 ){ /* The boolean index is empty */ - sqlite3VdbeMemSetNull(pIdx); + sqlite3VdbeMemSetNull(u.bx.pIdx); pc = pOp->p2 - 1; }else{ /* A value was pulled from the index */ assert( pOp->p3>0 && pOp->p3<=p->nMem ); - sqlite3VdbeMemSetInt64(pOut, val); - } - break; -} - - -#ifndef SQLITE_OMIT_TRIGGER -/* Opcode: ContextPush * * * -** -** Save the current Vdbe context such that it can be restored by a ContextPop -** opcode. The context stores the last insert row id, the last statement change -** count, and the current statement change count. -*/ -case OP_ContextPush: { - int i = p->contextStackTop++; - Context *pContext; - - assert( i>=0 ); - /* FIX ME: This should be allocated as part of the vdbe at compile-time */ - if( i>=p->contextStackDepth ){ - p->contextStackDepth = i+1; - p->contextStack = sqlite3DbReallocOrFree(db, p->contextStack, - sizeof(Context)*(i+1)); - if( p->contextStack==0 ) goto no_mem; - } - pContext = &p->contextStack[i]; - pContext->lastRowid = db->lastRowid; - pContext->nChange = p->nChange; - break; -} - -/* Opcode: ContextPop * * * -** -** Restore the Vdbe context to the state it was in when contextPush was last -** executed. The context stores the last insert row id, the last statement -** change count, and the current statement change count. -*/ -case OP_ContextPop: { - Context *pContext = &p->contextStack[--p->contextStackTop]; - assert( p->contextStackTop>=0 ); - db->lastRowid = pContext->lastRowid; - p->nChange = pContext->nChange; - break; -} + sqlite3VdbeMemSetInt64(pOut, u.bx.val); + } + break; +} + +/* Opcode: RowSetTest P1 P2 P3 P4 +** +** Register P3 is assumed to hold a 64-bit integer value. If register P1 +** contains a RowSet object and that RowSet object contains +** the value held in P3, jump to register P2. Otherwise, insert the +** integer in P3 into the RowSet and continue on to the +** next opcode. +** +** The RowSet object is optimized for the case where successive sets +** of integers, where each set contains no duplicates. Each set +** of values is identified by a unique P4 value. The first set +** must have P4==0, the final set P4=-1. P4 must be either -1 or +** non-negative. For non-negative values of P4 only the lower 4 +** bits are significant. +** +** This allows optimizations: (a) when P4==0 there is no need to test +** the rowset object for P3, as it is guaranteed not to contain it, +** (b) when P4==-1 there is no need to insert the value, as it will +** never be tested for, and (c) when a value that is part of set X is +** inserted, there is no need to search to see if the same value was +** previously inserted as part of set X (only if it was previously +** inserted as part of some other set). +*/ +case OP_RowSetTest: { /* jump, in1, in3 */ +#if 0 /* local variables moved into u.by */ + int iSet; + int exists; +#endif /* local variables moved into u.by */ + + u.by.iSet = pOp->p4.i; + assert( pIn3->flags&MEM_Int ); + + /* If there is anything other than a rowset object in memory cell P1, + ** delete it now and initialize P1 with an empty rowset + */ + if( (pIn1->flags & MEM_RowSet)==0 ){ + sqlite3VdbeMemSetRowSet(pIn1); + if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; + } + + assert( pOp->p4type==P4_INT32 ); + assert( u.by.iSet==-1 || u.by.iSet>=0 ); + if( u.by.iSet ){ + u.by.exists = sqlite3RowSetTest(pIn1->u.pRowSet, + (u8)(u.by.iSet>=0 ? u.by.iSet & 0xf : 0xff), + pIn3->u.i); + if( u.by.exists ){ + pc = pOp->p2 - 1; + break; + } + } + if( u.by.iSet>=0 ){ + sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); + } + break; +} + + +#ifndef SQLITE_OMIT_TRIGGER + +/* Opcode: Program P1 P2 P3 P4 * +** +** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). +** +** P1 contains the address of the memory cell that contains the first memory +** cell in an array of values used as arguments to the sub-program. P2 +** contains the address to jump to if the sub-program throws an IGNORE +** exception using the RAISE() function. Register P3 contains the address +** of a memory cell in this (the parent) VM that is used to allocate the +** memory required by the sub-vdbe at runtime. +** +** P4 is a pointer to the VM containing the trigger program. +*/ +case OP_Program: { /* jump */ +#if 0 /* local variables moved into u.bz */ + int nMem; /* Number of memory registers for sub-program */ + int nByte; /* Bytes of runtime space required for sub-program */ + Mem *pRt; /* Register to allocate runtime space */ + Mem *pMem; /* Used to iterate through memory cells */ + Mem *pEnd; /* Last memory cell in new array */ + VdbeFrame *pFrame; /* New vdbe frame to execute in */ + SubProgram *pProgram; /* Sub-program to execute */ + void *t; /* Token identifying trigger */ +#endif /* local variables moved into u.bz */ + + u.bz.pProgram = pOp->p4.pProgram; + u.bz.pRt = &p->aMem[pOp->p3]; + assert( u.bz.pProgram->nOp>0 ); + + /* If the SQLITE_RecTriggers flag is clear, then recursive invocation of + ** triggers is disabled for backwards compatibility (flag set/cleared by + ** the "PRAGMA recursive_triggers" command). + ** + ** It is recursive invocation of triggers, at the SQL level, that is + ** disabled. In some cases a single trigger may generate more than one + ** SubProgram (if the trigger may be executed with more than one different + ** ON CONFLICT algorithm). SubProgram structures associated with a + ** single trigger all have the same value for the SubProgram.token + ** variable. + */ + if( 0==(db->flags&SQLITE_RecTriggers) ){ + u.bz.t = u.bz.pProgram->token; + for(u.bz.pFrame=p->pFrame; u.bz.pFrame && u.bz.pFrame->token!=u.bz.t; u.bz.pFrame=u.bz.pFrame->pParent); + if( u.bz.pFrame ) break; + } + + if( p->nFrame>db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ + rc = SQLITE_ERROR; + sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion"); + break; + } + + /* Register u.bz.pRt is used to store the memory required to save the state + ** of the current program, and the memory required at runtime to execute + ** the trigger program. If this trigger has been fired before, then u.bz.pRt + ** is already allocated. Otherwise, it must be initialized. */ + if( (u.bz.pRt->flags&MEM_Frame)==0 ){ + /* SubProgram.nMem is set to the number of memory cells used by the + ** program stored in SubProgram.aOp. As well as these, one memory + ** cell is required for each cursor used by the program. Set local + ** variable u.bz.nMem (and later, VdbeFrame.nChildMem) to this value. + */ + u.bz.nMem = u.bz.pProgram->nMem + u.bz.pProgram->nCsr; + u.bz.nByte = ROUND8(sizeof(VdbeFrame)) + + u.bz.nMem * sizeof(Mem) + + u.bz.pProgram->nCsr * sizeof(VdbeCursor *); + u.bz.pFrame = sqlite3DbMallocZero(db, u.bz.nByte); + if( !u.bz.pFrame ){ + goto no_mem; + } + sqlite3VdbeMemRelease(u.bz.pRt); + u.bz.pRt->flags = MEM_Frame; + u.bz.pRt->u.pFrame = u.bz.pFrame; + + u.bz.pFrame->v = p; + u.bz.pFrame->nChildMem = u.bz.nMem; + u.bz.pFrame->nChildCsr = u.bz.pProgram->nCsr; + u.bz.pFrame->pc = pc; + u.bz.pFrame->aMem = p->aMem; + u.bz.pFrame->nMem = p->nMem; + u.bz.pFrame->apCsr = p->apCsr; + u.bz.pFrame->nCursor = p->nCursor; + u.bz.pFrame->aOp = p->aOp; + u.bz.pFrame->nOp = p->nOp; + u.bz.pFrame->token = u.bz.pProgram->token; + + u.bz.pEnd = &VdbeFrameMem(u.bz.pFrame)[u.bz.pFrame->nChildMem]; + for(u.bz.pMem=VdbeFrameMem(u.bz.pFrame); u.bz.pMem!=u.bz.pEnd; u.bz.pMem++){ + u.bz.pMem->flags = MEM_Null; + u.bz.pMem->db = db; + } + }else{ + u.bz.pFrame = u.bz.pRt->u.pFrame; + assert( u.bz.pProgram->nMem+u.bz.pProgram->nCsr==u.bz.pFrame->nChildMem ); + assert( u.bz.pProgram->nCsr==u.bz.pFrame->nChildCsr ); + assert( pc==u.bz.pFrame->pc ); + } + + p->nFrame++; + u.bz.pFrame->pParent = p->pFrame; + u.bz.pFrame->lastRowid = db->lastRowid; + u.bz.pFrame->nChange = p->nChange; + p->nChange = 0; + p->pFrame = u.bz.pFrame; + p->aMem = &VdbeFrameMem(u.bz.pFrame)[-1]; + p->nMem = u.bz.pFrame->nChildMem; + p->nCursor = (u16)u.bz.pFrame->nChildCsr; + p->apCsr = (VdbeCursor **)&p->aMem[p->nMem+1]; + p->aOp = u.bz.pProgram->aOp; + p->nOp = u.bz.pProgram->nOp; + pc = -1; + + break; +} + +/* Opcode: Param P1 P2 * * * +** +** This opcode is only ever present in sub-programs called via the +** OP_Program instruction. Copy a value currently stored in a memory +** cell of the calling (parent) frame to cell P2 in the current frames +** address space. This is used by trigger programs to access the new.* +** and old.* values. +** +** The address of the cell in the parent frame is determined by adding +** the value of the P1 argument to the value of the P1 argument to the +** calling OP_Program instruction. +*/ +case OP_Param: { /* out2-prerelease */ +#if 0 /* local variables moved into u.ca */ + VdbeFrame *pFrame; + Mem *pIn; +#endif /* local variables moved into u.ca */ + u.ca.pFrame = p->pFrame; + u.ca.pIn = &u.ca.pFrame->aMem[pOp->p1 + u.ca.pFrame->aOp[u.ca.pFrame->pc].p1]; + sqlite3VdbeMemShallowCopy(pOut, u.ca.pIn, MEM_Ephem); + break; +} + #endif /* #ifndef SQLITE_OMIT_TRIGGER */ #ifndef SQLITE_OMIT_AUTOINCREMENT /* Opcode: MemMax P1 P2 * * * ** -** Set the value of register P1 to the maximum of its current value -** and the value in register P2. +** P1 is a register in the root frame of this VM (the root frame is +** different from the current frame if this instruction is being executed +** within a sub-program). Set the value of register P1 to the maximum of +** its current value and the value in register P2. ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ -case OP_MemMax: { /* in1, in2 */ - sqlite3VdbeMemIntegerify(pIn1); +case OP_MemMax: { /* in2 */ +#if 0 /* local variables moved into u.cb */ + Mem *pIn1; + VdbeFrame *pFrame; +#endif /* local variables moved into u.cb */ + if( p->pFrame ){ + for(u.cb.pFrame=p->pFrame; u.cb.pFrame->pParent; u.cb.pFrame=u.cb.pFrame->pParent); + u.cb.pIn1 = &u.cb.pFrame->aMem[pOp->p1]; + }else{ + u.cb.pIn1 = &p->aMem[pOp->p1]; + } + sqlite3VdbeMemIntegerify(u.cb.pIn1); sqlite3VdbeMemIntegerify(pIn2); - if( pIn1->u.i<pIn2->u.i){ - pIn1->u.i = pIn2->u.i; + if( u.cb.pIn1->u.i<pIn2->u.i){ + u.cb.pIn1->u.i = pIn2->u.i; } break; } #endif /* SQLITE_OMIT_AUTOINCREMENT */ @@ -54254,47 +56814,51 @@ ** ** The P5 arguments are taken from register P2 and its ** successors. */ case OP_AggStep: { - int n = pOp->p5; - int i; - Mem *pMem, *pRec; +#if 0 /* local variables moved into u.cc */ + int n; + int i; + Mem *pMem; + Mem *pRec; sqlite3_context ctx; sqlite3_value **apVal; - - assert( n>=0 ); - pRec = &p->aMem[pOp->p2]; - apVal = p->apArg; - assert( apVal || n==0 ); - for(i=0; i<n; i++, pRec++){ - apVal[i] = pRec; - storeTypeInfo(pRec, encoding); - } - ctx.pFunc = pOp->p4.pFunc; +#endif /* local variables moved into u.cc */ + + u.cc.n = pOp->p5; + assert( u.cc.n>=0 ); + u.cc.pRec = &p->aMem[pOp->p2]; + u.cc.apVal = p->apArg; + assert( u.cc.apVal || u.cc.n==0 ); + for(u.cc.i=0; u.cc.i<u.cc.n; u.cc.i++, u.cc.pRec++){ + u.cc.apVal[u.cc.i] = u.cc.pRec; + storeTypeInfo(u.cc.pRec, encoding); + } + u.cc.ctx.pFunc = pOp->p4.pFunc; assert( pOp->p3>0 && pOp->p3<=p->nMem ); - ctx.pMem = pMem = &p->aMem[pOp->p3]; - pMem->n++; - ctx.s.flags = MEM_Null; - ctx.s.z = 0; - ctx.s.zMalloc = 0; - ctx.s.xDel = 0; - ctx.s.db = db; - ctx.isError = 0; - ctx.pColl = 0; - if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ + u.cc.ctx.pMem = u.cc.pMem = &p->aMem[pOp->p3]; + u.cc.pMem->n++; + u.cc.ctx.s.flags = MEM_Null; + u.cc.ctx.s.z = 0; + u.cc.ctx.s.zMalloc = 0; + u.cc.ctx.s.xDel = 0; + u.cc.ctx.s.db = db; + u.cc.ctx.isError = 0; + u.cc.ctx.pColl = 0; + if( u.cc.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); - ctx.pColl = pOp[-1].p4.pColl; - } - (ctx.pFunc->xStep)(&ctx, n, apVal); - if( ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); - rc = ctx.isError; - } - sqlite3VdbeMemRelease(&ctx.s); + u.cc.ctx.pColl = pOp[-1].p4.pColl; + } + (u.cc.ctx.pFunc->xStep)(&u.cc.ctx, u.cc.n, u.cc.apVal); + if( u.cc.ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cc.ctx.s)); + rc = u.cc.ctx.isError; + } + sqlite3VdbeMemRelease(&u.cc.ctx.s); break; } /* Opcode: AggFinal P1 P2 * P4 * ** @@ -54307,21 +56871,23 @@ ** functions that can take varying numbers of arguments. The ** P4 argument is only needed for the degenerate case where ** the step function was not previously called. */ case OP_AggFinal: { +#if 0 /* local variables moved into u.cd */ Mem *pMem; +#endif /* local variables moved into u.cd */ assert( pOp->p1>0 && pOp->p1<=p->nMem ); - pMem = &p->aMem[pOp->p1]; - assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); - rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); - if( rc==SQLITE_ERROR ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem)); - } - sqlite3VdbeChangeEncoding(pMem, encoding); - UPDATE_MAX_BLOBSIZE(pMem); - if( sqlite3VdbeMemTooBig(pMem) ){ + u.cd.pMem = &p->aMem[pOp->p1]; + assert( (u.cd.pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); + rc = sqlite3VdbeMemFinalize(u.cd.pMem, pOp->p4.pFunc); + if( rc ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cd.pMem)); + } + sqlite3VdbeChangeEncoding(u.cd.pMem, encoding); + UPDATE_MAX_BLOBSIZE(u.cd.pMem); + if( sqlite3VdbeMemTooBig(u.cd.pMem) ){ goto too_big; } break; } @@ -54347,16 +56913,18 @@ ** Perform a single step of the incremental vacuum procedure on ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ case OP_IncrVacuum: { /* jump */ +#if 0 /* local variables moved into u.ce */ Btree *pBt; +#endif /* local variables moved into u.ce */ assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); - pBt = db->aDb[pOp->p1].pBt; - rc = sqlite3BtreeIncrVacuum(pBt); + u.ce.pBt = db->aDb[pOp->p1].pBt; + rc = sqlite3BtreeIncrVacuum(u.ce.pBt); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; } break; @@ -54385,29 +56953,31 @@ /* Opcode: TableLock P1 P2 P3 P4 * ** ** Obtain a lock on a particular table. This instruction is only used when ** the shared-cache feature is enabled. ** -** If P1 is the index of the database in sqlite3.aDb[] of the database +** P1 is the index of the database in sqlite3.aDb[] of the database ** on which the lock is acquired. A readlock is obtained if P3==0 or ** a write lock if P3==1. ** ** P2 contains the root-page of the table to lock. ** ** P4 contains a pointer to the name of the table being locked. This is only ** used to generate an error message if the lock cannot be obtained. */ case OP_TableLock: { - int p1 = pOp->p1; u8 isWriteLock = (u8)pOp->p3; - assert( p1>=0 && p1<db->nDb ); - assert( (p->btreeMask & (1<<p1))!=0 ); - assert( isWriteLock==0 || isWriteLock==1 ); - rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); - if( (rc&0xFF)==SQLITE_LOCKED ){ - const char *z = pOp->p4.z; - sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z); + if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ + int p1 = pOp->p1; + assert( p1>=0 && p1<db->nDb ); + assert( (p->btreeMask & (1<<p1))!=0 ); + assert( isWriteLock==0 || isWriteLock==1 ); + rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); + if( (rc&0xFF)==SQLITE_LOCKED ){ + const char *z = pOp->p4.z; + sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z); + } } break; } #endif /* SQLITE_OMIT_SHARED_CACHE */ @@ -54420,16 +56990,19 @@ ** Also, whether or not P4 is set, check that this is not being called from ** within a callback to a virtual table xSync() method. If it is, the error ** code will be set to SQLITE_LOCKED. */ case OP_VBegin: { - sqlite3_vtab *pVtab = pOp->p4.pVtab; - rc = sqlite3VtabBegin(db, pVtab); - if( pVtab ){ +#if 0 /* local variables moved into u.cf */ + VTable *pVTab; +#endif /* local variables moved into u.cf */ + u.cf.pVTab = pOp->p4.pVtab; + rc = sqlite3VtabBegin(db, u.cf.pVTab); + if( u.cf.pVTab ){ sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + p->zErrMsg = u.cf.pVTab->pVtab->zErrMsg; + u.cf.pVTab->pVtab->zErrMsg = 0; } break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -54465,35 +57038,40 @@ ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** P1 is a cursor number. This opcode opens a cursor to the virtual ** table and stores that cursor in P1. */ case OP_VOpen: { - VdbeCursor *pCur = 0; - sqlite3_vtab_cursor *pVtabCursor = 0; - - sqlite3_vtab *pVtab = pOp->p4.pVtab; - sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; - - assert(pVtab && pModule); +#if 0 /* local variables moved into u.cg */ + VdbeCursor *pCur; + sqlite3_vtab_cursor *pVtabCursor; + sqlite3_vtab *pVtab; + sqlite3_module *pModule; +#endif /* local variables moved into u.cg */ + + u.cg.pCur = 0; + u.cg.pVtabCursor = 0; + u.cg.pVtab = pOp->p4.pVtab->pVtab; + u.cg.pModule = (sqlite3_module *)u.cg.pVtab->pModule; + assert(u.cg.pVtab && u.cg.pModule); if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - rc = pModule->xOpen(pVtab, &pVtabCursor); + rc = u.cg.pModule->xOpen(u.cg.pVtab, &u.cg.pVtabCursor); sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + p->zErrMsg = u.cg.pVtab->zErrMsg; + u.cg.pVtab->zErrMsg = 0; if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; if( SQLITE_OK==rc ){ /* Initialize sqlite3_vtab_cursor base class */ - pVtabCursor->pVtab = pVtab; + u.cg.pVtabCursor->pVtab = u.cg.pVtab; /* Initialise vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, 0, -1, 0); - if( pCur ){ - pCur->pVtabCursor = pVtabCursor; - pCur->pModule = pVtabCursor->pVtab->pModule; - }else{ - db->mallocFailed = 1; - pModule->xClose(pVtabCursor); + u.cg.pCur = allocateCursor(p, pOp->p1, 0, -1, 0); + if( u.cg.pCur ){ + u.cg.pCur->pVtabCursor = u.cg.pVtabCursor; + u.cg.pCur->pModule = u.cg.pVtabCursor->pVtab->pModule; + }else{ + db->mallocFailed = 1; + u.cg.pModule->xClose(u.cg.pVtabCursor); } } break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -54516,92 +57094,65 @@ ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. ** ** A jump is made to P2 if the result set after filtering would be empty. */ case OP_VFilter: { /* jump */ +#if 0 /* local variables moved into u.ch */ int nArg; int iQuery; const sqlite3_module *pModule; - Mem *pQuery = &p->aMem[pOp->p3]; - Mem *pArgc = &pQuery[1]; + Mem *pQuery; + Mem *pArgc; sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; - - VdbeCursor *pCur = p->apCsr[pOp->p1]; - - REGISTER_TRACE(pOp->p3, pQuery); - assert( pCur->pVtabCursor ); - pVtabCursor = pCur->pVtabCursor; - pVtab = pVtabCursor->pVtab; - pModule = pVtab->pModule; + VdbeCursor *pCur; + int res; + int i; + Mem **apArg; +#endif /* local variables moved into u.ch */ + + u.ch.pQuery = &p->aMem[pOp->p3]; + u.ch.pArgc = &u.ch.pQuery[1]; + u.ch.pCur = p->apCsr[pOp->p1]; + REGISTER_TRACE(pOp->p3, u.ch.pQuery); + assert( u.ch.pCur->pVtabCursor ); + u.ch.pVtabCursor = u.ch.pCur->pVtabCursor; + u.ch.pVtab = u.ch.pVtabCursor->pVtab; + u.ch.pModule = u.ch.pVtab->pModule; /* Grab the index number and argc parameters */ - assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); - nArg = (int)pArgc->u.i; - iQuery = (int)pQuery->u.i; + assert( (u.ch.pQuery->flags&MEM_Int)!=0 && u.ch.pArgc->flags==MEM_Int ); + u.ch.nArg = (int)u.ch.pArgc->u.i; + u.ch.iQuery = (int)u.ch.pQuery->u.i; /* Invoke the xFilter method */ { - int res = 0; - int i; - Mem **apArg = p->apArg; - for(i = 0; i<nArg; i++){ - apArg[i] = &pArgc[i+1]; - storeTypeInfo(apArg[i], 0); + u.ch.res = 0; + u.ch.apArg = p->apArg; + for(u.ch.i = 0; u.ch.i<u.ch.nArg; u.ch.i++){ + u.ch.apArg[u.ch.i] = &u.ch.pArgc[u.ch.i+1]; + storeTypeInfo(u.ch.apArg[u.ch.i], 0); } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - sqlite3VtabLock(pVtab); p->inVtabMethod = 1; - rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); + rc = u.ch.pModule->xFilter(u.ch.pVtabCursor, u.ch.iQuery, pOp->p4.z, u.ch.nArg, u.ch.apArg); p->inVtabMethod = 0; sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; - sqlite3VtabUnlock(db, pVtab); - if( rc==SQLITE_OK ){ - res = pModule->xEof(pVtabCursor); + p->zErrMsg = u.ch.pVtab->zErrMsg; + u.ch.pVtab->zErrMsg = 0; + if( rc==SQLITE_OK ){ + u.ch.res = u.ch.pModule->xEof(u.ch.pVtabCursor); } if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; - if( res ){ + if( u.ch.res ){ pc = pOp->p2 - 1; } } - pCur->nullRow = 0; - - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VRowid P1 P2 * * * -** -** Store into register P2 the rowid of -** the virtual-table that the P1 cursor is pointing to. -*/ -case OP_VRowid: { /* out2-prerelease */ - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - sqlite_int64 iRow; - VdbeCursor *pCur = p->apCsr[pOp->p1]; - - assert( pCur->pVtabCursor ); - if( pCur->nullRow ){ - break; - } - pVtab = pCur->pVtabCursor->pVtab; - pModule = pVtab->pModule; - assert( pModule->xRowid ); - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - rc = pModule->xRowid(pCur->pVtabCursor, &iRow); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; - MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = iRow; + u.ch.pCur->nullRow = 0; + break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -54610,55 +57161,60 @@ ** Store the value of the P2-th column of ** the row of the virtual-table that the ** P1 cursor is pointing to into register P3. */ case OP_VColumn: { +#if 0 /* local variables moved into u.ci */ sqlite3_vtab *pVtab; const sqlite3_module *pModule; Mem *pDest; sqlite3_context sContext; +#endif /* local variables moved into u.ci */ VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); - pDest = &p->aMem[pOp->p3]; + u.ci.pDest = &p->aMem[pOp->p3]; if( pCur->nullRow ){ - sqlite3VdbeMemSetNull(pDest); + sqlite3VdbeMemSetNull(u.ci.pDest); break; } - pVtab = pCur->pVtabCursor->pVtab; - pModule = pVtab->pModule; - assert( pModule->xColumn ); - memset(&sContext, 0, sizeof(sContext)); + u.ci.pVtab = pCur->pVtabCursor->pVtab; + u.ci.pModule = u.ci.pVtab->pModule; + assert( u.ci.pModule->xColumn ); + memset(&u.ci.sContext, 0, sizeof(u.ci.sContext)); /* The output cell may already have a buffer allocated. Move - ** the current contents to sContext.s so in case the user-function + ** the current contents to u.ci.sContext.s so in case the user-function ** can use the already allocated buffer instead of allocating a ** new one. */ - sqlite3VdbeMemMove(&sContext.s, pDest); - MemSetTypeFlag(&sContext.s, MEM_Null); + sqlite3VdbeMemMove(&u.ci.sContext.s, u.ci.pDest); + MemSetTypeFlag(&u.ci.sContext.s, MEM_Null); if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); + rc = u.ci.pModule->xColumn(pCur->pVtabCursor, &u.ci.sContext, pOp->p2); sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + p->zErrMsg = u.ci.pVtab->zErrMsg; + u.ci.pVtab->zErrMsg = 0; + if( u.ci.sContext.isError ){ + rc = u.ci.sContext.isError; + } /* Copy the result of the function to the P3 register. We ** do this regardless of whether or not an error occurred to ensure any - ** dynamic allocation in sContext.s (a Mem struct) is released. - */ - sqlite3VdbeChangeEncoding(&sContext.s, encoding); - REGISTER_TRACE(pOp->p3, pDest); - sqlite3VdbeMemMove(pDest, &sContext.s); - UPDATE_MAX_BLOBSIZE(pDest); + ** dynamic allocation in u.ci.sContext.s (a Mem struct) is released. + */ + sqlite3VdbeChangeEncoding(&u.ci.sContext.s, encoding); + REGISTER_TRACE(pOp->p3, u.ci.pDest); + sqlite3VdbeMemMove(u.ci.pDest, &u.ci.sContext.s); + UPDATE_MAX_BLOBSIZE(u.ci.pDest); if( sqlite3SafetyOn(db) ){ goto abort_due_to_misuse; } - if( sqlite3VdbeMemTooBig(pDest) ){ + if( sqlite3VdbeMemTooBig(u.ci.pDest) ){ goto too_big; } break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -54669,44 +57225,46 @@ ** Advance virtual table P1 to the next row in its result set and ** jump to instruction P2. Or, if the virtual table has reached ** the end of its result set, then fall through to the next instruction. */ case OP_VNext: { /* jump */ +#if 0 /* local variables moved into u.cj */ sqlite3_vtab *pVtab; const sqlite3_module *pModule; - int res = 0; - - VdbeCursor *pCur = p->apCsr[pOp->p1]; - assert( pCur->pVtabCursor ); - if( pCur->nullRow ){ + int res; + VdbeCursor *pCur; +#endif /* local variables moved into u.cj */ + + u.cj.res = 0; + u.cj.pCur = p->apCsr[pOp->p1]; + assert( u.cj.pCur->pVtabCursor ); + if( u.cj.pCur->nullRow ){ break; } - pVtab = pCur->pVtabCursor->pVtab; - pModule = pVtab->pModule; - assert( pModule->xNext ); + u.cj.pVtab = u.cj.pCur->pVtabCursor->pVtab; + u.cj.pModule = u.cj.pVtab->pModule; + assert( u.cj.pModule->xNext ); /* Invoke the xNext() method of the module. There is no way for the ** underlying implementation to return an error if one occurs during ** xNext(). Instead, if an error occurs, true is returned (indicating that ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - sqlite3VtabLock(pVtab); p->inVtabMethod = 1; - rc = pModule->xNext(pCur->pVtabCursor); + rc = u.cj.pModule->xNext(u.cj.pCur->pVtabCursor); p->inVtabMethod = 0; sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; - sqlite3VtabUnlock(db, pVtab); - if( rc==SQLITE_OK ){ - res = pModule->xEof(pCur->pVtabCursor); + p->zErrMsg = u.cj.pVtab->zErrMsg; + u.cj.pVtab->zErrMsg = 0; + if( rc==SQLITE_OK ){ + u.cj.res = u.cj.pModule->xEof(u.cj.pCur->pVtabCursor); } if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; - if( !res ){ + if( !u.cj.res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } break; } @@ -54718,24 +57276,25 @@ ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** This opcode invokes the corresponding xRename method. The value ** in register P1 is passed as the zName argument to the xRename method. */ case OP_VRename: { - sqlite3_vtab *pVtab = pOp->p4.pVtab; - Mem *pName = &p->aMem[pOp->p1]; - assert( pVtab->pModule->xRename ); - REGISTER_TRACE(pOp->p1, pName); - - Stringify(pName, encoding); - +#if 0 /* local variables moved into u.ck */ + sqlite3_vtab *pVtab; + Mem *pName; +#endif /* local variables moved into u.ck */ + + u.ck.pVtab = pOp->p4.pVtab->pVtab; + u.ck.pName = &p->aMem[pOp->p1]; + assert( u.ck.pVtab->pModule->xRename ); + REGISTER_TRACE(pOp->p1, u.ck.pName); + assert( u.ck.pName->flags & MEM_Str ); if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - sqlite3VtabLock(pVtab); - rc = pVtab->pModule->xRename(pVtab, pName->z); + rc = u.ck.pVtab->pModule->xRename(u.ck.pVtab, u.ck.pName->z); sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; - sqlite3VtabUnlock(db, pVtab); + p->zErrMsg = u.ck.pVtab->zErrMsg; + u.ck.pVtab->zErrMsg = 0; if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; break; } #endif @@ -54763,38 +57322,41 @@ ** P1 is a boolean flag. If it is set to true and the xUpdate call ** is successful, then the value returned by sqlite3_last_insert_rowid() ** is set to the value of the rowid for the row just inserted. */ case OP_VUpdate: { - sqlite3_vtab *pVtab = pOp->p4.pVtab; - sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; - int nArg = pOp->p2; +#if 0 /* local variables moved into u.cl */ + sqlite3_vtab *pVtab; + sqlite3_module *pModule; + int nArg; + int i; + sqlite_int64 rowid; + Mem **apArg; + Mem *pX; +#endif /* local variables moved into u.cl */ + + u.cl.pVtab = pOp->p4.pVtab->pVtab; + u.cl.pModule = (sqlite3_module *)u.cl.pVtab->pModule; + u.cl.nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); - if( pModule->xUpdate==0 ){ - sqlite3SetString(&p->zErrMsg, db, "read-only table"); - rc = SQLITE_ERROR; - }else{ - int i; - sqlite_int64 rowid; - Mem **apArg = p->apArg; - Mem *pX = &p->aMem[pOp->p3]; - for(i=0; i<nArg; i++){ - storeTypeInfo(pX, 0); - apArg[i] = pX; - pX++; + if( ALWAYS(u.cl.pModule->xUpdate) ){ + u.cl.apArg = p->apArg; + u.cl.pX = &p->aMem[pOp->p3]; + for(u.cl.i=0; u.cl.i<u.cl.nArg; u.cl.i++){ + storeTypeInfo(u.cl.pX, 0); + u.cl.apArg[u.cl.i] = u.cl.pX; + u.cl.pX++; } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - sqlite3VtabLock(pVtab); - rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); + rc = u.cl.pModule->xUpdate(u.cl.pVtab, u.cl.nArg, u.cl.apArg, &u.cl.rowid); sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; - sqlite3VtabUnlock(db, pVtab); + p->zErrMsg = u.cl.pVtab->zErrMsg; + u.cl.pVtab->zErrMsg = 0; if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; - if( pOp->p1 && rc==SQLITE_OK ){ - assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); - db->lastRowid = rowid; + if( rc==SQLITE_OK && pOp->p1 ){ + assert( u.cl.nArg>1 && u.cl.apArg[0] && (u.cl.apArg[0]->flags&MEM_Null) ); + db->lastRowid = u.cl.rowid; } p->nChange++; } break; } @@ -54804,18 +57366,25 @@ /* Opcode: Pagecount P1 P2 * * * ** ** Write the current number of pages in database P1 to memory cell P2. */ case OP_Pagecount: { /* out2-prerelease */ - int p1 = pOp->p1; +#if 0 /* local variables moved into u.cm */ + int p1; int nPage; - Pager *pPager = sqlite3BtreePager(db->aDb[p1].pBt); - - rc = sqlite3PagerPagecount(pPager, &nPage); - if( rc==SQLITE_OK ){ + Pager *pPager; +#endif /* local variables moved into u.cm */ + + u.cm.p1 = pOp->p1; + u.cm.pPager = sqlite3BtreePager(db->aDb[u.cm.p1].pBt); + rc = sqlite3PagerPagecount(u.cm.pPager, &u.cm.nPage); + /* OP_Pagecount is always called from within a read transaction. The + ** page count has already been successfully read and cached. So the + ** sqlite3PagerPagecount() call above cannot fail. */ + if( ALWAYS(rc==SQLITE_OK) ){ pOut->flags = MEM_Int; - pOut->u.i = nPage; + pOut->u.i = u.cm.nPage; } break; } #endif @@ -54824,18 +57393,22 @@ ** ** If tracing is enabled (by the sqlite3_trace()) interface, then ** the UTF-8 string contained in P4 is emitted on the trace callback. */ case OP_Trace: { - char *zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); - if( zTrace ){ +#if 0 /* local variables moved into u.cn */ + char *zTrace; +#endif /* local variables moved into u.cn */ + + u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); + if( u.cn.zTrace ){ if( db->xTrace ){ - db->xTrace(db->pTraceArg, zTrace); + db->xTrace(db->pTraceArg, u.cn.zTrace); } #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 ){ - sqlite3DebugPrintf("SQL-trace: %s\n", zTrace); + sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace); } #endif /* SQLITE_DEBUG */ } break; } @@ -54974,11 +57547,11 @@ ** ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: vdbeblob.c,v 1.31 2009/03/24 15:08:10 drh Exp $ +** $Id: vdbeblob.c,v 1.35 2009/07/02 07:47:33 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_INCRBLOB @@ -55026,60 +57599,66 @@ ** transaction. */ static const VdbeOpList openBlob[] = { {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */ {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */ - - /* One of the following two instructions is replaced by an - ** OP_Noop before exection. - */ - {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ - {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ - - {OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */ - {OP_NotExists, 0, 8, 1}, /* 5: Seek the cursor */ - {OP_Column, 0, 0, 1}, /* 6 */ - {OP_ResultRow, 1, 0, 0}, /* 7 */ - {OP_Close, 0, 0, 0}, /* 8 */ - {OP_Halt, 0, 0, 0}, /* 9 */ + {OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */ + + /* One of the following two instructions is replaced by an OP_Noop. */ + {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */ + {OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */ + + {OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */ + {OP_NotExists, 0, 9, 1}, /* 6: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 7 */ + {OP_ResultRow, 1, 0, 0}, /* 8 */ + {OP_Close, 0, 0, 0}, /* 9 */ + {OP_Halt, 0, 0, 0}, /* 10 */ }; Vdbe *v = 0; int rc = SQLITE_OK; - char zErr[128]; - - zErr[0] = 0; - sqlite3_mutex_enter(db->mutex); + char *zErr = 0; + Table *pTab; + Parse *pParse; + + *ppBlob = 0; + sqlite3_mutex_enter(db->mutex); + pParse = sqlite3StackAllocRaw(db, sizeof(*pParse)); + if( pParse==0 ){ + rc = SQLITE_NOMEM; + goto blob_open_out; + } do { - Parse sParse; - Table *pTab; - - memset(&sParse, 0, sizeof(Parse)); - sParse.db = db; + memset(pParse, 0, sizeof(Parse)); + pParse->db = db; if( sqlite3SafetyOn(db) ){ + sqlite3DbFree(db, zErr); + sqlite3StackFree(db, pParse); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE; } sqlite3BtreeEnterAll(db); - pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); + pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); if( pTab && IsVirtual(pTab) ){ pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); + sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); } #ifndef SQLITE_OMIT_VIEW if( pTab && pTab->pSelect ){ pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); + sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); } #endif if( !pTab ){ - if( sParse.zErrMsg ){ - sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg); - } - sqlite3DbFree(db, sParse.zErrMsg); + if( pParse->zErrMsg ){ + sqlite3DbFree(db, zErr); + zErr = pParse->zErrMsg; + pParse->zErrMsg = 0; + } rc = SQLITE_ERROR; (void)sqlite3SafetyOff(db); sqlite3BtreeLeaveAll(db); goto blob_open_out; } @@ -55089,11 +57668,12 @@ if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ break; } } if( iCol==pTab->nCol ){ - sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn); + sqlite3DbFree(db, zErr); + zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); rc = SQLITE_ERROR; (void)sqlite3SafetyOff(db); sqlite3BtreeLeaveAll(db); goto blob_open_out; } @@ -55106,11 +57686,12 @@ Index *pIdx; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int j; for(j=0; j<pIdx->nColumn; j++){ if( pIdx->aiColumn[j]==iCol ){ - sqlite3_snprintf(sizeof(zErr), zErr, + sqlite3DbFree(db, zErr); + zErr = sqlite3MPrintf(db, "cannot open indexed column for writing"); rc = SQLITE_ERROR; (void)sqlite3SafetyOff(db); sqlite3BtreeLeaveAll(db); goto blob_open_out; @@ -55121,55 +57702,62 @@ v = sqlite3VdbeCreate(db); if( v ){ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob); + flags = !!flags; /* flags = (flags ? 1 : 0); */ /* Configure the OP_Transaction */ sqlite3VdbeChangeP1(v, 0, iDb); - sqlite3VdbeChangeP2(v, 0, (flags ? 1 : 0)); + sqlite3VdbeChangeP2(v, 0, flags); /* Configure the OP_VerifyCookie */ sqlite3VdbeChangeP1(v, 1, iDb); sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); /* Make sure a mutex is held on the table to be accessed */ sqlite3VdbeUsesBtree(v, iDb); + /* Configure the OP_TableLock instruction */ + sqlite3VdbeChangeP1(v, 2, iDb); + sqlite3VdbeChangeP2(v, 2, pTab->tnum); + sqlite3VdbeChangeP3(v, 2, flags); + sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); + /* Remove either the OP_OpenWrite or OpenRead. Set the P2 - ** parameter of the other to pTab->tnum. - */ - sqlite3VdbeChangeToNoop(v, (flags ? 2 : 3), 1); - sqlite3VdbeChangeP2(v, (flags ? 3 : 2), pTab->tnum); - sqlite3VdbeChangeP3(v, (flags ? 3 : 2), iDb); + ** parameter of the other to pTab->tnum. */ + sqlite3VdbeChangeToNoop(v, 4 - flags, 1); + sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum); + sqlite3VdbeChangeP3(v, 3 + flags, iDb); /* Configure the number of columns. Configure the cursor to ** think that the table has one more column than it really ** does. An OP_Column to retrieve this imaginary column will ** always return an SQL NULL. This is useful because it means ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ - sqlite3VdbeChangeP4(v, flags ? 3 : 2, SQLITE_INT_TO_PTR(pTab->nCol+1), P4_INT32); - sqlite3VdbeChangeP2(v, 6, pTab->nCol); + sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); + sqlite3VdbeChangeP2(v, 7, pTab->nCol); if( !db->mallocFailed ){ - sqlite3VdbeMakeReady(v, 1, 1, 1, 0); + sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0); } } sqlite3BtreeLeaveAll(db); rc = sqlite3SafetyOff(db); - if( rc!=SQLITE_OK || db->mallocFailed ){ + if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){ goto blob_open_out; } sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow); rc = sqlite3_step((sqlite3_stmt *)v); if( rc!=SQLITE_ROW ){ nAttempt++; rc = sqlite3_finalize((sqlite3_stmt *)v); - sqlite3_snprintf(sizeof(zErr), zErr, sqlite3_errmsg(db)); + sqlite3DbFree(db, zErr); + zErr = sqlite3MPrintf(db, sqlite3_errmsg(db)); v = 0; } } while( nAttempt<5 && rc==SQLITE_SCHEMA ); if( rc==SQLITE_ROW ){ @@ -55179,11 +57767,12 @@ */ Incrblob *pBlob; u32 type = v->apCsr[0]->aType[iCol]; if( type<12 ){ - sqlite3_snprintf(sizeof(zErr), zErr, "cannot open value of type %s", + sqlite3DbFree(db, zErr); + zErr = sqlite3MPrintf(db, "cannot open value of type %s", type==0?"null": type==7?"real": "integer" ); rc = SQLITE_ERROR; goto blob_open_out; } @@ -55202,20 +57791,22 @@ pBlob->nByte = sqlite3VdbeSerialTypeLen(type); pBlob->db = db; *ppBlob = (sqlite3_blob *)pBlob; rc = SQLITE_OK; }else if( rc==SQLITE_OK ){ - sqlite3_snprintf(sizeof(zErr), zErr, "no such rowid: %lld", iRow); + sqlite3DbFree(db, zErr); + zErr = sqlite3MPrintf(db, "no such rowid: %lld", iRow); rc = SQLITE_ERROR; } blob_open_out: - zErr[sizeof(zErr)-1] = '\0'; if( v && (rc!=SQLITE_OK || db->mallocFailed) ){ sqlite3VdbeFinalize(v); } - sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr)); + sqlite3Error(db, rc, zErr); + sqlite3DbFree(db, zErr); + sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } @@ -55226,15 +57817,19 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; int rc; sqlite3 *db; - db = p->db; - sqlite3_mutex_enter(db->mutex); - rc = sqlite3_finalize(p->pStmt); - sqlite3DbFree(db, p); - sqlite3_mutex_leave(db->mutex); + if( p ){ + db = p->db; + sqlite3_mutex_enter(db->mutex); + rc = sqlite3_finalize(p->pStmt); + sqlite3DbFree(db, p); + sqlite3_mutex_leave(db->mutex); + }else{ + rc = SQLITE_OK; + } return rc; } /* ** Perform a read or write operation on a blob @@ -55247,12 +57842,14 @@ int (*xCall)(BtCursor*, u32, u32, void*) ){ int rc; Incrblob *p = (Incrblob *)pBlob; Vdbe *v; - sqlite3 *db = p->db; - + sqlite3 *db; + + if( p==0 ) return SQLITE_MISUSE; + db = p->db; sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ @@ -55304,11 +57901,11 @@ ** The Incrblob.nByte field is fixed for the lifetime of the Incrblob ** so no mutex is required for access. */ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; - return p->nByte; + return p ? p->nByte : 0; } #endif /* #ifndef SQLITE_OMIT_INCRBLOB */ /************** End of vdbeblob.c ********************************************/ @@ -55569,11 +58166,11 @@ ** ** This file contains code use to implement an in-memory rollback journal. ** The in-memory rollback journal is used to journal transactions for ** ":memory:" databases and when the journal_mode=MEMORY pragma is used. ** -** @(#) $Id: memjournal.c,v 1.11 2009/04/05 12:22:09 drh Exp $ +** @(#) $Id: memjournal.c,v 1.12 2009/05/04 11:42:30 danielk1977 Exp $ */ /* Forward references to internal structures */ typedef struct MemJournal MemJournal; typedef struct FilePoint FilePoint; @@ -55683,11 +58280,11 @@ u8 *zWrite = (u8 *)zBuf; /* An in-memory journal file should only ever be appended to. Random ** access writes are not required by sqlite. */ - assert(iOfst==p->endpoint.iOffset); + assert( iOfst==p->endpoint.iOffset ); UNUSED_PARAMETER(iOfst); while( nWrite>0 ){ FileChunk *pChunk = p->endpoint.pChunk; int iChunkOffset = (int)(p->endpoint.iOffset%JOURNAL_CHUNKSIZE); @@ -55828,11 +58425,11 @@ ** ************************************************************************* ** This file contains routines used for walking the parser tree for ** an SQL statement. ** -** $Id: walker.c,v 1.4 2009/04/08 13:51:52 drh Exp $ +** $Id: walker.c,v 1.7 2009/06/15 23:15:59 drh Exp $ */ /* ** Walk an expression tree. Invoke the callback once for each node @@ -55855,15 +58452,14 @@ */ SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ int rc; if( pExpr==0 ) return WRC_Continue; testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); - testcase( ExprHasProperty(pExpr, EP_SpanToken) ); testcase( ExprHasProperty(pExpr, EP_Reduced) ); rc = pWalker->xExprCallback(pWalker, pExpr); if( rc==WRC_Continue - && !ExprHasAnyProperty(pExpr,EP_TokenOnly|EP_SpanToken) ){ + && !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){ if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; }else{ @@ -55876,18 +58472,18 @@ /* ** Call sqlite3WalkExpr() for every expression in list p or until ** an abort request is seen. */ SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){ - int i, rc = WRC_Continue; + int i; struct ExprList_item *pItem; if( p ){ for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort; } } - return rc & WRC_Continue; + return WRC_Continue; } /* ** Walk all expressions associated with SELECT statement p. Do ** not invoke the SELECT callback on p, but do (of course) invoke @@ -55916,11 +58512,11 @@ SrcList *pSrc; int i; struct SrcList_item *pItem; pSrc = p->pSrc; - if( pSrc ){ + if( ALWAYS(pSrc) ){ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){ return WRC_Abort; } } @@ -55969,11 +58565,11 @@ ** ** This file contains routines used for walking the parser tree and ** resolve all identifiers by associating them with a particular ** table and column. ** -** $Id: resolve.c,v 1.20 2009/03/05 04:23:47 shane Exp $ +** $Id: resolve.c,v 1.30 2009/06/15 23:15:59 drh Exp $ */ /* ** Turn the pExpr expression into an alias for the iCol-th column of the ** result set in pEList. @@ -56015,20 +58611,31 @@ assert( iCol>=0 && iCol<pEList->nExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); assert( pOrig->flags & EP_Resolved ); db = pParse->db; - pDup = sqlite3ExprDup(db, pOrig, 0); - if( pDup==0 ) return; - sqlite3TokenCopy(db, &pDup->token, &pOrig->token); - if( pDup->op!=TK_COLUMN && zType[0]!='G' ){ + if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ + pDup = sqlite3ExprDup(db, pOrig, 0); pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); if( pDup==0 ) return; if( pEList->a[iCol].iAlias==0 ){ pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); } pDup->iTable = pEList->a[iCol].iAlias; + }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){ + pDup = sqlite3ExprDup(db, pOrig, 0); + if( pDup==0 ) return; + }else{ + char *zToken = pOrig->u.zToken; + assert( zToken!=0 ); + pOrig->u.zToken = 0; + pDup = sqlite3ExprDup(db, pOrig, 0); + pOrig->u.zToken = zToken; + if( pDup==0 ) return; + assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); + pDup->flags2 |= EP2_MallocedToken; + pDup->u.zToken = sqlite3DbStrDup(db, zToken); } if( pExpr->flags & EP_ExpCollate ){ pDup->pColl = pExpr->pColl; pDup->flags |= EP_ExpCollate; } @@ -56052,54 +58659,46 @@ ** pExpr->iColumn Set to the column number within the table. ** pExpr->op Set to TK_COLUMN. ** pExpr->pLeft Any expression this points to is deleted ** pExpr->pRight Any expression this points to is deleted. ** -** The pDbToken is the name of the database (the "X"). This value may be +** The zDb variable is the name of the database (the "X"). This value may be ** NULL meaning that name is of the form Y.Z or Z. Any available database -** can be used. The pTableToken is the name of the table (the "Y"). This -** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it +** can be used. The zTable variable is the name of the table (the "Y"). This +** value can be NULL if zDb is also NULL. If zTable is NULL it ** means that the form of the name is Z and that columns from any table ** can be used. ** ** If the name cannot be resolved unambiguously, leave an error message -** in pParse and return non-zero. Return zero on success. +** in pParse and return WRC_Abort. Return WRC_Prune on success. */ static int lookupName( Parse *pParse, /* The parsing context */ - Token *pDbToken, /* Name of the database containing table, or NULL */ - Token *pTableToken, /* Name of table containing column, or NULL */ - Token *pColumnToken, /* Name of the column. */ + const char *zDb, /* Name of the database containing table, or NULL */ + const char *zTab, /* Name of table containing column, or NULL */ + const char *zCol, /* Name of the column. */ NameContext *pNC, /* The name context used to resolve the name */ Expr *pExpr /* Make this EXPR node point to the selected column */ ){ - char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ - char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ - char *zCol = 0; /* Name of the column. The "Z" */ int i, j; /* Loop counters */ int cnt = 0; /* Number of matching column names */ int cntTab = 0; /* Number of matching table names */ sqlite3 *db = pParse->db; /* The database connection */ struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ - - assert( pNC ); /* the name context cannot be NULL. */ - assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ - - /* Dequote and zero-terminate the names */ - zDb = sqlite3NameFromToken(db, pDbToken); - zTab = sqlite3NameFromToken(db, pTableToken); - zCol = sqlite3NameFromToken(db, pColumnToken); - if( db->mallocFailed ){ - goto lookupname_end; - } + int isTrigger = 0; + + assert( pNC ); /* the name context cannot be NULL. */ + assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ + assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; + ExprSetIrreducible(pExpr); /* Start at the inner-most context and move outward until a match is found */ while( pNC && cnt==0 ){ ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; @@ -56118,11 +58717,13 @@ if( pItem->zAlias ){ char *zTabName = pItem->zAlias; if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; }else{ char *zTabName = pTab->zName; - if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; + if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){ + continue; + } if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ continue; } } } @@ -56139,11 +58740,11 @@ pExpr->iTable = pItem->iCursor; pExpr->pTab = pTab; pMatch = pItem; pSchema = pTab->pSchema; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ - pExpr->iColumn = j==pTab->iPKey ? -1 : j; + pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; if( i<pSrcList->nSrc-1 ){ if( pItem[1].jointype & JT_NATURAL ){ /* If this match occurred in the left table of a natural join, ** then skip the right table to avoid a duplicate match */ pItem++; @@ -56170,44 +58771,51 @@ #ifndef SQLITE_OMIT_TRIGGER /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ - if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){ - TriggerStack *pTriggerStack = pParse->trigStack; + if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){ + int op = pParse->eTriggerOp; Table *pTab = 0; - u32 *piColMask = 0; - if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){ - pExpr->iTable = pTriggerStack->newIdx; - assert( pTriggerStack->pTab ); - pTab = pTriggerStack->pTab; - piColMask = &(pTriggerStack->newColMask); - }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){ - pExpr->iTable = pTriggerStack->oldIdx; - assert( pTriggerStack->pTab ); - pTab = pTriggerStack->pTab; - piColMask = &(pTriggerStack->oldColMask); + assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); + if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ + pExpr->iTable = 1; + pTab = pParse->pTriggerTab; + }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ + pExpr->iTable = 0; + pTab = pParse->pTriggerTab; } if( pTab ){ int iCol; - Column *pCol = pTab->aCol; - pSchema = pTab->pSchema; cntTab++; - for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) { - if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ - cnt++; - pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol; - pExpr->pTab = pTab; - if( iCol>=0 ){ - testcase( iCol==31 ); - testcase( iCol==32 ); - *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0); - } - break; - } + if( sqlite3IsRowid(zCol) ){ + iCol = -1; + }else{ + for(iCol=0; iCol<pTab->nCol; iCol++){ + Column *pCol = &pTab->aCol[iCol]; + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + if( iCol==pTab->iPKey ){ + iCol = -1; + } + break; + } + } + } + if( iCol<pTab->nCol ){ + cnt++; + if( iCol<0 ){ + pExpr->affinity = SQLITE_AFF_INTEGER; + }else if( pExpr->iTable==0 ){ + testcase( iCol==31 ); + testcase( iCol==32 ); + pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); + } + pExpr->iColumn = (i16)iCol; + pExpr->pTab = pTab; + isTrigger = 1; } } } #endif /* !defined(SQLITE_OMIT_TRIGGER) */ @@ -56241,18 +58849,17 @@ assert( pExpr->x.pList==0 ); assert( pExpr->x.pSelect==0 ); pOrig = pEList->a[j].pExpr; if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); - sqlite3DbFree(db, zCol); - return 2; + return WRC_Abort; } resolveAlias(pParse, pEList, j, pExpr, ""); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); - goto lookupname_end_2; + goto lookupname_end; } } } /* Advance to the next name context. The loop will exit when either @@ -56271,15 +58878,14 @@ ** pExpr. ** ** Because no reference was made to outer contexts, the pNC->nRef ** fields are not changed in any context. */ - if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ - sqlite3DbFree(db, zCol); + if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ pExpr->op = TK_STRING; pExpr->pTab = 0; - return 0; + return WRC_Prune; } /* ** cnt==0 means there was not match. cnt>1 means there were two or ** more matches. Either way, we have an error. @@ -56311,22 +58917,18 @@ } assert( pMatch->iCursor==pExpr->iTable ); pMatch->colUsed |= ((Bitmask)1)<<n; } -lookupname_end: /* Clean up and return */ - sqlite3DbFree(db, zDb); - sqlite3DbFree(db, zTab); sqlite3ExprDelete(db, pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; - pExpr->op = TK_COLUMN; -lookupname_end_2: - sqlite3DbFree(db, zCol); + pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); +lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); /* Increment the nRef value on all name contexts from TopNC up to ** the point where the name matched. */ @@ -56334,13 +58936,13 @@ assert( pTopNC!=0 ); pTopNC->nRef++; if( pTopNC==pNC ) break; pTopNC = pTopNC->pNext; } - return 0; + return WRC_Prune; } else { - return 1; + return WRC_Abort; } } /* ** This routine is callback for sqlite3WalkExpr(). @@ -56395,37 +58997,35 @@ #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ /* A lone identifier is the name of a column. */ case TK_ID: { - lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr); - return WRC_Prune; + return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); } /* A table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID */ case TK_DOT: { - Token *pColumn; - Token *pTable; - Token *pDb; + const char *zColumn; + const char *zTable; + const char *zDb; Expr *pRight; /* if( pSrcList==0 ) break; */ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ - pDb = 0; - pTable = &pExpr->pLeft->token; - pColumn = &pRight->token; + zDb = 0; + zTable = pExpr->pLeft->u.zToken; + zColumn = pRight->u.zToken; }else{ assert( pRight->op==TK_DOT ); - pDb = &pExpr->pLeft->token; - pTable = &pRight->pLeft->token; - pColumn = &pRight->pRight->token; - } - lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); - return WRC_Prune; + zDb = pExpr->pLeft->u.zToken; + zTable = pRight->pLeft->u.zToken; + zColumn = pRight->pRight->u.zToken; + } + return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); } /* Resolve function names */ case TK_CONST_FUNC: @@ -56439,13 +59039,14 @@ int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ + testcase( pExpr->op==TK_CONST_FUNC ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - zId = (char*)pExpr->token.z; - nId = pExpr->token.n; + zId = pExpr->u.zToken; + nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); if( pDef==0 ){ no_such_func = 1; @@ -56493,13 +59094,14 @@ */ return WRC_Prune; } #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: - case TK_EXISTS: + case TK_EXISTS: testcase( pExpr->op==TK_EXISTS ); #endif case TK_IN: { + testcase( pExpr->op==TK_IN ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ int nRef = pNC->nRef; #ifndef SQLITE_OMIT_CHECK if( pNC->isCheck ){ sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); @@ -56542,24 +59144,20 @@ ExprList *pEList, /* List of expressions to scan */ Expr *pE /* Expression we are trying to match */ ){ int i; /* Loop counter */ - if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){ - sqlite3 *db = pParse->db; - char *zCol = sqlite3NameFromToken(db, &pE->token); - if( zCol==0 ){ - return -1; - } + UNUSED_PARAMETER(pParse); + + if( pE->op==TK_ID ){ + char *zCol = pE->u.zToken; for(i=0; i<pEList->nExpr; i++){ char *zAs = pEList->a[i].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ - sqlite3DbFree(db, zCol); return i+1; } } - sqlite3DbFree(db, zCol); } return 0; } /* @@ -56684,11 +59282,11 @@ int iCol = -1; Expr *pE, *pDup; if( pItem->done ) continue; pE = pItem->pExpr; if( sqlite3ExprIsInteger(pE, &iCol) ){ - if( iCol<0 || iCol>pEList->nExpr ){ + if( iCol<=0 || iCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); return 1; } }else{ iCol = resolveAsName(pParse, pEList, pE); @@ -56698,23 +59296,20 @@ assert(pDup); iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); } sqlite3ExprDelete(db, pDup); } - if( iCol<0 ){ - return 1; - } } if( iCol>0 ){ CollSeq *pColl = pE->pColl; int flags = pE->flags & EP_ExpCollate; sqlite3ExprDelete(db, pE); - pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0, 0, 0); + pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); if( pE==0 ) return 1; pE->pColl = pColl; pE->flags |= EP_IntValue | flags; - pE->iTable = iCol; + pE->u.iValue = iCol; pItem->iCol = (u16)iCol; pItem->done = 1; }else{ moreToDo = 1; } @@ -56807,13 +59402,10 @@ nResult = pSelect->pEList->nExpr; pParse = pNC->pParse; for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ Expr *pE = pItem->pExpr; iCol = resolveAsName(pParse, pSelect->pEList, pE); - if( iCol<0 ){ - return 1; /* OOM error */ - } if( iCol>0 ){ /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to ** sqlite3ResolveOrderGroupBy() will convert the expression to a ** copy of the iCol-th result-set expression. */ @@ -57084,11 +59676,11 @@ w.u.pNC = pNC; sqlite3WalkExpr(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 pNC->pParse->nHeight -= pExpr->nHeight; #endif - if( pNC->nErr>0 ){ + if( pNC->nErr>0 || w.pParse->nErr>0 ){ ExprSetProperty(pExpr, EP_Error); } if( pNC->hasAgg ){ ExprSetProperty(pExpr, EP_Agg); }else if( savedHasAgg ){ @@ -57138,12 +59730,10 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. -** -** $Id: expr.c,v 1.426 2009/04/08 13:51:51 drh Exp $ */ /* ** Return the 'affinity' of the expression pExpr if any. ** @@ -57166,11 +59756,12 @@ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ - return sqlite3AffinityType(&pExpr->token); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + return sqlite3AffinityType(pExpr->u.zToken); } #endif if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) && pExpr->pTab!=0 ){ @@ -57195,11 +59786,11 @@ char *zColl = 0; /* Dequoted name of collation sequence */ CollSeq *pColl; sqlite3 *db = pParse->db; zColl = sqlite3NameFromToken(db, pCollName); if( pExpr && zColl ){ - pColl = sqlite3LocateCollSeq(pParse, zColl, -1); + pColl = sqlite3LocateCollSeq(pParse, zColl); if( pColl ){ pExpr->pColl = pColl; pExpr->flags |= EP_ExpCollate; } } @@ -57212,24 +59803,26 @@ ** there is no default collation type, return 0. */ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ CollSeq *pColl = 0; Expr *p = pExpr; - while( p ){ + while( ALWAYS(p) ){ int op; pColl = p->pColl; if( pColl ) break; op = p->op; - if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){ + if( p->pTab!=0 && ( + op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER + )){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ const char *zColl; int j = p->iColumn; if( j>=0 ){ sqlite3 *db = pParse->db; zColl = p->pTab->aCol[j].zColl; - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0); + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); pExpr->pColl = pColl; } break; } if( op!=TK_CAST && op!=TK_UPLUS ){ @@ -57502,117 +60095,138 @@ #else #define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ /* +** This routine is the core allocator for Expr nodes. +** ** Construct a new expression node and return a pointer to it. Memory -** for this node is obtained from sqlite3_malloc(). The calling function +** for this node and for the pToken argument is a single allocation +** obtained from sqlite3DbMalloc(). The calling function ** is responsible for making sure the node eventually gets freed. -*/ -SQLITE_PRIVATE Expr *sqlite3Expr( +** +** If dequote is true, then the token (if it exists) is dequoted. +** If dequote is false, no dequoting is performance. The deQuote +** parameter is ignored if pToken is NULL or if the token does not +** appear to be quoted. If the quotes were of the form "..." (double-quotes) +** then the EP_DblQuoted flag is set on the expression node. +** +** Special case: If op==TK_INTEGER and pToken points to a string that +** can be translated into a 32-bit integer, then the token is not +** stored in u.zToken. Instead, the integer values is written +** into u.iValue and the EP_IntValue flag is set. No extra storage +** is allocated to hold the integer text and the dequote flag is ignored. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprAlloc( sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ int op, /* Expression opcode */ - Expr *pLeft, /* Left operand */ - Expr *pRight, /* Right operand */ - const Token *pToken /* Argument token */ + const Token *pToken, /* Token argument. Might be NULL */ + int dequote /* True to dequote */ ){ Expr *pNew; - pNew = sqlite3DbMallocZero(db, sizeof(Expr)); - if( pNew==0 ){ - /* When malloc fails, delete pLeft and pRight. Expressions passed to - ** this function must always be allocated with sqlite3Expr() for this - ** reason. - */ - sqlite3ExprDelete(db, pLeft); - sqlite3ExprDelete(db, pRight); - return 0; - } - pNew->op = (u8)op; - pNew->pLeft = pLeft; - pNew->pRight = pRight; - pNew->iAgg = -1; - pNew->span.z = (u8*)""; + int nExtra = 0; + int iValue = 0; + if( pToken ){ - int c; - assert( pToken->dyn==0 ); - pNew->span = *pToken; - - /* The pToken->z value is read-only. But the new expression - ** node created here might be passed to sqlite3DequoteExpr() which - ** will attempt to modify pNew->token.z. Hence, if the token - ** is quoted, make a copy now so that DequoteExpr() will change - ** the copy rather than the original text. - */ - if( pToken->n>=2 - && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ - sqlite3TokenCopy(db, &pNew->token, pToken); - }else{ - pNew->token = *pToken; - pNew->flags |= EP_Dequoted; - VVA_ONLY( pNew->vvaFlags |= EVVA_ReadOnlyToken; ) - } - }else if( pLeft ){ - if( pRight ){ - if( pRight->span.dyn==0 && pLeft->span.dyn==0 ){ - sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span); - } - if( pRight->flags & EP_ExpCollate ){ - pNew->flags |= EP_ExpCollate; - pNew->pColl = pRight->pColl; - } - } - if( pLeft->flags & EP_ExpCollate ){ - pNew->flags |= EP_ExpCollate; - pNew->pColl = pLeft->pColl; - } - } - - exprSetHeight(pNew); + if( op!=TK_INTEGER || pToken->z==0 + || sqlite3GetInt32(pToken->z, &iValue)==0 ){ + nExtra = pToken->n+1; + } + } + pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra); + if( pNew ){ + pNew->op = (u8)op; + pNew->iAgg = -1; + if( pToken ){ + if( nExtra==0 ){ + pNew->flags |= EP_IntValue; + pNew->u.iValue = iValue; + }else{ + int c; + pNew->u.zToken = (char*)&pNew[1]; + memcpy(pNew->u.zToken, pToken->z, pToken->n); + pNew->u.zToken[pToken->n] = 0; + if( dequote && nExtra>=3 + && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ + sqlite3Dequote(pNew->u.zToken); + if( c=='"' ) pNew->flags |= EP_DblQuoted; + } + } + } +#if SQLITE_MAX_EXPR_DEPTH>0 + pNew->nHeight = 1; +#endif + } return pNew; } /* -** Works like sqlite3Expr() except that it takes an extra Parse* -** argument and notifies the associated connection object if malloc fails. +** Allocate a new expression node from a zero-terminated token that has +** already been dequoted. +*/ +SQLITE_PRIVATE Expr *sqlite3Expr( + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + int op, /* Expression opcode */ + const char *zToken /* Token argument. Might be NULL */ +){ + Token x; + x.z = zToken; + x.n = zToken ? sqlite3Strlen30(zToken) : 0; + return sqlite3ExprAlloc(db, op, &x, 0); +} + +/* +** Attach subtrees pLeft and pRight to the Expr node pRoot. +** +** If pRoot==NULL that means that a memory allocation error has occurred. +** In that case, delete the subtrees pLeft and pRight. +*/ +SQLITE_PRIVATE void sqlite3ExprAttachSubtrees( + sqlite3 *db, + Expr *pRoot, + Expr *pLeft, + Expr *pRight +){ + if( pRoot==0 ){ + assert( db->mallocFailed ); + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + }else{ + if( pRight ){ + pRoot->pRight = pRight; + if( pRight->flags & EP_ExpCollate ){ + pRoot->flags |= EP_ExpCollate; + pRoot->pColl = pRight->pColl; + } + } + if( pLeft ){ + pRoot->pLeft = pLeft; + if( pLeft->flags & EP_ExpCollate ){ + pRoot->flags |= EP_ExpCollate; + pRoot->pColl = pLeft->pColl; + } + } + exprSetHeight(pRoot); + } +} + +/* +** Allocate a Expr node which joins as many as two subtrees. +** +** One or both of the subtrees can be NULL. Return a pointer to the new +** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed, +** free the subtrees and return NULL. */ SQLITE_PRIVATE Expr *sqlite3PExpr( Parse *pParse, /* Parsing context */ int op, /* Expression opcode */ Expr *pLeft, /* Left operand */ Expr *pRight, /* Right operand */ const Token *pToken /* Argument token */ ){ - Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken); - if( p ){ - sqlite3ExprCheckHeight(pParse, p->nHeight); - } - return p; -} - -/* -** When doing a nested parse, you can include terms in an expression -** that look like this: #1 #2 ... These terms refer to registers -** in the virtual machine. #N is the N-th register. -** -** This routine is called by the parser to deal with on of those terms. -** It immediately generates code to store the value in a memory location. -** The returns an expression that will code to extract the value from -** that memory location as needed. -*/ -SQLITE_PRIVATE Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ - Vdbe *v = pParse->pVdbe; - Expr *p; - if( pParse->nested==0 ){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken); - return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); - } - if( v==0 ) return 0; - p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken); - if( p==0 ){ - return 0; /* Malloc failed */ - } - p->iTable = atoi((char*)&pToken->z[1]); + Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); + sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); return p; } /* ** Join two expressions using an AND operator. If either expression is @@ -57622,28 +60236,13 @@ if( pLeft==0 ){ return pRight; }else if( pRight==0 ){ return pLeft; }else{ - return sqlite3Expr(db, TK_AND, pLeft, pRight, 0); - } -} - -/* -** Set the Expr.span field of the given expression to span all -** text between the two given tokens. Both tokens must be pointing -** at the same string. -*/ -SQLITE_PRIVATE void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ - assert( pRight!=0 ); - assert( pLeft!=0 ); - if( pExpr ){ - pExpr->span.z = pLeft->z; - /* The following assert() may fail when this is called - ** via sqlite3PExpr()/sqlite3Expr() from addWhereTerm(). */ - /* assert(pRight->z >= pLeft->z); */ - pExpr->span.n = pRight->n + (unsigned)(pRight->z - pLeft->z); + Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); + sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); + return pNew; } } /* ** Construct a new expression node for a function with multiple @@ -57651,21 +60250,17 @@ */ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ Expr *pNew; sqlite3 *db = pParse->db; assert( pToken ); - pNew = sqlite3DbMallocZero(db, sizeof(Expr) ); + pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); if( pNew==0 ){ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } - pNew->op = TK_FUNCTION; pNew->x.pList = pList; assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - assert( pToken->dyn==0 ); - pNew->span = *pToken; - sqlite3TokenCopy(db, &pNew->token, pToken); sqlite3ExprSetHeight(pParse, pNew); return pNew; } /* @@ -57677,32 +60272,33 @@ ** ** Wildcards of the form "?nnn" are assigned the number "nnn". We make ** sure "nnn" is not too be to avoid a denial of service attack when ** the SQL statement comes from an external source. ** -** Wildcards of the form ":aaa" or "$aaa" are assigned the same number +** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number ** as the previous instance of the same wildcard. Or if this is the first ** instance of the wildcard, the next sequenial variable number is ** assigned. */ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ - Token *pToken; - sqlite3 *db = pParse->db; + sqlite3 *db = pParse->db; + const char *z; if( pExpr==0 ) return; - pToken = &pExpr->token; - assert( pToken->n>=1 ); - assert( pToken->z!=0 ); - assert( pToken->z[0]!=0 ); - if( pToken->n==1 ){ + assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); + z = pExpr->u.zToken; + assert( z!=0 ); + assert( z[0]!=0 ); + if( z[1]==0 ){ /* Wildcard of the form "?". Assign the next variable number */ + assert( z[0]=='?' ); pExpr->iTable = ++pParse->nVar; - }else if( pToken->z[0]=='?' ){ + }else if( z[0]=='?' ){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ int i; - pExpr->iTable = i = atoi((char*)&pToken->z[1]); + pExpr->iTable = i = atoi((char*)&z[1]); testcase( i==0 ); testcase( i==1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); if( i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ @@ -57711,22 +60307,21 @@ } if( i>pParse->nVar ){ pParse->nVar = i; } }else{ - /* Wildcards of the form ":aaa" or "$aaa". Reuse the same variable + /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable ** number as the prior appearance of the same name, or if the name ** has never appeared before, reuse the same variable number */ int i; u32 n; - n = pToken->n; + n = sqlite3Strlen30(z); for(i=0; i<pParse->nVarExpr; i++){ - Expr *pE; - if( (pE = pParse->apVarExpr[i])!=0 - && pE->token.n==n - && memcmp(pE->token.z, pToken->z, n)==0 ){ + Expr *pE = pParse->apVarExpr[i]; + assert( pE!=0 ); + if( memcmp(pE->u.zToken, z, n)==0 && pE->u.zToken[n]==0 ){ pExpr->iTable = pE->iTable; break; } } if( i>=pParse->nVarExpr ){ @@ -57754,23 +60349,17 @@ /* ** Clear an expression structure without deleting the structure itself. ** Substructure is deleted. */ SQLITE_PRIVATE void sqlite3ExprClear(sqlite3 *db, Expr *p){ - if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z); - if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){ - if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z); - if( ExprHasProperty(p, EP_Reduced) ){ - /* Subtrees are part of the same memory allocation when EP_Reduced set */ - if( p->pLeft ) sqlite3ExprClear(db, p->pLeft); - if( p->pRight ) sqlite3ExprClear(db, p->pRight); - }else{ - /* Subtrees are separate allocations when EP_Reduced is clear */ - sqlite3ExprDelete(db, p->pLeft); - sqlite3ExprDelete(db, p->pRight); - } - /* x.pSelect and x.pList are always separately allocated */ + assert( p!=0 ); + if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ + sqlite3ExprDelete(db, p->pLeft); + sqlite3ExprDelete(db, p->pRight); + if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){ + sqlite3DbFree(db, p->u.zToken); + } if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); } @@ -57781,22 +60370,12 @@ ** Recursively delete an expression tree. */ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p==0 ) return; sqlite3ExprClear(db, p); - sqlite3DbFree(db, p); -} - -/* -** The Expr.token field might be a string literal that is quoted. -** If so, remove the quotation marks. -*/ -SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){ - if( !ExprHasAnyProperty(p, EP_Dequoted) ){ - ExprSetProperty(p, EP_Dequoted); - assert( (p->vvaFlags & EVVA_ReadOnlyToken)==0 ); - sqlite3Dequote((char*)p->token.z); + if( !ExprHasProperty(p, EP_Static) ){ + sqlite3DbFree(db, p); } } /* ** Return the number of bytes allocated for the expression structure @@ -57803,48 +60382,76 @@ ** passed as the first argument. This is always one of EXPR_FULLSIZE, ** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. */ static int exprStructSize(Expr *p){ if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE; - if( ExprHasProperty(p, EP_SpanToken) ) return EXPR_SPANTOKENSIZE; if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE; return EXPR_FULLSIZE; } /* -** sqlite3ExprDup() has been called to create a copy of expression p with -** the EXPRDUP_XXX flags passed as the second argument. This function -** returns the space required for the copy of the Expr structure only. -** This is always one of EXPR_FULLSIZE, EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. +** The dupedExpr*Size() routines each return the number of bytes required +** to store a copy of an expression or expression tree. They differ in +** how much of the tree is measured. +** +** dupedExprStructSize() Size of only the Expr structure +** dupedExprNodeSize() Size of Expr + space for token +** dupedExprSize() Expr + token + subtree components +** +*************************************************************************** +** +** The dupedExprStructSize() function returns two values OR-ed together: +** (1) the space required for a copy of the Expr structure only and +** (2) the EP_xxx flags that indicate what the structure size should be. +** The return values is always one of: +** +** EXPR_FULLSIZE +** EXPR_REDUCEDSIZE | EP_Reduced +** EXPR_TOKENONLYSIZE | EP_TokenOnly +** +** The size of the structure can be found by masking the return value +** of this routine with 0xfff. The flags can be found by masking the +** return value with EP_Reduced|EP_TokenOnly. +** +** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size +** (unreduced) Expr objects as they or originally constructed by the parser. +** During expression analysis, extra information is computed and moved into +** later parts of teh Expr object and that extra information might get chopped +** off if the expression is reduced. Note also that it does not work to +** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal +** to reduce a pristine expression tree from the parser. The implementation +** of dupedExprStructSize() contain multiple assert() statements that attempt +** to enforce this constraint. */ static int dupedExprStructSize(Expr *p, int flags){ int nSize; + assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; - }else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ - nSize = EXPR_REDUCEDSIZE; - }else if( flags&EXPRDUP_SPAN ){ - nSize = EXPR_SPANTOKENSIZE; - }else{ - nSize = EXPR_TOKENONLYSIZE; + }else{ + assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(p, EP_FromJoin) ); + assert( (p->flags2 & EP2_MallocedToken)==0 ); + assert( (p->flags2 & EP2_Irreducible)==0 ); + if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ + nSize = EXPR_REDUCEDSIZE | EP_Reduced; + }else{ + nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; + } } return nSize; } /* -** sqlite3ExprDup() has been called to create a copy of expression p with -** the EXPRDUP_XXX passed as the second argument. This function returns -** the space in bytes required to store the copy of the Expr structure -** and the copies of the Expr.token.z and Expr.span.z (if applicable) -** string buffers. +** This function returns the space in bytes required to store the copy +** of the Expr structure and a copy of the Expr.u.zToken string (if that +** string is defined.) */ static int dupedExprNodeSize(Expr *p, int flags){ - int nByte = dupedExprStructSize(p, flags) + (p->token.z ? p->token.n + 1 : 0); - if( (flags&EXPRDUP_SPAN)!=0 - && (p->token.z!=p->span.z || p->token.n!=p->span.n) - ){ - nByte += p->span.n; + int nByte = dupedExprStructSize(p, flags) & 0xfff; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nByte += sqlite3Strlen30(p->u.zToken)+1; } return ROUND8(nByte); } /* @@ -57851,13 +60458,11 @@ ** Return the number of bytes required to create a duplicate of the ** expression passed as the first argument. The second argument is a ** mask containing EXPRDUP_XXX flags. ** ** The value returned includes space to create a copy of the Expr struct -** itself and the buffer referred to by Expr.token, if any. If the -** EXPRDUP_SPAN flag is set, then space to create a copy of the buffer -** refered to by Expr.span is also included. +** itself and the buffer referred to by Expr.u.zToken, if any. ** ** If the EXPRDUP_REDUCE flag is set, then the return value includes ** space to duplicate all Expr nodes in the tree formed by Expr.pLeft ** and Expr.pRight variables (but not for any structures pointed to or ** descended from the Expr.x.pList or Expr.x.pSelect variables). @@ -57865,116 +60470,103 @@ static int dupedExprSize(Expr *p, int flags){ int nByte = 0; if( p ){ nByte = dupedExprNodeSize(p, flags); if( flags&EXPRDUP_REDUCE ){ - int f = flags&(~EXPRDUP_SPAN); - nByte += dupedExprSize(p->pLeft, f) + dupedExprSize(p->pRight, f); + nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); } } return nByte; } /* ** This function is similar to sqlite3ExprDup(), except that if pzBuffer ** is not NULL then *pzBuffer is assumed to point to a buffer large enough -** to store the copy of expression p, the copies of p->token and p->span +** to store the copy of expression p, the copies of p->u.zToken ** (if applicable), and the copies of the p->pLeft and p->pRight expressions, ** if any. Before returning, *pzBuffer is set to the first byte passed the ** portion of the buffer copied into by this function. */ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ Expr *pNew = 0; /* Value to return */ if( p ){ - const int isRequireSpan = (flags&EXPRDUP_SPAN); const int isReduced = (flags&EXPRDUP_REDUCE); u8 *zAlloc; + u32 staticFlag = 0; assert( pzBuffer==0 || isReduced ); /* Figure out where to write the new Expr structure. */ if( pzBuffer ){ zAlloc = *pzBuffer; + staticFlag = EP_Static; }else{ zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); } pNew = (Expr *)zAlloc; if( pNew ){ /* Set nNewSize to the size allocated for the structure pointed to ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed - ** by the copy of the p->token.z string (if any). - */ - const int nNewSize = dupedExprStructSize(p, flags); - const int nToken = (p->token.z ? p->token.n + 1 : 0); + ** by the copy of the p->u.zToken string (if any). + */ + const unsigned nStructSize = dupedExprStructSize(p, flags); + const int nNewSize = nStructSize & 0xfff; + int nToken; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30(p->u.zToken) + 1; + }else{ + nToken = 0; + } if( isReduced ){ assert( ExprHasProperty(p, EP_Reduced)==0 ); memcpy(zAlloc, p, nNewSize); }else{ int nSize = exprStructSize(p); memcpy(zAlloc, p, nSize); memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize); } - /* Set the EP_Reduced and EP_TokenOnly flags appropriately. */ - pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_SpanToken); - switch( nNewSize ){ - case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break; - case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break; - case EXPR_SPANTOKENSIZE: pNew->flags |= EP_SpanToken; break; - } - - /* Copy the p->token string, if any. */ + /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); + pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); + pNew->flags |= staticFlag; + + /* Copy the p->u.zToken string, if any. */ if( nToken ){ - unsigned char *zToken = &zAlloc[nNewSize]; - memcpy(zToken, p->token.z, nToken-1); - zToken[nToken-1] = '\0'; - pNew->token.dyn = 0; - pNew->token.z = zToken; - } - - if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ - /* Fill in the pNew->span token, if required. */ - if( isRequireSpan ){ - if( p->token.z!=p->span.z || p->token.n!=p->span.n ){ - pNew->span.z = &zAlloc[nNewSize+nToken]; - memcpy((char *)pNew->span.z, p->span.z, p->span.n); - pNew->span.dyn = 0; - }else{ - pNew->span.z = pNew->token.z; - pNew->span.n = pNew->token.n; - } - }else{ - pNew->span.z = 0; - pNew->span.n = 0; - } - } - - if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_SpanToken)) ){ + char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + memcpy(zToken, p->u.zToken, nToken); + } + + if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ if( ExprHasProperty(p, EP_xIsSelect) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced); }else{ pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced); } } /* Fill in pNew->pLeft and pNew->pRight. */ - if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly|EP_SpanToken) ){ + if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){ zAlloc += dupedExprNodeSize(p, flags); if( ExprHasProperty(pNew, EP_Reduced) ){ pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc); pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc); } if( pzBuffer ){ *pzBuffer = zAlloc; } - }else if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){ - pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); - pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); - } + }else{ + pNew->flags2 = 0; + if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ + pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); + pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); + } + } + } } return pNew; } @@ -57988,32 +60580,17 @@ ** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded ** by subsequent calls to sqlite*ListAppend() routines. ** ** Any tables that the SrcList might point to are not duplicated. ** -** The flags parameter contains a combination of the EXPRDUP_XXX flags. If -** the EXPRDUP_SPAN flag is set in the argument parameter, then the -** Expr.span field of the input expression is copied. If EXPRDUP_SPAN is -** clear, then the Expr.span field of the returned expression structure -** is zeroed. -** +** The flags parameter contains a combination of the EXPRDUP_XXX flags. ** If the EXPRDUP_REDUCE flag is set, then the structure returned is a ** truncated version of the usual Expr structure that will be stored as ** part of the in-memory representation of the database schema. */ SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){ return exprDup(db, p, flags, 0); -} -SQLITE_PRIVATE void sqlite3TokenCopy(sqlite3 *db, Token *pTo, const Token *pFrom){ - if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z); - if( pFrom->z ){ - pTo->n = pFrom->n; - pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n); - pTo->dyn = 1; - }else{ - pTo->z = 0; - } } SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; struct ExprList_item *pItem, *pOldItem; int i; @@ -58027,14 +60604,14 @@ sqlite3DbFree(db, pNew); return 0; } pOldItem = p->a; for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){ - Expr *pNewExpr; Expr *pOldExpr = pOldItem->pExpr; - pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr, flags); + pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags); pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); pItem->sortOrder = pOldItem->sortOrder; pItem->done = 0; pItem->iCol = pOldItem->iCol; pItem->iAlias = pOldItem->iAlias; } @@ -58105,14 +60682,11 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ Select *pNew; if( p==0 ) return 0; pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); if( pNew==0 ) return 0; - /* Always make a copy of the span for top-level expressions in the - ** expression list. The logic in SELECT processing that determines - ** the names of columns in the result set needs this information */ - pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags|EXPRDUP_SPAN); + pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags); pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags); @@ -58138,16 +60712,19 @@ /* ** Add a new element to the end of an expression list. If pList is ** initially NULL, then create a new expression list. +** +** If a memory allocation error occurs, the entire list is freed and +** NULL is returned. If non-NULL is returned, then it is guaranteed +** that the new entry was successfully appended. */ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to append. Might be NULL */ - Expr *pExpr, /* Expression to be appended */ - Token *pName /* AS keyword for the expression */ + Expr *pExpr /* Expression to be appended. Might be NULL */ ){ sqlite3 *db = pParse->db; if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(ExprList) ); if( pList==0 ){ @@ -58164,24 +60741,72 @@ } pList->a = a; pList->nAlloc = sqlite3DbMallocSize(db, a)/sizeof(a[0]); } assert( pList->a!=0 ); - if( pExpr || pName ){ + if( 1 ){ struct ExprList_item *pItem = &pList->a[pList->nExpr++]; memset(pItem, 0, sizeof(*pItem)); - pItem->zName = sqlite3NameFromToken(db, pName); - pItem->pExpr = pExpr; - pItem->iAlias = 0; + pItem->pExpr = pExpr; } return pList; no_mem: /* Avoid leaking memory if malloc has failed. */ sqlite3ExprDelete(db, pExpr); sqlite3ExprListDelete(db, pList); return 0; +} + +/* +** Set the ExprList.a[].zName element of the most recently added item +** on the expression list. +** +** pList might be NULL following an OOM error. But pName should never be +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag +** is set. +*/ +SQLITE_PRIVATE void sqlite3ExprListSetName( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to add the span. */ + Token *pName, /* Name to be added */ + int dequote /* True to cause the name to be dequoted */ +){ + assert( pList!=0 || pParse->db->mallocFailed!=0 ); + if( pList ){ + struct ExprList_item *pItem; + assert( pList->nExpr>0 ); + pItem = &pList->a[pList->nExpr-1]; + assert( pItem->zName==0 ); + pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); + if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName); + } +} + +/* +** Set the ExprList.a[].zSpan element of the most recently added item +** on the expression list. +** +** pList might be NULL following an OOM error. But pSpan should never be +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag +** is set. +*/ +SQLITE_PRIVATE void sqlite3ExprListSetSpan( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to add the span. */ + ExprSpan *pSpan /* The span to be added */ +){ + sqlite3 *db = pParse->db; + assert( pList!=0 || db->mallocFailed!=0 ); + if( pList ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; + assert( pList->nExpr>0 ); + assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); + sqlite3DbFree(db, pItem->zSpan); + pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + (int)(pSpan->zEnd - pSpan->zStart)); + } } /* ** If the expression list pEList contains more than iLimit elements, ** leave an error message in pParse. @@ -58209,10 +60834,11 @@ assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); assert( pList->nExpr<=pList->nAlloc ); for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ sqlite3ExprDelete(db, pItem->pExpr); sqlite3DbFree(db, pItem->zName); + sqlite3DbFree(db, pItem->zSpan); } sqlite3DbFree(db, pList->a); sqlite3DbFree(db, pList); } @@ -58247,23 +60873,19 @@ /* Fall through */ case TK_ID: case TK_COLUMN: case TK_AGG_FUNCTION: case TK_AGG_COLUMN: -#ifndef SQLITE_OMIT_SUBQUERY - case TK_SELECT: - case TK_EXISTS: - testcase( pExpr->op==TK_SELECT ); - testcase( pExpr->op==TK_EXISTS ); -#endif testcase( pExpr->op==TK_ID ); testcase( pExpr->op==TK_COLUMN ); testcase( pExpr->op==TK_AGG_FUNCTION ); testcase( pExpr->op==TK_AGG_COLUMN ); pWalker->u.i = 0; return WRC_Abort; default: + testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */ + testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */ return WRC_Continue; } } static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ UNUSED_PARAMETER(NotUsed); @@ -58321,16 +60943,17 @@ ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){ int rc = 0; if( p->flags & EP_IntValue ){ - *pValue = p->iTable; + *pValue = p->u.iValue; return 1; } switch( p->op ){ case TK_INTEGER: { - rc = sqlite3GetInt32((char*)p->token.z, pValue); + rc = sqlite3GetInt32(p->u.zToken, pValue); + assert( rc==0 ); break; } case TK_UPLUS: { rc = sqlite3ExprIsInteger(p->pLeft, pValue); break; @@ -58344,13 +60967,15 @@ break; } default: break; } if( rc ){ + assert( ExprHasAnyProperty(p, EP_Reduced|EP_TokenOnly) + || (p->flags2 & EP2_MallocedToken)==0 ); p->op = TK_INTEGER; p->flags |= EP_IntValue; - p->iTable = *pValue; + p->u.iValue = *pValue; } return rc; } /* @@ -58362,40 +60987,44 @@ if( sqlite3StrICmp(z, "OID")==0 ) return 1; return 0; } /* -** Return true if the IN operator optimization is enabled and -** the SELECT statement p exists and is of the -** simple form: -** -** SELECT <column> FROM <table> -** -** If this is the case, it may be possible to use an existing table -** or index instead of generating an epheremal table. +** Return true if we are able to the IN operator optimization on a +** query of the form +** +** x IN (SELECT ...) +** +** Where the SELECT... clause is as specified by the parameter to this +** routine. +** +** The Select object passed in has already been preprocessed and no +** errors have been found. */ #ifndef SQLITE_OMIT_SUBQUERY static int isCandidateForInOpt(Select *p){ SrcList *pSrc; ExprList *pEList; Table *pTab; if( p==0 ) return 0; /* right-hand side of IN is SELECT */ if( p->pPrior ) return 0; /* Not a compound SELECT */ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ - return 0; /* No DISTINCT keyword and no aggregate functions */ - } - if( p->pGroupBy ) return 0; /* Has no GROUP BY clause */ + testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); + testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); + return 0; /* No DISTINCT keyword and no aggregate functions */ + } + assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ if( p->pLimit ) return 0; /* Has no LIMIT clause */ - if( p->pOffset ) return 0; + assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */ if( p->pWhere ) return 0; /* Has no WHERE clause */ pSrc = p->pSrc; assert( pSrc!=0 ); if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ - if( pSrc->a[0].pSelect ) return 0; /* FROM clause is not a subquery */ + if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ pTab = pSrc->a[0].pTab; - if( pTab==0 ) return 0; - if( pTab->pSelect ) return 0; /* FROM clause is not a view */ + if( NEVER(pTab==0) ) return 0; + assert( pTab->pSelect==0 ); /* FROM clause is not a view */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */ return 1; @@ -58406,49 +61035,49 @@ ** This function is used by the implementation of the IN (...) operator. ** It's job is to find or create a b-tree structure that may be used ** either to test for membership of the (...) set or to iterate through ** its members, skipping duplicates. ** -** The cursor opened on the structure (database table, database index +** The index of the cursor opened on the b-tree (database table, database index ** or ephermal table) is stored in pX->iTable before this function returns. -** The returned value indicates the structure type, as follows: +** The returned value of this function indicates the b-tree type, as follows: ** ** IN_INDEX_ROWID - The cursor was opened on a database table. ** IN_INDEX_INDEX - The cursor was opened on a database index. ** IN_INDEX_EPH - The cursor was opened on a specially created and ** populated epheremal table. ** -** An existing structure may only be used if the SELECT is of the simple +** An existing b-tree may only be used if the SELECT is of the simple ** form: ** ** SELECT <column> FROM <table> ** -** If prNotFound parameter is 0, then the structure will be used to iterate +** If the prNotFound parameter is 0, then the b-tree will be used to iterate ** through the set members, skipping any duplicates. In this case an ** epheremal table must be used unless the selected <column> is guaranteed ** to be unique - either because it is an INTEGER PRIMARY KEY or it -** is unique by virtue of a constraint or implicit index. -** -** If the prNotFound parameter is not 0, then the structure will be used +** has a UNIQUE constraint or UNIQUE index. +** +** If the prNotFound parameter is not 0, then the b-tree will be used ** for fast set membership tests. In this case an epheremal table must ** be used unless <column> is an INTEGER PRIMARY KEY or an index can ** be found with <column> as its left-most column. ** -** When the structure is being used for set membership tests, the user +** When the b-tree is being used for membership tests, the calling function ** needs to know whether or not the structure contains an SQL NULL ** value in order to correctly evaluate expressions like "X IN (Y, Z)". -** If there is a chance that the structure may contain a NULL value at +** If there is a chance that the b-tree might contain a NULL value at ** runtime, then a register is allocated and the register number written -** to *prNotFound. If there is no chance that the structure contains a +** to *prNotFound. If there is no chance that the b-tree contains a ** NULL value, then *prNotFound is left unchanged. ** ** If a register is allocated and its location stored in *prNotFound, then -** its initial value is NULL. If the structure does not remain constant -** for the duration of the query (i.e. the set is a correlated sub-select), -** the value of the allocated register is reset to NULL each time the -** structure is repopulated. This allows the caller to use vdbe code -** equivalent to the following: +** its initial value is NULL. If the b-tree does not remain constant +** for the duration of the query (i.e. the SELECT that generates the b-tree +** is a correlated subquery) then the value of the allocated register is +** reset to NULL each time the b-tree is repopulated. This allows the +** caller to use vdbe code equivalent to the following: ** ** if( register==NULL ){ ** has_null = <test if data structure contains null> ** register = 1 ** } @@ -58456,25 +61085,21 @@ ** in order to avoid running the <test if data structure contains null> ** test more often than is necessary. */ #ifndef SQLITE_OMIT_SUBQUERY SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ - Select *p; - int eType = 0; - int iTab = pParse->nTab++; - int mustBeUnique = !prNotFound; - - /* The follwing if(...) expression is true if the SELECT is of the - ** simple form: - ** - ** SELECT <column> FROM <table> - ** - ** If this is the case, it may be possible to use an existing table - ** or index instead of generating an epheremal table. + Select *p; /* SELECT to the right of IN operator */ + int eType = 0; /* Type of RHS table. IN_INDEX_* */ + int iTab = pParse->nTab++; /* Cursor of the RHS table */ + int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */ + + /* Check to see if an existing table or index can be used to + ** satisfy the query. This is preferable to generating a new + ** ephemeral table. */ p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); - if( isCandidateForInOpt(p) ){ + if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ sqlite3 *db = pParse->db; /* Database connection */ Expr *pExpr = p->pEList->a[0].pExpr; /* Expression <column> */ int iCol = pExpr->iColumn; /* Index of column <column> */ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ Table *pTab = p->pSrc->a[0].pTab; /* Table <table>. */ @@ -58491,11 +61116,10 @@ */ assert(v); if( iCol<0 ){ int iMem = ++pParse->nMem; int iAddr; - sqlite3VdbeUsesBtree(v, iDb); iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); @@ -58517,21 +61141,18 @@ char aff = comparisonAffinity(pX); int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE); for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ if( (pIdx->aiColumn[0]==iCol) - && (pReq==sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], -1, 0)) + && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) ){ int iMem = ++pParse->nMem; int iAddr; char *pKey; pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); - iDb = sqlite3SchemaToIndex(db, pIdx->pSchema); - sqlite3VdbeUsesBtree(v, iDb); - iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, pKey,P4_KEYINFO_HANDOFF); @@ -58546,10 +61167,13 @@ } } } if( eType==0 ){ + /* Could not found an existing able or index to use as the RHS b-tree. + ** We will have to generate an ephemeral table to do the job. + */ int rMayHaveNull = 0; eType = IN_INDEX_EPH; if( prNotFound ){ *prNotFound = rMayHaveNull = ++pParse->nMem; }else if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){ @@ -58578,22 +61202,34 @@ ** If parameter isRowid is non-zero, then expression pExpr is guaranteed ** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference ** to some integer key column of a table B-Tree. In this case, use an ** intkey B-Tree to store the set of IN(...) values instead of the usual ** (slower) variable length keys B-Tree. +** +** If rMayHaveNull is non-zero, that means that the operation is an IN +** (not a SELECT or EXISTS) and that the RHS might contains NULLs. +** Furthermore, the IN is in a WHERE clause and that we really want +** to iterate over the RHS of the IN operator in order to quickly locate +** all corresponding LHS elements. All this routine does is initialize +** the register given by rMayHaveNull to NULL. Calling routines will take +** care of changing this register value to non-NULL if the RHS is NULL-free. +** +** If rMayHaveNull is zero, that means that the subquery is being used +** for membership testing only. There is no need to initialize any +** registers to indicate the presense or absence of NULLs on the RHS. */ #ifndef SQLITE_OMIT_SUBQUERY SQLITE_PRIVATE void sqlite3CodeSubselect( - Parse *pParse, - Expr *pExpr, - int rMayHaveNull, - int isRowid + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* The IN, SELECT, or EXISTS operator */ + int rMayHaveNull, /* Register that records whether NULLs exist in RHS */ + int isRowid /* If true, LHS of IN operator is a rowid */ ){ int testAddr = 0; /* One-time test address */ Vdbe *v = sqlite3GetVdbe(pParse); - if( v==0 ) return; - + if( NEVER(v==0) ) return; + sqlite3ExprCachePush(pParse); /* This code must be run in its entirety every time it is encountered ** if any of the following is true: ** ** * The right-hand side is a correlated subquery @@ -58601,11 +61237,11 @@ ** * We are inside a trigger ** ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ - if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){ + if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){ int mem = ++pParse->nMem; sqlite3VdbeAddOp1(v, OP_If, mem); testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem); assert( testAddr>0 || pParse->db->mallocFailed ); } @@ -58656,15 +61292,15 @@ assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){ return; } pEList = pExpr->x.pSelect->pEList; - if( pEList && pEList->nExpr>0 ){ + if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){ keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pEList->a[0].pExpr); } - }else if( pExpr->x.pList ){ + }else if( pExpr->x.pList!=0 ){ /* Case 2: expr IN (exprlist) ** ** For each expression, build an index key from the evaluation and ** store it in the temporary table. If <expr> is a column, then use ** that columns affinity when building index keys. If <expr> is not @@ -58696,15 +61332,11 @@ sqlite3VdbeChangeToNoop(v, testAddr-1, 2); testAddr = 0; } /* Evaluate the expression and insert it into the temp table */ - pParse->disableColCache++; - r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); - assert( pParse->disableColCache>0 ); - pParse->disableColCache--; - + r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); if( isRowid ){ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); @@ -58720,18 +61352,25 @@ } break; } case TK_EXISTS: - case TK_SELECT: { - /* This has to be a scalar SELECT. Generate code to put the + case TK_SELECT: + default: { + /* If this has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number - ** of the memory cell in iColumn. - */ - static const Token one = { (u8*)"1", 0, 1 }; - Select *pSel; - SelectDest dest; + ** of the memory cell in iColumn. If this is an EXISTS, write + ** an integer 0 (not exists) or 1 (exists) into a memory cell + ** and record that memory cell in iColumn. + */ + static const Token one = { "1", 1 }; /* Token for literal value 1 */ + Select *pSel; /* SELECT statement to encode */ + SelectDest dest; /* How to deal with SELECt result */ + + testcase( pExpr->op==TK_EXISTS ); + testcase( pExpr->op==TK_SELECT ); + assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); assert( ExprHasProperty(pExpr, EP_xIsSelect) ); pSel = pExpr->x.pSelect; sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); if( pExpr->op==TK_SELECT ){ @@ -58746,18 +61385,20 @@ sqlite3ExprDelete(pParse->db, pSel->pLimit); pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); if( sqlite3Select(pParse, pSel, &dest) ){ return; } - pExpr->iColumn = dest.iParm; + pExpr->iColumn = (i16)dest.iParm; + ExprSetIrreducible(pExpr); break; } } if( testAddr ){ sqlite3VdbeJumpHere(v, testAddr-1); } + sqlite3ExprCachePop(pParse, 1); return; } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -58778,25 +61419,19 @@ ** ** The z[] string will probably not be zero-terminated. But the ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ -static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){ - assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed ); - assert( !z || !sqlite3Isdigit(z[n]) ); - UNUSED_PARAMETER(n); - if( z ){ +static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ + if( ALWAYS(z!=0) ){ double value; char *zV; sqlite3AtoF(z, &value); - if( sqlite3IsNaN(value) ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, iMem); - }else{ - if( negateFlag ) value = -value; - zV = dup8bytes(v, (char*)&value); - sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); - } + assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ + if( negateFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); } } /* @@ -58806,35 +61441,162 @@ ** The z[] string will probably not be zero-terminated. But the ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ - const char *z; if( pExpr->flags & EP_IntValue ){ - int i = pExpr->iTable; + int i = pExpr->u.iValue; if( negFlag ) i = -i; sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); - }else if( (z = (char*)pExpr->token.z)!=0 ){ - int i; - int n = pExpr->token.n; - assert( !sqlite3Isdigit(z[n]) ); - if( sqlite3GetInt32(z, &i) ){ - if( negFlag ) i = -i; - sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); - }else if( sqlite3FitsIn64Bits(z, negFlag) ){ + }else{ + const char *z = pExpr->u.zToken; + assert( z!=0 ); + if( sqlite3FitsIn64Bits(z, negFlag) ){ i64 value; char *zV; sqlite3Atoi64(z, &value); if( negFlag ) value = -value; zV = dup8bytes(v, (char*)&value); sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); }else{ - codeReal(v, z, n, negFlag, iMem); - } - } -} - + codeReal(v, z, negFlag, iMem); + } + } +} + +/* +** Clear a cache entry. +*/ +static void cacheEntryClear(Parse *pParse, struct yColCache *p){ + if( p->tempReg ){ + if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ + pParse->aTempReg[pParse->nTempReg++] = p->iReg; + } + p->tempReg = 0; + } +} + + +/* +** Record in the column cache that a particular column from a +** particular table is stored in a particular register. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ + int i; + int minLru; + int idxLru; + struct yColCache *p; + + assert( iReg>0 ); /* Register numbers are always positive */ + assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ + + /* First replace any existing entry */ + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){ + cacheEntryClear(pParse, p); + p->iLevel = pParse->iCacheLevel; + p->iReg = iReg; + p->affChange = 0; + p->lru = pParse->iCacheCnt++; + return; + } + } + + /* Find an empty slot and replace it */ + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg==0 ){ + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->affChange = 0; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; + return; + } + } + + /* Replace the last recently used */ + minLru = 0x7fffffff; + idxLru = -1; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->lru<minLru ){ + idxLru = i; + minLru = p->lru; + } + } + if( ALWAYS(idxLru>=0) ){ + p = &pParse->aColCache[idxLru]; + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->affChange = 0; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; + return; + } +} + +/* +** Indicate that a register is being overwritten. Purge the register +** from the column cache. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg==iReg ){ + cacheEntryClear(pParse, p); + p->iReg = 0; + } + } +} + +/* +** Remember the current column cache context. Any new entries added +** added to the column cache after this call are removed when the +** corresponding pop occurs. +*/ +SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ + pParse->iCacheLevel++; +} + +/* +** Remove from the column cache any entries that were added since the +** the previous N Push operations. In other words, restore the cache +** to the state it was in N Pushes ago. +*/ +SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse, int N){ + int i; + struct yColCache *p; + assert( N>0 ); + assert( pParse->iCacheLevel>=N ); + pParse->iCacheLevel -= N; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg && p->iLevel>pParse->iCacheLevel ){ + cacheEntryClear(pParse, p); + p->iReg = 0; + } + } +} + +/* +** When a cached column is reused, make sure that its register is +** no longer available as a temp register. ticket #3879: that same +** register might be in the cache in multiple places, so be sure to +** get them all. +*/ +static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg==iReg ){ + p->tempReg = 0; + } + } +} /* ** Generate code that will extract the iColumn-th column from ** table pTab and store the column value in a register. An effort ** is made to store the column value in register iReg, but this is @@ -58859,67 +61621,41 @@ ){ Vdbe *v = pParse->pVdbe; int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ - if( p->iTable==iTable && p->iColumn==iColumn + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn && (!p->affChange || allowAffChng) ){ -#if 0 - sqlite3VdbeAddOp0(v, OP_Noop); - VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg)); -#endif + p->lru = pParse->iCacheCnt++; + sqlite3ExprCachePinRegister(pParse, p->iReg); return p->iReg; } } assert( v!=0 ); if( iColumn<0 ){ - int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; - sqlite3VdbeAddOp2(v, op, iTable, iReg); - }else if( pTab==0 ){ - sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg); - }else{ + sqlite3VdbeAddOp2(v, OP_Rowid, iTable, iReg); + }else if( ALWAYS(pTab!=0) ){ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg); - sqlite3ColumnDefault(v, pTab, iColumn); -#ifndef SQLITE_OMIT_FLOATING_POINT - if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); - } -#endif - } - if( pParse->disableColCache==0 ){ - i = pParse->iColCache; - p = &pParse->aColCache[i]; - p->iTable = iTable; - p->iColumn = iColumn; - p->iReg = iReg; - p->affChange = 0; - i++; - if( i>=ArraySize(pParse->aColCache) ) i = 0; - if( i>pParse->nColCache ) pParse->nColCache = i; - pParse->iColCache = i; - } + sqlite3ColumnDefault(v, pTab, iColumn, iReg); + } + sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); return iReg; } /* -** Clear all column cache entries associated with the vdbe -** cursor with cursor number iTable. -*/ -SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){ - if( iTable<0 ){ - pParse->nColCache = 0; - pParse->iColCache = 0; - }else{ - int i; - for(i=0; i<pParse->nColCache; i++){ - if( pParse->aColCache[i].iTable==iTable ){ - testcase( i==pParse->nColCache-1 ); - pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; - pParse->iColCache = pParse->nColCache; - } +** Clear all column cache entries. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ + int i; + struct yColCache *p; + + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg ){ + cacheEntryClear(pParse, p); + p->iReg = 0; } } } /* @@ -58927,14 +61663,15 @@ ** registers starting with iStart. */ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ int iEnd = iStart + iCount - 1; int i; - for(i=0; i<pParse->nColCache; i++){ - int r = pParse->aColCache[i].iReg; + struct yColCache *p; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + int r = p->iReg; if( r>=iStart && r<=iEnd ){ - pParse->aColCache[i].affChange = 1; + p->affChange = 1; } } } /* @@ -58941,16 +61678,17 @@ ** Generate code to move content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. */ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ int i; - if( iFrom==iTo ) return; + struct yColCache *p; + if( NEVER(iFrom==iTo) ) return; sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); - for(i=0; i<pParse->nColCache; i++){ - int x = pParse->aColCache[i].iReg; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + int x = p->iReg; if( x>=iFrom && x<iFrom+nReg ){ - pParse->aColCache[i].iReg += iTo-iFrom; + p->iReg += iTo-iFrom; } } } /* @@ -58957,11 +61695,11 @@ ** Generate code to copy content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. */ SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){ int i; - if( iFrom==iTo ) return; + if( NEVER(iFrom==iTo) ) return; for(i=0; i<nReg; i++){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i); } } @@ -58969,51 +61707,33 @@ ** Return true if any register in the range iFrom..iTo (inclusive) ** is used as part of the column cache. */ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; - for(i=0; i<pParse->nColCache; i++){ - int r = pParse->aColCache[i].iReg; + struct yColCache *p; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + int r = p->iReg; if( r>=iFrom && r<=iTo ) return 1; } return 0; -} - -/* -** There is a value in register iReg. -** -** We are going to modify the value, so we need to make sure it -** is not a cached register. If iReg is a cached register, -** then clear the corresponding cache line. -*/ -SQLITE_PRIVATE void sqlite3ExprWritableRegister(Parse *pParse, int iReg){ - int i; - if( usedAsColumnCache(pParse, iReg, iReg) ){ - for(i=0; i<pParse->nColCache; i++){ - if( pParse->aColCache[i].iReg==iReg ){ - pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; - pParse->iColCache = pParse->nColCache; - } - } - } } /* ** If the last instruction coded is an ephemeral copy of any of ** the registers in the nReg registers beginning with iReg, then ** convert the last instruction from OP_SCopy to OP_Copy. */ SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){ - int addr; VdbeOp *pOp; Vdbe *v; + assert( pParse->db->mallocFailed==0 ); v = pParse->pVdbe; - addr = sqlite3VdbeCurrentAddr(v); - pOp = sqlite3VdbeGetOp(v, addr-1); - assert( pOp || pParse->db->mallocFailed ); - if( pOp && pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){ + assert( v!=0 ); + pOp = sqlite3VdbeGetOp(v, -1); + assert( pOp!=0 ); + if( pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){ pOp->opcode = OP_Copy; } } /* @@ -59032,10 +61752,11 @@ ** pParse->aAlias[iAlias-1] records the register number where the value ** of the iAlias-th alias is stored. If zero, that means that the ** alias has not yet been computed. */ static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){ +#if 0 sqlite3 *db = pParse->db; int iReg; if( pParse->nAliasAlloc<pParse->nAlias ){ pParse->aAlias = sqlite3DbReallocOrFree(db, pParse->aAlias, sizeof(pParse->aAlias[0])*pParse->nAlias ); @@ -59046,19 +61767,23 @@ pParse->nAliasAlloc = pParse->nAlias; } assert( iAlias>0 && iAlias<=pParse->nAlias ); iReg = pParse->aAlias[iAlias-1]; if( iReg==0 ){ - if( pParse->disableColCache ){ + if( pParse->iCacheLevel>0 ){ iReg = sqlite3ExprCodeTarget(pParse, pExpr, target); }else{ iReg = ++pParse->nMem; sqlite3ExprCode(pParse, pExpr, iReg); pParse->aAlias[iAlias-1] = iReg; } } return iReg; +#else + UNUSED_PARAMETER(iAlias); + return sqlite3ExprCodeTarget(pParse, pExpr, target); +#endif } /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". @@ -59075,16 +61800,17 @@ int op; /* The opcode being coded */ int inReg = target; /* Results stored in register inReg */ int regFree1 = 0; /* If non-zero free this temporary register */ int regFree2 = 0; /* If non-zero free this temporary register */ int r1, r2, r3, r4; /* Various register numbers */ - sqlite3 *db; - - db = pParse->db; - assert( v!=0 || db->mallocFailed ); + sqlite3 *db = pParse->db; /* The database connection */ + assert( target>0 && target<=pParse->nMem ); - if( v==0 ) return 0; + if( v==0 ){ + assert( pParse->db->mallocFailed ); + return 0; + } if( pExpr==0 ){ op = TK_NULL; }else{ op = pExpr->op; @@ -59120,17 +61846,17 @@ case TK_INTEGER: { codeInteger(v, pExpr, 0, target); break; } case TK_FLOAT: { - codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pExpr->u.zToken, 0, target); break; } case TK_STRING: { - sqlite3DequoteExpr(pExpr); - sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0, - (char*)pExpr->token.z, pExpr->token.n); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); break; } case TK_NULL: { sqlite3VdbeAddOp2(v, OP_Null, 0, target); break; @@ -59138,27 +61864,28 @@ #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { int n; const char *z; char *zBlob; - assert( pExpr->token.n>=3 ); - assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); - assert( pExpr->token.z[1]=='\'' ); - assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); - n = pExpr->token.n - 3; - z = (char*)pExpr->token.z + 2; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); + z = &pExpr->u.zToken[2]; + n = sqlite3Strlen30(z) - 1; + assert( z[n]=='\'' ); zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); break; } #endif case TK_VARIABLE: { - int iPrior; VdbeOp *pOp; - if( pExpr->token.n<=1 - && (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0 - && (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken!=0 ); + assert( pExpr->u.zToken[0]!=0 ); + if( pExpr->u.zToken[1]==0 + && (pOp = sqlite3VdbeGetOp(v, -1))->opcode==OP_Variable && pOp->p1+pOp->p3==pExpr->iTable && pOp->p2+pOp->p3==target && pOp->p4.z==0 ){ /* If the previous instruction was a copy of the previous unnamed @@ -59167,12 +61894,12 @@ ** instruction. */ pOp->p3++; }else{ sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iTable, target, 1); - if( pExpr->token.n>1 ){ - sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n); + if( pExpr->u.zToken[1]!=0 ){ + sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0); } } break; } case TK_REGISTER: { @@ -59186,11 +61913,12 @@ #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ int aff, to_op; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - aff = sqlite3AffinityType(&pExpr->token); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + aff = sqlite3AffinityType(pExpr->u.zToken); to_op = aff - SQLITE_AFF_TEXT + OP_ToText; assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); @@ -59279,11 +62007,12 @@ } case TK_UMINUS: { Expr *pLeft = pExpr->pLeft; assert( pLeft ); if( pLeft->op==TK_FLOAT ){ - codeReal(v, (char*)pLeft->token.z, pLeft->token.n, 1, target); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pLeft->u.zToken, 1, target); }else if( pLeft->op==TK_INTEGER ){ codeInteger(v, pLeft, 1, target); }else{ regFree1 = r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); @@ -59322,12 +62051,12 @@ break; } case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; if( pInfo==0 ){ - sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", - &pExpr->span); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); }else{ inReg = pInfo->aFunc[pExpr->iAgg].iMem; } break; } @@ -59344,23 +62073,29 @@ CollSeq *pColl = 0; /* A collating sequence */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); testcase( op==TK_CONST_FUNC ); testcase( op==TK_FUNCTION ); - if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ){ + if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ pFarg = pExpr->x.pList; } nFarg = pFarg ? pFarg->nExpr : 0; - zId = (char*)pExpr->token.z; - nId = pExpr->token.n; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + zId = pExpr->u.zToken; + nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); - assert( pDef!=0 ); + if( pDef==0 ){ + sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId); + break; + } if( pFarg ){ r1 = sqlite3GetTempRange(pParse, nFarg); + sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ sqlite3ExprCodeExprList(pParse, pFarg, r1, 1); + sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */ }else{ r1 = 0; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* Possibly overload the function if the first argument is @@ -59379,12 +62114,12 @@ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); }else if( nFarg>0 ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); } #endif - for(i=0; i<nFarg && i<32; i++){ - if( sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){ + for(i=0; i<nFarg; i++){ + if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){ constMask |= (1<<i); } if( (pDef->flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); } @@ -59405,13 +62140,11 @@ #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { testcase( op==TK_EXISTS ); testcase( op==TK_SELECT ); - if( pExpr->iColumn==0 ){ - sqlite3CodeSubselect(pParse, pExpr, 0, 0); - } + sqlite3CodeSubselect(pParse, pExpr, 0, 0); inReg = pExpr->iColumn; break; } case TK_IN: { int rNotFound = 0; @@ -59434,13 +62167,12 @@ /* Code the <expr> from "<expr> IN (...)". The temporary table ** pExpr->iTable contains the values that make up the (...) set. */ - pParse->disableColCache++; - sqlite3ExprCode(pParse, pExpr->pLeft, target); - pParse->disableColCache--; + sqlite3ExprCachePush(pParse); + sqlite3ExprCode(pParse, pExpr->pLeft, target); j2 = sqlite3VdbeAddOp1(v, OP_IsNull, target); if( eType==IN_INDEX_ROWID ){ j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, target); j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, target); sqlite3VdbeAddOp2(v, OP_Integer, 1, target); @@ -59497,10 +62229,11 @@ sqlite3VdbeAddOp2(v, OP_Copy, rNotFound, target); } } sqlite3VdbeJumpHere(v, j2); sqlite3VdbeJumpHere(v, j5); + sqlite3ExprCachePop(pParse, 1); VdbeComment((v, "end IN expr r%d", target)); break; } #endif /* @@ -59541,10 +62274,62 @@ case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } + case TK_TRIGGER: { + /* If the opcode is TK_TRIGGER, then the expression is a reference + ** to a column in the new.* or old.* pseudo-tables available to + ** trigger programs. In this case Expr.iTable is set to 1 for the + ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn + ** is set to the column of the pseudo-table to read, or to -1 to + ** read the rowid field. + ** + ** The expression is implemented using an OP_Param opcode. The p1 + ** parameter is set to 0 for an old.rowid reference, or to (i+1) + ** to reference another column of the old.* pseudo-table, where + ** i is the index of the column. For a new.rowid reference, p1 is + ** set to (n+1), where n is the number of columns in each pseudo-table. + ** For a reference to any other column in the new.* pseudo-table, p1 + ** is set to (n+2+i), where n and i are as defined previously. For + ** example, if the table on which triggers are being fired is + ** declared as: + ** + ** CREATE TABLE t1(a, b); + ** + ** Then p1 is interpreted as follows: + ** + ** p1==0 -> old.rowid p1==3 -> new.rowid + ** p1==1 -> old.a p1==4 -> new.a + ** p1==2 -> old.b p1==5 -> new.b + */ + Table *pTab = pExpr->pTab; + int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; + + assert( pExpr->iTable==0 || pExpr->iTable==1 ); + assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol ); + assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey ); + assert( p1>=0 && p1<(pTab->nCol*2+2) ); + + sqlite3VdbeAddOp2(v, OP_Param, p1, target); + VdbeComment((v, "%s.%s -> $%d", + (pExpr->iTable ? "new" : "old"), + (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), + target + )); + + /* If the column has REAL affinity, it may currently be stored as an + ** integer. Use OP_RealAffinity to make sure it is really real. */ + if( pExpr->iColumn>=0 + && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL + ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, target); + } + break; + } + + /* ** Form A: ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END ** ** Form B: @@ -59562,11 +62347,11 @@ ** ** The result of the expression is the Ri for the first matching Ei, ** or if there is no matching Ei, the ELSE term Y, or if there is ** no ELSE term, NULL. */ - case TK_CASE: { + default: assert( op==TK_CASE ); { int endLabel; /* GOTO label for end of CASE stmt */ int nextCase; /* GOTO label for next WHEN clause */ int nExpr; /* 2x number of WHEN terms */ int i; /* Loop counter */ ExprList *pEList; /* List of WHEN terms */ @@ -59573,10 +62358,11 @@ struct ExprList_item *aListelem; /* Array of WHEN terms */ Expr opCompare; /* The X==Ei expression */ Expr cacheX; /* Cached expression X */ Expr *pX; /* The X expression */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ + VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); assert((pExpr->x.pList->nExpr % 2) == 0); assert(pExpr->x.pList->nExpr > 0); pEList = pExpr->x.pList; @@ -59583,65 +62369,72 @@ aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); if( (pX = pExpr->pLeft)!=0 ){ cacheX = *pX; - testcase( pX->op==TK_COLUMN || pX->op==TK_REGISTER ); + testcase( pX->op==TK_COLUMN ); + testcase( pX->op==TK_REGISTER ); cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); testcase( regFree1==0 ); cacheX.op = TK_REGISTER; opCompare.op = TK_EQ; opCompare.pLeft = &cacheX; pTest = &opCompare; } - pParse->disableColCache++; for(i=0; i<nExpr; i=i+2){ + sqlite3ExprCachePush(pParse); if( pX ){ assert( pTest!=0 ); opCompare.pRight = aListelem[i].pExpr; }else{ pTest = aListelem[i].pExpr; } nextCase = sqlite3VdbeMakeLabel(v); - testcase( pTest->op==TK_COLUMN || pTest->op==TK_REGISTER ); + testcase( pTest->op==TK_COLUMN ); sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); testcase( aListelem[i+1].pExpr->op==TK_REGISTER ); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); + sqlite3ExprCachePop(pParse, 1); sqlite3VdbeResolveLabel(v, nextCase); } if( pExpr->pRight ){ + sqlite3ExprCachePush(pParse); sqlite3ExprCode(pParse, pExpr->pRight, target); + sqlite3ExprCachePop(pParse, 1); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } - sqlite3VdbeResolveLabel(v, endLabel); - assert( pParse->disableColCache>0 ); - pParse->disableColCache--; + assert( db->mallocFailed || pParse->nErr>0 + || pParse->iCacheLevel==iCacheLevel ); + sqlite3VdbeResolveLabel(v, endLabel); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { - if( !pParse->trigStack ){ + assert( pExpr->affinity==OE_Rollback + || pExpr->affinity==OE_Abort + || pExpr->affinity==OE_Fail + || pExpr->affinity==OE_Ignore + ); + if( !pParse->pTriggerTab ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); return 0; } - if( pExpr->affinity!=OE_Ignore ){ - assert( pExpr->affinity==OE_Rollback || - pExpr->affinity == OE_Abort || - pExpr->affinity == OE_Fail ); - sqlite3DequoteExpr(pExpr); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0, - (char*)pExpr->token.z, pExpr->token.n); - } else { - assert( pExpr->affinity == OE_Ignore ); - sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); - sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump); - VdbeComment((v, "raise(IGNORE)")); - } + if( pExpr->affinity==OE_Abort ){ + sqlite3MayAbort(pParse); + } + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + if( pExpr->affinity==OE_Ignore ){ + sqlite3VdbeAddOp4( + v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); + }else{ + sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0); + } + break; } #endif } sqlite3ReleaseTempReg(pParse, regFree1); @@ -59702,11 +62495,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ Vdbe *v = pParse->pVdbe; int inReg; inReg = sqlite3ExprCode(pParse, pExpr, target); assert( target>0 ); - if( pExpr->op!=TK_REGISTER ){ + /* This routine is called for terms to INSERT or UPDATE. And the only + ** other place where expressions can be converted into TK_REGISTER is + ** in WHERE clause processing. So as currently implemented, there is + ** no way for a TK_REGISTER to exist here. But it seems prudent to + ** keep the ALWAYS() in case the conditions above change with future + ** modifications or enhancements. */ + if( ALWAYS(pExpr->op!=TK_REGISTER) ){ int iMem; iMem = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem); pExpr->iTable = iMem; pExpr->op = TK_REGISTER; @@ -59759,14 +62558,14 @@ ** up generating an OP_SCopy to move the value to the destination ** register. */ return 0; } case TK_UMINUS: { - if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){ - return 0; - } - break; + if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){ + return 0; + } + break; } default: { break; } } @@ -59781,11 +62580,11 @@ */ static int evalConstExpr(Walker *pWalker, Expr *pExpr){ Parse *pParse = pWalker->pParse; switch( pExpr->op ){ case TK_REGISTER: { - return 1; + return WRC_Prune; } case TK_FUNCTION: case TK_AGG_FUNCTION: case TK_CONST_FUNC: { /* The arguments to a function have a fixed destination. @@ -59796,21 +62595,22 @@ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( pList ){ int i = pList->nExpr; struct ExprList_item *pItem = pList->a; for(; i>0; i--, pItem++){ - if( pItem->pExpr ) pItem->pExpr->flags |= EP_FixedDest; + if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest; } } break; } } if( isAppropriateForFactoring(pExpr) ){ int r1 = ++pParse->nMem; int r2; r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); - if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1); + if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); + pExpr->op2 = pExpr->op; pExpr->op = TK_REGISTER; pExpr->iTable = r2; return WRC_Prune; } return WRC_Continue; @@ -59855,11 +62655,11 @@ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i); } }else{ sqlite3ExprCode(pParse, pItem->pExpr, target+i); } - if( doHardCopy ){ + if( doHardCopy && !pParse->db->mallocFailed ){ sqlite3ExprHardCopy(pParse, target, n); } } return n; } @@ -59884,33 +62684,28 @@ int regFree1 = 0; int regFree2 = 0; int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); - if( v==0 || pExpr==0 ) return; + if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */ + if( NEVER(pExpr==0) ) return; /* No way this can happen */ op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); - testcase( pParse->disableColCache==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); - pParse->disableColCache++; + sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - assert( pParse->disableColCache>0 ); - pParse->disableColCache--; sqlite3VdbeResolveLabel(v, d2); + sqlite3ExprCachePop(pParse, 1); break; } case TK_OR: { testcase( jumpIfNull==0 ); - testcase( pParse->disableColCache==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - pParse->disableColCache++; - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - assert( pParse->disableColCache>0 ); - pParse->disableColCache--; + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_NOT: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); @@ -60014,11 +62809,12 @@ int regFree1 = 0; int regFree2 = 0; int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); - if( v==0 || pExpr==0 ) return; + if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */ + if( pExpr==0 ) return; /* The value of pExpr->op and op are related as follows: ** ** pExpr->op op ** --------- ---------- @@ -60050,28 +62846,22 @@ assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ case TK_AND: { testcase( jumpIfNull==0 ); - testcase( pParse->disableColCache==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - pParse->disableColCache++; - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - assert( pParse->disableColCache>0 ); - pParse->disableColCache--; + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); - testcase( pParse->disableColCache==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); - pParse->disableColCache++; + sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - assert( pParse->disableColCache>0 ); - pParse->disableColCache--; sqlite3VdbeResolveLabel(v, d2); + sqlite3ExprCachePop(pParse, 1); break; } case TK_NOT: { sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; @@ -60168,10 +62958,12 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; if( pA==0||pB==0 ){ return pB==pA; } + assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 0; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; if( pA->op!=pB->op ) return 0; @@ -60188,14 +62980,17 @@ }else if( pA->x.pList || pB->x.pList ){ return 0; } if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; - if( pA->op!=TK_COLUMN && pA->token.z ){ - if( pB->token.z==0 ) return 0; - if( pB->token.n!=pA->token.n ) return 0; - if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ + if( ExprHasProperty(pA, EP_IntValue) ){ + if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ + return 0; + } + }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ + if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0; + if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ return 0; } } return 1; } @@ -60254,14 +63049,15 @@ case TK_COLUMN: { testcase( pExpr->op==TK_AGG_COLUMN ); testcase( pExpr->op==TK_COLUMN ); /* Check to see if the column is in one of the tables in the FROM ** clause of the aggregate query */ - if( pSrcList ){ + if( ALWAYS(pSrcList!=0) ){ struct SrcList_item *pItem = pSrcList->a; for(i=0; i<pSrcList->nSrc; i++, pItem++){ struct AggInfo_col *pCol; + assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); if( pExpr->iTable==pItem->iCursor ){ /* If we reach this point, it means that pExpr refers to a table ** that is in the FROM clause of the aggregate query. ** ** Make an entry for the column in pAggInfo->aCol[] if there @@ -60306,13 +63102,14 @@ /* There is now an entry for pExpr in pAggInfo->aCol[] (either ** because it was there before or because we just created it). ** Convert the pExpr to be a TK_AGG_COLUMN referring to that ** pAggInfo->aCol[] entry. */ + ExprSetIrreducible(pExpr); pExpr->pAggInfo = pAggInfo; pExpr->op = TK_AGG_COLUMN; - pExpr->iAgg = k; + pExpr->iAgg = (i16)k; break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } return WRC_Prune; @@ -60338,12 +63135,13 @@ if( i>=0 ){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = ++pParse->nMem; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite3FindFunction(pParse->db, - (char*)pExpr->token.z, pExpr->token.n, + pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; }else{ pItem->iDistinct = -1; @@ -60350,11 +63148,13 @@ } } } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ - pExpr->iAgg = i; + assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(pExpr); + pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; return WRC_Prune; } } } @@ -60383,10 +63183,11 @@ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; w.xExprCallback = analyzeAggregate; w.xSelectCallback = analyzeAggregatesInSelect; w.u.pNC = pNC; + assert( pNC->pSrcList!=0 ); sqlite3WalkExpr(&w, pExpr); } /* ** Call sqlite3ExprAnalyzeAggregates() for every expression in an @@ -60403,21 +63204,37 @@ } } } /* -** Allocate or deallocate temporary use registers during code generation. +** Allocate a single new register for use to hold some intermediate result. */ SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){ if( pParse->nTempReg==0 ){ return ++pParse->nMem; } return pParse->aTempReg[--pParse->nTempReg]; } + +/* +** Deallocate a register, making available for reuse for some other +** purpose. +** +** If a register is currently being used by the column cache, then +** the dallocation is deferred until the column cache line that uses +** the register becomes stale. +*/ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ - sqlite3ExprWritableRegister(pParse, iReg); + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ + if( p->iReg==iReg ){ + p->tempReg = 1; + return; + } + } pParse->aTempReg[pParse->nTempReg++] = iReg; } } /* @@ -60457,11 +63274,11 @@ ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.55 2009/03/24 15:08:10 drh Exp $ +** $Id: alter.c,v 1.62 2009/07/24 17:58:53 danielk1977 Exp $ */ /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. @@ -60510,11 +63327,11 @@ /* Ran out of input before finding an opening bracket. Return NULL. */ return; } /* Store the token that zCsr points to in tname. */ - tname.z = zCsr; + tname.z = (char*)zCsr; tname.n = len; /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ @@ -60523,11 +63340,11 @@ len = sqlite3GetToken(zCsr, &token); } while( token==TK_SPACE ); assert( len>0 ); } while( token!=TK_LP && token!=TK_USING ); - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } @@ -60569,11 +63386,11 @@ /* Ran out of input before finding the table name. Return NULL. */ return; } /* Store the token that zCsr points to in tname. */ - tname.z = zCsr; + tname.z = (char*)zCsr; tname.n = len; /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ @@ -60599,11 +63416,11 @@ } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); /* Variable tname now contains the token that is the old table-name ** in the CREATE TRIGGER statement. */ - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } #endif /* !SQLITE_OMIT_TRIGGER */ @@ -60640,14 +63457,14 @@ if( pTab->pSchema!=pTempSchema ){ sqlite3 *db = pParse->db; for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ if( pTrig->pSchema==pTempSchema ){ if( !zWhere ){ - zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->name); + zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->zName); }else{ tmp = zWhere; - zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name); + zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->zName); sqlite3DbFree(db, tmp); } } } } @@ -60669,21 +63486,21 @@ #ifndef SQLITE_OMIT_TRIGGER Trigger *pTrig; #endif v = sqlite3GetVdbe(pParse); - if( !v ) return; + if( NEVER(v==0) ) return; assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); assert( iDb>=0 ); #ifndef SQLITE_OMIT_TRIGGER /* Drop any table triggers from the internal schema. */ for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); assert( iTrigDb==iDb || iTrigDb==1 ); - sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->name, 0); + sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); } #endif /* Drop the table and index from the internal schema */ sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); @@ -60721,13 +63538,13 @@ const char *zTabName; /* Original name of the table */ Vdbe *v; #ifndef SQLITE_OMIT_TRIGGER char *zWhere = 0; /* Where clause to locate temp triggers */ #endif - int isVirtualRename = 0; /* True if this is a v-table with an xRename() */ - - if( db->mallocFailed ) goto exit_rename_table; + VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ + + if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_rename_table; @@ -60776,12 +63593,15 @@ #ifndef SQLITE_OMIT_VIRTUALTABLE if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto exit_rename_table; } - if( IsVirtual(pTab) && pTab->pMod->pModule->xRename ){ - isVirtualRename = 1; + if( IsVirtual(pTab) ){ + pVTab = sqlite3GetVTable(db, pTab); + if( pVTab->pVtab->pModule->xRename==0 ){ + pVTab = 0; + } } #endif /* Begin a transaction and code the VerifyCookie for database iDb. ** Then modify the schema cookie (since the ALTER TABLE modifies the @@ -60790,23 +63610,24 @@ */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } - sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); + sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb); sqlite3ChangeCookie(pParse, iDb); /* If this is a virtual table, invoke the xRename() function if ** one is defined. The xRename() callback will modify the names ** of any resources used by the v-table implementation (including other ** SQLite tables) that are identified by the name of the virtual table. */ #ifndef SQLITE_OMIT_VIRTUALTABLE - if( isVirtualRename ){ + if( pVTab ){ int i = ++pParse->nMem; sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0); - sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pTab->pVtab, P4_VTAB); + sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); + sqlite3MayAbort(pParse); } #endif /* figure out how many UTF-8 characters are in zName */ zTabName = pTab->zName; @@ -60869,10 +63690,35 @@ exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); } + +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + /* The VDBE should have been allocated before this routine is called. + ** If that allocation failed, we would have quit before reaching this + ** point */ + if( ALWAYS(v) ){ + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3GetTempReg(pParse); + int j1; + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); + sqlite3VdbeJumpHere(v, j1); + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } +} /* ** This function is called after an "ALTER TABLE ... ADD" statement ** has been parsed. Argument pColDef contains the text of the new ** column definition. @@ -60956,11 +63802,11 @@ /* Modify the CREATE TABLE statement. */ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; - while( (zEnd>zCol && *zEnd==';') || sqlite3Isspace(*zEnd) ){ + while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ *zEnd-- = '\0'; } sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " @@ -61055,10 +63901,11 @@ Column *pCol = &pNew->aCol[i]; pCol->zName = sqlite3DbStrDup(db, pCol->zName); pCol->zColl = 0; pCol->zType = 0; pCol->pDflt = 0; + pCol->zDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; pNew->nRef = 1; @@ -61087,75 +63934,94 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.51 2009/02/28 10:47:42 danielk1977 Exp $ +** @(#) $Id: analyze.c,v 1.52 2009/04/16 17:45:48 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE /* -** This routine generates code that opens the sqlite_stat1 table on cursor -** iStatCur. +** This routine generates code that opens the sqlite_stat1 table for +** writing with cursor iStatCur. If the library was built with the +** SQLITE_ENABLE_STAT2 macro defined, then the sqlite_stat2 table is +** opened for writing using cursor (iStatCur+1) ** ** If the sqlite_stat1 tables does not previously exist, it is created. -** If it does previously exist, all entires associated with table zWhere -** are removed. If zWhere==0 then all entries are removed. +** Similarly, if the sqlite_stat2 table does not exist and the library +** is compiled with SQLITE_ENABLE_STAT2 defined, it is created. +** +** Argument zWhere may be a pointer to a buffer containing a table name, +** or it may be a NULL pointer. If it is not NULL, then all entries in +** the sqlite_stat1 and (if applicable) sqlite_stat2 tables associated +** with the named table are deleted. If zWhere==0, then code is generated +** to delete all stat table entries. */ static void openStatTable( Parse *pParse, /* Parsing context */ int iDb, /* The database we are looking in */ int iStatCur, /* Open the sqlite_stat1 table on this cursor */ const char *zWhere /* Delete entries associated with this table */ ){ + static struct { + const char *zName; + const char *zCols; + } aTable[] = { + { "sqlite_stat1", "tbl,idx,stat" }, +#ifdef SQLITE_ENABLE_STAT2 + { "sqlite_stat2", "tbl,idx,sampleno,sample" }, +#endif + }; + + int aRoot[] = {0, 0}; + u8 aCreateTbl[] = {0, 0}; + + int i; sqlite3 *db = pParse->db; Db *pDb; - int iRootPage; - u8 createStat1 = 0; - Table *pStat; - Vdbe *v = sqlite3GetVdbe(pParse); - + Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3VdbeDb(v)==db ); pDb = &db->aDb[iDb]; - if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){ - /* The sqlite_stat1 tables does not exist. Create it. - ** Note that a side-effect of the CREATE TABLE statement is to leave - ** the rootpage of the new table in register pParse->regRoot. This is - ** important because the OpenWrite opcode below will be needing it. */ - sqlite3NestedParse(pParse, - "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)", - pDb->zName - ); - iRootPage = pParse->regRoot; - createStat1 = 1; /* Cause rootpage to be taken from top of stack */ - }else if( zWhere ){ - /* The sqlite_stat1 table exists. Delete all entries associated with - ** the table zWhere. */ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", - pDb->zName, zWhere - ); - iRootPage = pStat->tnum; - }else{ - /* The sqlite_stat1 table already exists. Delete all rows. */ - iRootPage = pStat->tnum; - sqlite3VdbeAddOp2(v, OP_Clear, pStat->tnum, iDb); - } - - /* Open the sqlite_stat1 table for writing. Unless it was created - ** by this vdbe program, lock it for writing at the shared-cache level. - ** If this vdbe did create the sqlite_stat1 table, then it must have - ** already obtained a schema-lock, making the write-lock redundant. - */ - if( !createStat1 ){ - sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); - } - sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb); - sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32); - sqlite3VdbeChangeP5(v, createStat1); + + for(i=0; i<ArraySize(aTable); i++){ + const char *zTab = aTable[i].zName; + Table *pStat; + if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){ + /* The sqlite_stat[12] table does not exist. Create it. Note that a + ** side-effect of the CREATE TABLE statement is to leave the rootpage + ** of the new table in register pParse->regRoot. This is important + ** because the OpenWrite opcode below will be needing it. */ + sqlite3NestedParse(pParse, + "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols + ); + aRoot[i] = pParse->regRoot; + aCreateTbl[i] = 1; + }else{ + /* The table already exists. If zWhere is not NULL, delete all entries + ** associated with the table zWhere. If zWhere is NULL, delete the + ** entire contents of the table. */ + aRoot[i] = pStat->tnum; + sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab); + if( zWhere ){ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE tbl=%Q", pDb->zName, zTab, zWhere + ); + }else{ + /* The sqlite_stat[12] table already exists. Delete all rows. */ + sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); + } + } + } + + /* Open the sqlite_stat[12] tables for writing. */ + for(i=0; i<ArraySize(aTable); i++){ + sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb); + sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32); + sqlite3VdbeChangeP5(v, aCreateTbl[i]); + } } /* ** Generate code to do an analysis of all indices associated with ** a single table. @@ -61164,105 +64030,189 @@ Parse *pParse, /* Parser context */ Table *pTab, /* Table whose indices are to be analyzed */ int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ int iMem /* Available memory locations begin here */ ){ - Index *pIdx; /* An index to being analyzed */ - int iIdxCur; /* Index of VdbeCursor for index being analyzed */ - int nCol; /* Number of columns in the index */ - Vdbe *v; /* The virtual machine being built up */ - int i; /* Loop counter */ - int topOfLoop; /* The top of the loop */ - int endOfLoop; /* The end of the loop */ - int addr; /* The address of an instruction */ - int iDb; /* Index of database containing pTab */ - - v = sqlite3GetVdbe(pParse); - if( v==0 || pTab==0 || pTab->pIndex==0 ){ + sqlite3 *db = pParse->db; /* Database handle */ + Index *pIdx; /* An index to being analyzed */ + int iIdxCur; /* Cursor open on index being analyzed */ + Vdbe *v; /* The virtual machine being built up */ + int i; /* Loop counter */ + int topOfLoop; /* The top of the loop */ + int endOfLoop; /* The end of the loop */ + int addr; /* The address of an instruction */ + int iDb; /* Index of database containing pTab */ + int regTabname = iMem++; /* Register containing table name */ + int regIdxname = iMem++; /* Register containing index name */ + int regSampleno = iMem++; /* Register containing next sample number */ + int regCol = iMem++; /* Content of a column analyzed table */ + int regRec = iMem++; /* Register holding completed record */ + int regTemp = iMem++; /* Temporary use register */ + int regRowid = iMem++; /* Rowid for the inserted record */ + +#ifdef SQLITE_ENABLE_STAT2 + int regTemp2 = iMem++; /* Temporary use register */ + int regSamplerecno = iMem++; /* Index of next sample to record */ + int regRecno = iMem++; /* Current sample index */ + int regLast = iMem++; /* Index of last sample to record */ + int regFirst = iMem++; /* Index of first sample to record */ +#endif + + v = sqlite3GetVdbe(pParse); + if( v==0 || NEVER(pTab==0) || pTab->pIndex==0 ){ /* Do no analysis for tables that have no indices */ return; } - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( sqlite3BtreeHoldsAllMutexes(db) ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - pParse->db->aDb[iDb].zName ) ){ + db->aDb[iDb].zName ) ){ return; } #endif /* Establish a read-lock on the table at the shared-cache level. */ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); iIdxCur = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int nCol = pIdx->nColumn; KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); - int regFields; /* Register block for building records */ - int regRec; /* Register holding completed record */ - int regTemp; /* Temporary use register */ - int regCol; /* Content of a column from the table being analyzed */ - int regRowid; /* Rowid for the inserted record */ - int regF2; - - /* Open a cursor to the index to be analyzed - */ - assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); - nCol = pIdx->nColumn; + + if( iMem+1+(nCol*2)>pParse->nMem ){ + pParse->nMem = iMem+1+(nCol*2); + } + + /* Open a cursor to the index to be analyzed. */ + assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); - regFields = iMem+nCol*2; - regTemp = regRowid = regCol = regFields+3; - regRec = regCol+1; - if( regRec>pParse->nMem ){ - pParse->nMem = regRec; - } - - /* Memory cells are used as follows: - ** - ** mem[iMem]: The total number of rows in the table. - ** mem[iMem+1]: Number of distinct values in column 1 - ** ... - ** mem[iMem+nCol]: Number of distinct values in column N - ** mem[iMem+nCol+1] Last observed value of column 1 - ** ... - ** mem[iMem+nCol+nCol]: Last observed value of column N - ** - ** Cells iMem through iMem+nCol are initialized to 0. The others - ** are initialized to NULL. + + /* Populate the registers containing the table and index names. */ + if( pTab->pIndex==pIdx ){ + sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); + } + sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0); + +#ifdef SQLITE_ENABLE_STAT2 + + /* If this iteration of the loop is generating code to analyze the + ** first index in the pTab->pIndex list, then register regLast has + ** not been populated. In this case populate it now. */ + if( pTab->pIndex==pIdx ){ + sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES, regSamplerecno); + sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES*2-1, regTemp); + sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES*2, regTemp2); + + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regLast); + sqlite3VdbeAddOp2(v, OP_Null, 0, regFirst); + addr = sqlite3VdbeAddOp3(v, OP_Lt, regSamplerecno, 0, regLast); + sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regLast, regFirst); + sqlite3VdbeAddOp3(v, OP_Multiply, regLast, regTemp, regLast); + sqlite3VdbeAddOp2(v, OP_AddImm, regLast, SQLITE_INDEX_SAMPLES*2-2); + sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regLast, regLast); + sqlite3VdbeJumpHere(v, addr); + } + + /* Zero the regSampleno and regRecno registers. */ + sqlite3VdbeAddOp2(v, OP_Integer, 0, regSampleno); + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRecno); + sqlite3VdbeAddOp2(v, OP_Copy, regFirst, regSamplerecno); +#endif + + /* The block of memory cells initialized here is used as follows. + ** + ** iMem: + ** The total number of rows in the table. + ** + ** iMem+1 .. iMem+nCol: + ** Number of distinct entries in index considering the + ** left-most N columns only, where N is between 1 and nCol, + ** inclusive. + ** + ** iMem+nCol+1 .. Mem+2*nCol: + ** Previous value of indexed columns, from left to right. + ** + ** Cells iMem through iMem+nCol are initialized to 0. The others are + ** initialized to contain an SQL NULL. */ for(i=0; i<=nCol; i++){ sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i); } for(i=0; i<nCol; i++){ sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1); } - /* Do the analysis. - */ + /* Start the analysis loop. This loop runs through all the entries in + ** the index b-tree. */ endOfLoop = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); + for(i=0; i<nCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol); +#ifdef SQLITE_ENABLE_STAT2 + if( i==0 ){ + /* Check if the record that cursor iIdxCur points to contains a + ** value that should be stored in the sqlite_stat2 table. If so, + ** store it. */ + int ne = sqlite3VdbeAddOp3(v, OP_Ne, regRecno, 0, regSamplerecno); + assert( regTabname+1==regIdxname + && regTabname+2==regSampleno + && regTabname+3==regCol + ); + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 4, regRec, "aaab", 0); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regRowid); + + /* Calculate new values for regSamplerecno and regSampleno. + ** + ** sampleno = sampleno + 1 + ** samplerecno = samplerecno+(remaining records)/(remaining samples) + */ + sqlite3VdbeAddOp2(v, OP_AddImm, regSampleno, 1); + sqlite3VdbeAddOp3(v, OP_Subtract, regRecno, regLast, regTemp); + sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1); + sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES, regTemp2); + sqlite3VdbeAddOp3(v, OP_Subtract, regSampleno, regTemp2, regTemp2); + sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regTemp, regTemp); + sqlite3VdbeAddOp3(v, OP_Add, regSamplerecno, regTemp, regSamplerecno); + + sqlite3VdbeJumpHere(v, ne); + sqlite3VdbeAddOp2(v, OP_AddImm, regRecno, 1); + } +#endif + sqlite3VdbeAddOp3(v, OP_Ne, regCol, 0, iMem+nCol+i+1); /**** TODO: add collating sequence *****/ sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); } + if( db->mallocFailed ){ + /* If a malloc failure has occurred, then the result of the expression + ** passed as the second argument to the call to sqlite3VdbeJumpHere() + ** below may be negative. Which causes an assert() to fail (or an + ** out-of-bounds write if SQLITE_DEBUG is not defined). */ + return; + } sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop); for(i=0; i<nCol; i++){ - sqlite3VdbeJumpHere(v, topOfLoop + 2*(i + 1)); + sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-(nCol*2)); sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1); } + + /* End of the analysis loop. */ sqlite3VdbeResolveLabel(v, endOfLoop); sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop); sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); - /* Store the results. + /* Store the results in sqlite_stat1. ** ** The result is a single row of the sqlite_stat1 table. The first ** two columns are the names of the table and index. The third column ** is a string composed of a list of integer statistics about the ** index. The first integer in the list is the total number of entries @@ -61277,24 +64227,21 @@ ** If K==0 then no entry is made into the sqlite_stat1 table. ** If K>0 then it is always the case the D>0 so division by zero ** is never possible. */ addr = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); - sqlite3VdbeAddOp4(v, OP_String8, 0, regFields, 0, pTab->zName, 0); - sqlite3VdbeAddOp4(v, OP_String8, 0, regFields+1, 0, pIdx->zName, 0); - regF2 = regFields+2; - sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regF2); + sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regSampleno); for(i=0; i<nCol; i++){ sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0); - sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); + sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regSampleno, regSampleno); sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp); sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1); sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp); sqlite3VdbeAddOp1(v, OP_ToInt, regTemp); - sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); - } - sqlite3VdbeAddOp4(v, OP_MakeRecord, regFields, 3, regRec, "aaa", 0); + sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regSampleno, regSampleno); + } + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeJumpHere(v, addr); } @@ -61320,11 +64267,12 @@ HashElem *k; int iStatCur; int iMem; sqlite3BeginWriteOperation(pParse, 0, iDb); - iStatCur = pParse->nTab++; + iStatCur = pParse->nTab; + pParse->nTab += 2; openStatTable(pParse, iDb, iStatCur, 0); iMem = pParse->nMem+1; for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, iStatCur, iMem); @@ -61342,11 +64290,12 @@ assert( pTab!=0 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); - iStatCur = pParse->nTab++; + iStatCur = pParse->nTab; + pParse->nTab += 2; openStatTable(pParse, iDb, iStatCur, pTab->zName); analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem+1); loadAnalysis(pParse, iDb); } @@ -61375,17 +64324,18 @@ assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ return; } + assert( pName2!=0 || pName1==0 ); if( pName1==0 ){ /* Form 1: Analyze everything */ for(i=0; i<db->nDb; i++){ if( i==1 ) continue; /* Do not analyze the TEMP database */ analyzeDatabase(pParse, i); } - }else if( pName2==0 || pName2->n==0 ){ + }else if( pName2->n==0 ){ /* Form 2: Analyze the database or table named */ iDb = sqlite3FindDb(db, pName1); if( iDb>=0 ){ analyzeDatabase(pParse, iDb); }else{ @@ -61461,11 +64411,51 @@ } return 0; } /* -** Load the content of the sqlite_stat1 table into the index hash tables. +** If the Index.aSample variable is not NULL, delete the aSample[] array +** and its contents. +*/ +SQLITE_PRIVATE void sqlite3DeleteIndexSamples(Index *pIdx){ +#ifdef SQLITE_ENABLE_STAT2 + if( pIdx->aSample ){ + int j; + sqlite3 *dbMem = pIdx->pTable->dbMem; + for(j=0; j<SQLITE_INDEX_SAMPLES; j++){ + IndexSample *p = &pIdx->aSample[j]; + if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){ + sqlite3DbFree(pIdx->pTable->dbMem, p->u.z); + } + } + sqlite3DbFree(dbMem, pIdx->aSample); + pIdx->aSample = 0; + } +#else + UNUSED_PARAMETER(pIdx); +#endif +} + +/* +** Load the content of the sqlite_stat1 and sqlite_stat2 tables. The +** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] +** arrays. The contents of sqlite_stat2 are used to populate the +** Index.aSample[] arrays. +** +** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR +** is returned. In this case, even if SQLITE_ENABLE_STAT2 was defined +** during compilation and the sqlite_stat2 table is present, no data is +** read from it. +** +** If SQLITE_ENABLE_STAT2 was defined during compilation and the +** sqlite_stat2 table is not present in the database, SQLITE_ERROR is +** returned. However, in this case, data is read from the sqlite_stat1 +** table (if it is present) before returning. +** +** If an OOM error occurs, this function always sets db->mallocFailed. +** This means if the caller does not care about other errors, the return +** code may be ignored. */ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ analysisInfo sInfo; HashElem *i; char *zSql; @@ -61477,31 +64467,110 @@ /* Clear any prior statistics */ for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); sqlite3DefaultRowEst(pIdx); - } - - /* Check to make sure the sqlite_stat1 table existss */ + sqlite3DeleteIndexSamples(pIdx); + } + + /* Check to make sure the sqlite_stat1 table exists */ sInfo.db = db; sInfo.zDatabase = db->aDb[iDb].zName; if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ - return SQLITE_ERROR; - } - + return SQLITE_ERROR; + } /* Load new statistics out of the sqlite_stat1 table */ - zSql = sqlite3MPrintf(db, "SELECT idx, stat FROM %Q.sqlite_stat1", - sInfo.zDatabase); + zSql = sqlite3MPrintf(db, + "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ (void)sqlite3SafetyOff(db); rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); (void)sqlite3SafetyOn(db); sqlite3DbFree(db, zSql); - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + } + + + /* Load the statistics from the sqlite_stat2 table. */ +#ifdef SQLITE_ENABLE_STAT2 + if( rc==SQLITE_OK && !sqlite3FindTable(db, "sqlite_stat2", sInfo.zDatabase) ){ + rc = SQLITE_ERROR; + } + if( rc==SQLITE_OK ){ + sqlite3_stmt *pStmt = 0; + + zSql = sqlite3MPrintf(db, + "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase); + if( !zSql ){ + rc = SQLITE_NOMEM; + }else{ + (void)sqlite3SafetyOff(db); + rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + (void)sqlite3SafetyOn(db); + sqlite3DbFree(db, zSql); + } + + if( rc==SQLITE_OK ){ + (void)sqlite3SafetyOff(db); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + char *zIndex = (char *)sqlite3_column_text(pStmt, 0); + Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase); + if( pIdx ){ + int iSample = sqlite3_column_int(pStmt, 1); + sqlite3 *dbMem = pIdx->pTable->dbMem; + assert( dbMem==db || dbMem==0 ); + if( iSample<SQLITE_INDEX_SAMPLES && iSample>=0 ){ + int eType = sqlite3_column_type(pStmt, 2); + + if( pIdx->aSample==0 ){ + static const int sz = sizeof(IndexSample)*SQLITE_INDEX_SAMPLES; + pIdx->aSample = (IndexSample *)sqlite3DbMallocZero(dbMem, sz); + if( pIdx->aSample==0 ){ + db->mallocFailed = 1; + break; + } + } + + assert( pIdx->aSample ); + { + IndexSample *pSample = &pIdx->aSample[iSample]; + pSample->eType = (u8)eType; + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + pSample->u.r = sqlite3_column_double(pStmt, 2); + }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + const char *z = (const char *)( + (eType==SQLITE_BLOB) ? + sqlite3_column_blob(pStmt, 2): + sqlite3_column_text(pStmt, 2) + ); + int n = sqlite3_column_bytes(pStmt, 2); + if( n>24 ){ + n = 24; + } + pSample->nByte = (u8)n; + pSample->u.z = sqlite3DbMallocRaw(dbMem, n); + if( pSample->u.z ){ + memcpy(pSample->u.z, z, n); + }else{ + db->mallocFailed = 1; + break; + } + } + } + } + } + } + rc = sqlite3_finalize(pStmt); + (void)sqlite3SafetyOn(db); + } + } +#endif + + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; } return rc; } @@ -61520,11 +64589,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.84 2009/04/08 13:51:51 drh Exp $ +** $Id: attach.c,v 1.93 2009/05/31 21:21:41 drh Exp $ */ #ifndef SQLITE_OMIT_ATTACH /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This @@ -61549,11 +64618,11 @@ int rc = SQLITE_OK; if( pExpr ){ if( pExpr->op!=TK_ID ){ rc = sqlite3ResolveExprNames(pName, pExpr); if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ - sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span); + sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken); return SQLITE_ERROR; } }else{ pExpr->op = TK_STRING; } @@ -61582,11 +64651,10 @@ sqlite3 *db = sqlite3_context_db_handle(context); const char *zName; const char *zFile; Db *aNew; char *zErrDyn = 0; - char zErr[128]; UNUSED_PARAMETER(NotUsed); zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); @@ -61598,26 +64666,24 @@ ** * Too many attached databases, ** * Transaction currently open ** * Specified database name already being used. */ if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ - sqlite3_snprintf( - sizeof(zErr), zErr, "too many attached databases - max %d", + zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", db->aLimit[SQLITE_LIMIT_ATTACHED] ); goto attach_error; } if( !db->autoCommit ){ - sqlite3_snprintf(sizeof(zErr), zErr, - "cannot ATTACH database within transaction"); + zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction"); goto attach_error; } for(i=0; i<db->nDb; i++){ char *z = db->aDb[i].zName; - if( z && zName && sqlite3StrICmp(z, zName)==0 ){ - sqlite3_snprintf(sizeof(zErr), zErr, - "database %s is already in use", zName); + assert( z && zName ); + if( sqlite3StrICmp(z, zName)==0 ){ + zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); goto attach_error; } } /* Allocate the new entry in the db->aDb[] array and initialise the schema @@ -61630,29 +64696,33 @@ }else{ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ) return; } db->aDb = aNew; - aNew = &db->aDb[db->nDb++]; + aNew = &db->aDb[db->nDb]; memset(aNew, 0, sizeof(*aNew)); /* Open the database file. If the btree is successfully opened, use ** it to obtain the database schema. At this point the schema may ** or may not be initialised. */ rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE, db->openFlags | SQLITE_OPEN_MAIN_DB, &aNew->pBt); - if( rc==SQLITE_OK ){ + db->nDb++; + if( rc==SQLITE_CONSTRAINT ){ + rc = SQLITE_ERROR; + zErrDyn = sqlite3MPrintf(db, "database is already attached"); + }else if( rc==SQLITE_OK ){ Pager *pPager; aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); if( !aNew->pSchema ){ rc = SQLITE_NOMEM; }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ - sqlite3_snprintf(sizeof(zErr), zErr, + zErrDyn = sqlite3MPrintf(db, "attached databases must use the same text encoding as main database"); - goto attach_error; + rc = SQLITE_ERROR; } pPager = sqlite3BtreePager(aNew->pBt); sqlite3PagerLockingMode(pPager, db->dfltLockMode); sqlite3PagerJournalMode(pPager, db->dfltJournalMode); } @@ -61711,13 +64781,14 @@ } sqlite3ResetInternalSchema(db, 0); db->nDb = iDb; if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; - sqlite3_snprintf(sizeof(zErr),zErr, "out of memory"); - }else{ - sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile); + sqlite3DbFree(db, zErrDyn); + zErrDyn = sqlite3MPrintf(db, "out of memory"); + }else if( zErrDyn==0 ){ + zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); } goto attach_error; } return; @@ -61725,13 +64796,10 @@ attach_error: /* Return an error if we get here */ if( zErrDyn ){ sqlite3_result_error(context, zErrDyn, -1); sqlite3DbFree(db, zErrDyn); - }else{ - zErr[sizeof(zErr)-1] = 0; - sqlite3_result_error(context, zErr, -1); } if( rc ) sqlite3_result_error_code(context, rc); } /* @@ -61807,25 +64875,10 @@ NameContext sName; Vdbe *v; sqlite3* db = pParse->db; int regArgs; -#ifndef SQLITE_OMIT_AUTHORIZATION - assert( db->mallocFailed || pAuthArg ); - if( pAuthArg ){ - char *zAuthArg = sqlite3NameFromToken(db, &pAuthArg->span); - if( !zAuthArg ){ - goto attach_end; - } - rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); - sqlite3DbFree(db, zAuthArg); - if(rc!=SQLITE_OK ){ - goto attach_end; - } - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; if( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || @@ -61833,10 +64886,24 @@ SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) ){ pParse->nErr++; goto attach_end; } + +#ifndef SQLITE_OMIT_AUTHORIZATION + if( pAuthArg ){ + char *zAuthArg = pAuthArg->u.zToken; + if( NEVER(zAuthArg==0) ){ + goto attach_end; + } + rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); + if(rc!=SQLITE_OK ){ + goto attach_end; + } + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + v = sqlite3GetVdbe(pParse); regArgs = sqlite3GetTempRange(pParse, 4); sqlite3ExprCode(pParse, pFilename, regArgs); sqlite3ExprCode(pParse, pDbname, regArgs+1); @@ -61919,11 +64986,11 @@ const char *zType, /* "view", "trigger", or "index" */ const Token *pName /* Name of the view, trigger, or index */ ){ sqlite3 *db; - if( iDb<0 || iDb==1 ) return 0; + if( NEVER(iDb<0) || iDb==1 ) return 0; db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; pFix->zDb = db->aDb[iDb].zName; pFix->zType = zType; @@ -61951,11 +65018,11 @@ ){ int i; const char *zDb; struct SrcList_item *pItem; - if( pList==0 ) return 0; + if( NEVER(pList==0) ) return 0; zDb = pFix->zDb; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->zDatabase==0 ){ pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb); }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){ @@ -61996,11 +65063,11 @@ SQLITE_PRIVATE int sqlite3FixExpr( DbFixer *pFix, /* Context of the fixation */ Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ - if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ) break; + if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; } @@ -62064,11 +65131,11 @@ ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** -** $Id: auth.c,v 1.29 2007/09/18 15:55:07 drh Exp $ +** $Id: auth.c,v 1.32 2009/07/02 18:40:35 danielk1977 Exp $ */ /* ** All of the code in this file may be omitted by defining a single ** macro. @@ -62135,14 +65202,12 @@ /* ** Write an error message into pParse->zErrMsg that explains that the ** user-supplied authorization function returned an illegal value. */ -static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ - sqlite3ErrorMsg(pParse, "illegal return value (%d) from the " - "authorization function - should be SQLITE_OK, SQLITE_IGNORE, " - "or SQLITE_DENY", rc); +static void sqliteAuthBadReturnCode(Parse *pParse){ + sqlite3ErrorMsg(pParse, "authorizer malfunction"); pParse->rc = SQLITE_ERROR; } /* ** The pExpr should be a TK_COLUMN expression. The table referred to @@ -62163,37 +65228,39 @@ int rc; Table *pTab = 0; /* The table being read */ const char *zCol; /* Name of the column of the table */ int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ - TriggerStack *pStack; /* The stack of current triggers */ int iDb; /* The index of the database the expression refers to */ - - if( db->xAuth==0 ) return; - if( pExpr->op!=TK_COLUMN ) return; + int iCol; /* Index of column in table */ + + if( db->xAuth==0 ) return; iDb = sqlite3SchemaToIndex(pParse->db, pSchema); if( iDb<0 ){ /* An attempt to read a column out of a subquery or other ** temporary table. */ return; } - for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){ - if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; - } - if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){ - pTab = pTabList->a[iSrc].pTab; - }else if( (pStack = pParse->trigStack)!=0 ){ - /* This must be an attempt to read the NEW or OLD pseudo-tables - ** of a trigger. - */ - assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx ); - pTab = pStack->pTab; - } - if( pTab==0 ) return; - if( pExpr->iColumn>=0 ){ - assert( pExpr->iColumn<pTab->nCol ); - zCol = pTab->aCol[pExpr->iColumn].zName; + + assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); + if( pExpr->op==TK_TRIGGER ){ + pTab = pParse->pTriggerTab; + }else{ + assert( pTabList ); + for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){ + if( pExpr->iTable==pTabList->a[iSrc].iCursor ){ + pTab = pTabList->a[iSrc].pTab; + break; + } + } + } + iCol = pExpr->iColumn; + if( NEVER(pTab==0) ) return; + + if( iCol>=0 ){ + assert( iCol<pTab->nCol ); + zCol = pTab->aCol[iCol].zName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKey<pTab->nCol ); zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; @@ -62211,11 +65278,11 @@ }else{ sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol); } pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_OK ){ - sqliteAuthBadReturnCode(pParse, rc); + sqliteAuthBadReturnCode(pParse); } } /* ** Do an authorization check using the code and arguments given. Return @@ -62247,11 +65314,11 @@ if( rc==SQLITE_DENY ){ sqlite3ErrorMsg(pParse, "not authorized"); pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ rc = SQLITE_DENY; - sqliteAuthBadReturnCode(pParse, rc); + sqliteAuthBadReturnCode(pParse); } return rc; } /* @@ -62262,15 +65329,14 @@ SQLITE_PRIVATE void sqlite3AuthContextPush( Parse *pParse, AuthContext *pContext, const char *zContext ){ + assert( pParse ); pContext->pParse = pParse; - if( pParse ){ - pContext->zAuthContext = pParse->zAuthContext; - pParse->zAuthContext = zContext; - } + pContext->zAuthContext = pParse->zAuthContext; + pParse->zAuthContext = zContext; } /* ** Pop an authorization context that was previously pushed ** by sqlite3AuthContextPush @@ -62308,11 +65374,11 @@ ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.528 2009/04/08 13:51:51 drh Exp $ +** $Id: build.c,v 1.557 2009/07/24 17:58:53 danielk1977 Exp $ */ /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. @@ -62349,38 +65415,36 @@ int iDb, /* Index of the database containing the table to lock */ int iTab, /* Root page number of the table to be locked */ u8 isWriteLock, /* True for a write lock */ const char *zName /* Name of the table to be locked */ ){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); int i; int nBytes; TableLock *p; - - if( iDb<0 ){ - return; - } - - for(i=0; i<pParse->nTableLock; i++){ - p = &pParse->aTableLock[i]; + assert( iDb>=0 ); + + for(i=0; i<pToplevel->nTableLock; i++){ + p = &pToplevel->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; } } - nBytes = sizeof(TableLock) * (pParse->nTableLock+1); - pParse->aTableLock = - sqlite3DbReallocOrFree(pParse->db, pParse->aTableLock, nBytes); - if( pParse->aTableLock ){ - p = &pParse->aTableLock[pParse->nTableLock++]; + nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1); + pToplevel->aTableLock = + sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes); + if( pToplevel->aTableLock ){ + p = &pToplevel->aTableLock[pToplevel->nTableLock++]; p->iDb = iDb; p->iTab = iTab; p->isWriteLock = isWriteLock; p->zName = zName; }else{ - pParse->nTableLock = 0; - pParse->db->mallocFailed = 1; + pToplevel->nTableLock = 0; + pToplevel->db->mallocFailed = 1; } } /* ** Code an OP_TableLock instruction for each table locked by the @@ -62388,13 +65452,12 @@ */ static void codeTableLocks(Parse *pParse){ int i; Vdbe *pVdbe; - if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){ - return; - } + pVdbe = sqlite3GetVdbe(pParse); + assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */ for(i=0; i<pParse->nTableLock; i++){ TableLock *p = &pParse->aTableLock[i]; int p1 = p->iDb; sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, @@ -62426,10 +65489,12 @@ /* Begin by generating some termination code at the end of the ** vdbe program */ v = sqlite3GetVdbe(pParse); + assert( !pParse->isMultiWrite + || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); if( v ){ sqlite3VdbeAddOp0(v, OP_Halt); /* The cookie mask contains one bit for each database file open. ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are @@ -62443,17 +65508,19 @@ sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); - sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + if( db->init.busy==0 ){ + sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + } } #ifndef SQLITE_OMIT_VIRTUALTABLE { int i; for(i=0; i<pParse->nVtabLock; i++){ - char *vtab = (char *)pParse->apVtabLock[i]->pVtab; + char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); } pParse->nVtabLock = 0; } #endif @@ -62461,25 +65528,32 @@ /* Once all the cookies have been verified and transactions opened, ** obtain the required table-locks. This is a no-op unless the ** shared-cache feature is enabled. */ codeTableLocks(pParse); + + /* Initialize any AUTOINCREMENT data structures required. + */ + sqlite3AutoincrementBegin(pParse); + + /* Finally, jump back to the beginning of the executable code. */ sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto); } } /* Get the VDBE program ready for execution */ - if( v && pParse->nErr==0 && !db->mallocFailed ){ + if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){ #ifdef SQLITE_DEBUG FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); #endif - assert( pParse->disableColCache==0 ); /* Disables and re-enables match */ + assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem, - pParse->nTab, pParse->explain); + pParse->nTab, pParse->nMaxArg, pParse->explain, + pParse->isMultiWrite && pParse->mayAbort); pParse->rc = SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } @@ -62544,11 +65618,11 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; int nName; assert( zName!=0 ); - nName = sqlite3Strlen(db, zName) + 1; + nName = sqlite3Strlen30(zName); for(i=OMIT_TEMPDB; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName); if( p ) break; @@ -62606,19 +65680,17 @@ ** using the ATTACH command. */ SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; - int nName = sqlite3Strlen(db, zName)+1; + int nName = sqlite3Strlen30(zName); for(i=OMIT_TEMPDB; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ Schema *pSchema = db->aDb[j].pSchema; + assert( pSchema ); if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; - assert( pSchema || (j==1 && !db->aDb[1].pBt) ); - if( pSchema ){ - p = sqlite3HashFind(&pSchema->idxHash, zName, nName); - } + p = sqlite3HashFind(&pSchema->idxHash, zName, nName); if( p ) break; } return p; } @@ -62625,10 +65697,13 @@ /* ** Reclaim the memory used by an index */ static void freeIndex(Index *p){ sqlite3 *db = p->pTable->dbMem; +#ifndef SQLITE_OMIT_ANALYZE + sqlite3DeleteIndexSamples(p); +#endif sqlite3DbFree(db, p->zColAff); sqlite3DbFree(db, p); } /* @@ -62642,11 +65717,11 @@ static void sqlite3DeleteIndex(Index *p){ Index *pOld; const char *zName = p->zName; pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, - sqlite3Strlen30(zName)+1, 0); + sqlite3Strlen30(zName), 0); assert( pOld==0 || pOld==p ); freeIndex(p); } /* @@ -62658,19 +65733,22 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; int len; Hash *pHash = &db->aDb[iDb].pSchema->idxHash; - len = sqlite3Strlen(db, zIdxName); - pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0); + len = sqlite3Strlen30(zIdxName); + pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0); if( pIndex ){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; }else{ Index *p; - for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} - if( p && p->pNext==pIndex ){ + /* Justification of ALWAYS(); The index must be on the list of + ** indices. */ + p = pIndex->pTable->pIndex; + while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; } + if( ALWAYS(p && p->pNext==pIndex) ){ p->pNext = pIndex->pNext; } } freeIndex(pIndex); } @@ -62703,25 +65781,19 @@ } if( iDb>0 ) return; } assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; + sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); /* If one or more of the auxiliary database files has been closed, ** then remove them from the auxiliary database list. We take the ** opportunity to do this here since we have just deleted all of the ** schema hash tables and therefore do not have to make any changes ** to any of those tables. */ - for(i=0; i<db->nDb; i++){ - struct Db *pDb = &db->aDb[i]; - if( pDb->pBt==0 ){ - if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); - pDb->pAux = 0; - } - } for(i=j=2; i<db->nDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ sqlite3DbFree(db, pDb->zName); pDb->zName = 0; @@ -62753,15 +65825,17 @@ */ static void sqliteResetColumnNames(Table *pTable){ int i; Column *pCol; sqlite3 *db = pTable->dbMem; + testcase( db==0 ); assert( pTable!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; i<pTable->nCol; i++, pCol++){ sqlite3DbFree(db, pCol->zName); sqlite3ExprDelete(db, pCol->pDflt); + sqlite3DbFree(db, pCol->zDflt); sqlite3DbFree(db, pCol->zType); sqlite3DbFree(db, pCol->zColl); } sqlite3DbFree(db, pTable->aCol); } @@ -62772,12 +65846,11 @@ /* ** Remove the memory data structures associated with the given ** Table. No changes are made to disk by this routine. ** ** This routine just deletes the data structure. It does not unlink -** the table data structure from the hash table. Nor does it remove -** foreign keys from the sqlite.aFKey hash table. But it does destroy +** the table data structure from the hash table. But it does destroy ** memory structures of the indices and foreign keys associated with ** the table. */ SQLITE_PRIVATE void sqlite3DeleteTable(Table *pTable){ Index *pIndex, *pNext; @@ -62784,10 +65857,11 @@ FKey *pFKey, *pNextFKey; sqlite3 *db; if( pTable==0 ) return; db = pTable->dbMem; + testcase( db==0 ); /* Do not delete the table until the reference count reaches zero. */ pTable->nRef--; if( pTable->nRef>0 ){ return; @@ -62801,17 +65875,13 @@ assert( pIndex->pSchema==pTable->pSchema ); sqlite3DeleteIndex(pIndex); } #ifndef SQLITE_OMIT_FOREIGN_KEY - /* Delete all foreign keys associated with this table. The keys - ** should have already been unlinked from the pSchema->aFKey hash table - */ + /* Delete all foreign keys associated with this table. */ for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ pNextFKey = pFKey->pNextFrom; - assert( sqlite3HashFind(&pTable->pSchema->aFKey, - pFKey->zTo, sqlite3Strlen30(pFKey->zTo)+1)!=pFKey ); sqlite3DbFree(db, pFKey); } #endif /* Delete the Table structure itself. @@ -62831,44 +65901,30 @@ ** Unlink the given table from the hash tables and the delete the ** table structure with all its indices and foreign keys. */ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ Table *p; - FKey *pF1, *pF2; Db *pDb; assert( db!=0 ); assert( iDb>=0 && iDb<db->nDb ); assert( zTabName && zTabName[0] ); pDb = &db->aDb[iDb]; p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, - sqlite3Strlen30(zTabName)+1,0); - if( p ){ -#ifndef SQLITE_OMIT_FOREIGN_KEY - for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ - int nTo = sqlite3Strlen30(pF1->zTo) + 1; - pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo); - if( pF2==pF1 ){ - sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo); - }else{ - while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } - if( pF2 ){ - pF2->pNextTo = pF1->pNextTo; - } - } - } -#endif - sqlite3DeleteTable(p); - } + sqlite3Strlen30(zTabName),0); + sqlite3DeleteTable(p); db->flags |= SQLITE_InternChanges; } /* ** Given a token, return a string that consists of the text of that -** token with any quotations removed. Space to hold the returned string +** token. Space to hold the returned string ** is obtained from sqliteMalloc() and must be freed by the calling ** function. +** +** Any quotation marks (ex: "name", 'name', [name], or `name`) that +** surround the body of the token are removed. ** ** Tokens are often just pointers into the original SQL text and so ** are not \000 terminated and are not persistent. The returned string ** is \000 terminated and is persistent. */ @@ -62956,11 +66012,11 @@ Token **pUnqual /* Write the unqualified object name here */ ){ int iDb; /* Database holding the object */ sqlite3 *db = pParse->db; - if( pName2 && pName2->n>0 ){ + if( ALWAYS(pName2!=0) && pName2->n>0 ){ if( db->init.busy ) { sqlite3ErrorMsg(pParse, "corrupt database"); pParse->nErr++; return -1; } @@ -63121,12 +66177,12 @@ } pTable->zName = zName; pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; - pTable->dbMem = db->lookaside.bEnabled ? db : 0; - if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable); + pTable->dbMem = 0; + assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; /* If this is the magic sqlite_sequence table used by autoincrement, ** then record a pointer to this table in the main database structure ** so that INSERT can find the table easily. @@ -63161,19 +66217,19 @@ ** set them now. */ reg1 = pParse->regRowid = ++pParse->nMem; reg2 = pParse->regRoot = ++pParse->nMem; reg3 = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, 1); /* file_format */ + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? 1 : SQLITE_MAX_FILE_FORMAT; sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, reg3); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3); sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 4, reg3); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3); sqlite3VdbeJumpHere(v, j1); /* This just creates a place-holder record in the sqlite_master table. ** The record created does not contain anything yet. It will be replaced ** by the real entry in code generated at sqlite3EndTable(). @@ -63278,14 +66334,13 @@ ** been seen on a column. This routine sets the notNull flag on ** the column currently under construction. */ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ Table *p; - int i; - if( (p = pParse->pNewTable)==0 ) return; - i = p->nCol-1; - if( i>=0 ) p->aCol[i].notNull = (u8)onError; + p = pParse->pNewTable; + if( p==0 || NEVER(p->nCol<1) ) return; + p->aCol[p->nCol-1].notNull = (u8)onError; } /* ** Scan the column type name zType (length nType) and return the ** associated affinity type. @@ -63309,18 +66364,16 @@ ** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ -SQLITE_PRIVATE char sqlite3AffinityType(const Token *pType){ +SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; - const unsigned char *zIn = pType->z; - const unsigned char *zEnd = &pType->z[pType->n]; - - while( zIn!=zEnd ){ - h = (h<<8) + sqlite3UpperToLower[*zIn]; + + if( zIn ) while( zIn[0] ){ + h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; zIn++; if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ aff = SQLITE_AFF_TEXT; }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ aff = SQLITE_AFF_TEXT; @@ -63358,22 +66411,18 @@ ** that contains the typename of the column and store that string ** in zType. */ SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){ Table *p; - int i; Column *pCol; - sqlite3 *db; - - if( (p = pParse->pNewTable)==0 ) return; - i = p->nCol-1; - if( i<0 ) return; - pCol = &p->aCol[i]; - db = pParse->db; - sqlite3DbFree(db, pCol->zType); - pCol->zType = sqlite3NameFromToken(db, pType); - pCol->affinity = sqlite3AffinityType(pType); + + p = pParse->pNewTable; + if( p==0 || NEVER(p->nCol<1) ) return; + pCol = &p->aCol[p->nCol-1]; + assert( pCol->zType==0 ); + pCol->zType = sqlite3NameFromToken(pParse->db, pType); + pCol->affinity = sqlite3AffinityType(pCol->zType); } /* ** The expression is the default value for the most recently added column ** of the table currently under construction. @@ -63382,29 +66431,33 @@ ** is not the case. ** ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. */ -SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ +SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ Table *p; Column *pCol; sqlite3 *db = pParse->db; - if( (p = pParse->pNewTable)!=0 ){ + p = pParse->pNewTable; + if( p!=0 ){ pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pExpr) ){ + if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ /* A copy of pExpr is used instead of the original, as pExpr contains ** tokens that point to volatile memory. The 'span' of the expression ** is required by pragma table_info. */ sqlite3ExprDelete(db, pCol->pDflt); - pCol->pDflt = sqlite3ExprDup(db, pExpr, EXPRDUP_REDUCE|EXPRDUP_SPAN); - } - } - sqlite3ExprDelete(db, pExpr); + pCol->pDflt = sqlite3ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE); + sqlite3DbFree(db, pCol->zDflt); + pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + (int)(pSpan->zEnd - pSpan->zStart)); + } + } + sqlite3ExprDelete(db, pSpan->pExpr); } /* ** Designate the PRIMARY KEY for the table. pList is a list of names ** of columns that form the primary key. If pList is NULL, then the @@ -63489,18 +66542,16 @@ ){ sqlite3 *db = pParse->db; #ifndef SQLITE_OMIT_CHECK Table *pTab = pParse->pNewTable; if( pTab && !IN_DECLARE_VTAB ){ - /* The CHECK expression must be duplicated so that tokens refer - ** to malloced space and not the (ephemeral) text of the CREATE TABLE - ** statement */ - pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, - sqlite3ExprDup(db, pCheckExpr, 0)); - } -#endif - sqlite3ExprDelete(db, pCheckExpr); + pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr); + }else +#endif + { + sqlite3ExprDelete(db, pCheckExpr); + } } /* ** Set the collation function of the most recently parsed table column ** to the CollSeq given. @@ -63515,11 +66566,11 @@ i = p->nCol-1; db = pParse->db; zColl = sqlite3NameFromToken(db, pToken); if( !zColl ) return; - if( sqlite3LocateCollSeq(pParse, zColl, -1) ){ + if( sqlite3LocateCollSeq(pParse, zColl) ){ Index *pIdx; p->aCol[i].zColl = zColl; /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>", ** then an index may have been created on this column before the @@ -63551,26 +66602,24 @@ ** pParse. ** ** This routine is a wrapper around sqlite3FindCollSeq(). This routine ** invokes the collation factory if the named collation cannot be found ** and generates an error message. -*/ -SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ +** +** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq() +*/ +SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ sqlite3 *db = pParse->db; u8 enc = ENC(db); u8 initbusy = db->init.busy; CollSeq *pColl; - pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); + pColl = sqlite3FindCollSeq(db, enc, zName, initbusy); if( !initbusy && (!pColl || !pColl->xCmp) ){ - pColl = sqlite3GetCollSeq(db, pColl, zName, nName); + pColl = sqlite3GetCollSeq(db, enc, pColl, zName); if( !pColl ){ - if( nName<0 ){ - nName = sqlite3Strlen(db, zName); - } - sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName); - pColl = 0; + sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); } } return pColl; } @@ -63595,11 +66644,11 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ int r1 = sqlite3GetTempReg(pParse); sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 0, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1); sqlite3ReleaseTempReg(pParse, r1); } /* ** Measure the number of characters needed to output the given @@ -63616,65 +66665,10 @@ } return n + 2; } /* -** This function is a wrapper around sqlite3GetToken() used by -** isValidDimension(). This function differs from sqlite3GetToken() in -** that: -** -** * Whitespace is ignored, and -** * The output variable *peToken is set to 0 if the end of the -** nul-terminated input string is reached. -*/ -static int getTokenNoSpace(unsigned char *z, int *peToken){ - int n = 0; - while( sqlite3Isspace(z[n]) ) n++; - if( !z[n] ){ - *peToken = 0; - return 0; - } - return n + sqlite3GetToken(&z[n], peToken); -} - -/* -** Parameter z points to a nul-terminated string. Return true if, when -** whitespace is ignored, the contents of this string matches one of -** the following patterns: -** -** "" -** "(number)" -** "(number,number)" -*/ -static int isValidDimension(unsigned char *z){ - int eToken; - int n = 0; - n += getTokenNoSpace(&z[n], &eToken); - if( eToken ){ - if( eToken!=TK_LP ) return 0; - n += getTokenNoSpace(&z[n], &eToken); - if( eToken==TK_PLUS || eToken==TK_MINUS ){ - n += getTokenNoSpace(&z[n], &eToken); - } - if( eToken!=TK_INTEGER && eToken!=TK_FLOAT ) return 0; - n += getTokenNoSpace(&z[n], &eToken); - if( eToken==TK_COMMA ){ - n += getTokenNoSpace(&z[n], &eToken); - if( eToken==TK_PLUS || eToken==TK_MINUS ){ - n += getTokenNoSpace(&z[n], &eToken); - } - if( eToken!=TK_INTEGER && eToken!=TK_FLOAT ) return 0; - n += getTokenNoSpace(&z[n], &eToken); - } - if( eToken!=TK_RP ) return 0; - getTokenNoSpace(&z[n], &eToken); - } - if( eToken ) return 0; - return 1; -} - -/* ** The first parameter is a pointer to an output buffer. The second ** parameter is a pointer to an integer that contains the offset at ** which to write into the output buffer. This function copies the ** nul-terminated string pointed to by the third parameter, zSignedIdent, ** to the specified offset in the buffer and updates *pIdx to refer @@ -63683,35 +66677,21 @@ ** If the string zSignedIdent consists entirely of alpha-numeric ** characters, does not begin with a digit and is not an SQL keyword, ** then it is copied to the output buffer exactly as it is. Otherwise, ** it is quoted using double-quotes. */ -static void identPut(char *z, int *pIdx, char *zSignedIdent, int isTypename){ +static void identPut(char *z, int *pIdx, char *zSignedIdent){ unsigned char *zIdent = (unsigned char*)zSignedIdent; int i, j, needQuote; i = *pIdx; for(j=0; zIdent[j]; j++){ if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break; } needQuote = sqlite3Isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID; if( !needQuote ){ - if( isTypename ){ - /* If this is a type-name, allow a little more flexibility. In SQLite, - ** a type-name is specified as: - ** - ** ids [ids] [(number [, number])] - ** - ** where "ids" is either a quoted string or a simple identifier (in the - ** above notation, [] means optional). It is a bit tricky to check - ** for all cases, but it is good to avoid unnecessarily quoting common - ** typenames like VARCHAR(10). - */ - needQuote = !isValidDimension(&zIdent[j]); - }else{ - needQuote = zIdent[j]; - } + needQuote = zIdent[j]; } if( needQuote ) z[i++] = '"'; for(j=0; zIdent[j]; j++){ z[i++] = zIdent[j]; @@ -63728,19 +66708,15 @@ ** from sqliteMalloc() and must be freed by the calling function. */ static char *createTableStmt(sqlite3 *db, Table *p){ int i, k, n; char *zStmt; - char *zSep, *zSep2, *zEnd, *z; + char *zSep, *zSep2, *zEnd; Column *pCol; n = 0; for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){ - n += identLength(pCol->zName); - z = pCol->zType; - if( z ){ - n += identLength(z); - } + n += identLength(pCol->zName) + 5; } n += identLength(p->zName); if( n<50 ){ zSep = ""; zSep2 = ","; @@ -63756,22 +66732,42 @@ db->mallocFailed = 1; return 0; } sqlite3_snprintf(n, zStmt, "CREATE TABLE "); k = sqlite3Strlen30(zStmt); - identPut(zStmt, &k, p->zName, 0); + identPut(zStmt, &k, p->zName); zStmt[k++] = '('; for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){ + static const char * const azType[] = { + /* SQLITE_AFF_TEXT */ " TEXT", + /* SQLITE_AFF_NONE */ "", + /* SQLITE_AFF_NUMERIC */ " NUM", + /* SQLITE_AFF_INTEGER */ " INT", + /* SQLITE_AFF_REAL */ " REAL" + }; + int len; + const char *zType; + sqlite3_snprintf(n-k, &zStmt[k], zSep); k += sqlite3Strlen30(&zStmt[k]); zSep = zSep2; - identPut(zStmt, &k, pCol->zName, 0); - if( (z = pCol->zType)!=0 ){ - zStmt[k++] = ' '; - assert( (int)(sqlite3Strlen30(z)+k+1)<=n ); - identPut(zStmt, &k, z, 1); - } + identPut(zStmt, &k, pCol->zName); + assert( pCol->affinity-SQLITE_AFF_TEXT >= 0 ); + assert( pCol->affinity-SQLITE_AFF_TEXT < sizeof(azType)/sizeof(azType[0]) ); + testcase( pCol->affinity==SQLITE_AFF_TEXT ); + testcase( pCol->affinity==SQLITE_AFF_NONE ); + testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); + testcase( pCol->affinity==SQLITE_AFF_INTEGER ); + testcase( pCol->affinity==SQLITE_AFF_REAL ); + + zType = azType[pCol->affinity - SQLITE_AFF_TEXT]; + len = sqlite3Strlen30(zType); + assert( pCol->affinity==SQLITE_AFF_NONE + || pCol->affinity==sqlite3AffinityType(zType) ); + memcpy(&zStmt[k], zType, len); + k += len; + assert( k<=n ); } sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd); return zStmt; } @@ -63803,11 +66799,11 @@ ){ Table *p; sqlite3 *db = pParse->db; int iDb; - if( (pEnd==0 && pSelect==0) || pParse->nErr || db->mallocFailed ) { + if( (pEnd==0 && pSelect==0) || db->mallocFailed ){ return; } p = pParse->pNewTable; if( p==0 ) return; @@ -63859,11 +66855,11 @@ char *zType; /* "view" or "table" */ char *zType2; /* "VIEW" or "TABLE" */ char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */ v = sqlite3GetVdbe(pParse); - if( v==0 ) return; + if( NEVER(v==0) ) return; sqlite3VdbeAddOp1(v, OP_Close, 0); /* ** Initialize zType for the new view or table. @@ -63966,32 +66962,20 @@ } /* Add the table to the in-memory representation of the database. */ - if( db->init.busy && pParse->nErr==0 ){ - Table *pOld; - FKey *pFKey; + if( db->init.busy ){ + Table *pOld; Schema *pSchema = p->pSchema; pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, - sqlite3Strlen30(p->zName)+1,p); + sqlite3Strlen30(p->zName),p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ db->mallocFailed = 1; return; } -#ifndef SQLITE_OMIT_FOREIGN_KEY - for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ - void *data; - int nTo = sqlite3Strlen30(pFKey->zTo) + 1; - pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo); - data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey); - if( data==(void *)pFKey ){ - db->mallocFailed = 1; - } - } -#endif pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; #ifndef SQLITE_OMIT_ALTERTABLE @@ -64022,11 +67006,11 @@ int isTemp, /* TRUE for a TEMPORARY view */ int noErr /* Suppress error messages if VIEW already exists */ ){ Table *p; int n; - const unsigned char *z; + const char *z; Token sEnd; DbFixer sFix; Token *pName; int iDb; sqlite3 *db = pParse->db; @@ -64036,14 +67020,16 @@ sqlite3SelectDelete(db, pSelect); return; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; - if( p==0 || pParse->nErr ){ + if( p==0 ){ sqlite3SelectDelete(db, pSelect); return; } + assert( pParse->nErr==0 ); /* If sqlite3StartTable return non-NULL then + ** there could not have been an error */ sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) && sqlite3FixSelect(&sFix, pSelect) ){ @@ -64067,17 +67053,17 @@ /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; - if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ + if( ALWAYS(sEnd.z[0]!=0) && sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } sEnd.n = 0; n = (int)(sEnd.z - pBegin->z); - z = (const unsigned char*)pBegin->z; - while( n>0 && (z[n-1]==';' || sqlite3Isspace(z[n-1])) ){ n--; } + z = pBegin->z; + while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; } sEnd.z = &z[n-1]; sEnd.n = 1; /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ sqlite3EndTable(pParse, 0, &sEnd, 0); @@ -64119,12 +67105,17 @@ ** a negative nCol, it means two or more views form a loop, like this: ** ** CREATE VIEW one AS SELECT * FROM two; ** CREATE VIEW two AS SELECT * FROM one; ** - ** Actually, this error is caught previously and so the following test - ** should always fail. But we will leave it in place just to be safe. + ** Actually, the error above is now caught prior to reaching this point. + ** But the following test is still important as it does come up + ** in the following: + ** + ** CREATE TABLE main.ex1(a); + ** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1; + ** SELECT * FROM temp.ex1; */ if( pTable->nCol<0 ){ sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); return 1; } @@ -64242,18 +67233,20 @@ */ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ Vdbe *v = sqlite3GetVdbe(pParse); int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); + sqlite3MayAbort(pParse); #ifndef SQLITE_OMIT_AUTOVACUUM /* OP_Destroy stores an in integer r1. If this integer ** is non-zero, then it is the root page number of a table moved to ** location iTable. The following code modifies the sqlite_master table to ** reflect this. ** ** The "#NNN" in the SQL is a special constant that means whatever value - ** is in register NNN. See sqlite3RegisterExpr(). + ** is in register NNN. See grammar rules associated with the TK_REGISTER + ** token for additional information. */ sqlite3NestedParse(pParse, "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1); #endif @@ -64327,13 +67320,14 @@ Table *pTab; Vdbe *v; sqlite3 *db = pParse->db; int iDb; - if( pParse->nErr || db->mallocFailed ){ + if( db->mallocFailed ){ goto exit_drop_table; } + assert( pParse->nErr==0 ); assert( pName->nSrc==1 ); pTab = sqlite3LocateTable(pParse, isView, pName->a[0].zName, pName->a[0].zDatabase); if( pTab==0 ){ @@ -64367,11 +67361,11 @@ code = SQLITE_DROP_VIEW; } #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( IsVirtual(pTab) ){ code = SQLITE_DROP_VTABLE; - zArg2 = pTab->pMod->zName; + zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName; #endif }else{ if( !OMIT_TEMPDB && iDb==1 ){ code = SQLITE_DROP_TEMP_TABLE; }else{ @@ -64414,13 +67408,11 @@ Db *pDb = &db->aDb[iDb]; sqlite3BeginWriteOperation(pParse, 1, iDb); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ - if( v ){ - sqlite3VdbeAddOp0(v, OP_VBegin); - } + sqlite3VdbeAddOp0(v, OP_VBegin); } #endif /* Drop all triggers associated with the table being dropped. Code ** is generated to remove entries from sqlite_master and/or @@ -64494,13 +67486,11 @@ ** pTo table that the foreign key points to. flags contains all ** information about the conflict resolution algorithms specified ** in the ON DELETE, ON UPDATE and ON INSERT clauses. ** ** An FKey structure is created and added to the table currently -** under construction in the pParse->pNewTable field. The new FKey -** is not linked into db->aFKey at this point - that does not happen -** until sqlite3EndTable(). +** under construction in the pParse->pNewTable field. ** ** The foreign key is set for IMMEDIATE processing. A subsequent call ** to sqlite3DeferForeignKey() might change this to DEFERRED. */ SQLITE_PRIVATE void sqlite3CreateForeignKey( @@ -64518,14 +67508,14 @@ int i; int nCol; char *z; assert( pTo!=0 ); - if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end; + if( p==0 || IN_DECLARE_VTAB ) goto fk_end; if( pFromCol==0 ){ int iCol = p->nCol-1; - if( iCol<0 ) goto fk_end; + if( NEVER(iCol<0) ) goto fk_end; if( pToCol && pToCol->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "foreign key on %s" " should reference only one column of table %T", p->aCol[iCol].zName, pTo); goto fk_end; @@ -64537,11 +67527,11 @@ "columns in the referenced table"); goto fk_end; }else{ nCol = pFromCol->nExpr; } - nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1; + nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1; if( pToCol ){ for(i=0; i<pToCol->nExpr; i++){ nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1; } } @@ -64549,18 +67539,16 @@ if( pFKey==0 ){ goto fk_end; } pFKey->pFrom = p; pFKey->pNextFrom = p->pFKey; - z = (char*)&pFKey[1]; - pFKey->aCol = (struct sColMap*)z; - z += sizeof(struct sColMap)*nCol; + z = (char*)&pFKey->aCol[nCol]; pFKey->zTo = z; memcpy(z, pTo->z, pTo->n); z[pTo->n] = 0; - z += pTo->n+1; - pFKey->pNextTo = 0; + sqlite3Dequote(z); + z += pTo->n+1; pFKey->nCol = nCol; if( pFromCol==0 ){ pFKey->aCol[0].iFrom = p->nCol-1; }else{ for(i=0; i<nCol; i++){ @@ -64673,23 +67661,29 @@ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); regRecord = sqlite3GetTempReg(pParse); regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); if( pIndex->onError!=OE_None ){ - int j1, j2; - int regRowid; - - regRowid = regIdxKey + pIndex->nColumn; - j1 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdxKey, 0, pIndex->nColumn); - j2 = sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, - 0, regRowid, SQLITE_INT_TO_PTR(regRecord), P4_INT32); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, 0, - "indexed columns are not unique", P4_STATIC); - sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeJumpHere(v, j2); + const int regRowid = regIdxKey + pIndex->nColumn; + const int j2 = sqlite3VdbeCurrentAddr(v) + 2; + void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey); + + /* The registers accessed by the OP_IsUnique opcode were allocated + ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey() + ** call above. Just before that function was freed they were released + ** (made available to the compiler for reuse) using + ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique + ** opcode use the values stored within seems dangerous. However, since + ** we can be sure that no other temp registers have been allocated + ** since sqlite3ReleaseTempRange() was called, it is safe to do so. + */ + sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32); + sqlite3HaltConstraint( + pParse, OE_Abort, "indexed columns are not unique", P4_STATIC); } sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_Close, iTab); sqlite3VdbeAddOp1(v, OP_Close, iIdx); @@ -64734,11 +67728,16 @@ struct ExprList_item *pListItem; /* For looping over pList */ int nCol; int nExtra = 0; char *zExtra; - if( pParse->nErr || db->mallocFailed || IN_DECLARE_VTAB ){ + assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */ + assert( pParse->nErr==0 ); /* Never called with prior errors */ + if( db->mallocFailed || IN_DECLARE_VTAB ){ + goto exit_create_index; + } + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; } /* ** Find the table that is to be indexed. Return early if not found. @@ -64758,11 +67757,11 @@ ** is a temp table. If so, set the database to 1. Do not do this ** if initialising a database schema. */ if( !db->init.busy ){ pTab = sqlite3SrcListLookup(pParse, pTblName); - if( pName2 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ + if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } } #endif @@ -64783,11 +67782,12 @@ if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; - if( pTab==0 || pParse->nErr ) goto exit_create_index; + assert( pTab!=0 ); + assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } @@ -64817,17 +67817,15 @@ ** dealing with a primary key or UNIQUE constraint. We have to invent our ** own name. */ if( pName ){ zName = sqlite3NameFromToken(db, pName); - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; if( zName==0 ) goto exit_create_index; if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto exit_create_index; } if( !db->init.busy ){ - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; if( sqlite3FindTable(db, zName, 0)!=0 ){ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); goto exit_create_index; } } @@ -64866,25 +67864,30 @@ /* If pList==0, it means this routine was called to make a primary ** key out of the last column added to the table under construction. ** So create a fake list to simulate this. */ if( pList==0 ){ - nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName; + nullId.z = pTab->aCol[pTab->nCol-1].zName; nullId.n = sqlite3Strlen30((char*)nullId.z); - pList = sqlite3ExprListAppend(pParse, 0, 0, &nullId); + pList = sqlite3ExprListAppend(pParse, 0, 0); if( pList==0 ) goto exit_create_index; + sqlite3ExprListSetName(pParse, pList, &nullId, 0); pList->a[0].sortOrder = (u8)sortOrder; } /* Figure out how many bytes of space are required to store explicitly ** specified collation sequence names. */ for(i=0; i<pList->nExpr; i++){ - Expr *pExpr; - CollSeq *pColl; - if( (pExpr = pList->a[i].pExpr)!=0 && (pColl = pExpr->pColl)!=0 ){ - nExtra += (1 + sqlite3Strlen30(pColl->zName)); + Expr *pExpr = pList->a[i].pExpr; + if( pExpr ){ + CollSeq *pColl = pExpr->pColl; + /* Either pColl!=0 or there was an OOM failure. But if an OOM + ** failure we have quit before reaching this point. */ + if( ALWAYS(pColl) ){ + nExtra += (1 + sqlite3Strlen30(pColl->zName)); + } } } /* ** Allocate the index structure. @@ -64925,10 +67928,16 @@ } /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. + ** + ** TODO: Add a test to make sure that the same column is not named + ** more than once within the same index. Only the first instance of + ** the column will ever be used by the optimizer. Note that using the + ** same column more than once cannot be an error because that would + ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ const char *zColName = pListItem->zName; Column *pTabCol; int requestedSortOrder; @@ -64940,29 +67949,32 @@ if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, zColName); goto exit_create_index; } - /* TODO: Add a test to make sure that the same column is not named - ** more than once within the same index. Only the first instance of - ** the column will ever be used by the optimizer. Note that using the - ** same column more than once cannot be an error because that would - ** break backwards compatibility - it needs to be a warning. - */ pIndex->aiColumn[i] = j; - if( pListItem->pExpr && pListItem->pExpr->pColl ){ - assert( pListItem->pExpr->pColl ); + /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of + ** the way the "idxlist" non-terminal is constructed by the parser, + ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl + ** must exist or else there must have been an OOM error. But if there + ** was an OOM error, we would never reach this point. */ + if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ + int nColl; + zColl = pListItem->pExpr->pColl->zName; + nColl = sqlite3Strlen30(zColl) + 1; + assert( nExtra>=nColl ); + memcpy(zExtra, zColl, nColl); zColl = zExtra; - sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName); - zExtra += (sqlite3Strlen30(zColl) + 1); + zExtra += nColl; + nExtra -= nColl; }else{ zColl = pTab->aCol[j].zColl; if( !zColl ){ zColl = db->pDfltColl->zName; } } - if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){ + if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ goto exit_create_index; } pIndex->azColl[i] = zColl; requestedSortOrder = pListItem->sortOrder & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; @@ -64980,10 +67992,18 @@ ** ** Either way, check to see if the table already has such an index. If ** so, don't bother creating this one. This only applies to ** automatically created indices. Users can do as they wish with ** explicit indices. + ** + ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent + ** (and thus suppressing the second one) even if they have different + ** sort orders. + ** + ** If there are different collating sequences or if the columns of + ** the constraint occur in different orders, then the constraints are + ** considered distinct and both result in separate indices. */ Index *pIdx; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int k; assert( pIdx->onError!=OE_None ); @@ -64990,14 +68010,15 @@ assert( pIdx->autoIndex ); assert( pIndex->onError!=OE_None ); if( pIdx->nColumn!=pIndex->nColumn ) continue; for(k=0; k<pIdx->nColumn; k++){ - const char *z1 = pIdx->azColl[k]; - const char *z2 = pIndex->azColl[k]; + const char *z1; + const char *z2; if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; - if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break; + z1 = pIdx->azColl[k]; + z2 = pIndex->azColl[k]; if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; } if( k==pIdx->nColumn ){ if( pIdx->onError!=pIndex->onError ){ /* This constraint creates the same index as a previous @@ -65024,11 +68045,11 @@ ** in-memory database structures. */ if( db->init.busy ){ Index *p; p = sqlite3HashInsert(&pIndex->pSchema->idxHash, - pIndex->zName, sqlite3Strlen30(pIndex->zName)+1, + pIndex->zName, sqlite3Strlen30(pIndex->zName), pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ db->mallocFailed = 1; goto exit_create_index; @@ -65052,11 +68073,11 @@ ** If pTblName==0 it means this index is generated as a primary key ** or UNIQUE constraint of a CREATE TABLE statement. Since the table ** has just been created, it contains no data and the index initialization ** step can be skipped. */ - else if( db->init.busy==0 ){ + else{ /* if( db->init.busy==0 ) */ Vdbe *v; char *zStmt; int iMem = ++pParse->nMem; v = sqlite3GetVdbe(pParse); @@ -65069,11 +68090,12 @@ sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem); /* Gather the complete text of the CREATE INDEX statement into ** the zStmt variable */ - if( pStart && pEnd ){ + if( pStart ){ + assert( pEnd!=0 ); /* A named index with an explicit CREATE INDEX statement */ zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", onError==OE_None ? "" : " UNIQUE", pEnd->z - pName->z + 1, pName->z); @@ -65107,12 +68129,13 @@ } } /* When adding an index to the list of indices for a table, make ** sure all indices labeled OE_Replace come after all those labeled - ** OE_Ignore. This is necessary for the correct operation of UPDATE - ** and INSERT. + ** OE_Ignore. This is necessary for the correct constraint check + ** processing (in sqlite3GenerateConstraintChecks()) as part of + ** UPDATE and INSERT statements. */ if( db->init.busy || pTblName==0 ){ if( onError!=OE_Replace || pTab->pIndex==0 || pTab->pIndex->onError==OE_Replace){ pIndex->pNext = pTab->pIndex; @@ -65136,32 +68159,10 @@ } sqlite3ExprListDelete(db, pList); sqlite3SrcListDelete(db, pTblName); sqlite3DbFree(db, zName); return; -} - -/* -** Generate code to make sure the file format number is at least minFormat. -** The generated code will increase the file format number if necessary. -*/ -SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ - Vdbe *v; - v = sqlite3GetVdbe(pParse); - if( v ){ - int r1 = sqlite3GetTempReg(pParse); - int r2 = sqlite3GetTempReg(pParse); - int j1; - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, 1); - sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, r2); - sqlite3VdbeJumpHere(v, j1); - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempReg(pParse, r2); - } } /* ** Fill the Index.aiRowEst[] array with default information - information ** to be used when we have not run the ANALYZE command. @@ -65205,11 +68206,12 @@ Index *pIndex; Vdbe *v; sqlite3 *db = pParse->db; int iDb; - if( pParse->nErr || db->mallocFailed ){ + assert( pParse->nErr==0 ); /* Never called with prior errors */ + if( db->mallocFailed ){ goto exit_drop_index; } assert( pName->nSrc==1 ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_drop_index; @@ -65396,14 +68398,12 @@ int i; /* Sanity checking on calling parameters */ assert( iStart>=0 ); assert( nExtra>=1 ); - if( pSrc==0 || iStart>pSrc->nSrc ){ - assert( db->mallocFailed ); - return pSrc; - } + assert( pSrc!=0 ); + assert( iStart<=pSrc->nSrc ); /* Allocate additional space if needed */ if( pSrc->nSrc+nExtra>pSrc->nAlloc ){ SrcList *pNew; int nAlloc = pSrc->nSrc+nExtra; @@ -65437,11 +68437,11 @@ } /* ** Append a new table name to the given SrcList. Create a new SrcList if -** need be. A new entry is created in the SrcList even if pToken is NULL. +** need be. A new entry is created in the SrcList even if pTable is NULL. ** ** A SrcList is returned, or NULL if there is an OOM error. The returned ** SrcList might be the same as the SrcList that was input or it might be ** a new one. If an OOM error does occurs, then the prior value of pList ** that is input to this routine is automatically freed. @@ -65461,19 +68461,26 @@ ** Then B is a table name and the database name is unspecified. If called ** like this: ** ** sqlite3SrcListAppend(D,A,B,C); ** -** Then C is the table name and B is the database name. +** Then C is the table name and B is the database name. If C is defined +** then so is B. In other words, we never have a case where: +** +** sqlite3SrcListAppend(D,A,0,C); +** +** Both pTable and pDatabase are assumed to be quoted. They are dequoted +** before being added to the SrcList. */ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend( sqlite3 *db, /* Connection to notify of malloc failures */ SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */ Token *pTable, /* Table to append */ Token *pDatabase /* Database of the table */ ){ struct SrcList_item *pItem; + assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(SrcList) ); if( pList==0 ) return 0; pList->nAlloc = 1; } @@ -65484,11 +68491,11 @@ } pItem = &pList->a[pList->nSrc-1]; if( pDatabase && pDatabase->z==0 ){ pDatabase = 0; } - if( pDatabase && pTable ){ + if( pDatabase ){ Token *pTemp = pDatabase; pDatabase = pTable; pTable = pTemp; } pItem->zName = sqlite3NameFromToken(db, pTable); @@ -65560,33 +68567,45 @@ Expr *pOn, /* The ON clause of a join */ IdList *pUsing /* The USING clause of a join */ ){ struct SrcList_item *pItem; sqlite3 *db = pParse->db; + if( !p && (pOn || pUsing) ){ + sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", + (pOn ? "ON" : "USING") + ); + goto append_from_error; + } p = sqlite3SrcListAppend(db, p, pTable, pDatabase); - if( p==0 || p->nSrc==0 ){ - sqlite3ExprDelete(db, pOn); - sqlite3IdListDelete(db, pUsing); - sqlite3SelectDelete(db, pSubquery); - return p; + if( p==0 || NEVER(p->nSrc==0) ){ + goto append_from_error; } pItem = &p->a[p->nSrc-1]; - if( pAlias && pAlias->n ){ + assert( pAlias!=0 ); + if( pAlias->n ){ pItem->zAlias = sqlite3NameFromToken(db, pAlias); } pItem->pSelect = pSubquery; pItem->pOn = pOn; pItem->pUsing = pUsing; return p; + + append_from_error: + assert( p==0 ); + sqlite3ExprDelete(db, pOn); + sqlite3IdListDelete(db, pUsing); + sqlite3SelectDelete(db, pSubquery); + return 0; } /* ** Add an INDEXED BY or NOT INDEXED clause to the most recently added ** element of the source-list passed as the second argument. */ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ - if( pIndexedBy && p && p->nSrc>0 ){ + assert( pIndexedBy!=0 ); + if( p && ALWAYS(p->nSrc>0) ){ struct SrcList_item *pItem = &p->a[p->nSrc-1]; assert( pItem->notIndexed==0 && pItem->zIndex==0 ); if( pIndexedBy->n==1 && !pIndexedBy->z ){ /* A "NOT INDEXED" clause was supplied. See parse.y ** construct "indexed_opt" for details. */ @@ -65628,14 +68647,17 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ sqlite3 *db; Vdbe *v; int i; - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || db->mallocFailed ) return; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; - + assert( pParse!=0 ); + db = pParse->db; + assert( db!=0 ); +/* if( db->aDb[0].pBt==0 ) return; */ + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ + return; + } v = sqlite3GetVdbe(pParse); if( !v ) return; if( type!=TK_DEFERRED ){ for(i=0; i<db->nDb; i++){ sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); @@ -65650,14 +68672,17 @@ */ SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){ sqlite3 *db; Vdbe *v; - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || db->mallocFailed ) return; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; - + assert( pParse!=0 ); + db = pParse->db; + assert( db!=0 ); +/* if( db->aDb[0].pBt==0 ) return; */ + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ + return; + } v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); } } @@ -65667,14 +68692,17 @@ */ SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){ sqlite3 *db; Vdbe *v; - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || db->mallocFailed ) return; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; - + assert( pParse!=0 ); + db = pParse->db; + assert( db!=0 ); +/* if( db->aDb[0].pBt==0 ) return; */ + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){ + return; + } v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1); } } @@ -65751,30 +68779,30 @@ ** If iDb<0 then code the OP_Goto only - don't set flag to verify the ** schema on any databases. This can be used to position the OP_Goto ** early in the code, before we know if any database tables will be used. */ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ - sqlite3 *db; - Vdbe *v; - int mask; - - v = sqlite3GetVdbe(pParse); - if( v==0 ) return; /* This only happens if there was a prior error */ - db = pParse->db; - if( pParse->cookieGoto==0 ){ - pParse->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; + Parse *pToplevel = sqlite3ParseToplevel(pParse); + + if( pToplevel->cookieGoto==0 ){ + Vdbe *v = sqlite3GetVdbe(pToplevel); + if( v==0 ) return; /* This only happens if there was a prior error */ + pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; } if( iDb>=0 ){ + sqlite3 *db = pToplevel->db; + int mask; + assert( iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDb<SQLITE_MAX_ATTACHED+2 ); mask = 1<<iDb; - if( (pParse->cookieMask & mask)==0 ){ - pParse->cookieMask |= mask; - pParse->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; + if( (pToplevel->cookieMask & mask)==0 ){ + pToplevel->cookieMask |= mask; + pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ - sqlite3OpenTempDatabase(pParse); + sqlite3OpenTempDatabase(pToplevel); } } } } @@ -65790,29 +68818,50 @@ ** rollback the whole transaction. For operations where all constraints ** can be checked before any changes are made to the database, it is never ** necessary to undo a write and the checkpoint should not be set. */ SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ - Vdbe *v = sqlite3GetVdbe(pParse); - if( v==0 ) return; + Parse *pToplevel = sqlite3ParseToplevel(pParse); sqlite3CodeVerifySchema(pParse, iDb); - pParse->writeMask |= 1<<iDb; - if( setStatement && pParse->nested==0 ){ - sqlite3VdbeAddOp1(v, OP_Statement, iDb); - } + pToplevel->writeMask |= 1<<iDb; + pToplevel->isMultiWrite |= setStatement; +} + +/* +** Set the "may throw abort exception" flag for the statement currently +** being coded. +*/ +SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); + pToplevel->mayAbort = 1; +} + +/* +** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT +** error. The onError parameter determines which (if any) of the statement +** and/or current transaction is rolled back. +*/ +SQLITE_PRIVATE void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( onError==OE_Abort ){ + sqlite3MayAbort(pParse); + } + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type); } /* ** Check to see if pIndex uses the collating sequence pColl. Return ** true if it does and false if it does not. */ #ifndef SQLITE_OMIT_REINDEX static int collationMatch(const char *zColl, Index *pIndex){ int i; + assert( zColl!=0 ); for(i=0; i<pIndex->nColumn; i++){ const char *z = pIndex->azColl[i]; - if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){ + assert( z!=0 ); + if( 0==sqlite3StrICmp(z, zColl) ){ return 1; } } return 0; } @@ -65887,24 +68936,22 @@ ** and code in pParse and return NULL. */ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ return; } - if( pName1==0 || pName1->z==0 ){ + if( pName1==0 ){ reindexDatabases(pParse, 0); return; - }else if( pName2==0 || pName2->z==0 ){ + }else if( NEVER(pName2==0) || pName2->z==0 ){ char *zColl; assert( pName1->z ); zColl = sqlite3NameFromToken(pParse->db, pName1); if( !zColl ) return; - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0); + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); if( pColl ){ - if( zColl ){ - reindexDatabases(pParse, zColl); - sqlite3DbFree(db, zColl); - } + reindexDatabases(pParse, zColl); + sqlite3DbFree(db, zColl); return; } sqlite3DbFree(db, zColl); } iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); @@ -65951,11 +68998,11 @@ pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); for(i=0; i<nCol; i++){ char *zColl = pIdx->azColl[i]; assert( zColl ); - pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1); + pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl); pKey->aSortOrder[i] = pIdx->aSortOrder[i]; } pKey->nField = (u16)nCol; } @@ -65981,33 +69028,31 @@ ************************************************************************* ** ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. ** -** $Id: callback.c,v 1.37 2009/03/24 15:08:10 drh Exp $ +** $Id: callback.c,v 1.42 2009/06/17 00:35:31 drh Exp $ */ /* ** Invoke the 'collation needed' callback to request a collation sequence -** in the database text encoding of name zName, length nName. -** If the collation sequence -*/ -static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ +** in the encoding enc of name zName, length nName. +*/ +static void callCollNeeded(sqlite3 *db, int enc, const char *zName){ assert( !db->xCollNeeded || !db->xCollNeeded16 ); - if( nName<0 ) nName = sqlite3Strlen(db, zName); if( db->xCollNeeded ){ - char *zExternal = sqlite3DbStrNDup(db, zName, nName); + char *zExternal = sqlite3DbStrDup(db, zName); if( !zExternal ) return; - db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal); + db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal); sqlite3DbFree(db, zExternal); } #ifndef SQLITE_OMIT_UTF16 if( db->xCollNeeded16 ){ char const *zExternal; sqlite3_value *pTmp = sqlite3ValueNew(db); - sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); + sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); if( zExternal ){ db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); } sqlite3ValueFree(pTmp); @@ -66023,15 +69068,14 @@ ** possible. */ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ CollSeq *pColl2; char *z = pColl->zName; - int n = sqlite3Strlen30(z); int i; static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; for(i=0; i<3; i++){ - pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0); + pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0); if( pColl2->xCmp!=0 ){ memcpy(pColl, pColl2, sizeof(CollSeq)); pColl->xDel = 0; /* Do not copy the destructor */ return SQLITE_OK; } @@ -66040,38 +69084,39 @@ } /* ** This function is responsible for invoking the collation factory callback ** or substituting a collation sequence of a different encoding when the -** requested collation sequence is not available in the database native -** encoding. +** requested collation sequence is not available in the desired encoding. ** ** If it is not NULL, then pColl must point to the database native encoding ** collation sequence with name zName, length nName. ** ** The return value is either the collation sequence to be used in database ** db for collation type name zName, length nName, or NULL, if no collation ** sequence can be found. +** +** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() */ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( - sqlite3* db, - CollSeq *pColl, - const char *zName, - int nName + sqlite3* db, /* The database connection */ + u8 enc, /* The desired encoding for the collating sequence */ + CollSeq *pColl, /* Collating sequence with native encoding, or NULL */ + const char *zName /* Collating sequence name */ ){ CollSeq *p; p = pColl; if( !p ){ - p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); + p = sqlite3FindCollSeq(db, enc, zName, 0); } if( !p || !p->xCmp ){ /* No collation sequence of this type for this encoding is registered. ** Call the collation factory to see if it can supply us with one. */ - callCollNeeded(db, zName, nName); - p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); + callCollNeeded(db, enc, zName); + p = sqlite3FindCollSeq(db, enc, zName, 0); } if( p && !p->xCmp && synthCollSeq(db, p) ){ p = 0; } assert( !p || p->xCmp ); @@ -66090,15 +69135,14 @@ ** from the main database is substituted, if one is available. */ SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ if( pColl ){ const char *zName = pColl->zName; - CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1); + sqlite3 *db = pParse->db; + CollSeq *p = sqlite3GetCollSeq(db, ENC(db), pColl, zName); if( !p ){ - if( pParse->nErr==0 ){ - sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); - } + sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); pParse->nErr++; return SQLITE_ERROR; } assert( p==pColl ); } @@ -66119,17 +69163,16 @@ ** Stored immediately after the three collation sequences is a copy of ** the collation sequence name. A pointer to this string is stored in ** each collation sequence structure. */ static CollSeq *findCollSeqEntry( - sqlite3 *db, - const char *zName, - int nName, - int create + sqlite3 *db, /* Database connection */ + const char *zName, /* Name of the collating sequence */ + int create /* Create a new entry if true */ ){ CollSeq *pColl; - if( nName<0 ) nName = sqlite3Strlen(db, zName); + int nName = sqlite3Strlen30(zName); pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); if( 0==pColl && create ){ pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); if( pColl ){ @@ -66169,21 +69212,22 @@ ** ** A separate function sqlite3LocateCollSeq() is a wrapper around ** this routine. sqlite3LocateCollSeq() invokes the collation factory ** if necessary and generates an error message if the collating sequence ** cannot be found. +** +** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq() */ SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq( sqlite3 *db, u8 enc, const char *zName, - int nName, int create ){ CollSeq *pColl; if( zName ){ - pColl = findCollSeqEntry(db, zName, nName, create); + pColl = findCollSeqEntry(db, zName, create); }else{ pColl = db->pDfltColl; } assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); @@ -66262,10 +69306,11 @@ int nName = sqlite3Strlen30(pDef->zName); u8 c1 = (u8)pDef->zName[0]; int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a); pOther = functionSearch(pHash, h, pDef->zName, nName); if( pOther ){ + assert( pOther!=pDef && pOther->pNext!=pDef ); pDef->pNext = pOther->pNext; pOther->pNext = pDef; }else{ pDef->pNext = 0; pDef->pHash = pHash->a[h]; @@ -66308,11 +69353,10 @@ int bestScore = 0; /* Score of best match */ int h; /* Hash value */ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); - if( nArg<-1 ) nArg = -1; h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); /* First search for a match amongst the application-defined functions. */ p = functionSearch(&db->aFunc, h, zName, nName); @@ -66380,18 +69424,17 @@ HashElem *pElem; Schema *pSchema = (Schema *)p; temp1 = pSchema->tblHash; temp2 = pSchema->trigHash; - sqlite3HashInit(&pSchema->trigHash, 0); - sqlite3HashClear(&pSchema->aFKey); + sqlite3HashInit(&pSchema->trigHash); sqlite3HashClear(&pSchema->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem)); } sqlite3HashClear(&temp2); - sqlite3HashInit(&pSchema->tblHash, 0); + sqlite3HashInit(&pSchema->tblHash); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); assert( pTab->dbMem==0 ); sqlite3DeleteTable(pTab); } @@ -66412,14 +69455,13 @@ p = (Schema *)sqlite3MallocZero(sizeof(Schema)); } if( !p ){ db->mallocFailed = 1; }else if ( 0==p->file_format ){ - sqlite3HashInit(&p->tblHash, 0); - sqlite3HashInit(&p->idxHash, 0); - sqlite3HashInit(&p->trigHash, 0); - sqlite3HashInit(&p->aFKey, 1); + sqlite3HashInit(&p->tblHash); + sqlite3HashInit(&p->idxHash); + sqlite3HashInit(&p->trigHash); p->enc = SQLITE_UTF8; } return p; } @@ -66437,11 +69479,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.198 2009/03/05 03:48:07 shane Exp $ +** $Id: delete.c,v 1.207 2009/08/08 18:01:08 drh Exp $ */ /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables @@ -66467,47 +69509,37 @@ ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is ** writable return 0; */ SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ - if( ((pTab->tabFlags & TF_Readonly)!=0 - && (pParse->db->flags & SQLITE_WriteSchema)==0 - && pParse->nested==0) -#ifndef SQLITE_OMIT_VIRTUALTABLE - || (pTab->pMod && pTab->pMod->pModule->xUpdate==0) -#endif + /* A table is not writable under the following circumstances: + ** + ** 1) It is a virtual table and no implementation of the xUpdate method + ** has been provided, or + ** 2) It is a system table (i.e. sqlite_master), this call is not + ** part of a nested parse and writable_schema pragma has not + ** been specified. + ** + ** In either case leave an error message in pParse and return non-zero. + */ + if( ( IsVirtual(pTab) + && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) + || ( (pTab->tabFlags & TF_Readonly)!=0 + && (pParse->db->flags & SQLITE_WriteSchema)==0 + && pParse->nested==0 ) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } + #ifndef SQLITE_OMIT_VIEW if( !viewOk && pTab->pSelect ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); return 1; } #endif return 0; -} - -/* -** Generate code that will open a table for reading. -*/ -SQLITE_PRIVATE void sqlite3OpenTable( - Parse *p, /* Generate code into this VDBE */ - int iCur, /* The cursor number of the table */ - int iDb, /* The database index in sqlite3.aDb[] */ - Table *pTab, /* The table to be opened */ - int opcode /* OP_OpenRead or OP_OpenWrite */ -){ - Vdbe *v; - if( IsVirtual(pTab) ) return; - v = sqlite3GetVdbe(p); - assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); - sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); - sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); - sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32); - VdbeComment((v, "%s", pTab->zName)); } #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) /* @@ -66526,16 +69558,22 @@ sqlite3 *db = pParse->db; pDup = sqlite3SelectDup(db, pView->pSelect, 0); if( pWhere ){ SrcList *pFrom; - Token viewName; pWhere = sqlite3ExprDup(db, pWhere, 0); - viewName.z = (u8*)pView->zName; - viewName.n = (unsigned int)sqlite3Strlen30((const char*)viewName.z); - pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0); + pFrom = sqlite3SrcListAppend(db, 0, 0, 0); + if( pFrom ){ + assert( pFrom->nSrc==1 ); + pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName); + pFrom->a[0].pSelect = pDup; + assert( pFrom->a[0].pOn==0 ); + assert( pFrom->a[0].pUsing==0 ); + }else{ + sqlite3SelectDelete(db, pDup); + } pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); } sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pDup, &dest); sqlite3SelectDelete(db, pDup); @@ -66591,13 +69629,13 @@ ** DELETE FROM table_a WHERE rowid IN ( ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 ** ); */ - pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0); + pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); if( pSelectRowid == 0 ) goto limit_where_cleanup_2; - pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0); + pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); if( pEList == 0 ) goto limit_where_cleanup_2; /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree ** and the SELECT subtree. */ pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); @@ -66610,11 +69648,11 @@ pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, pOrderBy,0,pLimit,pOffset); if( pSelect == 0 ) return 0; /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ - pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0); + pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); if( pWhereRowid == 0 ) goto limit_where_cleanup_1; pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0); if( pInClause == 0 ) goto limit_where_cleanup_1; pInClause->x.pSelect = pSelect; @@ -66656,27 +69694,21 @@ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ - int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ NameContext sNC; /* Name context to resolve expressions in */ int iDb; /* Database number */ int memCnt = -1; /* Memory cell used for change counting */ int rcauth; /* Value returned by authorization callback */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ #endif - int iBeginAfterTrigger = 0; /* Address of after trigger program */ - int iEndAfterTrigger = 0; /* Exit of after trigger program */ - int iBeginBeforeTrigger = 0; /* Address of before trigger program */ - int iEndBeforeTrigger = 0; /* Exit of before trigger program */ - u32 old_col_mask = 0; /* Mask of OLD.* columns in use */ - - sContext.pParse = 0; + + memset(&sContext, 0, sizeof(sContext)); db = pParse->db; if( pParse->nErr || db->mallocFailed ){ goto delete_from_cleanup; } assert( pTabList->nSrc==1 ); @@ -66702,10 +69734,16 @@ #ifdef SQLITE_OMIT_VIEW # undef isView # define isView 0 #endif + /* If pTab is really a view, make sure it has been initialized. + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto delete_from_cleanup; + } + if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ goto delete_from_cleanup; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb<db->nDb ); @@ -66714,22 +69752,10 @@ assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; } assert(!isView || pTrigger); - - /* If pTab is really a view, make sure it has been initialized. - */ - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto delete_from_cleanup; - } - - /* Allocate a cursor used to store the old.* data for a trigger. - */ - if( pTrigger ){ - oldIdx = pParse->nTab++; - } /* Assign cursor number to the table and all its indices. */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; @@ -66749,28 +69775,10 @@ if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, (pTrigger?1:0), iDb); - - if( pTrigger ){ - int orconf = ((pParse->trigStack)?pParse->trigStack->orconf:OE_Default); - int iGoto = sqlite3VdbeAddOp0(v, OP_Goto); - addr = sqlite3VdbeMakeLabel(v); - - iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v); - (void)sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, 0, - TRIGGER_BEFORE, pTab, -1, oldIdx, orconf, addr, &old_col_mask, 0); - iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto); - - iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v); - (void)sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, 0, - TRIGGER_AFTER, pTab, -1, oldIdx, orconf, addr, &old_col_mask, 0); - iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto); - - sqlite3VdbeJumpHere(v, iGoto); - } /* If we are trying to delete from a view, realize that view into ** a ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) @@ -66796,19 +69804,17 @@ sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); } #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION /* Special case: A DELETE without a WHERE clause deletes everything. - ** It is easier just to erase the whole table. Note, however, that - ** this means that the row change count will be incorrect. - */ + ** It is easier just to erase the whole table. Prior to version 3.6.5, + ** this optimization caused the row change count (the value returned by + ** API function sqlite3_count_changes) to be set incorrectly. */ if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) ){ assert( !isView ); - sqlite3VdbeAddOp3(v, OP_Clear, pTab->tnum, iDb, memCnt); - if( !pParse->nested ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); - } + sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, + pTab->zName, P4_STATIC); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else @@ -66815,114 +69821,81 @@ #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ { - int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */ + int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ + int regRowid; /* Actual register containing rowids */ /* Collect rowids of every row to be deleted. */ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, - WHERE_FILL_ROWSET, iRowSet); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK); if( pWInfo==0 ) goto delete_from_cleanup; + regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0); + sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid); if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } sqlite3WhereEnd(pWInfo); - /* Open the pseudo-table used to store OLD if there are triggers. - */ - if( pTrigger ){ - sqlite3VdbeAddOp3(v, OP_OpenPseudo, oldIdx, 0, pTab->nCol); - } - /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete - ** because deleting an item can change the scan order. - */ + ** because deleting an item can change the scan order. */ end = sqlite3VdbeMakeLabel(v); - if( !isView ){ - /* Open cursors for the table we are deleting from and - ** all its indices. - */ + /* Unless this is a view, open cursors for the table we are + ** deleting from and all its indices. If this is a view, then the + ** only effect this statement has is to fire the INSTEAD OF + ** triggers. */ + if( !isView ){ sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); } - /* This is the beginning of the delete loop. If a trigger encounters - ** an IGNORE constraint, it jumps back to here. - */ - if( pTrigger ){ - sqlite3VdbeResolveLabel(v, addr); - } addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid); - if( pTrigger ){ - int iData = ++pParse->nMem; /* For storing row data of OLD table */ - - /* If the record is no longer present in the table, jump to the - ** next iteration of the loop through the contents of the fifo. - */ - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid); - - /* Populate the OLD.* pseudo-table */ - if( old_col_mask ){ - sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, iData); - } - sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid); - - /* Jump back and run the BEFORE triggers */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger); - sqlite3VdbeJumpHere(v, iEndBeforeTrigger); - } - - if( !isView ){ - /* Delete the row */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - const char *pVtab = (const char *)pTab->pVtab; - sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB); - }else -#endif - { - sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0); - } - } - - /* If there are row triggers, close all cursors then invoke - ** the AFTER triggers - */ - if( pTrigger ){ - /* Jump back and run the AFTER triggers */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger); - sqlite3VdbeJumpHere(v, iEndAfterTrigger); + /* Delete the row */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); + sqlite3VtabMakeWritable(pParse, pTab); + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB); + sqlite3MayAbort(pParse); + }else +#endif + { + int count = (pParse->nested==0); /* True to count changes */ + sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default); } /* End of the delete loop */ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); sqlite3VdbeResolveLabel(v, end); - /* Close the cursors after the loop if there are no row triggers */ - if( !isView && !IsVirtual(pTab) ){ + /* Close the cursors open on the table and its indexes. */ + if( !isView && !IsVirtual(pTab) ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp1(v, OP_Close, iCur); } } - /* - ** Return the number of rows that were deleted. If this routine is + /* Update the sqlite_sequence table by storing the content of the + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. + */ + if( pParse->nested==0 && pParse->pTriggerTab==0 ){ + sqlite3AutoincrementEnd(pParse); + } + + /* Return the number of rows that were deleted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ + if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); } @@ -66947,32 +69920,92 @@ ** cursor number base+i for the i-th index. ** ** 3. The record number of the row to be deleted must be stored in ** memory cell iRowid. ** -** This routine pops the top of the stack to remove the record number -** and then generates code to remove both the table record and all index -** entries that point to that record. +** This routine generates code to remove both the table record and all +** index entries that point to that record. */ SQLITE_PRIVATE void sqlite3GenerateRowDelete( Parse *pParse, /* Parsing context */ Table *pTab, /* Table containing the row to be deleted */ int iCur, /* Cursor number for the table */ int iRowid, /* Memory cell that contains the rowid to delete */ - int count /* Increment the row change counter */ -){ - int addr; - Vdbe *v; - - v = pParse->pVdbe; - addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid); - sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); - sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); - if( count ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); - } - sqlite3VdbeJumpHere(v, addr); + int count, /* If non-zero, increment the row change counter */ + Trigger *pTrigger, /* List of triggers to (potentially) fire */ + int onconf /* Default ON CONFLICT policy for triggers */ +){ + Vdbe *v = pParse->pVdbe; /* Vdbe */ + int iOld = 0; /* First register in OLD.* array */ + int iLabel; /* Label resolved to end of generated code */ + + /* Vdbe is guaranteed to have been allocated by this stage. */ + assert( v ); + + /* Seek cursor iCur to the row to delete. If this row no longer exists + ** (this can happen if a trigger program has already deleted it), do + ** not attempt to delete it or fire any DELETE triggers. */ + iLabel = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid); + + /* If there are any triggers to fire, allocate a range of registers to + ** use for the old.* references in the triggers. */ + if( pTrigger ){ + u32 mask; /* Mask of OLD.* columns in use */ + int iCol; /* Iterator used while populating OLD.* */ + + /* TODO: Could use temporary registers here. Also could attempt to + ** avoid copying the contents of the rowid register. */ + mask = sqlite3TriggerOldmask(pParse, pTrigger, TK_DELETE, 0, pTab, onconf); + iOld = pParse->nMem+1; + pParse->nMem += (1 + pTab->nCol); + + /* Populate the OLD.* pseudo-table register array. These values will be + ** used by any BEFORE and AFTER triggers that exist. */ + sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld); + for(iCol=0; iCol<pTab->nCol; iCol++){ + if( mask==0xffffffff || mask&(1<<iCol) ){ + int iTarget = iOld + iCol + 1; + sqlite3VdbeAddOp3(v, OP_Column, iCur, iCol, iTarget); + sqlite3ColumnDefault(v, pTab, iCol, iTarget); + } + } + + /* Invoke any BEFORE trigger programs */ + sqlite3CodeRowTrigger(pParse, pTrigger, + TK_DELETE, 0, TRIGGER_BEFORE, pTab, -1, iOld, onconf, iLabel + ); + + /* Seek the cursor to the row to be deleted again. It may be that + ** the BEFORE triggers coded above have already removed the row + ** being deleted. Do not attempt to delete the row a second time, and + ** do not fire AFTER triggers. */ + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid); + } + + /* Delete the index and table entries. Skip this step if pTab is really + ** a view (in which case the only effect of the DELETE statement is to + ** fire the INSTEAD OF triggers). */ + if( pTab->pSelect==0 ){ + sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); + sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); + if( count ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + } + } + + /* Invoke AFTER triggers. */ + if( pTrigger ){ + sqlite3CodeRowTrigger(pParse, pTrigger, + TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, iOld, onconf, iLabel + ); + } + + /* Jump here if the row had already been deleted before any BEFORE + ** trigger programs were invoked. Or if a trigger program throws a + ** RAISE(IGNORE) exception. */ + sqlite3VdbeResolveLabel(v, iLabel); } /* ** This routine generates VDBE code that causes the deletion of all ** index entries associated with a single row of a single table. @@ -67037,16 +70070,16 @@ int idx = pIdx->aiColumn[j]; if( idx==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j); }else{ sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); - sqlite3ColumnDefault(v, pTab, idx); + sqlite3ColumnDefault(v, pTab, idx, -1); } } if( doMakeRec ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); - sqlite3IndexAffinityStr(v, pIdx); + sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0); sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1); } sqlite3ReleaseTempRange(pParse, regBase, nCol+1); return regBase; } @@ -67073,12 +70106,10 @@ ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. -** -** $Id: func.c,v 1.231 2009/04/08 23:04:14 drh Exp $ */ /* ** Return the collating function associated with a function. */ @@ -67301,23 +70332,28 @@ */ #ifndef SQLITE_OMIT_FLOATING_POINT static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ int n = 0; double r; - char zBuf[500]; /* larger than the %f representation of the largest double */ + char *zBuf; assert( argc==1 || argc==2 ); if( argc==2 ){ if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; n = sqlite3_value_int(argv[1]); if( n>30 ) n = 30; if( n<0 ) n = 0; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; r = sqlite3_value_double(argv[0]); - sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r); - sqlite3AtoF(zBuf, &r); - sqlite3_result_double(context, r); + zBuf = sqlite3_mprintf("%.*f",n,r); + if( zBuf==0 ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3AtoF(zBuf, &r); + sqlite3_free(zBuf); + sqlite3_result_double(context, r); + } } #endif /* ** Allocate nByte bytes of space using sqlite3_malloc(). If the @@ -67751,20 +70787,34 @@ sqlite3_result_value(context, argv[0]); } } /* -** Implementation of the VERSION(*) function. The result is the version +** Implementation of the sqlite_version() function. The result is the version ** of the SQLite library that is running. */ static void versionFunc( sqlite3_context *context, int NotUsed, sqlite3_value **NotUsed2 ){ UNUSED_PARAMETER2(NotUsed, NotUsed2); sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); +} + +/* +** Implementation of the sqlite_source_id() function. The result is a string +** that identifies the particular version of the source code used to build +** SQLite. +*/ +static void sourceidFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **NotUsed2 +){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + sqlite3_result_text(context, SQLITE_SOURCE_ID, -1, SQLITE_STATIC); } /* Array for converting from half-bytes (nybbles) into ASCII hex ** digits. */ static const char hexdigits[] = { @@ -68233,16 +71283,18 @@ p = sqlite3_aggregate_context(context, sizeof(*p)); if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ p->n++; } +#ifndef SQLITE_OMIT_DEPRECATED /* The sqlite3_aggregate_count() function is deprecated. But just to make ** sure it still operates correctly, verify that its count agrees with our ** internal count when using count(*) and when the total count can be ** expressed as a 32-bit integer. */ assert( argc==1 || p==0 || p->n>0x7fffffff || p->n==sqlite3_aggregate_count(context) ); +#endif } static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, 0); sqlite3_result_int64(context, p ? p->n : 0); @@ -68312,13 +71364,14 @@ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); if( pAccum ){ sqlite3 *db = sqlite3_context_db_handle(context); + int firstTerm = pAccum->useMalloc==0; pAccum->useMalloc = 1; pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; - if( pAccum->nChar ){ + if( !firstTerm ){ if( argc==2 ){ zSep = (char*)sqlite3_value_text(argv[1]); nSep = sqlite3_value_bytes(argv[1]); }else{ zSep = ","; @@ -68360,13 +71413,10 @@ assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; } } -#ifdef SQLITE_SSE - (void)sqlite3SseFunctions(db); -#endif } /* ** Set the LIKEOPT flag on the 2-argument function with the given name. */ @@ -68414,12 +71464,13 @@ || pExpr->x.pList->nExpr!=2 ){ return 0; } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2, - SQLITE_UTF8, 0); + pDef = sqlite3FindFunction(db, pExpr->u.zToken, + sqlite3Strlen30(pExpr->u.zToken), + 2, SQLITE_UTF8, 0); if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ return 0; } /* The memcpy() statement assumes that the wildcard characters are @@ -68481,10 +71532,11 @@ FUNCTION(ifnull, 2, 0, 1, ifnullFunc ), FUNCTION(random, 0, 0, 0, randomFunc ), FUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), + FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), FUNCTION(quote, 1, 0, 0, quoteFunc ), FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), FUNCTION(changes, 0, 0, 0, changes ), FUNCTION(total_changes, 0, 0, 0, total_changes ), FUNCTION(replace, 3, 0, 0, replaceFunc ), @@ -68539,17 +71591,37 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.260 2009/02/28 10:47:42 danielk1977 Exp $ -*/ - -/* -** Set P4 of the most recently inserted opcode to a column affinity -** string for index pIdx. A column affinity string has one character -** for each column in the table, according to the affinity of the column: +** $Id: insert.c,v 1.270 2009/07/24 17:58:53 danielk1977 Exp $ +*/ + +/* +** Generate code that will open a table for reading. +*/ +SQLITE_PRIVATE void sqlite3OpenTable( + Parse *p, /* Generate code into this VDBE */ + int iCur, /* The cursor number of the table */ + int iDb, /* The database index in sqlite3.aDb[] */ + Table *pTab, /* The table to be opened */ + int opcode /* OP_OpenRead or OP_OpenWrite */ +){ + Vdbe *v; + if( IsVirtual(pTab) ) return; + v = sqlite3GetVdbe(p); + assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); + sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); + sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); + sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32); + VdbeComment((v, "%s", pTab->zName)); +} + +/* +** Return a pointer to the column affinity string associated with index +** pIdx. A column affinity string has one character for each column in +** the table, according to the affinity of the column: ** ** Character Column affinity ** ------------------------------ ** 'a' TEXT ** 'b' NONE @@ -68557,12 +71629,16 @@ ** 'd' INTEGER ** 'e' REAL ** ** An extra 'b' is appended to the end of the string to cover the ** rowid that appears as the last column in every index. -*/ -SQLITE_PRIVATE void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ +** +** Memory for the buffer containing the column index affinity string +** is managed along with the rest of the Index structure. It will be +** released when sqlite3DeleteIndex() is called. +*/ +SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ if( !pIdx->zColAff ){ /* The first time a column affinity string for a particular index is ** required, it is allocated and populated here. It is then stored as ** a member of the Index structure for subsequent use. ** @@ -68574,20 +71650,20 @@ Table *pTab = pIdx->pTable; sqlite3 *db = sqlite3VdbeDb(v); pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2); if( !pIdx->zColAff ){ db->mallocFailed = 1; - return; + return 0; } for(n=0; n<pIdx->nColumn; n++){ pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; } pIdx->zColAff[n++] = SQLITE_AFF_NONE; pIdx->zColAff[n] = 0; } - sqlite3VdbeChangeP4(v, -1, pIdx->zColAff, 0); + return pIdx->zColAff; } /* ** Set P4 of the most recently inserted opcode to a column affinity ** string for table pTab. A column affinity string has one character @@ -68637,13 +71713,18 @@ ** have been opened at any point in the VDBE program beginning at location ** iStartAddr throught the end of the program. This is used to see if ** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can ** run without using temporary table for the results of the SELECT. */ -static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){ +static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){ + Vdbe *v = sqlite3GetVdbe(p); int i; int iEnd = sqlite3VdbeCurrentAddr(v); +#ifndef SQLITE_OMIT_VIRTUALTABLE + VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0; +#endif + for(i=iStartAddr; i<iEnd; i++){ VdbeOp *pOp = sqlite3VdbeGetOp(v, i); assert( pOp!=0 ); if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){ Index *pIndex; @@ -68656,11 +71737,11 @@ return 1; } } } #ifndef SQLITE_OMIT_VIRTUALTABLE - if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pTab->pVtab ){ + if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pVTab ){ assert( pOp->p4.pVtab!=0 ); assert( pOp->p4type==P4_VTAB ); return 1; } #endif @@ -68668,57 +71749,92 @@ return 0; } #ifndef SQLITE_OMIT_AUTOINCREMENT /* -** Write out code to initialize the autoincrement logic. This code -** looks up the current autoincrement value in the sqlite_sequence -** table and stores that value in a register. Code generated by -** autoIncStep() will keep that register holding the largest -** rowid value. Code generated by autoIncEnd() will write the new -** largest value of the counter back into the sqlite_sequence table. -** -** This routine returns the index of the mem[] cell that contains -** the maximum rowid counter. -** -** Three consecutive registers are allocated by this routine. The -** first two hold the name of the target table and the maximum rowid -** inserted into the target table, respectively. -** The third holds the rowid in sqlite_sequence where we will -** write back the revised maximum rowid. This routine returns the -** index of the second of these three registers. +** Locate or create an AutoincInfo structure associated with table pTab +** which is in database iDb. Return the register number for the register +** that holds the maximum rowid. +** +** There is at most one AutoincInfo structure per table even if the +** same table is autoincremented multiple times due to inserts within +** triggers. A new AutoincInfo structure is created if this is the +** first use of table pTab. On 2nd and subsequent uses, the original +** AutoincInfo structure is used. +** +** Three memory locations are allocated: +** +** (1) Register to hold the name of the pTab table. +** (2) Register to hold the maximum ROWID of pTab. +** (3) Register to hold the rowid in sqlite_sequence of pTab +** +** The 2nd register is the one that is returned. That is all the +** insert routine needs to know about. */ static int autoIncBegin( Parse *pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ if( pTab->tabFlags & TF_Autoincrement ){ - Vdbe *v = pParse->pVdbe; - Db *pDb = &pParse->db->aDb[iDb]; - int iCur = pParse->nTab++; - int addr; /* Address of the top of the loop */ - assert( v ); - pParse->nMem++; /* Holds name of table */ - memId = ++pParse->nMem; - pParse->nMem++; - sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); - addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+9); - sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, memId); - sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); - sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1); - sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); - sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+2); - sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); - sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); + Parse *pToplevel = sqlite3ParseToplevel(pParse); + AutoincInfo *pInfo; + + pInfo = pToplevel->pAinc; + while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } + if( pInfo==0 ){ + pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo)); + if( pInfo==0 ) return 0; + pInfo->pNext = pToplevel->pAinc; + pToplevel->pAinc = pInfo; + pInfo->pTab = pTab; + pInfo->iDb = iDb; + pToplevel->nMem++; /* Register to hold name of table */ + pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ + pToplevel->nMem++; /* Rowid in sqlite_sequence */ + } + memId = pInfo->regCtr; } return memId; +} + +/* +** This routine generates code that will initialize all of the +** register used by the autoincrement tracker. +*/ +SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ + AutoincInfo *p; /* Information about an AUTOINCREMENT */ + sqlite3 *db = pParse->db; /* The database connection */ + Db *pDb; /* Database only autoinc table */ + int memId; /* Register holding max rowid */ + int addr; /* A VDBE address */ + Vdbe *v = pParse->pVdbe; /* VDBE under construction */ + + /* This routine is never called during trigger-generation. It is + ** only called from the top-level */ + assert( pParse->pTriggerTab==0 ); + assert( pParse==sqlite3ParseToplevel(pParse) ); + + assert( v ); /* We failed long ago if this is not so */ + for(p = pParse->pAinc; p; p = p->pNext){ + pDb = &db->aDb[p->iDb]; + memId = p->regCtr; + sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); + sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); + sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); + sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); + sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); + sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); + sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); + sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); + sqlite3VdbeAddOp0(v, OP_Close); + } } /* ** Update the maximum rowid for an autoincrement calculation. ** @@ -68732,46 +71848,56 @@ sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); } } /* -** After doing one or more inserts, the maximum rowid is stored -** in reg[memId]. Generate code to write this value back into the -** the sqlite_sequence table. -*/ -static void autoIncEnd( - Parse *pParse, /* The parsing context */ - int iDb, /* Index of the database holding pTab */ - Table *pTab, /* Table we are inserting into */ - int memId /* Memory cell holding the maximum rowid */ -){ - if( pTab->tabFlags & TF_Autoincrement ){ - int iCur = pParse->nTab++; - Vdbe *v = pParse->pVdbe; - Db *pDb = &pParse->db->aDb[iDb]; - int j1; - int iRec = ++pParse->nMem; /* Memory cell used for record */ - - assert( v ); - sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); +** This routine generates the code needed to write autoincrement +** maximum rowid values back into the sqlite_sequence register. +** Every statement that might do an INSERT into an autoincrement +** table (either directly or through triggers) needs to call this +** routine just before the "exit" code. +*/ +SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ + AutoincInfo *p; + Vdbe *v = pParse->pVdbe; + sqlite3 *db = pParse->db; + + assert( v ); + for(p = pParse->pAinc; p; p = p->pNext){ + Db *pDb = &db->aDb[p->iDb]; + int j1, j2, j3, j4, j5; + int iRec; + int memId = p->regCtr; + + iRec = sqlite3GetTempReg(pParse); + sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); - sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1); + j2 = sqlite3VdbeAddOp0(v, OP_Rewind); + j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); + j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); + sqlite3VdbeAddOp2(v, OP_Next, 0, j3); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); + j5 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j4); + sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeJumpHere(v, j5); sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); - sqlite3VdbeAddOp3(v, OP_Insert, iCur, iRec, memId+1); + sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3VdbeAddOp1(v, OP_Close, iCur); + sqlite3VdbeAddOp0(v, OP_Close); + sqlite3ReleaseTempReg(pParse, iRec); } } #else /* ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines ** above are all no-ops */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) -# define autoIncEnd(A,B,C,D) #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* Forward declaration */ static int xferOptimization( @@ -68908,11 +72034,10 @@ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ int addrInsTop = 0; /* Jump to label "D" */ int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ int addrSelect = 0; /* Address of coroutine that implements the SELECT */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ - int newIdx = -1; /* Cursor for the NEW pseudo-table */ int iDb; /* Index of database holding TABLE */ Db *pDb; /* The database containing table being inserted into */ int appendFlag = 0; /* True if the insert is likely to be an append */ /* Register allocations */ @@ -68923,11 +72048,10 @@ int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ int regRecord; /* Holds the assemblied row record */ int regEof = 0; /* Register recording end of SELECT data */ int *aRegIdx = 0; /* One register allocated to each index */ - #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ int tmask; /* Mask of trigger times */ @@ -68941,11 +72065,11 @@ /* Locate the table into which we will be inserting new information. */ assert( pTabList->nSrc==1 ); zTab = pTabList->a[0].zName; - if( zTab==0 ) goto insert_cleanup; + if( NEVER(zTab==0) ) goto insert_cleanup; pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ){ goto insert_cleanup; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); @@ -68971,38 +72095,32 @@ # undef isView # define isView 0 #endif assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); + /* If pTab is really a view, make sure it has been initialized. + ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual + ** module table). + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto insert_cleanup; + } + /* Ensure that: * (a) the table is not read-only, * (b) that if it is a view then ON INSERT triggers exist */ if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ - goto insert_cleanup; - } - assert( pTab!=0 ); - - /* If pTab is really a view, make sure it has been initialized. - ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual - ** module table). - */ - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto insert_cleanup; } /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb); - - /* if there are row triggers, allocate a temp table for new.* references. */ - if( pTrigger ){ - newIdx = pParse->nTab++; - } #ifndef SQLITE_OMIT_XFER_OPT /* If the statement is of the form ** ** INSERT INTO <table1> SELECT * FROM <table2>; @@ -69013,11 +72131,11 @@ ** This is the 2nd template. */ if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ assert( !pTrigger ); assert( pList==0 ); - goto insert_cleanup; + goto insert_end; } #endif /* SQLITE_OMIT_XFER_OPT */ /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell regAutoinc. @@ -69063,11 +72181,12 @@ j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); VdbeComment((v, "Jump over SELECT coroutine")); /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, &dest); - if( rc || pParse->nErr || db->mallocFailed ){ + assert( pParse->nErr==0 || rc ); + if( rc || NEVER(pParse->nErr) || db->mallocFailed ){ goto insert_cleanup; } sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); /* yield X */ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); @@ -69086,11 +72205,11 @@ ** ** A temp table must be used if the table being updated is also one ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ - if( pTrigger || readsTable(v, addrSelect, iDb, pTab) ){ + if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){ useTempTable = 1; } if( useTempTable ){ /* Invoke the coroutine to extract information from the SELECT @@ -69149,11 +72268,11 @@ } } if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ sqlite3ErrorMsg(pParse, "table %S has %d columns but %d values were supplied", - pTabList, 0, pTab->nCol, nColumn); + pTabList, 0, pTab->nCol-nHidden, nColumn); goto insert_cleanup; } if( pColumn!=0 && nColumn!=pColumn->nId ){ sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; @@ -69201,16 +72320,10 @@ ** key, the set the keyColumn variable to the primary key column index ** in the original table definition. */ if( pColumn==0 && nColumn>0 ){ keyColumn = pTab->iPKey; - } - - /* Open the temp table for FOR EACH ROW triggers - */ - if( pTrigger ){ - sqlite3VdbeAddOp3(v, OP_OpenPseudo, newIdx, 0, pTab->nCol); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ @@ -69274,81 +72387,74 @@ /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); if( tmask & TRIGGER_BEFORE ){ - int regTrigRowid; - int regCols; - int regRec; + int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1); /* build the NEW.* reference row. Note that if there is an INTEGER ** PRIMARY KEY into which a NULL is being inserted, that NULL will be ** translated into a unique ID for the row. But on a BEFORE trigger, ** we do not know what the unique ID will be (because the insert has ** not happened yet) so we substitute a rowid of -1 */ - regTrigRowid = sqlite3GetTempReg(pParse); if( keyColumn<0 ){ - sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid); - }else if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regTrigRowid); + sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); }else{ int j1; - assert( pSelect==0 ); /* Otherwise useTempTable is true */ - sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regTrigRowid); - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regTrigRowid); - sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid); + if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols); + }else{ + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols); + } + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); + sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regTrigRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); } /* Cannot have triggers on a virtual table. If it were possible, ** this block would have to account for hidden column. */ - assert(!IsVirtual(pTab)); + assert( !IsVirtual(pTab) ); /* Create the new column data */ - regCols = sqlite3GetTempRange(pParse, pTab->nCol); for(i=0; i<pTab->nCol; i++){ if( pColumn==0 ){ j = i; }else{ for(j=0; j<pColumn->nId; j++){ if( pColumn->a[j].idx==i ) break; } } if( pColumn && j>=pColumn->nId ){ - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i); + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1); }else if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i); + sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); }else{ assert( pSelect==0 ); /* Otherwise useTempTable is true */ - sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i); - } - } - regRec = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRec); + sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1); + } + } /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, ** do not attempt any conversions before assembling the record. ** If this is a real table, attempt conversions as required by the ** table column affinities. */ if( !isView ){ + sqlite3VdbeAddOp2(v, OP_Affinity, regCols+1, pTab->nCol); sqlite3TableAffinityStr(v, pTab); } - sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regTrigRowid); - sqlite3ReleaseTempReg(pParse, regRec); - sqlite3ReleaseTempReg(pParse, regTrigRowid); - sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); /* Fire BEFORE or INSTEAD OF triggers */ - if( sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, - pTab, newIdx, -1, onError, endOfLoop, 0, 0) ){ - goto insert_cleanup; - } + sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, + pTab, -1, regCols-pTab->nCol-1, onError, endOfLoop); + + sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1); } /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRowid ** except when the table has an INTEGER PRIMARY KEY column, in which @@ -69365,12 +72471,12 @@ }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); - pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1); - if( pOp && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ + pOp = sqlite3VdbeGetOp(v, -1); + if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ appendFlag = 1; pOp->opcode = OP_NewRowid; pOp->p1 = baseCur; pOp->p2 = regRowid; pOp->p3 = regAutoinc; @@ -69440,37 +72546,24 @@ /* Generate code to check constraints and generate index keys and ** do the insertion. */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ + const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, - (const char*)pTab->pVtab, P4_VTAB); + sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); + sqlite3MayAbort(pParse); }else #endif { - sqlite3GenerateConstraintChecks( - pParse, - pTab, - baseCur, - regIns, - aRegIdx, - keyColumn>=0, - 0, - onError, - endOfLoop + int isReplace; /* Set to true if constraints may cause a replace */ + sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx, + keyColumn>=0, 0, onError, endOfLoop, &isReplace ); sqlite3CompleteInsertion( - pParse, - pTab, - baseCur, - regIns, - aRegIdx, - 0, - (tmask&TRIGGER_AFTER) ? newIdx : -1, - appendFlag - ); + pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0 + ); } } /* Update the count of rows that are inserted */ @@ -69478,14 +72571,12 @@ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( pTrigger ){ /* Code AFTER triggers */ - if( sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, - pTab, newIdx, -1, onError, endOfLoop, 0, 0) ){ - goto insert_cleanup; - } + sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, + pTab, -1, regData-2-pTab->nCol, onError, endOfLoop); } /* The bottom of the main insertion loop, if the data source ** is a SELECT statement. */ @@ -69505,22 +72596,25 @@ for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur); } } +insert_end: /* Update the sqlite_sequence table by storing the content of the - ** counter value in memory regAutoinc back into the sqlite_sequence - ** table. - */ - autoIncEnd(pParse, iDb, pTab, regAutoinc); + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. + */ + if( pParse->nested==0 && pParse->pTriggerTab==0 ){ + sqlite3AutoincrementEnd(pParse); + } /* ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ + if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); } @@ -69535,30 +72629,28 @@ /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE. ** ** The input is a range of consecutive registers as follows: ** -** 1. The rowid of the row to be updated before the update. This -** value is omitted unless we are doing an UPDATE that involves a -** change to the record number or writing to a virtual table. -** -** 2. The rowid of the row after the update. -** -** 3. The data in the first column of the entry after the update. +** 1. The rowid of the row after the update. +** +** 2. The data in the first column of the entry after the update. ** ** i. Data from middle columns... ** ** N. The data in the last column of the entry after the update. ** -** The regRowid parameter is the index of the register containing (2). -** -** The old rowid shown as entry (1) above is omitted unless both isUpdate -** and rowidChng are 1. isUpdate is true for UPDATEs and false for -** INSERTs. RowidChng means that the new rowid is explicitly specified by -** the update or insert statement. If rowidChng is false, it means that -** the rowid is computed automatically in an insert or that the rowid value -** is not modified by the update. +** The regRowid parameter is the index of the register containing (1). +** +** If isUpdate is true and rowidChng is non-zero, then rowidChng contains +** the address of a register containing the rowid before the update takes +** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate +** is false, indicating an INSERT statement, then a non-zero rowidChng +** indicates that the rowid was explicitly specified as part of the +** INSERT statement. If rowidChng is false, it means that the rowid is +** computed automatically in an insert or that the rowid value is not +** modified by an update. ** ** The code generated by this routine store new index entries into ** registers identified by aRegIdx[]. No index entry is created for ** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is ** the same as the order of indices on the linked list of indices @@ -69616,30 +72708,30 @@ int regRowid, /* Index of the range of input registers */ int *aRegIdx, /* Register used by each index. 0 for unused indices */ int rowidChng, /* True if the rowid might collide with existing entry */ int isUpdate, /* True for UPDATE, False for INSERT */ int overrideError, /* Override onError to this if not OE_Default */ - int ignoreDest /* Jump to this label on an OE_Ignore resolution */ -){ - int i; - Vdbe *v; - int nCol; - int onError; + int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ + int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */ +){ + int i; /* loop counter */ + Vdbe *v; /* VDBE under constrution */ + int nCol; /* Number of columns */ + int onError; /* Conflict resolution strategy */ int j1; /* Addresss of jump instruction */ int j2 = 0, j3; /* Addresses of jump instructions */ int regData; /* Register containing first data column */ - int iCur; - Index *pIdx; - int seenReplace = 0; - int hasTwoRowids = (isUpdate && rowidChng); + int iCur; /* Table cursor number */ + Index *pIdx; /* Pointer to one of the indices */ + int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ + int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid; v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ nCol = pTab->nCol; regData = regRowid + 1; - /* Test all NOT NULL constraints. */ for(i=0; i<nCol; i++){ if( i==pTab->iPKey ){ @@ -69656,12 +72748,13 @@ onError = OE_Abort; } assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail || onError==OE_Ignore || onError==OE_Replace ); switch( onError ){ - case OE_Rollback: case OE_Abort: + sqlite3MayAbort(pParse); + case OE_Rollback: case OE_Fail: { char *zMsg; j1 = sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT, onError, regData+i); zMsg = sqlite3MPrintf(pParse->db, "%s.%s may not be NULL", @@ -69671,11 +72764,12 @@ } case OE_Ignore: { sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest); break; } - case OE_Replace: { + default: { + assert( onError==OE_Replace ); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i); sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i); sqlite3VdbeJumpHere(v, j1); break; } @@ -69691,11 +72785,11 @@ sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL); onError = overrideError!=OE_Default ? overrideError : OE_Abort; if( onError==OE_Ignore ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); }else{ - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CONSTRAINT, onError); + sqlite3HaltConstraint(pParse, onError, 0, 0); } sqlite3VdbeResolveLabel(v, allOk); } #endif /* !defined(SQLITE_OMIT_CHECK) */ @@ -69711,11 +72805,11 @@ onError = OE_Abort; } if( onError!=OE_Replace || pTab->pIndex ){ if( isUpdate ){ - j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1); + j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng); } j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid); switch( onError ){ default: { onError = OE_Abort; @@ -69722,16 +72816,35 @@ /* Fall thru into the next case */ } case OE_Rollback: case OE_Abort: case OE_Fail: { - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, - "PRIMARY KEY must be unique", P4_STATIC); + sqlite3HaltConstraint( + pParse, onError, "PRIMARY KEY must be unique", P4_STATIC); break; } case OE_Replace: { - sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); + /* If there are DELETE triggers on this table and the + ** recursive-triggers flag is set, call GenerateRowDelete() to + ** remove the conflicting row from the the table. This will fire + ** the triggers and remove both the table and index b-tree entries. + ** + ** Otherwise, if there are no triggers or the recursive-triggers + ** flag is not set, call GenerateRowIndexDelete(). This removes + ** the index b-tree entries only. The table b-tree entry will be + ** replaced by the new entry when it is inserted. */ + Trigger *pTrigger = 0; + if( pParse->db->flags&SQLITE_RecTriggers ){ + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); + } + if( pTrigger ){ + sqlite3GenerateRowDelete( + pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace + ); + }else{ + sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); + } seenReplace = 1; break; } case OE_Ignore: { assert( seenReplace==0 ); @@ -69766,17 +72879,19 @@ sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i); } } sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); - sqlite3IndexAffinityStr(v, pIdx); - sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1); - sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); + sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0); + sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1); /* Find out what action to take in case there is an indexing conflict */ onError = pIdx->onError; - if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ + if( onError==OE_None ){ + sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); + continue; /* pIdx is not a UNIQUE index */ + } if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } @@ -69783,66 +72898,70 @@ if( seenReplace ){ if( onError==OE_Ignore ) onError = OE_Replace; else if( onError==OE_Fail ) onError = OE_Abort; } - - /* Check to see if the new index entry will be unique */ - j2 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdx, 0, pIdx->nColumn); + /* Check to see if the new index entry will be unique */ regR = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_SCopy, regRowid-hasTwoRowids, regR); + sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR); j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0, - regR, SQLITE_INT_TO_PTR(aRegIdx[iCur]), + regR, SQLITE_INT_TO_PTR(regIdx), P4_INT32); + sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); /* Generate code that executes if the new index entry is not unique */ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail || onError==OE_Ignore || onError==OE_Replace ); switch( onError ){ case OE_Rollback: case OE_Abort: case OE_Fail: { - int j, n1, n2; - char zErrMsg[200]; - sqlite3_snprintf(ArraySize(zErrMsg), zErrMsg, - pIdx->nColumn>1 ? "columns " : "column "); - n1 = sqlite3Strlen30(zErrMsg); - for(j=0; j<pIdx->nColumn && n1<ArraySize(zErrMsg)-30; j++){ + int j; + StrAccum errMsg; + const char *zSep; + char *zErr; + + sqlite3StrAccumInit(&errMsg, 0, 0, 200); + errMsg.db = pParse->db; + zSep = pIdx->nColumn>1 ? "columns " : "column "; + for(j=0; j<pIdx->nColumn; j++){ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; - n2 = sqlite3Strlen30(zCol); - if( j>0 ){ - sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], ", "); - n1 += 2; - } - if( n1+n2>ArraySize(zErrMsg)-30 ){ - sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "..."); - n1 += 3; - break; - }else{ - sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol); - n1 += n2; - } - } - sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], - pIdx->nColumn>1 ? " are not unique" : " is not unique"); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErrMsg,0); + sqlite3StrAccumAppend(&errMsg, zSep, -1); + zSep = ", "; + sqlite3StrAccumAppend(&errMsg, zCol, -1); + } + sqlite3StrAccumAppend(&errMsg, + pIdx->nColumn>1 ? " are not unique" : " is not unique", -1); + zErr = sqlite3StrAccumFinish(&errMsg); + sqlite3HaltConstraint(pParse, onError, zErr, 0); + sqlite3DbFree(errMsg.db, zErr); break; } case OE_Ignore: { assert( seenReplace==0 ); sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); break; } - case OE_Replace: { - sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0); + default: { + Trigger *pTrigger = 0; + assert( onError==OE_Replace ); + if( pParse->db->flags&SQLITE_RecTriggers ){ + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); + } + sqlite3GenerateRowDelete( + pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace + ); seenReplace = 1; break; } } - sqlite3VdbeJumpHere(v, j2); sqlite3VdbeJumpHere(v, j3); sqlite3ReleaseTempReg(pParse, regR); + } + + if( pbMayReplace ){ + *pbMayReplace = seenReplace; } } /* ** This routine generates code to finish the INSERT or UPDATE operation @@ -69858,12 +72977,12 @@ Table *pTab, /* the table into which we are inserting */ int baseCur, /* Index of a read/write cursor pointing at pTab */ int regRowid, /* Range of content */ int *aRegIdx, /* Register used by each index. 0 for unused indices */ int isUpdate, /* True for UPDATE, False for INSERT */ - int newIdx, /* Index of NEW table for triggers. -1 if none */ - int appendBias /* True if this is likely to be an append */ + int appendBias, /* True if this is likely to be an append */ + int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ ){ int i; Vdbe *v; int nIdx; Index *pIdx; @@ -69876,29 +72995,30 @@ assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} for(i=nIdx-1; i>=0; i--){ if( aRegIdx[i]==0 ) continue; sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); + if( useSeekResult ){ + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + } } regData = regRowid + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); -#ifndef SQLITE_OMIT_TRIGGER - if( newIdx>=0 ){ - sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); - } -#endif if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE; pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } if( appendBias ){ pik_flags |= OPFLAG_APPEND; + } + if( useSeekResult ){ + pik_flags |= OPFLAG_USESEEKRESULT; } sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid); if( !pParse->nested ){ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); } @@ -69933,11 +73053,11 @@ assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); } - if( pParse->nTab<=baseCur+i ){ + if( pParse->nTab<baseCur+i ){ pParse->nTab = baseCur+i; } return i-1; } @@ -69993,11 +73113,11 @@ return 0; /* Different columns indexed */ } if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ return 0; /* Different sort orders */ } - if( pSrc->azColl[i]!=pDest->azColl[i] ){ + if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){ return 0; /* Different collating sequences */ } } /* If no test above fails then the indices must be compatible */ @@ -70207,12 +73327,12 @@ regData = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, - "PRIMARY KEY must be unique", P4_STATIC); + sqlite3HaltConstraint( + pParse, onError, "PRIMARY KEY must be unique", P4_STATIC); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ @@ -70222,13 +73342,12 @@ sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); - autoIncEnd(pParse, iDbDest, pDest, regAutoinc); for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ - for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } assert( pSrcIdx ); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); @@ -70283,11 +73402,11 @@ ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: legacy.c,v 1.32 2009/03/19 18:51:07 danielk1977 Exp $ +** $Id: legacy.c,v 1.35 2009/08/07 16:56:00 danielk1977 Exp $ */ /* ** Execute SQL code. Return one of the SQLITE_ success/failure @@ -70304,17 +73423,16 @@ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ - int rc = SQLITE_OK; - const char *zLeftover; - sqlite3_stmt *pStmt = 0; - char **azCols = 0; - - int nRetry = 0; - int nCallback; + int rc = SQLITE_OK; /* Return code */ + const char *zLeftover; /* Tail of unprocessed SQL */ + sqlite3_stmt *pStmt = 0; /* The current SQL statement */ + char **azCols = 0; /* Names of result columns */ + int nRetry = 0; /* Number of retry attempts */ + int callbackIsInit; /* True if callback data is initialized */ if( zSql==0 ) zSql = ""; sqlite3_mutex_enter(db->mutex); sqlite3Error(db, SQLITE_OK, 0); @@ -70332,34 +73450,33 @@ /* this happens for a comment or white-space */ zSql = zLeftover; continue; } - nCallback = 0; + callbackIsInit = 0; nCol = sqlite3_column_count(pStmt); while( 1 ){ int i; rc = sqlite3_step(pStmt); /* Invoke the callback function if required */ if( xCallback && (SQLITE_ROW==rc || - (SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){ - if( 0==nCallback ){ + (SQLITE_DONE==rc && !callbackIsInit + && db->flags&SQLITE_NullCallback)) ){ + if( !callbackIsInit ){ + azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); if( azCols==0 ){ - azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); - if( azCols==0 ){ - goto exec_out; - } + goto exec_out; } for(i=0; i<nCol; i++){ azCols[i] = (char *)sqlite3_column_name(pStmt, i); /* sqlite3VdbeSetColName() installs column names as UTF8 ** strings so there is no way for sqlite3_column_name() to fail. */ assert( azCols[i]!=0 ); } - nCallback++; + callbackIsInit = 1; } if( rc==SQLITE_ROW ){ azVals = &azCols[nCol]; for(i=0; i<nCol; i++){ azVals[i] = (char *)sqlite3_column_text(pStmt, i); @@ -70397,15 +73514,18 @@ exec_out: if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt); sqlite3DbFree(db, azCols); rc = sqlite3ApiExit(db, rc); - if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ + if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){ int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db)); *pzErrMsg = sqlite3Malloc(nErrMsg); if( *pzErrMsg ){ memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); + }else{ + rc = SQLITE_NOMEM; + sqlite3Error(db, SQLITE_NOMEM, 0); } }else if( pzErrMsg ){ *pzErrMsg = 0; } @@ -70428,11 +73548,11 @@ ** ************************************************************************* ** This file contains code used to dynamically load extensions into ** the SQLite library. ** -** $Id: loadext.c,v 1.58 2009/01/20 16:53:40 danielk1977 Exp $ +** $Id: loadext.c,v 1.60 2009/06/03 01:24:54 drh Exp $ */ #ifndef SQLITE_CORE #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ #endif @@ -71151,10 +74271,13 @@ sqlite3_vfs *pVfs = db->pVfs; void *handle; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); char *zErrmsg = 0; void **aHandle; + const int nMsg = 300; + + if( pzErrMsg ) *pzErrMsg = 0; /* Ticket #1863. To avoid a creating security problems for older ** applications that relink against newer versions of SQLite, the ** ability to run load_extension is turned off by default. One ** must call sqlite3_enable_load_extension() to turn on extension @@ -71172,29 +74295,33 @@ } handle = sqlite3OsDlOpen(pVfs, zFile); if( handle==0 ){ if( pzErrMsg ){ - char zErr[256]; - zErr[sizeof(zErr)-1] = '\0'; - sqlite3_snprintf(sizeof(zErr)-1, zErr, - "unable to open shared library [%s]", zFile); - sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); - *pzErrMsg = sqlite3DbStrDup(0, zErr); + zErrmsg = sqlite3StackAllocZero(db, nMsg); + if( zErrmsg ){ + sqlite3_snprintf(nMsg, zErrmsg, + "unable to open shared library [%s]", zFile); + sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); + *pzErrMsg = sqlite3DbStrDup(0, zErrmsg); + sqlite3StackFree(db, zErrmsg); + } } return SQLITE_ERROR; } xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) sqlite3OsDlSym(pVfs, handle, zProc); if( xInit==0 ){ if( pzErrMsg ){ - char zErr[256]; - zErr[sizeof(zErr)-1] = '\0'; - sqlite3_snprintf(sizeof(zErr)-1, zErr, - "no entry point [%s] in shared library [%s]", zProc,zFile); - sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); - *pzErrMsg = sqlite3DbStrDup(0, zErr); + zErrmsg = sqlite3StackAllocZero(db, nMsg); + if( zErrmsg ){ + sqlite3_snprintf(nMsg, zErrmsg, + "no entry point [%s] in shared library [%s]", zProc,zFile); + sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); + *pzErrMsg = sqlite3DbStrDup(0, zErrmsg); + sqlite3StackFree(db, zErrmsg); + } sqlite3OsDlClose(pVfs, handle); } return SQLITE_ERROR; }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){ if( pzErrMsg ){ @@ -71226,10 +74353,11 @@ char **pzErrMsg /* Put error message here if not 0 */ ){ int rc; sqlite3_mutex_enter(db->mutex); rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg); + rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } /* @@ -71362,24 +74490,25 @@ } } /* ** Load all automatic extensions. -*/ -SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3 *db){ - int i; - int go = 1; - int rc = SQLITE_OK; +** +** If anything goes wrong, set an error in the database connection. +*/ +SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ + int i; + int go = 1; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); wsdAutoextInit; if( wsdAutoext.nExt==0 ){ /* Common case: early out without every having to acquire a mutex */ - return SQLITE_OK; + return; } for(i=0; go; i++){ - char *zErrmsg = 0; + char *zErrmsg; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); if( i>=wsdAutoext.nExt ){ @@ -71388,19 +74517,18 @@ }else{ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) wsdAutoext.aExt[i]; } sqlite3_mutex_leave(mutex); + zErrmsg = 0; if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){ sqlite3Error(db, SQLITE_ERROR, "automatic extension loading failed: %s", zErrmsg); go = 0; - rc = SQLITE_ERROR; - sqlite3_free(zErrmsg); - } - } - return rc; + } + sqlite3_free(zErrmsg); + } } /************** End of loadext.c *********************************************/ /************** Begin file pragma.c ******************************************/ /* @@ -71414,16 +74542,16 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.209 2009/04/07 22:05:43 drh Exp $ +** $Id: pragma.c,v 1.214 2009/07/02 07:47:33 danielk1977 Exp $ */ /* Ignore this whole file if pragmas are disabled */ -#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER) +#if !defined(SQLITE_OMIT_PRAGMA) /* ** Interpret the given string as a safety level. Return 0 for OFF, ** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or ** unrecognized string argument. @@ -71592,10 +74720,11 @@ { "omit_readlock", SQLITE_NoReadlock }, /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted ** flag if there are any active statements. */ { "read_uncommitted", SQLITE_ReadUncommitted }, + { "recursive_triggers", SQLITE_RecTriggers }, }; int i; const struct sPragmaType *p; for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){ if( sqlite3StrICmp(zLeft, p->zName)==0 ){ @@ -71720,16 +74849,17 @@ ** synchronous setting. A negative value means synchronous is off ** and a positive value means synchronous is on. */ if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ static const VdbeOpList getCacheSize[] = { - { OP_ReadCookie, 0, 1, 2}, /* 0 */ - { OP_IfPos, 1, 6, 0}, + { OP_Transaction, 0, 0, 0}, /* 0 */ + { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ + { OP_IfPos, 1, 7, 0}, { OP_Integer, 0, 2, 0}, { OP_Subtract, 1, 2, 1}, - { OP_IfPos, 1, 6, 0}, - { OP_Integer, 0, 1, 0}, /* 5 */ + { OP_IfPos, 1, 7, 0}, + { OP_Integer, 0, 1, 0}, /* 6 */ { OP_ResultRow, 1, 1, 0}, }; int addr; if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeUsesBtree(v, iDb); @@ -71737,21 +74867,22 @@ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); pParse->nMem += 2; addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr, iDb); - sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); + sqlite3VdbeChangeP1(v, addr+1, iDb); + sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); }else{ int size = atoi(zRight); if( size<0 ) size = -size; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp2(v, OP_Integer, size, 1); - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, 2); + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, BTREE_DEFAULT_CACHE_SIZE); addr = sqlite3VdbeAddOp2(v, OP_IfPos, 2, 0); sqlite3VdbeAddOp2(v, OP_Integer, -size, 1); sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 2, 1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else @@ -71984,16 +75115,16 @@ ** "incremental", write the value of meta[6] in the database ** file. Before writing to meta[6], check that meta[3] indicates ** that this really is an auto-vacuum capable database. */ static const VdbeOpList setMeta6[] = { - { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, 3}, /* 1 */ - { OP_If, 1, 0, 0}, /* 2 */ - { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ - { OP_Integer, 0, 1, 0}, /* 4 */ - { OP_SetCookie, 0, 6, 1}, /* 5 */ + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, + { OP_If, 1, 0, 0}, /* 2 */ + { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ + { OP_Integer, 0, 1, 0}, /* 4 */ + { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ }; int iAddr; iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); sqlite3VdbeChangeP1(v, iAddr, iDb); sqlite3VdbeChangeP1(v, iAddr+1, iDb); @@ -72242,14 +75373,12 @@ sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pCol->zType ? pCol->zType : "", 0); sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); - if( pCol->pDflt ){ - const Token *p = &pCol->pDflt->span; - assert( p->z ); - sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)p->z, p->n); + if( pCol->zDflt ){ + sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, 5); } sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); @@ -72677,27 +75806,25 @@ */ if( sqlite3StrICmp(zLeft, "schema_version")==0 || sqlite3StrICmp(zLeft, "user_version")==0 || sqlite3StrICmp(zLeft, "freelist_count")==0 ){ - int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */ + int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ sqlite3VdbeUsesBtree(v, iDb); switch( zLeft[0] ){ - case 's': case 'S': - iCookie = 0; - break; case 'f': case 'F': - iCookie = 1; - iDb = (-1*(iDb+1)); - assert(iDb<=0); + iCookie = BTREE_FREE_PAGE_COUNT; + break; + case 's': case 'S': + iCookie = BTREE_SCHEMA_VERSION; break; default: - iCookie = 5; - break; - } - - if( zRight && iDb>=0 ){ + iCookie = BTREE_USER_VERSION; + break; + } + + if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){ /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ { OP_Integer, 0, 1, 0}, /* 1 */ { OP_SetCookie, 0, 0, 1}, /* 2 */ @@ -72708,16 +75835,18 @@ sqlite3VdbeChangeP1(v, addr+2, iDb); sqlite3VdbeChangeP2(v, addr+2, iCookie); }else{ /* Read the specified cookie value */ static const VdbeOpList readCookie[] = { - { OP_ReadCookie, 0, 1, 0}, /* 0 */ + { OP_Transaction, 0, 0, 0}, /* 0 */ + { OP_ReadCookie, 0, 1, 0}, /* 1 */ { OP_ResultRow, 1, 1, 0} }; int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); sqlite3VdbeChangeP1(v, addr, iDb); - sqlite3VdbeChangeP3(v, addr, iCookie); + sqlite3VdbeChangeP1(v, addr+1, iDb); + sqlite3VdbeChangeP3(v, addr+1, iCookie); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); } }else #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ @@ -72751,21 +75880,10 @@ } sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } - }else -#endif - -#ifdef SQLITE_SSE - /* - ** Check to see if the sqlite_statements table exists. Create it - ** if it does not. - */ - if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){ - extern int sqlite3CreateStatementsTable(Parse*); - sqlite3CreateStatementsTable(pParse); }else #endif #if SQLITE_HAS_CODEC if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){ @@ -72829,11 +75947,11 @@ pragma_out: sqlite3DbFree(db, zLeft); sqlite3DbFree(db, zRight); } -#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */ +#endif /* SQLITE_OMIT_PRAGMA */ /************** End of pragma.c **********************************************/ /************** Begin file prepare.c *****************************************/ /* ** 2005 May 25 @@ -72848,11 +75966,11 @@ ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.116 2009/04/02 18:32:27 drh Exp $ +** $Id: prepare.c,v 1.131 2009/08/06 17:43:31 drh Exp $ */ /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. @@ -72863,18 +75981,18 @@ const char *zExtra /* Error information */ ){ sqlite3 *db = pData->db; if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ if( zObj==0 ) zObj = "?"; - sqlite3SetString(pData->pzErrMsg, pData->db, - "malformed database schema (%s)", zObj); - if( zExtra && zExtra[0] ){ - *pData->pzErrMsg = sqlite3MAppendf(pData->db, *pData->pzErrMsg, "%s - %s", - *pData->pzErrMsg, zExtra); - } - } - pData->rc = SQLITE_CORRUPT; + sqlite3SetString(pData->pzErrMsg, db, + "malformed database schema (%s)", zObj); + if( zExtra ){ + *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg, + "%s - %s", *pData->pzErrMsg, zExtra); + } + } + pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT; } /* ** This is the callback routine for the code that initializes the ** database. See sqlite3Init() below for additional information. @@ -72896,11 +76014,11 @@ UNUSED_PARAMETER2(NotUsed, argc); assert( sqlite3_mutex_held(db->mutex) ); DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ){ corruptSchema(pData, argv[0], 0); - return SQLITE_NOMEM; + return 1; } assert( iDb>=0 && iDb<db->nDb ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ @@ -72914,19 +76032,24 @@ char *zErr; int rc; assert( db->init.busy ); db->init.iDb = iDb; db->init.newTnum = atoi(argv[1]); + db->init.orphanTrigger = 0; rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); db->init.iDb = 0; assert( rc!=SQLITE_OK || zErr==0 ); if( SQLITE_OK!=rc ){ - pData->rc = rc; - if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; - }else if( rc!=SQLITE_INTERRUPT && (rc&0xff)!=SQLITE_LOCKED ){ - corruptSchema(pData, argv[0], zErr); + if( db->init.orphanTrigger ){ + assert( iDb==1 ); + }else{ + pData->rc = rc; + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + }else if( rc!=SQLITE_INTERRUPT && rc!=SQLITE_LOCKED ){ + corruptSchema(pData, argv[0], zErr); + } } sqlite3DbFree(db, zErr); } }else if( argv[0]==0 ){ corruptSchema(pData, 0, 0); @@ -72937,19 +76060,19 @@ ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ Index *pIndex; pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); - if( pIndex==0 || pIndex->tnum!=0 ){ + if( pIndex==0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since ** the permanent table is hidden by the TEMP table, we can also ** safely ignore the index on the permanent table. */ /* Do Nothing */; - }else{ - pIndex->tnum = atoi(argv[1]); + }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){ + corruptSchema(pData, argv[0], "invalid rootpage"); } } return 0; } @@ -72961,19 +76084,20 @@ ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; - BtCursor *curMain; + int i; int size; Table *pTab; Db *pDb; char const *azArg[4]; - int meta[10]; + int meta[5]; InitData initData; char const *zMasterSchema; char const *zMasterName = SCHEMA_TABLE(iDb); + int openedTransaction = 0; /* ** The master database table has a structure like this */ static const char master_schema[] = @@ -73030,79 +76154,75 @@ if( initData.rc ){ rc = initData.rc; goto error_out; } pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); - if( pTab ){ + if( ALWAYS(pTab) ){ pTab->tabFlags |= TF_Readonly; } /* Create a cursor to hold the database open */ pDb = &db->aDb[iDb]; if( pDb->pBt==0 ){ - if( !OMIT_TEMPDB && iDb==1 ){ + if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){ DbSetProperty(db, 1, DB_SchemaLoaded); } return SQLITE_OK; } - curMain = sqlite3MallocZero(sqlite3BtreeCursorSize()); - if( !curMain ){ - rc = SQLITE_NOMEM; - goto error_out; - } + + /* If there is not already a read-only (or read-write) transaction opened + ** on the b-tree database, open one now. If a transaction is opened, it + ** will be closed before this function returns. */ sqlite3BtreeEnter(pDb->pBt); - rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain); - if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ - sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); - goto initone_error_out; + if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ + rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); + if( rc!=SQLITE_OK ){ + sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); + goto initone_error_out; + } + openedTransaction = 1; } /* Get the database meta information. ** ** Meta values are as follows: ** meta[0] Schema cookie. Changes with each schema change. ** meta[1] File format of schema layer. ** meta[2] Size of the page cache. - ** meta[3] Use freelist if 0. Autovacuum if greater than zero. + ** meta[3] Largest rootpage (auto/incr_vacuum mode) ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE - ** meta[5] The user cookie. Used by the application. - ** meta[6] Incremental-vacuum flag. - ** meta[7] - ** meta[8] - ** meta[9] + ** meta[5] User version + ** meta[6] Incremental vacuum mode + ** meta[7] unused + ** meta[8] unused + ** meta[9] unused ** ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ - if( rc==SQLITE_OK ){ - int i; - for(i=0; i<ArraySize(meta); i++){ - rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); - if( rc ){ - sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); - goto initone_error_out; - } - } - }else{ - memset(meta, 0, sizeof(meta)); - } - pDb->pSchema->schema_cookie = meta[0]; + for(i=0; i<ArraySize(meta); i++){ + sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); + } + pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. ** For an attached db, it is an error if the encoding is not the same ** as sqlite3.enc. */ - if( meta[4] ){ /* text encoding */ + if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ if( iDb==0 ){ + u8 encoding; /* If opening the main database, set ENC(db). */ - ENC(db) = (u8)meta[4]; - db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0); + encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; + if( encoding==0 ) encoding = SQLITE_UTF8; + ENC(db) = encoding; + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0); }else{ /* If opening an attached database, the encoding much match ENC(db) */ - if( meta[4]!=ENC(db) ){ + if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){ sqlite3SetString(pzErrMsg, db, "attached databases must use the same" " text encoding as main database"); rc = SQLITE_ERROR; goto initone_error_out; } @@ -73111,11 +76231,11 @@ DbSetProperty(db, iDb, DB_Empty); } pDb->pSchema->enc = ENC(db); if( pDb->pSchema->cache_size==0 ){ - size = meta[2]; + size = meta[BTREE_DEFAULT_CACHE_SIZE-1]; if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } if( size<0 ) size = -size; pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } @@ -73124,11 +76244,11 @@ ** file_format==1 Version 3.0.0. ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants */ - pDb->pSchema->file_format = (u8)meta[1]; + pDb->pSchema->file_format = (u8)meta[BTREE_FILE_FORMAT-1]; if( pDb->pSchema->file_format==0 ){ pDb->pSchema->file_format = 1; } if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ sqlite3SetString(pzErrMsg, db, "unsupported file format"); @@ -73139,21 +76259,18 @@ /* Ticket #2804: When we open a database in the newer file format, ** clear the legacy_file_format pragma flag so that a VACUUM will ** not downgrade the database and thus invalidate any descending ** indices that the user might have created. */ - if( iDb==0 && meta[1]>=4 ){ + if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){ db->flags &= ~SQLITE_LegacyFileFmt; } /* Read the schema information out of the schema tables */ assert( db->init.busy ); - if( rc==SQLITE_EMPTY ){ - /* For an empty database, there is nothing to read */ - rc = SQLITE_OK; - }else{ + { char *zSql; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s", db->aDb[iDb].zName, zMasterName); (void)sqlite3SafetyOff(db); @@ -73197,12 +76314,13 @@ /* Jump here for an error that occurs after successfully allocating ** curMain and calling sqlite3BtreeEnter(). For an error that occurs ** before that point, jump to error_out. */ initone_error_out: - sqlite3BtreeCloseCursor(curMain); - sqlite3_free(curMain); + if( openedTransaction ){ + sqlite3BtreeCommit(pDb->pBt); + } sqlite3BtreeLeave(pDb->pBt); error_out: if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; @@ -73223,11 +76341,10 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; int commit_internal = !(db->flags&SQLITE_InternChanges); assert( sqlite3_mutex_held(db->mutex) ); - if( db->init.busy ) return SQLITE_OK; rc = SQLITE_OK; db->init.busy = 1; for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); @@ -73239,11 +76356,12 @@ /* Once all the other databases have been initialised, load the schema ** for the TEMP database. This is loaded last, as the TEMP database ** schema may contain references to objects in other databases. */ #ifndef SQLITE_OMIT_TEMPDB - if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ + if( rc==SQLITE_OK && ALWAYS(db->nDb>1) + && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ sqlite3ResetInternalSchema(db, 1); } } @@ -73276,46 +76394,51 @@ } /* ** Check schema cookies in all databases. If any cookie is out -** of date, return 0. If all schema cookies are current, return 1. -*/ -static int schemaIsValid(sqlite3 *db){ +** of date set pParse->rc to SQLITE_SCHEMA. If all schema cookies +** make no changes to pParse->rc. +*/ +static void schemaIsValid(Parse *pParse){ + sqlite3 *db = pParse->db; int iDb; int rc; - BtCursor *curTemp; int cookie; - int allOk = 1; - - curTemp = (BtCursor *)sqlite3Malloc(sqlite3BtreeCursorSize()); - if( curTemp ){ - assert( sqlite3_mutex_held(db->mutex) ); - for(iDb=0; allOk && iDb<db->nDb; iDb++){ - Btree *pBt; - pBt = db->aDb[iDb].pBt; - if( pBt==0 ) continue; - memset(curTemp, 0, sqlite3BtreeCursorSize()); - rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); - if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - allOk = 0; - } - sqlite3BtreeCloseCursor(curTemp); - } + + assert( pParse->checkSchema ); + assert( sqlite3_mutex_held(db->mutex) ); + for(iDb=0; iDb<db->nDb; iDb++){ + int openedTransaction = 0; /* True if a transaction is opened */ + Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */ + if( pBt==0 ) continue; + + /* If there is not already a read-only (or read-write) transaction opened + ** on the b-tree database, open one now. If a transaction is opened, it + ** will be closed immediately after reading the meta-value. */ + if( !sqlite3BtreeIsInReadTrans(pBt) ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; } - } - sqlite3_free(curTemp); - }else{ - allOk = 0; - db->mallocFailed = 1; - } - - return allOk; + if( rc!=SQLITE_OK ) return; + openedTransaction = 1; + } + + /* Read the schema cookie from the database. If it does not match the + ** value stored as part of the in the in-memory schema representation, + ** set Parse.rc to SQLITE_SCHEMA. */ + sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); + if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ + pParse->rc = SQLITE_SCHEMA; + } + + /* Close the transaction, if one was opened. */ + if( openedTransaction ){ + sqlite3BtreeCommit(pBt); + } + } } /* ** Convert a schema pointer into the iDb index that indicates ** which database file in db->aDb[] the schema refers to. @@ -73357,16 +76480,26 @@ int nBytes, /* Length of zSql in bytes. */ int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ - Parse sParse; - char *zErrMsg = 0; - int rc = SQLITE_OK; - int i; - - if( sqlite3SafetyOn(db) ) return SQLITE_MISUSE; + Parse *pParse; /* Parsing context */ + char *zErrMsg = 0; /* Error message */ + int rc = SQLITE_OK; /* Result code */ + int i; /* Loop counter */ + + /* Allocate the parsing context */ + pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); + if( pParse==0 ){ + rc = SQLITE_NOMEM; + goto end_prepare; + } + + if( sqlite3SafetyOn(db) ){ + rc = SQLITE_MISUSE; + goto end_prepare; + } assert( ppStmt && *ppStmt==0 ); assert( !db->mallocFailed ); assert( sqlite3_mutex_held(db->mutex) ); /* Check to verify that it is possible to get a read lock on all @@ -73400,72 +76533,78 @@ if( rc ){ const char *zDb = db->aDb[i].zName; sqlite3Error(db, rc, "database schema is locked: %s", zDb); (void)sqlite3SafetyOff(db); testcase( db->flags & SQLITE_ReadUncommitted ); - return sqlite3ApiExit(db, rc); - } - } - } - - memset(&sParse, 0, sizeof(sParse)); - sParse.db = db; + goto end_prepare; + } + } + } + + sqlite3VtabUnlockList(db); + + pParse->db = db; if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; + testcase( nBytes==mxLen ); + testcase( nBytes==mxLen+1 ); if( nBytes>mxLen ){ sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); (void)sqlite3SafetyOff(db); - return sqlite3ApiExit(db, SQLITE_TOOBIG); + rc = sqlite3ApiExit(db, SQLITE_TOOBIG); + goto end_prepare; } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ - sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); sqlite3DbFree(db, zSqlCopy); - sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; - }else{ - sParse.zTail = &zSql[nBytes]; - } - }else{ - sqlite3RunParser(&sParse, zSql, &zErrMsg); + pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; + }else{ + pParse->zTail = &zSql[nBytes]; + } + }else{ + sqlite3RunParser(pParse, zSql, &zErrMsg); } if( db->mallocFailed ){ - sParse.rc = SQLITE_NOMEM; - } - if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; - if( sParse.checkSchema && !schemaIsValid(db) ){ - sParse.rc = SQLITE_SCHEMA; - } - if( sParse.rc==SQLITE_SCHEMA ){ + pParse->rc = SQLITE_NOMEM; + } + if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; + if( pParse->checkSchema ){ + schemaIsValid(pParse); + } + if( pParse->rc==SQLITE_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } if( db->mallocFailed ){ - sParse.rc = SQLITE_NOMEM; + pParse->rc = SQLITE_NOMEM; } if( pzTail ){ - *pzTail = sParse.zTail; - } - rc = sParse.rc; + *pzTail = pParse->zTail; + } + rc = pParse->rc; #ifndef SQLITE_OMIT_EXPLAIN - if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ - if( sParse.explain==2 ){ - sqlite3VdbeSetNumCols(sParse.pVdbe, 3); - sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", SQLITE_STATIC); - }else{ - sqlite3VdbeSetNumCols(sParse.pVdbe, 8); - sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 5, COLNAME_NAME, "p4", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 6, COLNAME_NAME, "p5", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 7, COLNAME_NAME, "comment", SQLITE_STATIC); + if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){ + static const char * const azColName[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", + "order", "from", "detail" + }; + int iFirst, mx; + if( pParse->explain==2 ){ + sqlite3VdbeSetNumCols(pParse->pVdbe, 3); + iFirst = 8; + mx = 11; + }else{ + sqlite3VdbeSetNumCols(pParse->pVdbe, 8); + iFirst = 0; + mx = 8; + } + for(i=iFirst; i<mx; i++){ + sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME, + azColName[i], SQLITE_STATIC); } } #endif if( sqlite3SafetyOff(db) ){ @@ -73472,27 +76611,38 @@ rc = SQLITE_MISUSE; } assert( db->init.busy==0 || saveSqlFlag==0 ); if( db->init.busy==0 ){ - Vdbe *pVdbe = sParse.pVdbe; - sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); - } - if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ - sqlite3VdbeFinalize(sParse.pVdbe); + Vdbe *pVdbe = pParse->pVdbe; + sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); + } + if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ + sqlite3VdbeFinalize(pParse->pVdbe); assert(!(*ppStmt)); }else{ - *ppStmt = (sqlite3_stmt*)sParse.pVdbe; + *ppStmt = (sqlite3_stmt*)pParse->pVdbe; } if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); sqlite3DbFree(db, zErrMsg); }else{ sqlite3Error(db, rc, 0); } + /* Delete any TriggerPrg structures allocated while parsing this statement. */ + while( pParse->pTriggerPrg ){ + TriggerPrg *pT = pParse->pTriggerPrg; + pParse->pTriggerPrg = pT->pNext; + sqlite3VdbeProgramDelete(db, pT->pProgram, 0); + sqlite3DbFree(db, pT); + } + +end_prepare: + + sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); assert( (rc&db->errMask)==rc ); return rc; } static int sqlite3LockAndPrepare( @@ -73510,10 +76660,14 @@ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); + if( rc==SQLITE_SCHEMA ){ + sqlite3_finalize(*ppStmt); + rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); + } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return rc; } @@ -73683,11 +76837,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.507 2009/04/02 16:59:47 drh Exp $ +** $Id: select.c,v 1.526 2009/08/01 15:09:58 drh Exp $ */ /* ** Delete all the content of a Select structure but do not deallocate @@ -73741,11 +76895,11 @@ if( pNew==0 ){ pNew = &standin; memset(pNew, 0, sizeof(*pNew)); } if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0,0,0), 0); + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0)); } pNew->pEList = pEList; pNew->pSrc = pSrc; pNew->pWhere = pWhere; pNew->pGroupBy = pGroupBy; @@ -73753,10 +76907,11 @@ pNew->pOrderBy = pOrderBy; pNew->selFlags = isDistinct ? SF_Distinct : 0; pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; + assert( pOffset==0 || pLimit!=0 ); pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; if( db->mallocFailed ) { clearSelect(db, pNew); @@ -73795,37 +76950,40 @@ */ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int jointype = 0; Token *apAll[3]; Token *p; + /* 0123456789 123456789 123456789 123 */ + static const char zKeyText[] = "naturaleftouterightfullinnercross"; static const struct { - const char zKeyword[8]; - u8 nChar; - u8 code; - } keywords[] = { - { "natural", 7, JT_NATURAL }, - { "left", 4, JT_LEFT|JT_OUTER }, - { "right", 5, JT_RIGHT|JT_OUTER }, - { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, - { "outer", 5, JT_OUTER }, - { "inner", 5, JT_INNER }, - { "cross", 5, JT_INNER|JT_CROSS }, + u8 i; /* Beginning of keyword text in zKeyText[] */ + u8 nChar; /* Length of the keyword in characters */ + u8 code; /* Join type mask */ + } aKeyword[] = { + /* natural */ { 0, 7, JT_NATURAL }, + /* left */ { 6, 4, JT_LEFT|JT_OUTER }, + /* outer */ { 10, 5, JT_OUTER }, + /* right */ { 14, 5, JT_RIGHT|JT_OUTER }, + /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, + /* inner */ { 23, 5, JT_INNER }, + /* cross */ { 28, 5, JT_INNER|JT_CROSS }, }; int i, j; apAll[0] = pA; apAll[1] = pB; apAll[2] = pC; for(i=0; i<3 && apAll[i]; i++){ p = apAll[i]; - for(j=0; j<ArraySize(keywords); j++){ - if( p->n==keywords[j].nChar - && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){ - jointype |= keywords[j].code; - break; - } - } - if( j>=ArraySize(keywords) ){ + for(j=0; j<ArraySize(aKeyword); j++){ + if( p->n==aKeyword[j].nChar + && sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){ + jointype |= aKeyword[j].code; + break; + } + } + testcase( j==0 || j==1 || j==2 || j==3 || j==4 || j==5 || j==6 ); + if( j>=ArraySize(aKeyword) ){ jointype |= JT_ERROR; break; } } if( @@ -73836,11 +76994,12 @@ assert( pB!=0 ); if( pC==0 ){ zSp++; } sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " "%T %T%s%T", pA, pB, zSp, pC); jointype = JT_INNER; - }else if( jointype & JT_RIGHT ){ + }else if( (jointype & JT_OUTER)!=0 + && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){ sqlite3ErrorMsg(pParse, "RIGHT and FULL OUTER JOINs are not currently supported"); jointype = JT_INNER; } return jointype; @@ -73857,61 +77016,14 @@ } return -1; } /* -** Set the value of a token to a '\000'-terminated string. -*/ -static void setToken(Token *p, const char *z){ - p->z = (u8*)z; - p->n = z ? sqlite3Strlen30(z) : 0; - p->dyn = 0; -} - -/* -** Set the token to the double-quoted and escaped version of the string pointed -** to by z. For example; -** -** {a"bc} -> {"a""bc"} -*/ -static void setQuotedToken(Parse *pParse, Token *p, const char *z){ - - /* Check if the string appears to be quoted using "..." or `...` - ** or [...] or '...' or if the string contains any " characters. - ** If it does, then record a version of the string with the special - ** characters escaped. - */ - const char *z2 = z; - if( *z2!='[' && *z2!='`' && *z2!='\'' ){ - while( *z2 ){ - if( *z2=='"' ) break; - z2++; - } - } - - if( *z2 ){ - /* String contains " characters - copy and quote the string. */ - p->z = (u8 *)sqlite3MPrintf(pParse->db, "\"%w\"", z); - if( p->z ){ - p->n = sqlite3Strlen30((char *)p->z); - p->dyn = 1; - } - }else{ - /* String contains no " characters - copy the pointer. */ - p->z = (u8*)z; - p->n = (int)(z2 - z); - p->dyn = 0; - } -} - -/* ** Create an expression node for an identifier with the name of zName */ SQLITE_PRIVATE Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){ - Token dummy; - setToken(&dummy, zName); - return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy); + return sqlite3Expr(pParse->db, TK_ID, zName); } /* ** Add a term to the WHERE expression in *ppExpr that requires the ** zCol column to be equal in the two tables pTab1 and pTab2. @@ -73944,11 +77056,13 @@ pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0); pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0); pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0); if( pE && isOuterJoin ){ ExprSetProperty(pE, EP_FromJoin); - pE->iRightJoinTable = iRightJoinTable; + assert( !ExprHasAnyProperty(pE, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(pE); + pE->iRightJoinTable = (i16)iRightJoinTable; } *ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE); } /* @@ -73978,11 +77092,13 @@ ** the output, which is incorrect. */ static void setJoinExpr(Expr *p, int iTable){ while( p ){ ExprSetProperty(p, EP_FromJoin); - p->iRightJoinTable = iTable; + assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(p); + p->iRightJoinTable = (i16)iTable; setJoinExpr(p->pLeft, iTable); p = p->pRight; } } @@ -74091,10 +77207,11 @@ ){ Vdbe *v = pParse->pVdbe; int nExpr = pOrderBy->nExpr; int regBase = sqlite3GetTempRange(pParse, nExpr+2); int regRecord = sqlite3GetTempReg(pParse); + sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); @@ -74243,10 +77360,11 @@ } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ + sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output); } nColumn = nResultCol; /* If the DISTINCT keyword was present on the SELECT statement @@ -74293,10 +77411,12 @@ /* Store the result as data using a unique key. */ case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); + testcase( eDest==SRT_Table ); + testcase( eDest==SRT_EphemTab ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p, r1); }else{ int r2 = sqlite3GetTempReg(pParse); @@ -74361,10 +77481,12 @@ ** case of a subroutine, the subroutine itself is responsible for ** popping the data from the stack. */ case SRT_Coroutine: case SRT_Output: { + testcase( eDest==SRT_Coroutine ); + testcase( eDest==SRT_Output ); if( pOrderBy ){ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); @@ -74468,18 +77590,20 @@ int regRow; int regRowid; iTab = pOrderBy->iECursor; + regRow = sqlite3GetTempReg(pParse); if( eDest==SRT_Output || eDest==SRT_Coroutine ){ pseudoTab = pParse->nTab++; - sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output, nColumn); + sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn); + regRowid = 0; + }else{ + regRowid = sqlite3GetTempReg(pParse); } addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); codeOffset(v, p, addrContinue); - regRow = sqlite3GetTempReg(pParse); - regRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow); switch( eDest ){ case SRT_Table: case SRT_EphemTab: { testcase( eDest==SRT_Table ); @@ -74502,31 +77626,28 @@ sqlite3ExprCodeMove(pParse, regRow, iParm, 1); /* The LIMIT clause will terminate the loop for us */ break; } #endif - case SRT_Output: - case SRT_Coroutine: { + default: { int i; + assert( eDest==SRT_Output || eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); testcase( eDest==SRT_Coroutine ); - sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); for(i=0; i<nColumn; i++){ assert( regRow!=pDest->iMem+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); + if( i==0 ){ + sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); + } } if( eDest==SRT_Output ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn); }else{ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); } - break; - } - default: { - /* Do nothing */ break; } } sqlite3ReleaseTempReg(pParse, regRow); sqlite3ReleaseTempReg(pParse, regRowid); @@ -74573,11 +77694,11 @@ char const *zType = 0; char const *zOriginDb = 0; char const *zOriginTab = 0; char const *zOriginCol = 0; int j; - if( pExpr==0 || pNC->pSrcList==0 ) return 0; + if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0; switch( pExpr->op ){ case TK_AGG_COLUMN: case TK_COLUMN: { /* The expression is a column. Locate the table the column is being @@ -74585,10 +77706,12 @@ ** database table or a subquery. */ Table *pTab = 0; /* Table structure column is extracted from */ Select *pS = 0; /* Select the column is extracted from */ int iCol = pExpr->iColumn; /* Index of column in pTab */ + testcase( pExpr->op==TK_AGG_COLUMN ); + testcase( pExpr->op==TK_COLUMN ); while( pNC && !pTab ){ SrcList *pTabList = pNC->pSrcList; for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); if( j<pTabList->nSrc ){ pTab = pTabList->a[j].pTab; @@ -74597,25 +77720,31 @@ pNC = pNC->pNext; } } if( pTab==0 ){ - /* FIX ME: - ** This can occurs if you have something like "SELECT new.x;" inside - ** a trigger. In other words, if you reference the special "new" - ** table in the result set of a select. We do not have a good way - ** to find the actual table type, so call it "TEXT". This is really - ** something of a bug, but I do not know how to fix it. - ** - ** This code does not produce the correct answer - it just prevents - ** a segfault. See ticket #1229. - */ - zType = "TEXT"; - break; - } - - assert( pTab ); + /* At one time, code such as "SELECT new.x" within a trigger would + ** cause this condition to run. Since then, we have restructured how + ** trigger code is generated and so this condition is no longer + ** possible. However, it can still be true for statements like + ** the following: + ** + ** CREATE TABLE t1(col INTEGER); + ** SELECT (SELECT t1.col) FROM FROM t1; + ** + ** when columnType() is called on the expression "t1.col" in the + ** sub-select. In this case, set the column type to NULL, even + ** though it should really be "INTEGER". + ** + ** This is not a problem, as the column type of "t1.col" is never + ** used. When columnType() is called on the expression + ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT + ** branch below. */ + break; + } + + assert( pTab && pExpr->pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ @@ -74625,11 +77754,11 @@ ** test case misc2.2.2) - it always evaluates to NULL. */ NameContext sNC; Expr *p = pS->pEList->a[iCol].pExpr; sNC.pSrcList = pS->pSrc; - sNC.pNext = 0; + sNC.pNext = pNC; sNC.pParse = pNC->pParse; zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); } }else if( ALWAYS(pTab->pSchema) ){ /* A real table */ @@ -74738,20 +77867,19 @@ if( pParse->explain ){ return; } #endif - assert( v!=0 ); if( pParse->colNamesSet || NEVER(v==0) || db->mallocFailed ) return; pParse->colNamesSet = 1; fullNames = (db->flags & SQLITE_FullColNames)!=0; shortNames = (db->flags & SQLITE_ShortColNames)!=0; sqlite3VdbeSetNumCols(v, pEList->nExpr); for(i=0; i<pEList->nExpr; i++){ Expr *p; p = pEList->a[i].pExpr; - if( p==0 ) continue; + if( NEVER(p==0) ) continue; if( pEList->a[i].zName ){ char *zName = pEList->a[i].zName; sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){ Table *pTab; @@ -74769,21 +77897,21 @@ }else{ zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames ){ sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC); + sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); }else if( fullNames ){ char *zName = 0; zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); }else{ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); } }else{ sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC); + sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); } } generateColumnTypes(pParse, pTabList, pEList); } @@ -74836,35 +77964,38 @@ if( aCol==0 ) return SQLITE_NOMEM; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; - assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); + assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) + || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ zName = sqlite3DbStrDup(db, zName); }else{ Expr *pColExpr = p; /* The expression that is the result column name */ Table *pTab; /* Table associated with this expression */ while( pColExpr->op==TK_DOT ) pColExpr = pColExpr->pRight; - if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->pTab)!=0 ){ + if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; + pTab = pColExpr->pTab; if( iCol<0 ) iCol = pTab->iPKey; zName = sqlite3MPrintf(db, "%s", iCol>=0 ? pTab->aCol[iCol].zName : "rowid"); + }else if( pColExpr->op==TK_ID ){ + assert( !ExprHasProperty(pColExpr, EP_IntValue) ); + zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken); }else{ /* Use the original text of the column expression as its name */ - Token *pToken = (pColExpr->span.z?&pColExpr->span:&pColExpr->token); - zName = sqlite3MPrintf(db, "%T", pToken); + zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan); } } if( db->mallocFailed ){ sqlite3DbFree(db, zName); break; } - sqlite3Dequote(zName); /* Make sure the column name is unique. If the name is not unique, ** append a integer to the name so that it becomes unique. */ nName = sqlite3Strlen30(zName); @@ -74927,10 +78058,11 @@ a = pSelect->pEList->a; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ p = a[i].pExpr; pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0)); pCol->affinity = sqlite3ExprAffinity(p); + if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } } @@ -74954,11 +78086,14 @@ db->flags = savedFlags; pTab = sqlite3DbMallocZero(db, sizeof(Table) ); if( pTab==0 ){ return 0; } - pTab->dbMem = db->lookaside.bEnabled ? db : 0; + /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside + ** is disabled, so we might as well hard-code pTab->dbMem to NULL. */ + assert( db->lookaside.bEnabled==0 ); + pTab->dbMem = 0; pTab->nRef = 1; pTab->zName = 0; selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect); pTab->iPKey = -1; @@ -75016,33 +78151,29 @@ ** "LIMIT -1" always shows all rows. There is some ** contraversy about what the correct behavior should be. ** The current implementation interprets "LIMIT 0" to mean ** no rows. */ + sqlite3ExprCacheClear(pParse); + assert( p->pOffset==0 || p->pLimit!=0 ); if( p->pLimit ){ p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); - if( v==0 ) return; + if( NEVER(v==0) ) return; /* VDBE should have already been allocated */ sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeComment((v, "LIMIT counter")); sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); - } - if( p->pOffset ){ - p->iOffset = iOffset = ++pParse->nMem; - if( p->pLimit ){ + if( p->pOffset ){ + p->iOffset = iOffset = ++pParse->nMem; pParse->nMem++; /* Allocate an extra register for limit+offset */ - } - v = sqlite3GetVdbe(pParse); - if( v==0 ) return; - sqlite3ExprCode(pParse, p->pOffset, iOffset); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); - VdbeComment((v, "OFFSET counter")); - addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); - sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); - sqlite3VdbeJumpHere(v, addr1); - if( p->pLimit ){ + sqlite3ExprCode(pParse, p->pOffset, iOffset); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); + VdbeComment((v, "OFFSET counter")); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); + sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); VdbeComment((v, "LIMIT+OFFSET")); addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); sqlite3VdbeJumpHere(v, addr1); @@ -75064,11 +78195,12 @@ if( p->pPrior ){ pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); }else{ pRet = 0; } - if( pRet==0 ){ + assert( iCol>=0 ); + if( pRet==0 && iCol<p->pEList->nExpr ){ pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); } return pRet; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ @@ -75195,15 +78327,13 @@ if( p->iLimit ){ addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeComment((v, "Jump ahead if LIMIT reached")); } rc = sqlite3Select(pParse, p, &dest); + testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; p->pPrior = pPrior; - if( rc ){ - goto multi_select_end; - } if( addr ){ sqlite3VdbeJumpHere(v, addr); } break; } @@ -75214,10 +78344,12 @@ int priorOp; /* The SRT_ operation to apply to prior selects */ Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ int addr; SelectDest uniondest; + testcase( p->op==TK_EXCEPT ); + testcase( p->op==TK_UNION ); priorOp = SRT_Union; if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){ /* We can reuse a temporary table generated by a SELECT to our ** right. */ @@ -75261,10 +78393,11 @@ p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; uniondest.eDest = op; rc = sqlite3Select(pParse, p, &uniondest); + testcase( rc!=SQLITE_OK ); /* Query flattening in sqlite3Select() might refill p->pOrderBy. ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ sqlite3ExprListDelete(db, p->pOrderBy); pDelete = p->pPrior; p->pPrior = pPrior; @@ -75272,19 +78405,16 @@ sqlite3ExprDelete(db, p->pLimit); p->pLimit = pLimit; p->pOffset = pOffset; p->iLimit = 0; p->iOffset = 0; - if( rc ){ - goto multi_select_end; - } - /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ - if( dest.eDest!=priorOp || unionTab!=dest.iParm ){ + assert( unionTab==dest.iParm || dest.eDest!=priorOp ); + if( dest.eDest!=priorOp ){ int iCont, iBreak, iStart; assert( p->pEList ); if( dest.eDest==SRT_Output ){ Select *pFirst = p; while( pFirst->pPrior ) pFirst = pFirst->pPrior; @@ -75302,11 +78432,11 @@ sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); } break; } - case TK_INTERSECT: { + default: assert( p->op==TK_INTERSECT ); { int tab1, tab2; int iCont, iBreak, iStart; Expr *pLimit, *pOffset; int addr; SelectDest intersectdest; @@ -75344,18 +78474,16 @@ p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; intersectdest.iParm = tab2; rc = sqlite3Select(pParse, p, &intersectdest); + testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; p->pPrior = pPrior; sqlite3ExprDelete(db, p->pLimit); p->pLimit = pLimit; p->pOffset = pOffset; - if( rc ){ - goto multi_select_end; - } /* Generate code to take the intersection of the two temporary ** tables. */ assert( p->pEList ); @@ -75504,10 +78632,12 @@ */ case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); + testcase( pDest->eDest==SRT_Table ); + testcase( pDest->eDest==SRT_EphemTab ); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1); sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); @@ -75566,30 +78696,24 @@ sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iMem, pDest->nMem); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); break; } - /* Results are stored in a sequence of registers. Then the - ** OP_ResultRow opcode is used to cause sqlite3_step() to return - ** the next row of result. - */ - case SRT_Output: { + /* If none of the above, then the result destination must be + ** SRT_Output. This routine is never called with any other + ** destination other than the ones handled above or SRT_Output. + ** + ** For SRT_Output, results are stored in a sequence of registers. + ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to + ** return the next row of result. + */ + default: { + assert( pDest->eDest==SRT_Output ); sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem); sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem); break; } - -#if !defined(SQLITE_OMIT_TRIGGER) - /* Discard the results. This is used for SELECT statements inside - ** the body of a TRIGGER. The purpose of such selects is to call - ** user-defined functions that have side effects. We do not care - ** about the actual results of the select. - */ - default: { - break; - } -#endif } /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ @@ -75734,11 +78858,11 @@ assert( p->pOrderBy!=0 ); assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ db = pParse->db; v = pParse->pVdbe; - if( v==0 ) return SQLITE_NOMEM; + assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */ labelEnd = sqlite3VdbeMakeLabel(v); labelCmpr = sqlite3VdbeMakeLabel(v); /* Patch up the ORDER BY clause @@ -75760,22 +78884,22 @@ for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){ assert( pItem->iCol>0 ); if( pItem->iCol==i ) break; } if( j==nOrderBy ){ - Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return SQLITE_NOMEM; pNew->flags |= EP_IntValue; - pNew->iTable = i; - pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0); + pNew->u.iValue = i; + pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); pOrderBy->a[nOrderBy++].iCol = (u16)i; } } } /* Compute the comparison permutation and keyinfo that is used with - ** the permutation in order to comparisons to determine if the next + ** the permutation used to determine if the next ** row of results comes from selectA or selectB. Also add explicit ** collations to the ORDER BY clause terms so that when the subqueries ** to the right and the left are evaluated, they use the correct ** collation. */ @@ -76049,56 +79173,41 @@ ** FROM clause of a SELECT such that the VDBE cursor assigned to that ** FORM clause entry is iTable. This routine make the necessary ** changes to pExpr so that it refers directly to the source table ** of the subquery rather the result set of the subquery. */ -static void substExpr( +static Expr *substExpr( sqlite3 *db, /* Report malloc errors to this connection */ Expr *pExpr, /* Expr in which substitution occurs */ int iTable, /* Table to be substituted */ ExprList *pEList /* Substitute expressions */ ){ - if( pExpr==0 ) return; + if( pExpr==0 ) return 0; if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - pNew = pEList->a[pExpr->iColumn].pExpr; - assert( pNew!=0 ); - pExpr->op = pNew->op; - assert( pExpr->pLeft==0 ); - pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft, 0); - assert( pExpr->pRight==0 ); - pExpr->pRight = sqlite3ExprDup(db, pNew->pRight, 0); - pExpr->iTable = pNew->iTable; - pExpr->pTab = pNew->pTab; - pExpr->iColumn = pNew->iColumn; - pExpr->iAgg = pNew->iAgg; - sqlite3TokenCopy(db, &pExpr->token, &pNew->token); - sqlite3TokenCopy(db, &pExpr->span, &pNew->span); - assert( pExpr->x.pList==0 && pExpr->x.pSelect==0 ); - if( ExprHasProperty(pNew, EP_xIsSelect) ){ - pExpr->x.pSelect = sqlite3SelectDup(db, pNew->x.pSelect, 0); - }else{ - pExpr->x.pList = sqlite3ExprListDup(db, pNew->x.pList, 0); - } - pExpr->flags = pNew->flags; - pExpr->pAggInfo = pNew->pAggInfo; - pNew->pAggInfo = 0; - } - }else{ - substExpr(db, pExpr->pLeft, iTable, pEList); - substExpr(db, pExpr->pRight, iTable, pEList); + pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); + if( pNew && pExpr->pColl ){ + pNew->pColl = pExpr->pColl; + } + sqlite3ExprDelete(db, pExpr); + pExpr = pNew; + } + }else{ + pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); + pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ substSelect(db, pExpr->x.pSelect, iTable, pEList); }else{ substExprList(db, pExpr->x.pList, iTable, pEList); } } + return pExpr; } static void substExprList( sqlite3 *db, /* Report malloc errors here */ ExprList *pList, /* List to scan and in which to make substitutes */ int iTable, /* Table to be substituted */ @@ -76105,11 +79214,11 @@ ExprList *pEList /* Substitute values */ ){ int i; if( pList==0 ) return; for(i=0; i<pList->nExpr; i++){ - substExpr(db, pList->a[i].pExpr, iTable, pEList); + pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList); } } static void substSelect( sqlite3 *db, /* Report malloc errors here */ Select *p, /* SELECT statement in which to make substitutions */ @@ -76121,12 +79230,12 @@ int i; if( !p ) return; substExprList(db, p->pEList, iTable, pEList); substExprList(db, p->pGroupBy, iTable, pEList); substExprList(db, p->pOrderBy, iTable, pEList); - substExpr(db, p->pHaving, iTable, pEList); - substExpr(db, p->pWhere, iTable, pEList); + p->pHaving = substExpr(db, p->pHaving, iTable, pEList); + p->pWhere = substExpr(db, p->pWhere, iTable, pEList); substSelect(db, p->pPrior, iTable, pEList); pSrc = p->pSrc; assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ if( ALWAYS(pSrc) ){ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ @@ -76348,13 +79457,15 @@ } if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){ return 0; } for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ + testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); + testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 || (pSub1->pPrior && pSub1->op!=TK_ALL) - || !pSub1->pSrc || pSub1->pSrc->nSrc!=1 + || NEVER(pSub1->pSrc==0) || pSub1->pSrc->nSrc!=1 ){ return 0; } } @@ -76450,16 +79561,19 @@ /* Defer deleting the Table object associated with the ** subquery until code generation is ** complete, since there may still exist Expr.pTab entries that ** refer to the subquery even after flattening. Ticket #3346. - */ - if( pSubitem->pTab!=0 ){ + ** + ** pSubitem->pTab is always non-NULL by test restrictions and tests above. + */ + if( ALWAYS(pSubitem->pTab!=0) ){ Table *pTabToDel = pSubitem->pTab; if( pTabToDel->nRef==1 ){ - pTabToDel->pNextZombie = pParse->pZombieTab; - pParse->pZombieTab = pTabToDel; + Parse *pToplevel = sqlite3ParseToplevel(pParse); + pTabToDel->pNextZombie = pToplevel->pZombieTab; + pToplevel->pZombieTab = pTabToDel; }else{ pTabToDel->nRef--; } pSubitem->pTab = 0; } @@ -76520,10 +79634,11 @@ /* Transfer the FROM clause terms from the subquery into the ** outer query. */ for(i=0; i<nSubSrc; i++){ + sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing); pSrc->a[i+iFrom] = pSubSrc->a[i]; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } pSrc->a[iFrom].jointype = jointype; @@ -76539,20 +79654,21 @@ ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ pList = pParent->pEList; for(i=0; i<pList->nExpr; i++){ - Expr *pExpr; - if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ - pList->a[i].zName = - sqlite3DbStrNDup(db, (char*)pExpr->span.z, pExpr->span.n); + if( pList->a[i].zName==0 ){ + const char *zSpan = pList->a[i].zSpan; + if( ALWAYS(zSpan) ){ + pList->a[i].zName = sqlite3DbStrDup(db, zSpan); + } } } substExprList(db, pParent->pEList, iParent, pSub->pEList); if( isAgg ){ substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); - substExpr(db, pParent->pHaving, iParent, pSub->pEList); + pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); } if( pSub->pOrderBy ){ assert( pParent->pOrderBy==0 ); pParent->pOrderBy = pSub->pOrderBy; pSub->pOrderBy = 0; @@ -76566,17 +79682,17 @@ } if( subqueryIsAgg ){ assert( pParent->pHaving==0 ); pParent->pHaving = pParent->pWhere; pParent->pWhere = pWhere; - substExpr(db, pParent->pHaving, iParent, pSub->pEList); + pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, sqlite3ExprDup(db, pSub->pHaving, 0)); assert( pParent->pGroupBy==0 ); pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); }else{ - substExpr(db, pParent->pWhere, iParent, pSub->pEList); + pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList); pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); } /* The flattened query is distinct if either the inner or the ** outer query is distinct. @@ -76619,18 +79735,19 @@ Expr *pExpr; ExprList *pEList = p->pEList; if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; pExpr = pEList->a[0].pExpr; - if( ExprHasProperty(pExpr, EP_xIsSelect) ) return 0; + if( pExpr->op!=TK_AGG_FUNCTION ) return 0; + if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0; pEList = pExpr->x.pList; - if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0; + if( pEList==0 || pEList->nExpr!=1 ) return 0; if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; - if( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL; - if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ return WHERE_ORDERBY_MIN; - }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ + }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ return WHERE_ORDERBY_MAX; } return WHERE_ORDERBY_NORMAL; } @@ -76726,11 +79843,11 @@ sqlite3 *db = pParse->db; if( db->mallocFailed ){ return WRC_Abort; } - if( p->pSrc==0 || (p->selFlags & SF_Expanded)!=0 ){ + if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } p->selFlags |= SF_Expanded; pTabList = p->pSrc; pEList = p->pEList; @@ -76778,20 +79895,13 @@ pTab->nRef++; #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( pTab->pSelect || IsVirtual(pTab) ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; - - /* If pFrom->pSelect!=0 it means we are dealing with a - ** view within a view. The SELECT structure has already been - ** copied by the outer view so we can skip the copy step here - ** in the inner view. - */ - if( pFrom->pSelect==0 ){ - pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); - sqlite3WalkSelect(pWalker, pFrom->pSelect); - } + assert( pFrom->pSelect==0 ); + pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); + sqlite3WalkSelect(pWalker, pFrom->pSelect); } #endif } /* Locate the index named by the INDEXED BY clause, if any. */ @@ -76817,12 +79927,13 @@ ** that need expanding. */ for(k=0; k<pEList->nExpr; k++){ Expr *pE = pEList->a[k].pExpr; if( pE->op==TK_ALL ) break; - if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL - && pE->pLeft && pE->pLeft->op==TK_ID ) break; + assert( pE->op!=TK_DOT || pE->pRight!=0 ); + assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); + if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; } if( k<pEList->nExpr ){ /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression @@ -76834,34 +79945,38 @@ int longNames = (flags & SQLITE_FullColNames)!=0 && (flags & SQLITE_ShortColNames)==0; for(k=0; k<pEList->nExpr; k++){ Expr *pE = a[k].pExpr; - if( pE->op!=TK_ALL && - (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){ + assert( pE->op!=TK_DOT || pE->pRight!=0 ); + if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){ /* This particular expression does not need to be expanded. */ - pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0); + pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); if( pNew ){ pNew->a[pNew->nExpr-1].zName = a[k].zName; - } - a[k].pExpr = 0; - a[k].zName = 0; + pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan; + a[k].zName = 0; + a[k].zSpan = 0; + } + a[k].pExpr = 0; }else{ /* This expression is a "*" or a "TABLE.*" and needs to be ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName; /* text of name of TABLE */ - if( pE->op==TK_DOT && pE->pLeft ){ - zTName = sqlite3NameFromToken(db, &pE->pLeft->token); + if( pE->op==TK_DOT ){ + assert( pE->pLeft!=0 ); + assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); + zTName = pE->pLeft->u.zToken; }else{ zTName = 0; } for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; char *zTabName = pFrom->zAlias; - if( zTabName==0 || zTabName[0]==0 ){ + if( zTabName==0 ){ zTabName = pTab->zName; } if( db->mallocFailed ) break; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; @@ -76868,10 +79983,13 @@ } tableSeen = 1; for(j=0; j<pTab->nCol; j++){ Expr *pExpr, *pRight; char *zName = pTab->aCol[j].zName; + char *zColname; /* The computed column name */ + char *zToFree; /* Malloced string that needs to be freed */ + Token sColname; /* Computed column name as a token */ /* If a column is marked as 'hidden' (currently only possible ** for virtual tables), do not include it in the expanded ** result-set list. */ @@ -76892,44 +80010,38 @@ /* In a join with a USING clause, omit columns in the ** using clause from the table on the right. */ continue; } } - pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); - if( pRight==0 ) break; - setQuotedToken(pParse, &pRight->token, zName); + pRight = sqlite3Expr(db, TK_ID, zName); + zColname = zName; + zToFree = 0; if( longNames || pTabList->nSrc>1 ){ - Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); + Expr *pLeft; + pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - if( pExpr==0 ) break; - setQuotedToken(pParse, &pLeft->token, zTabName); - setToken(&pExpr->span, - sqlite3MPrintf(db, "%s.%s", zTabName, zName)); - pExpr->span.dyn = 1; - pExpr->token.z = 0; - pExpr->token.n = 0; - pExpr->token.dyn = 0; + if( longNames ){ + zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); + zToFree = zColname; + } }else{ pExpr = pRight; - pExpr->span = pExpr->token; - pExpr->span.dyn = 0; - } - if( longNames ){ - pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span); - }else{ - pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token); - } + } + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); + sColname.z = zColname; + sColname.n = sqlite3Strlen30(zColname); + sqlite3ExprListSetName(pParse, pNew, &sColname, 0); + sqlite3DbFree(db, zToFree); } } if( !tableSeen ){ if( zTName ){ sqlite3ErrorMsg(pParse, "no such table: %s", zTName); }else{ sqlite3ErrorMsg(pParse, "no tables specified"); } } - sqlite3DbFree(db, zTName); } } sqlite3ExprListDelete(db, pEList); p->pEList = pNew; } @@ -76996,23 +80108,22 @@ int i; SrcList *pTabList; struct SrcList_item *pFrom; assert( p->selFlags & SF_Resolved ); - if( (p->selFlags & SF_HasTypeInfo)==0 ){ - p->selFlags |= SF_HasTypeInfo; - pParse = pWalker->pParse; - pTabList = p->pSrc; - for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ - Table *pTab = pFrom->pTab; - if( pTab && (pTab->tabFlags & TF_Ephemeral)!=0 ){ - /* A sub-query in the FROM clause of a SELECT */ - Select *pSel = pFrom->pSelect; - assert( pSel ); - while( pSel->pPrior ) pSel = pSel->pPrior; - selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); - } + assert( (p->selFlags & SF_HasTypeInfo)==0 ); + p->selFlags |= SF_HasTypeInfo; + pParse = pWalker->pParse; + pTabList = p->pSrc; + for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ + Table *pTab = pFrom->pTab; + if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ + /* A sub-query in the FROM clause of a SELECT */ + Select *pSel = pFrom->pSelect; + assert( pSel ); + while( pSel->pPrior ) pSel = pSel->pPrior; + selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); } } return WRC_Continue; } #endif @@ -77052,14 +80163,13 @@ Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ sqlite3 *db; - if( p==0 ) return; + if( NEVER(p==0) ) return; db = pParse->db; if( p->selFlags & SF_HasTypeInfo ) return; - if( pParse->nErr || db->mallocFailed ) return; sqlite3SelectExpand(pParse, p); if( pParse->nErr || db->mallocFailed ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); if( pParse->nErr || db->mallocFailed ) return; sqlite3SelectAddTypeInfo(pParse, p); @@ -77125,10 +80235,11 @@ int i; struct AggInfo_func *pF; struct AggInfo_col *pC; pAggInfo->directMode = 1; + sqlite3ExprCacheClear(pParse); for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){ int nArg; int addrNext = 0; int regAgg; ExprList *pList = pF->pExpr->x.pList; @@ -77164,16 +80275,18 @@ sqlite3VdbeChangeP5(v, (u8)nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg); sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); + sqlite3ExprCacheClear(pParse); } } for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } pAggInfo->directMode = 0; + sqlite3ExprCacheClear(pParse); } /* ** Generate code for the SELECT statement given in the p argument. ** @@ -77256,42 +80369,28 @@ return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); - pOrderBy = p->pOrderBy; - if( IgnorableOrderby(pDest) ){ - p->pOrderBy = 0; - - /* In these cases the DISTINCT operator makes no difference to the - ** results, so remove it if it were specified. - */ + if( IgnorableOrderby(pDest) ){ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard); + /* If ORDER BY makes no difference in the output then neither does + ** DISTINCT so it can be removed too. */ + sqlite3ExprListDelete(db, p->pOrderBy); + p->pOrderBy = 0; p->selFlags &= ~SF_Distinct; } sqlite3SelectPrep(pParse, p, 0); + pOrderBy = p->pOrderBy; pTabList = p->pSrc; pEList = p->pEList; if( pParse->nErr || db->mallocFailed ){ goto select_end; } - p->pOrderBy = pOrderBy; isAgg = (p->selFlags & SF_Aggregate)!=0; - if( pEList==0 ) goto select_end; - - /* - ** Do not even attempt to generate any code if we have already seen - ** errors before this routine starts. - */ - if( pParse->nErr>0 ) goto select_end; - - /* ORDER BY is ignored for some destinations. - */ - if( IgnorableOrderby(pDest) ){ - pOrderBy = 0; - } + assert( pEList!=0 ); /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; @@ -77328,11 +80427,11 @@ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); assert( pItem->isPopulated==0 ); sqlite3Select(pParse, pSub, &dest); pItem->isPopulated = 1; } - if( pParse->nErr || db->mallocFailed ){ + if( /*pParse->nErr ||*/ db->mallocFailed ){ goto select_end; } pParse->nHeight -= sqlite3SelectExprHeight(p); pTabList = p->pSrc; if( !IgnorableOrderby(pDest) ){ @@ -77379,11 +80478,12 @@ #endif /* If possible, rewrite the query to use GROUP BY instead of DISTINCT. ** GROUP BY might use an index, DISTINCT never does. */ - if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && !p->pGroupBy ){ + assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 ); + if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){ p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); pGroupBy = p->pGroupBy; p->selFlags &= ~SF_Distinct; isDistinct = 0; } @@ -77434,11 +80534,11 @@ /* Aggregate and non-aggregate queries are handled differently */ if( !isAgg && pGroupBy==0 ){ /* This case is for non-aggregate queries ** Begin the database scan */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0, 0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0); if( pWInfo==0 ) goto select_end; /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. @@ -77556,11 +80656,11 @@ ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0); if( pWInfo==0 ) goto select_end; if( pGroupBy==0 ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo @@ -77587,10 +80687,11 @@ nCol++; j++; } } regBase = sqlite3GetTempRange(pParse, nCol); + sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); j = nGroupBy+1; for(i=0; i<sAggInfo.nColumn; i++){ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; @@ -77613,18 +80714,20 @@ sqlite3ReleaseTempRange(pParse, regBase, nCol); sqlite3WhereEnd(pWInfo); sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); sAggInfo.useSortingIdx = 1; + sqlite3ExprCacheClear(pParse); } /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... */ addrTopOfLoop = sqlite3VdbeCurrentAddr(v); + sqlite3ExprCacheClear(pParse); for(j=0; j<pGroupBy->nExpr; j++){ if( groupBySort ){ sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j); }else{ sAggInfo.directMode = 1; @@ -77694,13 +80797,11 @@ addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, &sAggInfo); - if( pHaving ){ - sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); - } + sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, distinct, pDest, addrOutputRow+1, addrSetAbort); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); VdbeComment((v, "end groupby result generator")); @@ -77709,11 +80810,11 @@ */ sqlite3VdbeResolveLabel(v, addrReset); resetAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp1(v, OP_Return, regReset); - } /* endif pGroupBy */ + } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ else { ExprList *pDel = 0; #ifndef SQLITE_OMIT_BTREECOUNT Table *pTab; if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){ @@ -77811,11 +80912,11 @@ /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag, 0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag); if( pWInfo==0 ){ sqlite3ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); @@ -77827,13 +80928,11 @@ sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); } pOrderBy = 0; - if( pHaving ){ - sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); - } + sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, pDest, addrEnd, addrEnd); sqlite3ExprListDelete(db, pDel); } sqlite3VdbeResolveLabel(v, addrEnd); @@ -77886,12 +80985,12 @@ ** These routine are not called anywhere from within the normal ** code base. Then are intended to be called from within the debugger ** or from temporary "printf" statements inserted for debugging. */ SQLITE_PRIVATE void sqlite3PrintExpr(Expr *p){ - if( p->token.z && p->token.n>0 ){ - sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z); + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + sqlite3DebugPrintf("(%s", p->u.zToken); }else{ sqlite3DebugPrintf("(%d", p->op); } if( p->pLeft ){ sqlite3DebugPrintf(" "); @@ -78179,11 +81278,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** -** $Id: trigger.c,v 1.135 2009/02/28 10:47:42 danielk1977 Exp $ +** $Id: trigger.c,v 1.143 2009/08/10 03:57:58 shane Exp $ */ #ifndef SQLITE_OMIT_TRIGGER /* ** Delete a linked list of TriggerStep structures. @@ -78191,11 +81290,10 @@ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ while( pTriggerStep ){ TriggerStep * pTmp = pTriggerStep; pTriggerStep = pTriggerStep->pNext; - if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z); sqlite3ExprDelete(db, pTmp->pWhere); sqlite3ExprListDelete(db, pTmp->pExprList); sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); @@ -78204,10 +81302,20 @@ } /* ** Given table pTab, return a list of all the triggers attached to ** the table. The list is connected by Trigger.pNext pointers. +** +** All of the triggers on pTab that are in the same database as pTab +** are already attached to pTab->pTrigger. But there might be additional +** triggers on pTab in the TEMP schema. This routine prepends all +** TEMP triggers on pTab to the beginning of the pTab->pTrigger list +** and returns the combined list. +** +** To state it another way: This routine returns a list of all triggers +** that fire off of pTab. The list will include any TEMP triggers on +** pTab as well as the triggers lised in pTab->pTrigger. */ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ Schema * const pTmpSchema = pParse->db->aDb[1].pSchema; Trigger *pList = 0; /* List of triggers to return */ @@ -78245,18 +81353,18 @@ SrcList *pTableName,/* The name of the table/view the trigger applies to */ Expr *pWhen, /* WHEN clause */ int isTemp, /* True if the TEMPORARY keyword is present */ int noErr /* Suppress errors if the trigger already exists */ ){ - Trigger *pTrigger = 0; - Table *pTab; + Trigger *pTrigger = 0; /* The new trigger */ + Table *pTab; /* Table that the trigger fires off of */ char *zName = 0; /* Name of the trigger */ - sqlite3 *db = pParse->db; + sqlite3 *db = pParse->db; /* The database connection */ int iDb; /* The database to store the trigger in */ Token *pName; /* The unqualified db name */ - DbFixer sFix; - int iTabDb; + DbFixer sFix; /* State vector for the DB fixer */ + int iTabDb; /* Index of the database holding pTab */ assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ assert( pName2!=0 ); assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE ); assert( op>0 && op<0xff ); @@ -78297,10 +81405,21 @@ goto trigger_cleanup; } pTab = sqlite3SrcListLookup(pParse, pTableName); if( !pTab ){ /* The table does not exist. */ + if( db->init.iDb==1 ){ + /* Ticket #3810. + ** Normally, whenever a table is dropped, all associated triggers are + ** dropped too. But if a TEMP trigger is created on a non-TEMP table + ** and the table is dropped by a different database connection, the + ** trigger is not visible to the database connection that does the + ** drop so the trigger cannot be dropped. This results in an + ** "orphaned trigger" - a trigger whose associated table is missing. + */ + db->init.orphanTrigger = 1; + } goto trigger_cleanup; } if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); goto trigger_cleanup; @@ -78367,20 +81486,19 @@ } /* Build the Trigger object */ pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; - pTrigger->name = zName; + pTrigger->zName = zName; zName = 0; pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); pTrigger->pSchema = db->aDb[iDb].pSchema; pTrigger->pTabSchema = pTab->pSchema; pTrigger->op = (u8)op; pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); pTrigger->pColumns = sqlite3IdListDup(db, pColumns); - sqlite3TokenCopy(db, &pTrigger->nameToken,pName); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; trigger_cleanup: sqlite3DbFree(db, zName); @@ -78406,22 +81524,25 @@ Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ char *zName; /* Name of trigger */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; int iDb; /* Database containing the trigger */ + Token nameToken; /* Trigger name for error reporting */ pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; - if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; - zName = pTrig->name; + if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; + zName = pTrig->zName; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } - if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) + nameToken.z = pTrig->zName; + nameToken.n = sqlite3Strlen30(nameToken.z); + if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ goto triggerfinish_cleanup; } /* if we are not initializing, and this trigger is not on a TEMP table, @@ -78453,11 +81574,11 @@ pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig); if( pTrig ){ db->mallocFailed = 1; }else if( pLink->pSchema==pLink->pTabSchema ){ Table *pTab; - int n = sqlite3Strlen30(pLink->table) + 1; + int n = sqlite3Strlen30(pLink->table); pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n); assert( pTab!=0 ); pLink->pNext = pTab->pTrigger; pTab->pTrigger = pLink; } @@ -78468,47 +81589,10 @@ assert( !pParse->pNewTrigger ); sqlite3DeleteTriggerStep(db, pStepList); } /* -** Make a copy of all components of the given trigger step. This has -** the effect of copying all Expr.token.z values into memory obtained -** from sqlite3_malloc(). As initially created, the Expr.token.z values -** all point to the input string that was fed to the parser. But that -** string is ephemeral - it will go away as soon as the sqlite3_exec() -** call that started the parser exits. This routine makes a persistent -** copy of all the Expr.token.z strings so that the TriggerStep structure -** will be valid even after the sqlite3_exec() call returns. -*/ -static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){ - if( p->target.z ){ - p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n); - p->target.dyn = 1; - } - if( p->pSelect ){ - Select *pNew = sqlite3SelectDup(db, p->pSelect, 1); - sqlite3SelectDelete(db, p->pSelect); - p->pSelect = pNew; - } - if( p->pWhere ){ - Expr *pNew = sqlite3ExprDup(db, p->pWhere, EXPRDUP_REDUCE); - sqlite3ExprDelete(db, p->pWhere); - p->pWhere = pNew; - } - if( p->pExprList ){ - ExprList *pNew = sqlite3ExprListDup(db, p->pExprList, 1); - sqlite3ExprListDelete(db, p->pExprList); - p->pExprList = pNew; - } - if( p->pIdList ){ - IdList *pNew = sqlite3IdListDup(db, p->pIdList); - sqlite3IdListDelete(db, p->pIdList); - p->pIdList = pNew; - } -} - -/* ** Turn a SELECT statement (that the pSelect parameter points to) into ** a trigger step. Return a pointer to a TriggerStep structure. ** ** The parser calls this routine when it finds a SELECT statement in ** body of a TRIGGER. @@ -78517,16 +81601,37 @@ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); if( pTriggerStep==0 ) { sqlite3SelectDelete(db, pSelect); return 0; } - pTriggerStep->op = TK_SELECT; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; - sqlitePersistTriggerStep(db, pTriggerStep); - + return pTriggerStep; +} + +/* +** Allocate space to hold a new trigger step. The allocated space +** holds both the TriggerStep object and the TriggerStep.target.z string. +** +** If an OOM error occurs, NULL is returned and db->mallocFailed is set. +*/ +static TriggerStep *triggerStepAllocate( + sqlite3 *db, /* Database connection */ + u8 op, /* Trigger opcode */ + Token *pName /* The target name */ +){ + TriggerStep *pTriggerStep; + + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n); + if( pTriggerStep ){ + char *z = (char*)&pTriggerStep[1]; + memcpy(z, pName->z, pName->n); + pTriggerStep->target.z = z; + pTriggerStep->target.n = pName->n; + pTriggerStep->op = op; + } return pTriggerStep; } /* ** Build a trigger step out of an INSERT statement. Return a pointer @@ -78539,31 +81644,28 @@ sqlite3 *db, /* The database connection */ Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ Select *pSelect, /* A SELECT statement that supplies values */ - int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ + u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ){ TriggerStep *pTriggerStep; assert(pEList == 0 || pSelect == 0); assert(pEList != 0 || pSelect != 0 || db->mallocFailed); - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); if( pTriggerStep ){ - pTriggerStep->op = TK_INSERT; - pTriggerStep->pSelect = pSelect; - pTriggerStep->target = *pTableName; + pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; - pTriggerStep->pExprList = pEList; - pTriggerStep->orconf = orconf; - sqlitePersistTriggerStep(db, pTriggerStep); + pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); + pTriggerStep->orconf = orconf; }else{ sqlite3IdListDelete(db, pColumn); - sqlite3ExprListDelete(db, pEList); - sqlite3SelectDelete(db, pSelect); - } + } + sqlite3ExprListDelete(db, pEList); + sqlite3SelectDelete(db, pSelect); return pTriggerStep; } /* @@ -78574,26 +81676,22 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( sqlite3 *db, /* The database connection */ Token *pTableName, /* Name of the table to be updated */ ExprList *pEList, /* The SET clause: list of column and new values */ Expr *pWhere, /* The WHERE clause */ - int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ -){ - TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); - if( pTriggerStep==0 ){ - sqlite3ExprListDelete(db, pEList); - sqlite3ExprDelete(db, pWhere); - return 0; - } - - pTriggerStep->op = TK_UPDATE; - pTriggerStep->target = *pTableName; - pTriggerStep->pExprList = pEList; - pTriggerStep->pWhere = pWhere; - pTriggerStep->orconf = orconf; - sqlitePersistTriggerStep(db, pTriggerStep); - + u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ +){ + TriggerStep *pTriggerStep; + + pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); + if( pTriggerStep ){ + pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); + pTriggerStep->orconf = orconf; + } + sqlite3ExprListDelete(db, pEList); + sqlite3ExprDelete(db, pWhere); return pTriggerStep; } /* ** Construct a trigger step that implements a DELETE statement and return @@ -78603,36 +81701,31 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( sqlite3 *db, /* Database connection */ Token *pTableName, /* The table from which rows are deleted */ Expr *pWhere /* The WHERE clause */ ){ - TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); - if( pTriggerStep==0 ){ - sqlite3ExprDelete(db, pWhere); - return 0; - } - - pTriggerStep->op = TK_DELETE; - pTriggerStep->target = *pTableName; - pTriggerStep->pWhere = pWhere; - pTriggerStep->orconf = OE_Default; - sqlitePersistTriggerStep(db, pTriggerStep); - + TriggerStep *pTriggerStep; + + pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); + if( pTriggerStep ){ + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); + pTriggerStep->orconf = OE_Default; + } + sqlite3ExprDelete(db, pWhere); return pTriggerStep; } /* ** Recursively delete a Trigger structure */ SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ if( pTrigger==0 ) return; sqlite3DeleteTriggerStep(db, pTrigger->step_list); - sqlite3DbFree(db, pTrigger->name); + sqlite3DbFree(db, pTrigger->zName); sqlite3DbFree(db, pTrigger->table); sqlite3ExprDelete(db, pTrigger->pWhen); sqlite3IdListDelete(db, pTrigger->pColumns); - if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z); sqlite3DbFree(db, pTrigger); } /* ** This function is called to drop a trigger from the database schema. @@ -78680,11 +81773,11 @@ /* ** Return a pointer to the Table structure for the table that a trigger ** is set on. */ static Table *tableOfTrigger(Trigger *pTrigger){ - int n = sqlite3Strlen30(pTrigger->table) + 1; + int n = sqlite3Strlen30(pTrigger->table); return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); } /* @@ -78705,11 +81798,11 @@ { int code = SQLITE_DROP_TRIGGER; const char *zDb = db->aDb[iDb].zName; const char *zTab = SCHEMA_TABLE(iDb); if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; - if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || + if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ return; } } #endif @@ -78732,15 +81825,15 @@ }; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); - sqlite3VdbeChangeP4(v, base+1, pTrigger->name, 0); + sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, 0); sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp2(v, OP_Close, 0, 0); - sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->name, 0); + sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); if( pParse->nMem<3 ){ pParse->nMem = 3; } } } @@ -78750,11 +81843,11 @@ */ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ Hash *pHash = &(db->aDb[iDb].pSchema->trigHash); Trigger *pTrigger; pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0); - if( pTrigger ){ + if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); Trigger **pp; for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); *pp = (*pp)->pNext; @@ -78771,13 +81864,13 @@ ** then return TRUE. If pIdList==NULL, then it is considered a ** wildcard that matches anything. Likewise if pEList==NULL then ** it matches anything so always return true. Return false only ** if there is no match. */ -static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ +static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){ int e; - if( !pIdList || !pEList ) return 1; + if( pIdList==0 || NEVER(pEList==0) ) return 1; for(e=0; e<pEList->nExpr; e++){ if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; } return 0; } @@ -78798,11 +81891,11 @@ int mask = 0; Trigger *pList = sqlite3TriggerList(pParse, pTab); Trigger *p; assert( pList==0 || IsVirtual(pTab)==0 ); for(p=pList; p; p=p->pNext){ - if( p->op==op && checkColumnOverLap(p->pColumns, pChanges) ){ + if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){ mask |= p->tr_tm; } } if( pMask ){ *pMask = mask; @@ -78822,99 +81915,274 @@ */ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ - Token sDb; /* Dummy database name token */ int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ - iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); - if( iDb==0 || iDb>=2 ){ - assert( iDb<pParse->db->nDb ); - sDb.z = (u8*)pParse->db->aDb[iDb].zName; - sDb.n = sqlite3Strlen30((char*)sDb.z); - pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target); - } else { - pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + if( pSrc ){ + assert( pSrc->nSrc>0 ); + assert( pSrc->a!=0 ); + iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); + if( iDb==0 || iDb>=2 ){ + sqlite3 *db = pParse->db; + assert( iDb<pParse->db->nDb ); + pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + } } return pSrc; } /* -** Generate VDBE code for zero or more statements inside the body of a +** Generate VDBE code for the statements inside the body of a single ** trigger. */ static int codeTriggerProgram( Parse *pParse, /* The parser context */ TriggerStep *pStepList, /* List of statements inside the trigger body */ - int orconfin /* Conflict algorithm. (OE_Abort, etc) */ -){ - TriggerStep * pTriggerStep = pStepList; - int orconf; + int orconf /* Conflict algorithm. (OE_Abort, etc) */ +){ + TriggerStep *pStep; Vdbe *v = pParse->pVdbe; sqlite3 *db = pParse->db; - assert( pTriggerStep!=0 ); + assert( pParse->pTriggerTab && pParse->pToplevel ); + assert( pStepList ); assert( v!=0 ); - sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0); - VdbeComment((v, "begin trigger %s", pStepList->pTrig->name)); - while( pTriggerStep ){ - sqlite3ExprClearColumnCache(pParse, -1); - orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; - pParse->trigStack->orconf = orconf; - switch( pTriggerStep->op ){ - case TK_SELECT: { - Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect, 0); - if( ss ){ - SelectDest dest; - - sqlite3SelectDestInit(&dest, SRT_Discard, 0); - sqlite3Select(pParse, ss, &dest); - sqlite3SelectDelete(db, ss); - } - break; - } + for(pStep=pStepList; pStep; pStep=pStep->pNext){ + /* Figure out the ON CONFLICT policy that will be used for this step + ** of the trigger program. If the statement that caused this trigger + ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use + ** the ON CONFLICT policy that was specified as part of the trigger + ** step statement. Example: + ** + ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN; + ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b); + ** END; + ** + ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy + ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy + */ + pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; + + switch( pStep->op ){ case TK_UPDATE: { - SrcList *pSrc; - pSrc = targetSrcList(pParse, pTriggerStep); - sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0); - sqlite3Update(pParse, pSrc, - sqlite3ExprListDup(db, pTriggerStep->pExprList, 0), - sqlite3ExprDup(db, pTriggerStep->pWhere, 0), orconf); - sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0); + sqlite3Update(pParse, + targetSrcList(pParse, pStep), + sqlite3ExprListDup(db, pStep->pExprList, 0), + sqlite3ExprDup(db, pStep->pWhere, 0), + pParse->eOrconf + ); break; } case TK_INSERT: { - SrcList *pSrc; - pSrc = targetSrcList(pParse, pTriggerStep); - sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0); - sqlite3Insert(pParse, pSrc, - sqlite3ExprListDup(db, pTriggerStep->pExprList, 0), - sqlite3SelectDup(db, pTriggerStep->pSelect, 0), - sqlite3IdListDup(db, pTriggerStep->pIdList), orconf); - sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0); + sqlite3Insert(pParse, + targetSrcList(pParse, pStep), + sqlite3ExprListDup(db, pStep->pExprList, 0), + sqlite3SelectDup(db, pStep->pSelect, 0), + sqlite3IdListDup(db, pStep->pIdList), + pParse->eOrconf + ); break; } case TK_DELETE: { - SrcList *pSrc; - sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0); - pSrc = targetSrcList(pParse, pTriggerStep); - sqlite3DeleteFrom(pParse, pSrc, - sqlite3ExprDup(db, pTriggerStep->pWhere, 0)); - sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0); - break; - } - default: - assert(0); - } - pTriggerStep = pTriggerStep->pNext; - } - sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); - VdbeComment((v, "end trigger %s", pStepList->pTrig->name)); - - return 0; + sqlite3DeleteFrom(pParse, + targetSrcList(pParse, pStep), + sqlite3ExprDup(db, pStep->pWhere, 0) + ); + break; + } + default: assert( pStep->op==TK_SELECT ); { + SelectDest sDest; + Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0); + sqlite3SelectDestInit(&sDest, SRT_Discard, 0); + sqlite3Select(pParse, pSelect, &sDest); + sqlite3SelectDelete(db, pSelect); + break; + } + } + if( pStep->op!=TK_SELECT ){ + sqlite3VdbeAddOp0(v, OP_ResetCount); + } + } + + return 0; +} + +#ifdef SQLITE_DEBUG +/* +** This function is used to add VdbeComment() annotations to a VDBE +** program. It is not used in production code, only for debugging. +*/ +static const char *onErrorText(int onError){ + switch( onError ){ + case OE_Abort: return "abort"; + case OE_Rollback: return "rollback"; + case OE_Fail: return "fail"; + case OE_Replace: return "replace"; + case OE_Ignore: return "ignore"; + case OE_Default: return "default"; + } + return "n/a"; +} +#endif + +/* +** Parse context structure pFrom has just been used to create a sub-vdbe +** (trigger program). If an error has occurred, transfer error information +** from pFrom to pTo. +*/ +static void transferParseError(Parse *pTo, Parse *pFrom){ + assert( pFrom->zErrMsg==0 || pFrom->nErr ); + assert( pTo->zErrMsg==0 || pTo->nErr ); + if( pTo->nErr==0 ){ + pTo->zErrMsg = pFrom->zErrMsg; + pTo->nErr = pFrom->nErr; + }else{ + sqlite3DbFree(pFrom->db, pFrom->zErrMsg); + } +} + +/* +** Create and populate a new TriggerPrg object with a sub-program +** implementing trigger pTrigger with ON CONFLICT policy orconf. +*/ +static TriggerPrg *codeRowTrigger( + Parse *pParse, /* Current parse context */ + Trigger *pTrigger, /* Trigger to code */ + Table *pTab, /* The table pTrigger is attached to */ + int orconf /* ON CONFLICT policy to code trigger program with */ +){ + Parse *pTop = sqlite3ParseToplevel(pParse); + sqlite3 *db = pParse->db; /* Database handle */ + TriggerPrg *pPrg; /* Value to return */ + Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ + Vdbe *v; /* Temporary VM */ + NameContext sNC; /* Name context for sub-vdbe */ + SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ + Parse *pSubParse; /* Parse context for sub-vdbe */ + int iEndTrigger = 0; /* Label to jump to if WHEN is false */ + + assert( pTab==tableOfTrigger(pTrigger) ); + + /* Allocate the TriggerPrg and SubProgram objects. To ensure that they + ** are freed if an error occurs, link them into the Parse.pTriggerPrg + ** list of the top-level Parse object sooner rather than later. */ + pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg)); + if( !pPrg ) return 0; + pPrg->pNext = pTop->pTriggerPrg; + pTop->pTriggerPrg = pPrg; + pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); + if( !pProgram ) return 0; + pProgram->nRef = 1; + pPrg->pTrigger = pTrigger; + pPrg->orconf = orconf; + + /* Allocate and populate a new Parse context to use for coding the + ** trigger sub-program. */ + pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); + if( !pSubParse ) return 0; + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pSubParse; + pSubParse->db = db; + pSubParse->pTriggerTab = pTab; + pSubParse->pToplevel = pTop; + pSubParse->zAuthContext = pTrigger->zName; + pSubParse->eTriggerOp = pTrigger->op; + + v = sqlite3GetVdbe(pSubParse); + if( v ){ + VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", + pTrigger->zName, onErrorText(orconf), + (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), + (pTrigger->op==TK_UPDATE ? "UPDATE" : ""), + (pTrigger->op==TK_INSERT ? "INSERT" : ""), + (pTrigger->op==TK_DELETE ? "DELETE" : ""), + pTab->zName + )); +#ifndef SQLITE_OMIT_TRACE + sqlite3VdbeChangeP4(v, -1, + sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC + ); +#endif + + /* If one was specified, code the WHEN clause. If it evaluates to false + ** (or NULL) the sub-vdbe is immediately halted by jumping to the + ** OP_Halt inserted at the end of the program. */ + if( pTrigger->pWhen ){ + pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); + if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) + && db->mallocFailed==0 + ){ + iEndTrigger = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); + } + sqlite3ExprDelete(db, pWhen); + } + + /* Code the trigger program into the sub-vdbe. */ + codeTriggerProgram(pSubParse, pTrigger->step_list, orconf); + + /* Insert an OP_Halt at the end of the sub-program. */ + if( iEndTrigger ){ + sqlite3VdbeResolveLabel(v, iEndTrigger); + } + sqlite3VdbeAddOp0(v, OP_Halt); + VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); + + transferParseError(pParse, pSubParse); + if( db->mallocFailed==0 ){ + pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); + } + pProgram->nMem = pSubParse->nMem; + pProgram->nCsr = pSubParse->nTab; + pProgram->token = (void *)pTrigger; + pPrg->oldmask = pSubParse->oldmask; + sqlite3VdbeDelete(v); + } + + assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); + assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); + sqlite3StackFree(db, pSubParse); + + return pPrg; +} + +/* +** Return a pointer to a TriggerPrg object containing the sub-program for +** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such +** TriggerPrg object exists, a new object is allocated and populated before +** being returned. +*/ +static TriggerPrg *getRowTrigger( + Parse *pParse, /* Current parse context */ + Trigger *pTrigger, /* Trigger to code */ + Table *pTab, /* The table trigger pTrigger is attached to */ + int orconf /* ON CONFLICT algorithm. */ +){ + Parse *pRoot = sqlite3ParseToplevel(pParse); + TriggerPrg *pPrg; + + assert( pTab==tableOfTrigger(pTrigger) ); + + /* It may be that this trigger has already been coded (or is in the + ** process of being coded). If this is the case, then an entry with + ** a matching TriggerPrg.pTrigger field will be present somewhere + ** in the Parse.pTriggerPrg list. Search for such an entry. */ + for(pPrg=pRoot->pTriggerPrg; + pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); + pPrg=pPrg->pNext + ); + + /* If an existing TriggerPrg could not be located, create a new one. */ + if( !pPrg ){ + pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf); + } + + return pPrg; } /* ** This is called to code FOR EACH ROW triggers. ** @@ -78940,108 +82208,105 @@ ** pseudo-table is read at least once, the corresponding bit of the output ** mask is set. If a column with an index greater than 32 is read, the ** output mask is set to the special value 0xffffffff. ** */ -SQLITE_PRIVATE int sqlite3CodeRowTrigger( +SQLITE_PRIVATE void sqlite3CodeRowTrigger( Parse *pParse, /* Parse context */ Trigger *pTrigger, /* List of triggers on table pTab */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int newIdx, /* The indice of the "new" row to access */ int oldIdx, /* The indice of the "old" row to access */ int orconf, /* ON CONFLICT policy */ - int ignoreJump, /* Instruction to jump to for RAISE(IGNORE) */ - u32 *piOldColMask, /* OUT: Mask of columns used from the OLD.* table */ - u32 *piNewColMask /* OUT: Mask of columns used from the NEW.* table */ + int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ Trigger *p; - sqlite3 *db = pParse->db; - TriggerStack trigStackEntry; - - trigStackEntry.oldColMask = 0; - trigStackEntry.newColMask = 0; + + UNUSED_PARAMETER(newIdx); assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); - assert(newIdx != -1 || oldIdx != -1); - for(p=pTrigger; p; p=p->pNext){ - int fire_this = 0; + + /* Sanity checking: The schema for the trigger and for the table are + ** always defined. The trigger must be in the same schema as the table + ** or else it must be a TEMP trigger. */ + assert( p->pSchema!=0 ); + assert( p->pTabSchema!=0 ); + assert( p->pSchema==p->pTabSchema + || p->pSchema==pParse->db->aDb[1].pSchema ); /* Determine whether we should code this trigger */ - if( - p->op==op && - p->tr_tm==tr_tm && - (p->pSchema==p->pTabSchema || p->pSchema==db->aDb[1].pSchema) && - (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges)) - ){ - TriggerStack *pS; /* Pointer to trigger-stack entry */ - for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){} - if( !pS ){ - fire_this = 1; - } -#if 0 /* Give no warning for recursive triggers. Just do not do them */ - else{ - sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)", - p->name); - return SQLITE_ERROR; - } -#endif - } - - if( fire_this ){ - int endTrigger; - Expr * whenExpr; - AuthContext sContext; - NameContext sNC; - -#ifndef SQLITE_OMIT_TRACE - sqlite3VdbeAddOp4(pParse->pVdbe, OP_Trace, 0, 0, 0, - sqlite3MPrintf(db, "-- TRIGGER %s", p->name), - P4_DYNAMIC); -#endif - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - - /* Push an entry on to the trigger stack */ - trigStackEntry.pTrigger = p; - trigStackEntry.newIdx = newIdx; - trigStackEntry.oldIdx = oldIdx; - trigStackEntry.pTab = pTab; - trigStackEntry.pNext = pParse->trigStack; - trigStackEntry.ignoreJump = ignoreJump; - pParse->trigStack = &trigStackEntry; - sqlite3AuthContextPush(pParse, &sContext, p->name); - - /* code the WHEN clause */ - endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); - whenExpr = sqlite3ExprDup(db, p->pWhen, 0); - if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){ - pParse->trigStack = trigStackEntry.pNext; - sqlite3ExprDelete(db, whenExpr); - return 1; - } - sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL); - sqlite3ExprDelete(db, whenExpr); - - codeTriggerProgram(pParse, p->step_list, orconf); - - /* Pop the entry off the trigger stack */ - pParse->trigStack = trigStackEntry.pNext; - sqlite3AuthContextPop(&sContext); - - sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); - } - } - if( piOldColMask ) *piOldColMask |= trigStackEntry.oldColMask; - if( piNewColMask ) *piNewColMask |= trigStackEntry.newColMask; - return 0; -} + if( p->op==op + && p->tr_tm==tr_tm + && checkColumnOverlap(p->pColumns,pChanges) + ){ + Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ + TriggerPrg *pPrg; + pPrg = getRowTrigger(pParse, p, pTab, orconf); + assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); + + /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program + ** is a pointer to the sub-vdbe containing the trigger program. */ + if( pPrg ){ + sqlite3VdbeAddOp3(v, OP_Program, oldIdx, ignoreJump, ++pParse->nMem); + pPrg->pProgram->nRef++; + sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM); + VdbeComment((v, "Call: %s.%s", p->zName, onErrorText(orconf))); + } + } + } +} + +/* +** Triggers fired by UPDATE or DELETE statements may access values stored +** in the old.* pseudo-table. This function returns a 32-bit bitmask +** indicating which columns of the old.* table actually are used by +** triggers. This information may be used by the caller to avoid having +** to load the entire old.* record into memory when executing an UPDATE +** or DELETE command. +** +** Bit 0 of the returned mask is set if the left-most column of the +** table may be accessed using an old.<col> reference. Bit 1 is set if +** the second leftmost column value is required, and so on. If there +** are more than 32 columns in the table, and at least one of the columns +** with an index greater than 32 may be accessed, 0xffffffff is returned. +** +** It is not possible to determine if the old.rowid column is accessed +** by triggers. The caller must always assume that it is. +** +** There is no equivalent function for new.* references. +*/ +SQLITE_PRIVATE u32 sqlite3TriggerOldmask( + Parse *pParse, /* Parse context */ + Trigger *pTrigger, /* List of triggers on table pTab */ + int op, /* Either TK_UPDATE or TK_DELETE */ + ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ + Table *pTab, /* The table to code triggers from */ + int orconf /* Default ON CONFLICT policy for trigger steps */ +){ + u32 mask = 0; + Trigger *p; + + assert(op==TK_UPDATE || op==TK_DELETE); + for(p=pTrigger; p; p=p->pNext){ + if( p->op==op && checkColumnOverlap(p->pColumns,pChanges) ){ + TriggerPrg *pPrg; + pPrg = getRowTrigger(pParse, p, pTab, orconf); + if( pPrg ){ + mask |= pPrg->oldmask; + } + } + } + + return mask; +} + #endif /* !defined(SQLITE_OMIT_TRIGGER) */ /************** End of trigger.c *********************************************/ /************** Begin file update.c ******************************************/ /* @@ -79056,11 +82321,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.196 2009/02/28 10:47:42 danielk1977 Exp $ +** $Id: update.c,v 1.207 2009/08/08 18:01:08 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ static void updateVirtualTable( @@ -79096,13 +82361,19 @@ ** ** Therefore, the P4 parameter is only required if the default value for ** the column is a literal number, string or null. The sqlite3ValueFromExpr() ** function is capable of transforming these types of expressions into ** sqlite3_value objects. -*/ -SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){ - if( pTab && !pTab->pSelect ){ +** +** If parameter iReg is not negative, code an OP_RealAffinity instruction +** on register iReg. This is used when an equivalent integer value is +** stored in place of an 8-byte floating point value in order to save +** space. +*/ +SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ + assert( pTab!=0 ); + if( !pTab->pSelect ){ sqlite3_value *pValue; u8 enc = ENC(sqlite3VdbeDb(v)); Column *pCol = &pTab->aCol[i]; VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); assert( i<pTab->nCol ); @@ -79109,10 +82380,15 @@ sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, pCol->affinity, &pValue); if( pValue ){ sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); } +#ifndef SQLITE_OMIT_FLOATING_POINT + if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); + } +#endif } } /* ** Process an UPDATE statement. @@ -79152,28 +82428,22 @@ #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ #endif - int iBeginAfterTrigger = 0; /* Address of after trigger program */ - int iEndAfterTrigger = 0; /* Exit of after trigger program */ - int iBeginBeforeTrigger = 0; /* Address of before trigger program */ - int iEndBeforeTrigger = 0; /* Exit of before trigger program */ - u32 old_col_mask = 0; /* Mask of OLD.* columns in use */ - u32 new_col_mask = 0; /* Mask of NEW.* columns in use */ - - int newIdx = -1; /* index of trigger "new" temp table */ - int oldIdx = -1; /* index of trigger "old" temp table */ + u32 oldmask = 0; /* Mask of OLD.* columns in use */ /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ int regOldRowid; /* The old rowid */ int regNewRowid; /* The new rowid */ - int regData; /* New data for the row */ + int regNew; + int regOld = 0; int regRowSet = 0; /* Rowset of rows to be updated */ - - sContext.pParse = 0; + int regRec; /* Register used for new table record to insert */ + + memset(&sContext, 0, sizeof(sContext)); db = pParse->db; if( pParse->nErr || db->mallocFailed ){ goto update_cleanup; } assert( pTabList->nSrc==1 ); @@ -79183,11 +82453,11 @@ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto update_cleanup; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); /* Figure out if we have any triggers and if the table being - ** updated is a view + ** updated is a view. */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, 0); isView = pTab->pSelect!=0; #else @@ -79197,27 +82467,19 @@ #ifdef SQLITE_OMIT_VIEW # undef isView # define isView 0 #endif - if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto update_cleanup; } - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ goto update_cleanup; } aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); if( aXRef==0 ) goto update_cleanup; for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; - - /* If there are FOR EACH ROW triggers, allocate cursors for the - ** special OLD and NEW tables - */ - if( pTrigger ){ - newIdx = pParse->nTab++; - oldIdx = pParse->nTab++; - } /* Allocate a cursors for the main database table and for all indices. ** The index cursors might not be used, but if they are used they ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. @@ -79300,28 +82562,11 @@ } } aRegIdx[j] = reg; } - /* Allocate a block of register used to store the change record - ** sent to sqlite3GenerateConstraintChecks(). There are either - ** one or two registers for holding the rowid. One rowid register - ** is used if chngRowid is false and two are used if chngRowid is - ** true. Following these are pTab->nCol register holding column - ** data. - */ - regOldRowid = regNewRowid = pParse->nMem + 1; - pParse->nMem += pTab->nCol + 1; - if( chngRowid ){ - regNewRowid++; - pParse->nMem++; - } - regData = regNewRowid+1; - - - /* Begin generating code. - */ + /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, 1, iDb); @@ -79334,44 +82579,31 @@ pTabList = 0; goto update_cleanup; } #endif - /* Start the view context - */ + /* Allocate required registers. */ + regOldRowid = regNewRowid = ++pParse->nMem; + if( pTrigger ){ + regOld = pParse->nMem + 1; + pParse->nMem += pTab->nCol; + } + if( chngRowid || pTrigger ){ + regNewRowid = ++pParse->nMem; + } + regNew = pParse->nMem + 1; + pParse->nMem += pTab->nCol; + regRec = ++pParse->nMem; + + /* Start the view context. */ if( isView ){ sqlite3AuthContextPush(pParse, &sContext, pTab->zName); } - /* Generate the code for triggers. - */ - if( pTrigger ){ - int iGoto; - - /* Create pseudo-tables for NEW and OLD - */ - sqlite3VdbeAddOp3(v, OP_OpenPseudo, oldIdx, 0, pTab->nCol); - sqlite3VdbeAddOp3(v, OP_OpenPseudo, newIdx, 0, pTab->nCol); - - iGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - addr = sqlite3VdbeMakeLabel(v); - iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v); - if( sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_BEFORE, pTab, newIdx, oldIdx, onError, addr, - &old_col_mask, &new_col_mask) ){ - goto update_cleanup; - } - iEndBeforeTrigger = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v); - if( sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_AFTER, pTab, newIdx, oldIdx, onError, addr, - &old_col_mask, &new_col_mask) ){ - goto update_cleanup; - } - iEndAfterTrigger = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - sqlite3VdbeJumpHere(v, iGoto); - } + /* If there are any triggers, set oldmask and new_col_mask. */ + oldmask = sqlite3TriggerOldmask( + pParse, pTrigger, TK_UPDATE, pChanges, pTab, onError); /* If we are trying to update a view, realize that view into ** a ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) @@ -79388,18 +82620,17 @@ } /* Begin the database scan */ sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, - WHERE_ONEPASS_DESIRED, 0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED); if( pWInfo==0 ) goto update_cleanup; okOnePass = pWInfo->okOnePass; /* Remember the rowid of every item to be updated. */ - sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid); if( !okOnePass ){ regRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); } @@ -79407,16 +82638,16 @@ */ sqlite3WhereEnd(pWInfo); /* Initialize the count of updated rows */ - if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ + if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } - if( !isView && !IsVirtual(pTab) ){ + if( !isView ){ /* ** Open every index that needs updating. Note that if any ** index could potentially invoke a REPLACE conflict resolution ** action, then we need to open all indices because we might need ** to be deleting some records. @@ -79441,157 +82672,111 @@ assert( pParse->nTab>iCur+i+1 ); } } } - /* Jump back to this point if a trigger encounters an IGNORE constraint. */ - if( pTrigger ){ - sqlite3VdbeResolveLabel(v, addr); - } - /* Top of the update loop */ if( okOnePass ){ int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid); addr = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, a1); }else{ addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid); } + /* Make cursor iCur point to the record that is being updated. If + ** this record does not exist for some reason (deleted by a trigger, + ** for example, then jump to the next iteration of the RowSet loop. */ + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); + + /* If there are triggers on this table, populate an array of registers + ** with the required old.* column data. */ if( pTrigger ){ - int regRowid; - int regRow; - int regCols; - - /* Make cursor iCur point to the record that is being updated. - */ - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); - - /* Generate the OLD table - */ - regRowid = sqlite3GetTempReg(pParse); - regRow = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid); - if( !old_col_mask ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regRow); - }else{ - sqlite3VdbeAddOp2(v, OP_RowData, iCur, regRow); - } - sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, regRow, regRowid); - - /* Generate the NEW table - */ - if( chngRowid ){ - sqlite3ExprCodeAndCache(pParse, pRowidExpr, regRowid); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); - }else{ - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid); - } - regCols = sqlite3GetTempRange(pParse, pTab->nCol); for(i=0; i<pTab->nCol; i++){ - if( i==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i); - continue; - } + if( aXRef[i]<0 || oldmask==0xffffffff || (oldmask & (1<<i)) ){ + sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i); + sqlite3ColumnDefault(v, pTab, i, regOld+i); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i); + } + } + } + + /* If the record number will change, set register regNewRowid to + ** contain the new value. If the record number is not being modified, + ** then regNewRowid is the same register as regOldRowid, which is + ** already populated. */ + assert( chngRowid || pTrigger || regOldRowid==regNewRowid ); + if( chngRowid ){ + sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); + }else if( pTrigger ){ + sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); + } + + /* Populate the array of registers beginning at regNew with the new + ** row data. This array is used to check constaints, create the new + ** table and index records, and as the values for any new.* references + ** made by triggers. */ + for(i=0; i<pTab->nCol; i++){ + if( i==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); + }else{ j = aXRef[i]; - if( new_col_mask&((u32)1<<i) || new_col_mask==0xffffffff ){ - if( j<0 ){ - sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regCols+i); - sqlite3ColumnDefault(v, pTab, i); - }else{ - sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr, regCols+i); - } - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i); - } - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow); - if( !isView ){ - sqlite3TableAffinityStr(v, pTab); - sqlite3ExprCacheAffinityChange(pParse, regCols, pTab->nCol); - } - sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); - /* if( pParse->nErr ) goto update_cleanup; */ - sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRow, regRowid); - sqlite3ReleaseTempReg(pParse, regRowid); - sqlite3ReleaseTempReg(pParse, regRow); - - sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger); - sqlite3VdbeJumpHere(v, iEndBeforeTrigger); - } - - if( !isView && !IsVirtual(pTab) ){ - /* Loop over every record that needs updating. We have to load - ** the old data for each record to be updated because some columns - ** might not change and we will need to copy the old value. - ** Also, the old data is needed to delete the old index entries. - ** So make the cursor point at the old record. - */ + if( j<0 ){ + sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); + sqlite3ColumnDefault(v, pTab, i, regNew+i); + }else{ + sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); + } + } + } + + /* Fire any BEFORE UPDATE triggers. This happens before constraints are + ** verified. One could argue that this is wrong. */ + if( pTrigger ){ + sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); + sqlite3TableAffinityStr(v, pTab); + sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, + TRIGGER_BEFORE, pTab, -1, regOldRowid, onError, addr); + + /* The row-trigger may have deleted the row being updated. In this + ** case, jump to the next row. No updates or AFTER triggers are + ** required. This behaviour - what happens when the row being updated + ** is deleted or renamed by a BEFORE trigger - is left undefined in the + ** documentation. */ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); - - /* If the record number will change, push the record number as it - ** will be after the update. (The old record number is currently - ** on top of the stack.) - */ - if( chngRowid ){ - sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); - } - - /* Compute new data for this record. - */ - for(i=0; i<pTab->nCol; i++){ - if( i==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regData+i); - continue; - } - j = aXRef[i]; - if( j<0 ){ - sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regData+i); - sqlite3ColumnDefault(v, pTab, i); - }else{ - sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regData+i); - } - } - - /* Do constraint checks - */ + } + + if( !isView ){ + + /* Do constraint checks. */ sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, - aRegIdx, chngRowid, 1, - onError, addr); - - /* Delete the old indices for the current record. - */ + aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0); + + /* Delete the index entries associated with the current record. */ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid); sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx); - /* If changing the record number, delete the old record. - */ + /* If changing the record number, delete the old record. */ if( chngRowid ){ sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0); } sqlite3VdbeJumpHere(v, j1); - /* Create the new index entries and the new record. - */ - sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, - aRegIdx, 1, -1, 0); + /* Insert the new index entries and the new record. */ + sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0); } /* Increment the row counter */ - if( db->flags & SQLITE_CountRows && !pParse->trigStack){ + if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } - /* If there are triggers, close all the cursors after each iteration - ** through the loop. The fire the after triggers. - */ - if( pTrigger ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger); - sqlite3VdbeJumpHere(v, iEndAfterTrigger); - } + sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, + TRIGGER_AFTER, pTab, -1, regOldRowid, onError, addr); /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); @@ -79602,21 +82787,25 @@ if( openAll || aRegIdx[i]>0 ){ sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0); } } sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); - if( pTrigger ){ - sqlite3VdbeAddOp2(v, OP_Close, newIdx, 0); - sqlite3VdbeAddOp2(v, OP_Close, oldIdx, 0); + + /* Update the sqlite_sequence table by storing the content of the + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. + */ + if( pParse->nested==0 && pParse->pTriggerTab==0 ){ + sqlite3AutoincrementEnd(pParse); } /* ** Return the number of rows that were changed. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){ + if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); } @@ -79666,30 +82855,30 @@ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ int addr; /* Address of top of loop */ int iReg; /* First register in set passed to OP_VUpdate */ sqlite3 *db = pParse->db; /* Database connection */ - const char *pVtab = (const char*)pTab->pVtab; + const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); SelectDest dest; /* Construct the SELECT statement that will find the new values for ** all updated rows. */ pEList = sqlite3ExprListAppend(pParse, 0, - sqlite3CreateIdExpr(pParse, "_rowid_"), 0); + sqlite3CreateIdExpr(pParse, "_rowid_")); if( pRowid ){ pEList = sqlite3ExprListAppend(pParse, pEList, - sqlite3ExprDup(db, pRowid, 0), 0); + sqlite3ExprDup(db, pRowid, 0)); } assert( pTab->iPKey<0 ); for(i=0; i<pTab->nCol; i++){ if( aXRef[i]>=0 ){ pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0); }else{ pExpr = sqlite3CreateIdExpr(pParse, pTab->aCol[i].zName); } - pEList = sqlite3ExprListAppend(pParse, pEList, pExpr, 0); + pEList = sqlite3ExprListAppend(pParse, pEList, pExpr); } pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); /* Create the ephemeral table into which the update results will ** be stored. @@ -79704,21 +82893,21 @@ sqlite3Select(pParse, pSelect, &dest); /* Generate code to scan the ephemeral table and call VUpdate. */ iReg = ++pParse->nMem; pParse->nMem += pTab->nCol+1; - sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); - addr = sqlite3VdbeCurrentAddr(v); + addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); for(i=0; i<pTab->nCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); } sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVtab, P4_VTAB); - sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr); - sqlite3VdbeJumpHere(v, addr-1); + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); + sqlite3MayAbort(pParse); + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); + sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); /* Cleanup */ sqlite3SelectDelete(db, pSelect); } @@ -79745,26 +82934,28 @@ ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.87 2009/04/02 20:16:59 drh Exp $ +** $Id: vacuum.c,v 1.91 2009/07/02 07:47:33 danielk1977 Exp $ */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* ** Execute zSql on database db. Return an error code. */ static int execSql(sqlite3 *db, const char *zSql){ sqlite3_stmt *pStmt; + VVA_ONLY( int rc; ) if( !zSql ){ return SQLITE_NOMEM; } if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ return sqlite3_errcode(db); } - while( SQLITE_ROW==sqlite3_step(pStmt) ){} + VVA_ONLY( rc = ) sqlite3_step(pStmt); + assert( rc!=SQLITE_ROW ); return sqlite3_finalize(pStmt); } /* ** Execute zSql on database db. The statement returns exactly @@ -79810,18 +83001,17 @@ ** This routine implements the OP_Vacuum opcode of the VDBE. */ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ - Pager *pMainPager; /* Pager for database being vacuumed */ Btree *pTemp; /* The temporary database we vacuum into */ char *zSql = 0; /* SQL statements */ int saved_flags; /* Saved value of the db->flags */ int saved_nChange; /* Saved value of db->nChange */ int saved_nTotalChange; /* Saved value of db->nTotalChange */ Db *pDb = 0; /* Database to detach at end of vacuum */ - int isMemDb; /* True is vacuuming a :memory: database */ + int isMemDb; /* True if vacuuming a :memory: database */ int nRes; if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); return SQLITE_ERROR; @@ -79832,12 +83022,11 @@ saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; pMain = db->aDb[0].pBt; - pMainPager = sqlite3BtreePager(pMain); - isMemDb = sqlite3PagerFile(pMainPager)->pMethods==0; + isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma ** can be set to 'off' for this file, as it is not recovered if a crash ** occurs anyway. The integrity of the database is maintained by a ** (possibly synchronous) transaction opened on the main database before @@ -79871,11 +83060,11 @@ } #endif if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0) || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0)) - || db->mallocFailed + || NEVER(db->mallocFailed) ){ rc = SQLITE_NOMEM; goto end_of_vacuum; } rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); @@ -79959,11 +83148,11 @@ ** call to sqlite3BtreeCopyFile(). The main database btree level ** transaction is then committed, so the SQL level never knows it was ** opened for writing. This way, the SQL transaction used to create the ** temporary database never needs to be committed. */ - if( rc==SQLITE_OK ){ + { u32 meta; int i; /* This array determines which meta meta values are preserved in the ** vacuum. Even entries are the meta value number and odd entries @@ -79970,25 +83159,26 @@ ** are an increment to apply to the meta value after the vacuum. ** The increment is used to increase the schema cookie so that other ** connections to the same database will know to reread the schema. */ static const unsigned char aCopy[] = { - 1, 1, /* Add one to the old schema cookie */ - 3, 0, /* Preserve the default page cache size */ - 5, 0, /* Preserve the default text encoding */ - 6, 0, /* Preserve the user version */ + BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ + BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ + BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ + BTREE_USER_VERSION, 0, /* Preserve the user version */ }; assert( 1==sqlite3BtreeIsInTrans(pTemp) ); assert( 1==sqlite3BtreeIsInTrans(pMain) ); /* Copy Btree meta values */ for(i=0; i<ArraySize(aCopy); i+=2){ - rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); - if( rc!=SQLITE_OK ) goto end_of_vacuum; + /* GetMeta() and UpdateMeta() cannot fail in this context because + ** we already have page 1 loaded into cache and marked dirty. */ + sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]); - if( rc!=SQLITE_OK ) goto end_of_vacuum; + if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum; } rc = sqlite3BtreeCopyFile(pMain, pTemp); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeCommit(pTemp); @@ -79996,13 +83186,12 @@ #ifndef SQLITE_OMIT_AUTOVACUUM sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp)); #endif } - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1); - } + assert( rc==SQLITE_OK ); + rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1); end_of_vacuum: /* Restore the original value of db->flags */ db->flags = saved_flags; db->nChange = saved_nChange; @@ -80042,11 +83231,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: vtab.c,v 1.85 2009/04/11 16:27:20 drh Exp $ +** $Id: vtab.c,v 1.94 2009/08/08 18:01:08 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** The actual function that does the work of creating a new module. @@ -80057,11 +83246,11 @@ sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ -) { +){ int rc, nName; Module *pMod; sqlite3_mutex_enter(db->mutex); nName = sqlite3Strlen30(zName); @@ -80123,54 +83312,157 @@ ** If an unlock is omitted, resources leaks will occur. ** ** If a disconnect is attempted while a virtual table is locked, ** the disconnect is deferred until all locks have been removed. */ -SQLITE_PRIVATE void sqlite3VtabLock(sqlite3_vtab *pVtab){ - pVtab->nRef++; -} - -/* -** Unlock a virtual table. When the last lock is removed, -** disconnect the virtual table. -*/ -SQLITE_PRIVATE void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){ - assert( pVtab->nRef>0 ); - pVtab->nRef--; - assert(db); +SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){ + pVTab->nRef++; +} + + +/* +** pTab is a pointer to a Table structure representing a virtual-table. +** Return a pointer to the VTable object used by connection db to access +** this virtual-table, if one has been created, or NULL otherwise. +*/ +SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ + VTable *pVtab; + assert( IsVirtual(pTab) ); + for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); + return pVtab; +} + +/* +** Decrement the ref-count on a virtual table object. When the ref-count +** reaches zero, call the xDisconnect() method to delete the object. +*/ +SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){ + sqlite3 *db = pVTab->db; + + assert( db ); + assert( pVTab->nRef>0 ); assert( sqlite3SafetyCheckOk(db) ); - if( pVtab->nRef==0 ){ - if( db->magic==SQLITE_MAGIC_BUSY ){ - (void)sqlite3SafetyOff(db); - pVtab->pModule->xDisconnect(pVtab); - (void)sqlite3SafetyOn(db); - } else { - pVtab->pModule->xDisconnect(pVtab); - } + + pVTab->nRef--; + if( pVTab->nRef==0 ){ + sqlite3_vtab *p = pVTab->pVtab; + if( p ){ +#ifdef SQLITE_DEBUG + if( pVTab->db->magic==SQLITE_MAGIC_BUSY ){ + (void)sqlite3SafetyOff(db); + p->pModule->xDisconnect(p); + (void)sqlite3SafetyOn(db); + } else +#endif + { + p->pModule->xDisconnect(p); + } + } + sqlite3DbFree(db, pVTab); + } +} + +/* +** Table p is a virtual table. This function moves all elements in the +** p->pVTable list to the sqlite3.pDisconnect lists of their associated +** database connections to be disconnected at the next opportunity. +** Except, if argument db is not NULL, then the entry associated with +** connection db is left in the p->pVTable list. +*/ +static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ + VTable *pRet = 0; + VTable *pVTable = p->pVTable; + p->pVTable = 0; + + /* Assert that the mutex (if any) associated with the BtShared database + ** that contains table p is held by the caller. See header comments + ** above function sqlite3VtabUnlockList() for an explanation of why + ** this makes it safe to access the sqlite3.pDisconnect list of any + ** database connection that may have an entry in the p->pVTable list. */ + assert( db==0 || + sqlite3BtreeHoldsMutex(db->aDb[sqlite3SchemaToIndex(db, p->pSchema)].pBt) + ); + + while( pVTable ){ + sqlite3 *db2 = pVTable->db; + VTable *pNext = pVTable->pNext; + assert( db2 ); + if( db2==db ){ + pRet = pVTable; + p->pVTable = pRet; + pRet->pNext = 0; + }else{ + pVTable->pNext = db2->pDisconnect; + db2->pDisconnect = pVTable; + } + pVTable = pNext; + } + + assert( !db || pRet ); + return pRet; +} + + +/* +** Disconnect all the virtual table objects in the sqlite3.pDisconnect list. +** +** This function may only be called when the mutexes associated with all +** shared b-tree databases opened using connection db are held by the +** caller. This is done to protect the sqlite3.pDisconnect list. The +** sqlite3.pDisconnect list is accessed only as follows: +** +** 1) By this function. In this case, all BtShared mutexes and the mutex +** associated with the database handle itself must be held. +** +** 2) By function vtabDisconnectAll(), when it adds a VTable entry to +** the sqlite3.pDisconnect list. In this case either the BtShared mutex +** associated with the database the virtual table is stored in is held +** or, if the virtual table is stored in a non-sharable database, then +** the database handle mutex is held. +** +** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously +** by multiple threads. It is thread-safe. +*/ +SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){ + VTable *p = db->pDisconnect; + db->pDisconnect = 0; + + assert( sqlite3BtreeHoldsAllMutexes(db) ); + assert( sqlite3_mutex_held(db->mutex) ); + + if( p ){ + sqlite3ExpirePreparedStatements(db); + do { + VTable *pNext = p->pNext; + sqlite3VtabUnlock(p); + p = pNext; + }while( p ); } } /* ** Clear any and all virtual-table information from the Table record. ** This routine is called, for example, just before deleting the Table ** record. +** +** Since it is a virtual-table, the Table structure contains a pointer +** to the head of a linked list of VTable structures. Each VTable +** structure is associated with a single sqlite3* user of the schema. +** The reference count of the VTable structure associated with database +** connection db is decremented immediately (which may lead to the +** structure being xDisconnected and free). Any other VTable structures +** in the list are moved to the sqlite3.pDisconnect list of the associated +** database connection. */ SQLITE_PRIVATE void sqlite3VtabClear(Table *p){ - sqlite3_vtab *pVtab = p->pVtab; - Schema *pSchema = p->pSchema; - sqlite3 *db = pSchema ? pSchema->db : 0; - if( pVtab ){ - assert( p->pMod && p->pMod->pModule ); - sqlite3VtabUnlock(db, pVtab); - p->pVtab = 0; - } + vtabDisconnectAll(0, p); if( p->azModuleArg ){ int i; for(i=0; i<p->nModuleArg; i++){ - sqlite3DbFree(db, p->azModuleArg[i]); - } - sqlite3DbFree(db, p->azModuleArg); + sqlite3DbFree(p->dbMem, p->azModuleArg[i]); + } + sqlite3DbFree(p->dbMem, p->azModuleArg); } } /* ** Add a new module argument to pTable->azModuleArg[]. @@ -80211,18 +83503,13 @@ ){ int iDb; /* The database the table is being created in */ Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ - if( pParse->db->flags & SQLITE_SharedCache ){ - sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode"); - return; - } - sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0); pTable = pParse->pNewTable; - if( pTable==0 || pParse->nErr ) return; + if( pTable==0 ) return; assert( 0==pTable->pIndex ); db = pParse->db; iDb = sqlite3SchemaToIndex(db, pTable->pSchema); assert( iDb>=0 ); @@ -80251,11 +83538,11 @@ ** This routine takes the module argument that has been accumulating ** in pParse->zArg[] and appends it to the list of arguments on the ** virtual table currently under construction in pParse->pTable. */ static void addArgumentToVtab(Parse *pParse){ - if( pParse->sArg.z && pParse->pNewTable ){ + if( pParse->sArg.z && ALWAYS(pParse->pNewTable) ){ const char *z = (const char*)pParse->sArg.z; int n = pParse->sArg.n; sqlite3 *db = pParse->db; addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); } @@ -80264,27 +83551,17 @@ /* ** The parser calls this routine after the CREATE VIRTUAL TABLE statement ** has been completely parsed. */ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ - Table *pTab; /* The table being constructed */ - sqlite3 *db; /* The database connection */ - char *zModule; /* The module name of the table: USING modulename */ - Module *pMod = 0; - + Table *pTab = pParse->pNewTable; /* The table being constructed */ + sqlite3 *db = pParse->db; /* The database connection */ + + if( pTab==0 ) return; addArgumentToVtab(pParse); pParse->sArg.z = 0; - - /* Lookup the module name. */ - pTab = pParse->pNewTable; - if( pTab==0 ) return; - db = pParse->db; - if( pTab->nModuleArg<1 ) return; - zModule = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zModule, - sqlite3Strlen30(zModule)); - pTab->pMod = pMod; + if( pTab->nModuleArg<1 ) return; /* If the CREATE VIRTUAL TABLE statement is being entered for the ** first time (in other words if the virtual table is actually being ** created now instead of just being read out of sqlite_master) then ** do additional initialization work and store the statement text @@ -80331,18 +83608,19 @@ sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, pTab->zName, sqlite3Strlen30(pTab->zName) + 1); } /* If we are rereading the sqlite_master table create the in-memory - ** record of the table. If the module has already been registered, - ** also call the xConnect method here. - */ + ** record of the table. The xConnect() method is not called until + ** the first time the virtual table is used in an SQL statement. This + ** allows a schema that contains virtual tables to be loaded before + ** the required virtual table implementations are registered. */ else { Table *pOld; Schema *pSchema = pTab->pSchema; const char *zName = pTab->zName; - int nName = sqlite3Strlen30(zName) + 1; + int nName = sqlite3Strlen30(zName); pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); if( pOld ){ db->mallocFailed = 1; assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ return; @@ -80387,91 +83665,101 @@ Table *pTab, Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ - int rc; - int rc2; - sqlite3_vtab *pVtab = 0; + VTable *pVTable; + int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM; } + pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); + if( !pVTable ){ + sqlite3DbFree(db, zModuleName); + return SQLITE_NOMEM; + } + pVTable->db = db; + pVTable->pMod = pMod; + assert( !db->pVTab ); assert( xConstruct ); - db->pVTab = pTab; - rc = sqlite3SafetyOff(db); - assert( rc==SQLITE_OK ); - rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVtab, &zErr); - rc2 = sqlite3SafetyOn(db); - if( rc==SQLITE_OK && pVtab ){ - pVtab->pModule = pMod->pModule; - pVtab->nRef = 1; - pTab->pVtab = pVtab; - } + + /* Invoke the virtual table constructor */ + (void)sqlite3SafetyOff(db); + rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); + (void)sqlite3SafetyOn(db); + if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; if( SQLITE_OK!=rc ){ if( zErr==0 ){ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); }else { *pzErr = sqlite3MPrintf(db, "%s", zErr); sqlite3DbFree(db, zErr); } - }else if( db->pVTab ){ - const char *zFormat = "vtable constructor did not declare schema: %s"; - *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); - rc = SQLITE_ERROR; - } - if( rc==SQLITE_OK ){ - rc = rc2; - } - db->pVTab = 0; + sqlite3DbFree(db, pVTable); + }else if( ALWAYS(pVTable->pVtab) ){ + /* Justification of ALWAYS(): A correct vtab constructor must allocate + ** the sqlite3_vtab object if successful. */ + pVTable->pVtab->pModule = pMod->pModule; + pVTable->nRef = 1; + if( db->pVTab ){ + const char *zFormat = "vtable constructor did not declare schema: %s"; + *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); + sqlite3VtabUnlock(pVTable); + rc = SQLITE_ERROR; + }else{ + int iCol; + /* If everything went according to plan, link the new VTable structure + ** into the linked list headed by pTab->pVTable. Then loop through the + ** columns of the table to see if any of them contain the token "hidden". + ** If so, set the Column.isHidden flag and remove the token from + ** the type string. */ + pVTable->pNext = pTab->pVTable; + pTab->pVTable = pVTable; + + for(iCol=0; iCol<pTab->nCol; iCol++){ + char *zType = pTab->aCol[iCol].zType; + int nType; + int i = 0; + if( !zType ) continue; + nType = sqlite3Strlen30(zType); + if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ + for(i=0; i<nType; i++){ + if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7)) + && (zType[i+7]=='\0' || zType[i+7]==' ') + ){ + i++; + break; + } + } + } + if( i<nType ){ + int j; + int nDel = 6 + (zType[i+6] ? 1 : 0); + for(j=i; (j+nDel)<=nType; j++){ + zType[j] = zType[j+nDel]; + } + if( zType[i]=='\0' && i>0 ){ + assert(zType[i-1]==' '); + zType[i-1] = '\0'; + } + pTab->aCol[iCol].isHidden = 1; + } + } + } + } + sqlite3DbFree(db, zModuleName); - - /* If everything went according to plan, loop through the columns - ** of the table to see if any of them contain the token "hidden". - ** If so, set the Column.isHidden flag and remove the token from - ** the type string. - */ - if( rc==SQLITE_OK ){ - int iCol; - for(iCol=0; iCol<pTab->nCol; iCol++){ - char *zType = pTab->aCol[iCol].zType; - int nType; - int i = 0; - if( !zType ) continue; - nType = sqlite3Strlen30(zType); - if( sqlite3StrNICmp("hidden", zType, 6) || (zType[6] && zType[6]!=' ') ){ - for(i=0; i<nType; i++){ - if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7)) - && (zType[i+7]=='\0' || zType[i+7]==' ') - ){ - i++; - break; - } - } - } - if( i<nType ){ - int j; - int nDel = 6 + (zType[i+6] ? 1 : 0); - for(j=i; (j+nDel)<=nType; j++){ - zType[j] = zType[j+nDel]; - } - if( zType[i]=='\0' && i>0 ){ - assert(zType[i-1]==' '); - zType[i-1] = '\0'; - } - pTab->aCol[iCol].isHidden = 1; - } - } - } + db->pVTab = 0; return rc; } /* ** This function is invoked by the parser to call the xConnect() method @@ -80479,25 +83767,30 @@ ** and an error left in pParse. ** ** This call is a no-op if table pTab is not a virtual table. */ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ + sqlite3 *db = pParse->db; + const char *zMod; Module *pMod; - int rc = SQLITE_OK; - - if( !pTab || (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){ + int rc; + + assert( pTab ); + if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){ return SQLITE_OK; } - pMod = pTab->pMod; + /* Locate the required virtual table module */ + zMod = pTab->azModuleArg[0]; + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); + if( !pMod ){ const char *zModule = pTab->azModuleArg[0]; sqlite3ErrorMsg(pParse, "no such module: %s", zModule); rc = SQLITE_ERROR; - } else { - char *zErr = 0; - sqlite3 *db = pParse->db; + }else{ + char *zErr = 0; rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "%s", zErr); } sqlite3DbFree(db, zErr); @@ -80505,18 +83798,18 @@ return rc; } /* -** Add the virtual table pVtab to the array sqlite3.aVTrans[]. -*/ -static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){ +** Add the virtual table pVTab to the array sqlite3.aVTrans[]. +*/ +static int addToVTrans(sqlite3 *db, VTable *pVTab){ const int ARRAY_INCR = 5; /* Grow the sqlite3.aVTrans array if required */ if( (db->nVTrans%ARRAY_INCR)==0 ){ - sqlite3_vtab **aVTrans; + VTable **aVTrans; int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); if( !aVTrans ){ return SQLITE_NOMEM; } @@ -80523,12 +83816,12 @@ memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); db->aVTrans = aVTrans; } /* Add pVtab to the end of sqlite3.aVTrans */ - db->aVTrans[db->nVTrans++] = pVtab; - sqlite3VtabLock(pVtab); + db->aVTrans[db->nVTrans++] = pVTab; + sqlite3VtabLock(pVTab); return SQLITE_OK; } /* ** This function is invoked by the vdbe to call the xCreate method @@ -80540,30 +83833,34 @@ */ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ int rc = SQLITE_OK; Table *pTab; Module *pMod; - const char *zModule; + const char *zMod; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); - assert(pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVtab); - pMod = pTab->pMod; - zModule = pTab->azModuleArg[0]; + assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); + + /* Locate the required virtual table module */ + zMod = pTab->azModuleArg[0]; + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); /* If the module has been registered and includes a Create method, ** invoke it now. If the module has not been registered, return an ** error. Otherwise, do nothing. */ if( !pMod ){ - *pzErr = sqlite3MPrintf(db, "no such module: %s", zModule); + *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); rc = SQLITE_ERROR; }else{ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); } - if( rc==SQLITE_OK && pTab->pVtab ){ - rc = addToVTrans(db, pTab->pVtab); + /* Justification of ALWAYS(): The xConstructor method is required to + ** create a valid sqlite3_vtab if it returns SQLITE_OK. */ + if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){ + rc = addToVTrans(db, sqlite3GetVTable(db, pTab)); } return rc; } @@ -80571,11 +83868,11 @@ ** This function is used to set the schema of a virtual table. It is only ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ - Parse sParse; + Parse *pParse; int rc = SQLITE_OK; Table *pTab; char *zErr = 0; @@ -80584,39 +83881,45 @@ if( !pTab ){ sqlite3Error(db, SQLITE_MISUSE, 0); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE; } - assert((pTab->tabFlags & TF_Virtual)!=0 && pTab->nCol==0 && pTab->aCol==0); - - memset(&sParse, 0, sizeof(Parse)); - sParse.declareVtab = 1; - sParse.db = db; - - if( - SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) && - sParse.pNewTable && - !sParse.pNewTable->pSelect && - (sParse.pNewTable->tabFlags & TF_Virtual)==0 - ){ - pTab->aCol = sParse.pNewTable->aCol; - pTab->nCol = sParse.pNewTable->nCol; - sParse.pNewTable->nCol = 0; - sParse.pNewTable->aCol = 0; - db->pVTab = 0; - } else { - sqlite3Error(db, SQLITE_ERROR, zErr); - sqlite3DbFree(db, zErr); - rc = SQLITE_ERROR; - } - sParse.declareVtab = 0; - - if( sParse.pVdbe ){ - sqlite3VdbeFinalize(sParse.pVdbe); - } - sqlite3DeleteTable(sParse.pNewTable); - sParse.pNewTable = 0; + assert( (pTab->tabFlags & TF_Virtual)!=0 ); + + pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); + if( pParse==0 ){ + rc = SQLITE_NOMEM; + }else{ + pParse->declareVtab = 1; + pParse->db = db; + + if( + SQLITE_OK == sqlite3RunParser(pParse, zCreateTable, &zErr) && + pParse->pNewTable && + !pParse->pNewTable->pSelect && + (pParse->pNewTable->tabFlags & TF_Virtual)==0 + ){ + if( !pTab->aCol ){ + pTab->aCol = pParse->pNewTable->aCol; + pTab->nCol = pParse->pNewTable->nCol; + pParse->pNewTable->nCol = 0; + pParse->pNewTable->aCol = 0; + } + db->pVTab = 0; + } else { + sqlite3Error(db, SQLITE_ERROR, zErr); + sqlite3DbFree(db, zErr); + rc = SQLITE_ERROR; + } + pParse->declareVtab = 0; + + if( pParse->pVdbe ){ + sqlite3VdbeFinalize(pParse->pVdbe); + } + sqlite3DeleteTable(pParse->pNewTable); + sqlite3StackFree(db, pParse); + } assert( (rc&0xff)==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; @@ -80627,34 +83930,29 @@ ** of the virtual table named zTab in database iDb. This occurs ** when a DROP TABLE is mentioned. ** ** This call is a no-op if zTab is not a virtual table. */ -SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab) -{ +SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ int rc = SQLITE_OK; Table *pTab; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); - assert(pTab); - if( pTab->pVtab ){ - int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy; + if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ + VTable *p = vtabDisconnectAll(db, pTab); + rc = sqlite3SafetyOff(db); assert( rc==SQLITE_OK ); - if( xDestroy ){ - rc = xDestroy(pTab->pVtab); - } + rc = p->pMod->pModule->xDestroy(p->pVtab); (void)sqlite3SafetyOn(db); - if( rc==SQLITE_OK ){ - int i; - for(i=0; i<db->nVTrans; i++){ - if( db->aVTrans[i]==pTab->pVtab ){ - db->aVTrans[i] = db->aVTrans[--db->nVTrans]; - break; - } - } - pTab->pVtab = 0; + + /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ + if( rc==SQLITE_OK ){ + assert( pTab->pVTable==p && p->pNext==0 ); + p->pVtab = 0; + pTab->pVTable = 0; + sqlite3VtabUnlock(p); } } return rc; } @@ -80668,16 +83966,19 @@ ** The array is cleared after invoking the callbacks. */ static void callFinaliser(sqlite3 *db, int offset){ int i; if( db->aVTrans ){ - for(i=0; i<db->nVTrans && db->aVTrans[i]; i++){ - sqlite3_vtab *pVtab = db->aVTrans[i]; - int (*x)(sqlite3_vtab *); - x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset); - if( x ) x(pVtab); - sqlite3VtabUnlock(db, pVtab); + for(i=0; i<db->nVTrans; i++){ + VTable *pVTab = db->aVTrans[i]; + sqlite3_vtab *p = pVTab->pVtab; + if( p ){ + int (*x)(sqlite3_vtab *); + x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset); + if( x ) x(p); + } + sqlite3VtabUnlock(pVTab); } sqlite3DbFree(db, db->aVTrans); db->nVTrans = 0; db->aVTrans = 0; } @@ -80693,19 +83994,18 @@ */ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ int i; int rc = SQLITE_OK; int rcsafety; - sqlite3_vtab **aVTrans = db->aVTrans; + VTable **aVTrans = db->aVTrans; rc = sqlite3SafetyOff(db); db->aVTrans = 0; - for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){ - sqlite3_vtab *pVtab = aVTrans[i]; + for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ int (*x)(sqlite3_vtab *); - x = pVtab->pModule->xSync; - if( x ){ + sqlite3_vtab *pVtab = aVTrans[i]->pVtab; + if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ rc = x(pVtab); sqlite3DbFree(db, *pzErrmsg); *pzErrmsg = pVtab->zErrMsg; pVtab->zErrMsg = 0; } @@ -80743,42 +84043,42 @@ ** not currently open, invoke the xBegin method now. ** ** If the xBegin call is successful, place the sqlite3_vtab pointer ** in the sqlite3.aVTrans array. */ -SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){ +SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ int rc = SQLITE_OK; const sqlite3_module *pModule; /* Special case: If db->aVTrans is NULL and db->nVTrans is greater ** than zero, then this function is being called from within a ** virtual module xSync() callback. It is illegal to write to - ** virtual module tables in this case, so return SQLITE_MISUSE. + ** virtual module tables in this case, so return SQLITE_LOCKED. */ if( sqlite3VtabInSync(db) ){ return SQLITE_LOCKED; } - if( !pVtab ){ + if( !pVTab ){ return SQLITE_OK; } - pModule = pVtab->pModule; + pModule = pVTab->pVtab->pModule; if( pModule->xBegin ){ int i; /* If pVtab is already in the aVTrans array, return early */ - for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){ - if( db->aVTrans[i]==pVtab ){ + for(i=0; i<db->nVTrans; i++){ + if( db->aVTrans[i]==pVTab ){ return SQLITE_OK; } } /* Invoke the xBegin method */ - rc = pModule->xBegin(pVtab); - if( rc==SQLITE_OK ){ - rc = addToVTrans(db, pVtab); + rc = pModule->xBegin(pVTab->pVtab); + if( rc==SQLITE_OK ){ + rc = addToVTrans(db, pVTab); } } return rc; } @@ -80811,16 +84111,16 @@ char *zLowerName; unsigned char *z; /* Check to see the left operand is a column in a virtual table */ - if( pExpr==0 ) return pDef; + if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; pTab = pExpr->pTab; - if( pTab==0 ) return pDef; + if( NEVER(pTab==0) ) return pDef; if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef; - pVtab = pTab->pVtab; + pVtab = sqlite3GetVTable(db, pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction==0 ) return pDef; @@ -80832,24 +84132,19 @@ for(z=(unsigned char*)zLowerName; *z; z++){ *z = sqlite3UpperToLower[*z]; } rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg); sqlite3DbFree(db, zLowerName); - if( pVtab->zErrMsg ){ - sqlite3Error(db, rc, "%s", pVtab->zErrMsg); - sqlite3DbFree(db, pVtab->zErrMsg); - pVtab->zErrMsg = 0; - } } if( rc==0 ){ return pDef; } /* Create a new ephemeral function definition for the overloaded ** function */ pNew = sqlite3DbMallocZero(db, sizeof(*pNew) - + sqlite3Strlen30(pDef->zName) ); + + sqlite3Strlen30(pDef->zName) + 1); if( pNew==0 ){ return pDef; } *pNew = *pDef; pNew->zName = (char *)&pNew[1]; @@ -80865,21 +84160,25 @@ ** array so that an OP_VBegin will get generated for it. Add pTab to the ** array if it is missing. If pTab is already in the array, this routine ** is a no-op. */ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); int i, n; + Table **apVtabLock; + assert( IsVirtual(pTab) ); - for(i=0; i<pParse->nVtabLock; i++){ - if( pTab==pParse->apVtabLock[i] ) return; - } - n = (pParse->nVtabLock+1)*sizeof(pParse->apVtabLock[0]); - pParse->apVtabLock = sqlite3_realloc(pParse->apVtabLock, n); - if( pParse->apVtabLock ){ - pParse->apVtabLock[pParse->nVtabLock++] = pTab; - }else{ - pParse->db->mallocFailed = 1; + for(i=0; i<pToplevel->nVtabLock; i++){ + if( pTab==pToplevel->apVtabLock[i] ) return; + } + n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); + apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n); + if( apVtabLock ){ + pToplevel->apVtabLock = apVtabLock; + pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; + }else{ + pToplevel->db->mallocFailed = 1; } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -80901,11 +84200,11 @@ ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.382 2009/04/07 13:48:12 drh Exp $ +** $Id: where.c,v 1.411 2009/07/31 06:14:52 danielk1977 Exp $ */ /* ** Trace output macros */ @@ -80927,14 +84226,12 @@ typedef struct WhereCost WhereCost; /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE -** clause subexpression is separated from the others by AND operators. -** (Note: the same data structure is also reused to hold a group of terms -** separated by OR operators. But at the top-level, everything is AND -** separated.) +** clause subexpression is separated from the others by AND operators, +** usually, or sometimes subexpressions separated by OR. ** ** All WhereTerms are collected into a single WhereClause structure. ** The following identity holds: ** ** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm @@ -81013,15 +84310,20 @@ ** WHERE clause. Mostly this is a container for one or more WhereTerms. */ struct WhereClause { Parse *pParse; /* The parser context */ WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */ + Bitmask vmask; /* Bitmask identifying virtual table cursors */ u8 op; /* Split operator. TK_AND or TK_OR */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ - WhereTerm aStatic[4]; /* Initial static space for a[] */ +#if defined(SQLITE_SMALL_STACK) + WhereTerm aStatic[1]; /* Initial static space for a[] */ +#else + WhereTerm aStatic[8]; /* Initial static space for a[] */ +#endif }; /* ** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to ** a dynamically allocated instance of the following structure. @@ -81076,10 +84378,11 @@ */ struct WhereCost { WherePlan plan; /* The lookup strategy */ double rCost; /* Overall cost of pursuing this search strategy */ double nRow; /* Estimated number of output rows */ + Bitmask used; /* Bitmask of cursors used by this plan */ }; /* ** Bitmasks for the operators that indices are able to exploit. An ** OR-ed combination of these values can be used when searching for @@ -81112,15 +84415,16 @@ ** ISNULL constraints will then not be used on the right table of a left ** join. Tickets #2177 and #2189. */ #define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */ #define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */ -#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) */ +#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ -#define WHERE_INDEXED 0x00070000 /* Anything that uses an index */ -#define WHERE_IN_ABLE 0x00071000 /* Able to support an IN operator */ +#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ +#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ +#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */ #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ #define WHERE_IDX_ONLY 0x00800000 /* Use index only - omit table */ #define WHERE_ORDERBY 0x01000000 /* Output will appear in correct order */ #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */ @@ -81139,10 +84443,11 @@ pWC->pParse = pParse; pWC->pMaskSet = pMaskSet; pWC->nTerm = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; + pWC->vmask = 0; } /* Forward reference */ static void whereClauseClear(WhereClause*); @@ -81259,20 +84564,21 @@ whereSplit(pWC, pExpr->pRight, op); } } /* -** Initialize an expression mask set +** Initialize an expression mask set (a WhereMaskSet object) */ #define initMaskSet(P) memset(P, 0, sizeof(*P)) /* ** Return the bitmask for the given cursor number. Return 0 if ** iCursor is not in the set. */ static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){ int i; + assert( pMaskSet->n<=sizeof(Bitmask)*8 ); for(i=0; i<pMaskSet->n; i++){ if( pMaskSet->ix[i]==iCursor ){ return ((Bitmask)1)<<i; } } @@ -81532,30 +84838,29 @@ if( pLeft->op!=TK_COLUMN ){ return 0; } pColl = sqlite3ExprCollSeq(pParse, pLeft); assert( pColl!=0 || pLeft->iColumn==-1 ); - if( pColl==0 ){ - /* No collation is defined for the ROWID. Use the default. */ - pColl = db->pDfltColl; - } + if( pColl==0 ) return 0; if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) && (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ return 0; } - sqlite3DequoteExpr(pRight); - z = (char *)pRight->token.z; - cnt = 0; - if( z ){ - while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; } - } - if( cnt==0 || 255==(u8)z[cnt-1] ){ - return 0; - } - *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0; - *pnPattern = cnt; - return 1; + if( sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ) return 0; + z = pRight->u.zToken; + if( ALWAYS(z) ){ + cnt = 0; + while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ + cnt++; + } + if( cnt!=0 && c!=0 && 255!=(u8)z[cnt-1] ){ + *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0; + *pnPattern = cnt; + return 1; + } + } + return 0; } #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -81572,12 +84877,11 @@ ExprList *pList; if( pExpr->op!=TK_FUNCTION ){ return 0; } - if( pExpr->token.n!=5 || - sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){ + if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){ return 0; } pList = pExpr->x.pList; if( pList->nExpr!=2 ){ return 0; @@ -81710,11 +85014,12 @@ assert( pOrWc->nTerm>=2 ); /* ** Compute the set of tables that might satisfy cases 1 or 2. */ - indexable = chngToIN = ~(Bitmask)0; + indexable = ~(Bitmask)0; + chngToIN = ~(pWC->vmask); for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ WhereAndInfo *pAndInfo; assert( pOrTerm->eOperator==0 ); assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); @@ -81771,10 +85076,26 @@ /* ** chngToIN holds a set of tables that *might* satisfy case 1. But ** we have to do some additional checking to see if case 1 really ** is satisfied. + ** + ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means + ** that there is no possibility of transforming the OR clause into an + ** IN operator because one or more terms in the OR clause contain + ** something other than == on a column in the single table. The 1-bit + ** case means that every term of the OR clause is of the form + ** "table.column=expr" for some single table. The one bit that is set + ** will correspond to the common table. We still need to check to make + ** sure the same column is used on all terms. The 2-bit case is when + ** the all terms are of the form "table1.column=table2.column". It + ** might be possible to form an IN operator with either table1.column + ** or table2.column as the LHS if either is common to every term of + ** the OR clause. + ** + ** Note that terms of the form "table.column1=table.column2" (the + ** same table on both sizes of the ==) cannot be optimized. */ if( chngToIN ){ int okToChngToIN = 0; /* True if the conversion to IN is valid */ int iColumn = -1; /* Column index on lhs of IN operator */ int iCursor = -1; /* Table cursor common to all terms */ @@ -81789,22 +85110,42 @@ for(j=0; j<2 && !okToChngToIN; j++){ pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ assert( pOrTerm->eOperator==WO_EQ ); pOrTerm->wtFlags &= ~TERM_OR_OK; - if( pOrTerm->leftCursor==iColumn ) continue; - if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ) continue; + if( pOrTerm->leftCursor==iCursor ){ + /* This is the 2-bit case and we are on the second iteration and + ** current term is from the first iteration. So skip this term. */ + assert( j==1 ); + continue; + } + if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){ + /* This term must be of the form t1.a==t2.b where t2 is in the + ** chngToIN set but t1 is not. This term will be either preceeded + ** or follwed by an inverted copy (t2.b==t1.a). Skip this term + ** and use its inversion. */ + testcase( pOrTerm->wtFlags & TERM_COPIED ); + testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); + assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) ); + continue; + } iColumn = pOrTerm->u.leftColumn; iCursor = pOrTerm->leftCursor; break; } if( i<0 ){ + /* No candidate table+column was found. This can only occur + ** on the second iteration */ assert( j==1 ); assert( (chngToIN&(chngToIN-1))==0 ); - assert( chngToIN==getMask(pMaskSet, iColumn) ); - break; - } + assert( chngToIN==getMask(pMaskSet, iCursor) ); + break; + } + testcase( j==1 ); + + /* We have found a candidate table and column. Check to see if that + ** table and column is common to every term in the OR clause */ okToChngToIN = 1; for(; i>=0 && okToChngToIN; i--, pOrTerm++){ assert( pOrTerm->eOperator==WO_EQ ); if( pOrTerm->leftCursor!=iCursor ){ pOrTerm->wtFlags &= ~TERM_OR_OK; @@ -81841,16 +85182,16 @@ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; assert( pOrTerm->eOperator==WO_EQ ); assert( pOrTerm->leftCursor==iCursor ); assert( pOrTerm->u.leftColumn==iColumn ); pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); - pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0); + pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); pDup = sqlite3ExprDup(db, pLeft, 0); - pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0); + pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0); if( pNew ){ int idxNew; transferJoinMarkings(pNew, pExpr); assert( !ExprHasProperty(pNew, EP_xIsSelect) ); pNew->x.pList = pList; @@ -81999,11 +85340,12 @@ assert( pList!=0 ); assert( pList->nExpr==2 ); for(i=0; i<2; i++){ Expr *pNewExpr; int idxNew; - pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0), + pNewExpr = sqlite3PExpr(pParse, ops[i], + sqlite3ExprDup(db, pExpr->pLeft, 0), sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); exprAnalyze(pSrc, pWC, idxNew); pTerm = &pWC->a[idxTerm]; @@ -82018,10 +85360,11 @@ ** an OR operator. */ else if( pExpr->op==TK_OR ){ assert( pWC->op==TK_AND ); exprAnalyzeOrTerm(pSrc, pWC, idxTerm); + pTerm = &pWC->a[idxTerm]; } #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ #ifndef SQLITE_OMIT_LIKE_OPTIMIZATION /* Add constraints to reduce the search space on a LIKE or GLOB @@ -82041,24 +85384,26 @@ Expr *pNewExpr1, *pNewExpr2; int idxNew1, idxNew2; pLeft = pExpr->x.pList->a[1].pExpr; pRight = pExpr->x.pList->a[0].pExpr; - pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0); - if( pStr1 ){ - sqlite3TokenCopy(db, &pStr1->token, &pRight->token); - pStr1->token.n = nPattern; - pStr1->flags = EP_Dequoted; - } + pStr1 = sqlite3Expr(db, TK_STRING, pRight->u.zToken); + if( pStr1 ) pStr1->u.zToken[nPattern] = 0; pStr2 = sqlite3ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ - u8 c, *pC; - /* assert( pStr2->token.dyn ); */ - pC = (u8*)&pStr2->token.z[nPattern-1]; + u8 c, *pC; /* Last character before the first wildcard */ + pC = (u8*)&pStr2->u.zToken[nPattern-1]; c = *pC; if( noCase ){ - if( c=='@' ) isComplete = 0; + /* The point is to increment the last character before the first + ** wildcard. But if we increment '@', that will push it into the + ** alphabetic range where case conversions will mess up the + ** inequality. To avoid this, make sure to also run the full + ** LIKE on all candidate expressions by clearing the isComplete flag + */ + if( c=='A'-1 ) isComplete = 0; + c = sqlite3UpperToLower[c]; } *pC = c + 1; } pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft,0),pStr1,0); @@ -82095,11 +85440,12 @@ pLeft = pExpr->x.pList->a[1].pExpr; prereqExpr = exprTableUsage(pMaskSet, pRight); prereqColumn = exprTableUsage(pMaskSet, pLeft); if( (prereqExpr & prereqColumn)==0 ){ Expr *pNewExpr; - pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight, 0), 0); + pNewExpr = sqlite3PExpr(pParse, TK_MATCH, + 0, sqlite3ExprDup(db, pRight, 0), 0); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); pNewTerm = &pWC->a[idxNew]; pNewTerm->prereqRight = prereqExpr; pNewTerm->leftCursor = pLeft->iTable; @@ -82176,10 +85522,15 @@ assert( pOrderBy!=0 ); nTerm = pOrderBy->nExpr; assert( nTerm>0 ); + /* Argument pIdx must either point to a 'real' named index structure, + ** or an index structure allocated on the stack by bestBtreeIndex() to + ** represent the rowid index that is part of every table. */ + assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) ); + /* Match terms of the ORDER BY clause against columns of ** the index. ** ** Note that indices have pIdx->nColumn regular columns plus ** one additional column containing the rowid. The rowid column @@ -82202,11 +85553,11 @@ } pColl = sqlite3ExprCollSeq(pParse, pExpr); if( !pColl ){ pColl = db->pDfltColl; } - if( i<pIdx->nColumn ){ + if( pIdx->zName && i<pIdx->nColumn ){ iColumn = pIdx->aiColumn[i]; if( iColumn==pIdx->pTable->iPKey ){ iColumn = -1; } iSortOrder = pIdx->aSortOrder[i]; @@ -82231,11 +85582,11 @@ ** then the index cannot satisfy the ORDER BY constraint. */ return 0; } } - assert( pIdx->aSortOrder!=0 ); + assert( pIdx->aSortOrder!=0 || iColumn==-1 ); assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 ); assert( iSortOrder==0 || iSortOrder==1 ); termSortOrder = iSortOrder ^ pTerm->sortOrder; if( i>nEqCol ){ if( termSortOrder!=sortOrder ){ @@ -82269,34 +85620,10 @@ && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){ /* All terms of this index match some prefix of the ORDER BY clause ** and the index is UNIQUE and no terms on the tail of the ORDER BY ** clause reference other tables in a join. If this is all true then ** the order by clause is superfluous. */ - return 1; - } - return 0; -} - -/* -** Check table to see if the ORDER BY clause in pOrderBy can be satisfied -** by sorting in order of ROWID. Return true if so and set *pbRev to be -** true for reverse ROWID and false for forward ROWID order. -*/ -static int sortableByRowid( - int base, /* Cursor number for table to be sorted */ - ExprList *pOrderBy, /* The ORDER BY clause */ - WhereMaskSet *pMaskSet, /* Mapping from table cursors to bitmaps */ - int *pbRev /* Set to 1 if ORDER BY is DESC */ -){ - Expr *p; - - assert( pOrderBy!=0 ); - assert( pOrderBy->nExpr>0 ); - p = pOrderBy->a[0].pExpr; - if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1 - && !referencesOtherTables(pOrderBy, pMaskSet, 1, base) ){ - *pbRev = pOrderBy->a[0].sortOrder; return 1; } return 0; } @@ -82359,11 +85686,253 @@ #else #define TRACE_IDX_INPUTS(A) #define TRACE_IDX_OUTPUTS(A) #endif +/* +** Required because bestIndex() is called by bestOrClauseIndex() +*/ +static void bestIndex( + Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*); + +/* +** This routine attempts to find an scanning strategy that can be used +** to optimize an 'OR' expression that is part of a WHERE clause. +** +** The table associated with FROM clause term pSrc may be either a +** regular B-Tree table or a virtual table. +*/ +static void bestOrClauseIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + struct SrcList_item *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors that are not available */ + ExprList *pOrderBy, /* The ORDER BY clause */ + WhereCost *pCost /* Lowest cost query plan */ +){ +#ifndef SQLITE_OMIT_OR_OPTIMIZATION + const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ + const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */ + WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */ + WhereTerm *pTerm; /* A single term of the WHERE clause */ + + /* Search the WHERE clause terms for a usable WO_OR term. */ + for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ + if( pTerm->eOperator==WO_OR + && ((pTerm->prereqAll & ~maskSrc) & notReady)==0 + && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 + ){ + WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; + WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; + WhereTerm *pOrTerm; + int flags = WHERE_MULTI_OR; + double rTotal = 0; + double nRow = 0; + Bitmask used = 0; + + for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ + WhereCost sTermCost; + WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", + (pOrTerm - pOrWC->a), (pTerm - pWC->a) + )); + if( pOrTerm->eOperator==WO_AND ){ + WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc; + bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost); + }else if( pOrTerm->leftCursor==iCur ){ + WhereClause tempWC; + tempWC.pParse = pWC->pParse; + tempWC.pMaskSet = pWC->pMaskSet; + tempWC.op = TK_AND; + tempWC.a = pOrTerm; + tempWC.nTerm = 1; + bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost); + }else{ + continue; + } + rTotal += sTermCost.rCost; + nRow += sTermCost.nRow; + used |= sTermCost.used; + if( rTotal>=pCost->rCost ) break; + } + + /* If there is an ORDER BY clause, increase the scan cost to account + ** for the cost of the sort. */ + if( pOrderBy!=0 ){ + rTotal += nRow*estLog(nRow); + WHERETRACE(("... sorting increases OR cost to %.9g\n", rTotal)); + } + + /* If the cost of scanning using this OR term for optimization is + ** less than the current cost stored in pCost, replace the contents + ** of pCost. */ + WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow)); + if( rTotal<pCost->rCost ){ + pCost->rCost = rTotal; + pCost->nRow = nRow; + pCost->used = used; + pCost->plan.wsFlags = flags; + pCost->plan.u.pTerm = pTerm; + } + } + } +#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ +} + #ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Allocate and populate an sqlite3_index_info structure. It is the +** responsibility of the caller to eventually release the structure +** by passing the pointer returned by this function to sqlite3_free(). +*/ +static sqlite3_index_info *allocateIndexInfo( + Parse *pParse, + WhereClause *pWC, + struct SrcList_item *pSrc, + ExprList *pOrderBy +){ + int i, j; + int nTerm; + struct sqlite3_index_constraint *pIdxCons; + struct sqlite3_index_orderby *pIdxOrderBy; + struct sqlite3_index_constraint_usage *pUsage; + WhereTerm *pTerm; + int nOrderBy; + sqlite3_index_info *pIdxInfo; + + WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName)); + + /* Count the number of possible WHERE clause constraints referring + ** to this virtual table */ + for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ + if( pTerm->leftCursor != pSrc->iCursor ) continue; + assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; + nTerm++; + } + + /* If the ORDER BY clause contains only columns in the current + ** virtual table then allocate space for the aOrderBy part of + ** the sqlite3_index_info structure. + */ + nOrderBy = 0; + if( pOrderBy ){ + for(i=0; i<pOrderBy->nExpr; i++){ + Expr *pExpr = pOrderBy->a[i].pExpr; + if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; + } + if( i==pOrderBy->nExpr ){ + nOrderBy = pOrderBy->nExpr; + } + } + + /* Allocate the sqlite3_index_info structure + */ + pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + + sizeof(*pIdxOrderBy)*nOrderBy ); + if( pIdxInfo==0 ){ + sqlite3ErrorMsg(pParse, "out of memory"); + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ + return 0; + } + + /* Initialize the structure. The sqlite3_index_info structure contains + ** many fields that are declared "const" to prevent xBestIndex from + ** changing them. We have to do some funky casting in order to + ** initialize those fields. + */ + pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; + pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; + pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; + *(int*)&pIdxInfo->nConstraint = nTerm; + *(int*)&pIdxInfo->nOrderBy = nOrderBy; + *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; + *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; + *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = + pUsage; + + for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ + if( pTerm->leftCursor != pSrc->iCursor ) continue; + assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; + pIdxCons[j].iColumn = pTerm->u.leftColumn; + pIdxCons[j].iTermOffset = i; + pIdxCons[j].op = (u8)pTerm->eOperator; + /* The direct assignment in the previous line is possible only because + ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The + ** following asserts verify this fact. */ + assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); + assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); + assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); + assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); + assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); + assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); + assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); + j++; + } + for(i=0; i<nOrderBy; i++){ + Expr *pExpr = pOrderBy->a[i].pExpr; + pIdxOrderBy[i].iColumn = pExpr->iColumn; + pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; + } + + return pIdxInfo; +} + +/* +** The table object reference passed as the second argument to this function +** must represent a virtual table. This function invokes the xBestIndex() +** method of the virtual table with the sqlite3_index_info pointer passed +** as the argument. +** +** If an error occurs, pParse is populated with an error message and a +** non-zero value is returned. Otherwise, 0 is returned and the output +** part of the sqlite3_index_info structure is left populated. +** +** Whether or not an error is returned, it is the responsibility of the +** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates +** that this is required. +*/ +static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ + sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; + int i; + int rc; + + (void)sqlite3SafetyOff(pParse->db); + WHERETRACE(("xBestIndex for %s\n", pTab->zName)); + TRACE_IDX_INPUTS(p); + rc = pVtab->pModule->xBestIndex(pVtab, p); + TRACE_IDX_OUTPUTS(p); + (void)sqlite3SafetyOn(pParse->db); + + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + pParse->db->mallocFailed = 1; + }else if( !pVtab->zErrMsg ){ + sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); + }else{ + sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); + } + } + sqlite3DbFree(pParse->db, pVtab->zErrMsg); + pVtab->zErrMsg = 0; + + for(i=0; i<p->nConstraint; i++){ + if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ + sqlite3ErrorMsg(pParse, + "table %s: xBestIndex returned an invalid plan", pTab->zName); + } + } + + return pParse->nErr; +} + + /* ** Compute the best index for a virtual table. ** ** The best index is computed by the xBestIndex method of the virtual ** table module. This routine is really just a wrapper that sets up @@ -82376,118 +85945,43 @@ ** invocations. The sqlite3_index_info structure is also used when ** code is generated to access the virtual table. The whereInfoDelete() ** routine takes care of freeing the sqlite3_index_info structure after ** everybody has finished with it. */ -static double bestVirtualIndex( - Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause */ - struct SrcList_item *pSrc, /* The FROM clause term to search */ - Bitmask notReady, /* Mask of cursors that are not available */ - ExprList *pOrderBy, /* The order by clause */ - int orderByUsable, /* True if we can potential sort */ - sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */ +static void bestVirtualIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + struct SrcList_item *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors that are not available */ + ExprList *pOrderBy, /* The order by clause */ + WhereCost *pCost, /* Lowest cost query plan */ + sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */ ){ Table *pTab = pSrc->pTab; - sqlite3_vtab *pVtab = pTab->pVtab; sqlite3_index_info *pIdxInfo; struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_orderby *pIdxOrderBy; struct sqlite3_index_constraint_usage *pUsage; WhereTerm *pTerm; int i, j; int nOrderBy; - int rc; + + /* Make sure wsFlags is initialized to some sane value. Otherwise, if the + ** malloc in allocateIndexInfo() fails and this function returns leaving + ** wsFlags in an uninitialized state, the caller may behave unpredictably. + */ + memset(pCost, 0, sizeof(*pCost)); + pCost->plan.wsFlags = WHERE_VIRTUALTABLE; /* If the sqlite3_index_info structure has not been previously - ** allocated and initialized for this virtual table, then allocate - ** and initialize it now + ** allocated and initialized, then allocate and initialize it now. */ pIdxInfo = *ppIdxInfo; if( pIdxInfo==0 ){ - int nTerm; - WHERETRACE(("Recomputing index info for %s...\n", pTab->zName)); - - /* Count the number of possible WHERE clause constraints referring - ** to this virtual table */ - for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ - if( pTerm->leftCursor != pSrc->iCursor ) continue; - assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); - testcase( pTerm->eOperator==WO_IN ); - testcase( pTerm->eOperator==WO_ISNULL ); - if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; - nTerm++; - } - - /* If the ORDER BY clause contains only columns in the current - ** virtual table then allocate space for the aOrderBy part of - ** the sqlite3_index_info structure. - */ - nOrderBy = 0; - if( pOrderBy ){ - for(i=0; i<pOrderBy->nExpr; i++){ - Expr *pExpr = pOrderBy->a[i].pExpr; - if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; - } - if( i==pOrderBy->nExpr ){ - nOrderBy = pOrderBy->nExpr; - } - } - - /* Allocate the sqlite3_index_info structure - */ - pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) - + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy ); - if( pIdxInfo==0 ){ - sqlite3ErrorMsg(pParse, "out of memory"); - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - return (double)0; - } - *ppIdxInfo = pIdxInfo; - - /* Initialize the structure. The sqlite3_index_info structure contains - ** many fields that are declared "const" to prevent xBestIndex from - ** changing them. We have to do some funky casting in order to - ** initialize those fields. - */ - pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; - pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; - pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - *(int*)&pIdxInfo->nConstraint = nTerm; - *(int*)&pIdxInfo->nOrderBy = nOrderBy; - *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; - *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; - *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = - pUsage; - - for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ - if( pTerm->leftCursor != pSrc->iCursor ) continue; - assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); - testcase( pTerm->eOperator==WO_IN ); - testcase( pTerm->eOperator==WO_ISNULL ); - if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; - pIdxCons[j].iColumn = pTerm->u.leftColumn; - pIdxCons[j].iTermOffset = i; - pIdxCons[j].op = (u8)pTerm->eOperator; - /* The direct assignment in the previous line is possible only because - ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The - ** following asserts verify this fact. */ - assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); - assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); - assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); - assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); - assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); - assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); - assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); - j++; - } - for(i=0; i<nOrderBy; i++){ - Expr *pExpr = pOrderBy->a[i].pExpr; - pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; - } + *ppIdxInfo = pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pOrderBy); + } + if( pIdxInfo==0 ){ + return; } /* At this point, the sqlite3_index_info structure that pIdxInfo points ** to will have been initialized, either during the current invocation or ** during some prior invocation. Now we just have to customize the @@ -82498,18 +85992,11 @@ /* The module name must be defined. Also, by this point there must ** be a pointer to an sqlite3_vtab structure. Otherwise ** sqlite3ViewGetColumnNames() would have picked up the error. */ assert( pTab->azModuleArg && pTab->azModuleArg[0] ); - assert( pVtab ); -#if 0 - if( pTab->pVtab==0 ){ - sqlite3ErrorMsg(pParse, "undefined module %s for table %s", - pTab->azModuleArg[0], pTab->zName); - return 0.0; - } -#endif + assert( sqlite3GetVTable(pParse->db, pTab) ); /* Set the aConstraint[].usable fields and initialize all ** output variables to zero. ** ** aConstraint[].usable is true for constraints where the right-hand @@ -82532,11 +86019,11 @@ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; pUsage = pIdxInfo->aConstraintUsage; for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ j = pIdxCons->iTermOffset; pTerm = &pWC->a[j]; - pIdxCons->usable = (pTerm->prereqRight & notReady)==0 ?1:0; + pIdxCons->usable = (pTerm->prereqRight¬Ready) ? 0 : 1; } memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } @@ -82545,46 +86032,257 @@ pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); nOrderBy = pIdxInfo->nOrderBy; - if( pIdxInfo->nOrderBy && !orderByUsable ){ - *(int*)&pIdxInfo->nOrderBy = 0; - } - - (void)sqlite3SafetyOff(pParse->db); - WHERETRACE(("xBestIndex for %s\n", pTab->zName)); - TRACE_IDX_INPUTS(pIdxInfo); - rc = pVtab->pModule->xBestIndex(pVtab, pIdxInfo); - TRACE_IDX_OUTPUTS(pIdxInfo); - (void)sqlite3SafetyOn(pParse->db); - - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ){ - pParse->db->mallocFailed = 1; - }else if( !pVtab->zErrMsg ){ - sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); - }else{ - sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); - } - } - sqlite3DbFree(pParse->db, pVtab->zErrMsg); - pVtab->zErrMsg = 0; - + if( !pOrderBy ){ + pIdxInfo->nOrderBy = 0; + } + + if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ + return; + } + + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++){ - if( !pIdxInfo->aConstraint[i].usable && pUsage[i].argvIndex>0 ){ - sqlite3ErrorMsg(pParse, - "table %s: xBestIndex returned an invalid plan", pTab->zName); - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - return (double)0; - } - } - - *(int*)&pIdxInfo->nOrderBy = nOrderBy; - return pIdxInfo->estimatedCost; + if( pUsage[i].argvIndex>0 ){ + pCost->used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight; + } + } + + /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the + ** inital value of lowestCost in this loop. If it is, then the + ** (cost<lowestCost) test below will never be true. + ** + ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT + ** is defined. + */ + if( (SQLITE_BIG_DBL/((double)2))<pIdxInfo->estimatedCost ){ + pCost->rCost = (SQLITE_BIG_DBL/((double)2)); + }else{ + pCost->rCost = pIdxInfo->estimatedCost; + } + pCost->plan.u.pVtabIdx = pIdxInfo; + if( pIdxInfo->orderByConsumed ){ + pCost->plan.wsFlags |= WHERE_ORDERBY; + } + pCost->plan.nEq = 0; + pIdxInfo->nOrderBy = nOrderBy; + + /* Try to find a more efficient access pattern by using multiple indexes + ** to optimize an OR expression within the WHERE clause. + */ + bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/* +** Argument pIdx is a pointer to an index structure that has an array of +** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column +** stored in Index.aSample. The domain of values stored in said column +** may be thought of as divided into (SQLITE_INDEX_SAMPLES+1) regions. +** Region 0 contains all values smaller than the first sample value. Region +** 1 contains values larger than or equal to the value of the first sample, +** but smaller than the value of the second. And so on. +** +** If successful, this function determines which of the regions value +** pVal lies in, sets *piRegion to the region index (a value between 0 +** and SQLITE_INDEX_SAMPLES+1, inclusive) and returns SQLITE_OK. +** Or, if an OOM occurs while converting text values between encodings, +** SQLITE_NOMEM is returned and *piRegion is undefined. +*/ +#ifdef SQLITE_ENABLE_STAT2 +static int whereRangeRegion( + Parse *pParse, /* Database connection */ + Index *pIdx, /* Index to consider domain of */ + sqlite3_value *pVal, /* Value to consider */ + int *piRegion /* OUT: Region of domain in which value lies */ +){ + if( ALWAYS(pVal) ){ + IndexSample *aSample = pIdx->aSample; + int i = 0; + int eType = sqlite3_value_type(pVal); + + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + double r = sqlite3_value_double(pVal); + for(i=0; i<SQLITE_INDEX_SAMPLES; i++){ + if( aSample[i].eType==SQLITE_NULL ) continue; + if( aSample[i].eType>=SQLITE_TEXT || aSample[i].u.r>r ) break; + } + }else{ + sqlite3 *db = pParse->db; + CollSeq *pColl; + const u8 *z; + int n; + + /* pVal comes from sqlite3ValueFromExpr() so the type cannot be NULL */ + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); + + if( eType==SQLITE_BLOB ){ + z = (const u8 *)sqlite3_value_blob(pVal); + pColl = db->pDfltColl; + assert( pColl->enc==SQLITE_UTF8 ); + }else{ + pColl = sqlite3GetCollSeq(db, SQLITE_UTF8, 0, *pIdx->azColl); + if( pColl==0 ){ + sqlite3ErrorMsg(pParse, "no such collation sequence: %s", + *pIdx->azColl); + return SQLITE_ERROR; + } + z = (const u8 *)sqlite3ValueText(pVal, pColl->enc); + if( !z ){ + return SQLITE_NOMEM; + } + assert( z && pColl && pColl->xCmp ); + } + n = sqlite3ValueBytes(pVal, pColl->enc); + + for(i=0; i<SQLITE_INDEX_SAMPLES; i++){ + int r; + int eSampletype = aSample[i].eType; + if( eSampletype==SQLITE_NULL || eSampletype<eType ) continue; + if( (eSampletype!=eType) ) break; + if( pColl->enc==SQLITE_UTF8 ){ + r = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z); + }else{ + int nSample; + char *zSample = sqlite3Utf8to16( + db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample + ); + if( !zSample ){ + assert( db->mallocFailed ); + return SQLITE_NOMEM; + } + r = pColl->xCmp(pColl->pUser, nSample, zSample, n, z); + sqlite3DbFree(db, zSample); + } + if( r>0 ) break; + } + } + + assert( i>=0 && i<=SQLITE_INDEX_SAMPLES ); + *piRegion = i; + } + return SQLITE_OK; +} +#endif /* #ifdef SQLITE_ENABLE_STAT2 */ + +/* +** This function is used to estimate the number of rows that will be visited +** by scanning an index for a range of values. The range may have an upper +** bound, a lower bound, or both. The WHERE clause terms that set the upper +** and lower bounds are represented by pLower and pUpper respectively. For +** example, assuming that index p is on t1(a): +** +** ... FROM t1 WHERE a > ? AND a < ? ... +** |_____| |_____| +** | | +** pLower pUpper +** +** If either of the upper or lower bound is not present, then NULL is passed in +** place of the corresponding WhereTerm. +** +** The nEq parameter is passed the index of the index column subject to the +** range constraint. Or, equivalently, the number of equality constraints +** optimized by the proposed index scan. For example, assuming index p is +** on t1(a, b), and the SQL query is: +** +** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... +** +** then nEq should be passed the value 1 (as the range restricted column, +** b, is the second left-most column of the index). Or, if the query is: +** +** ... FROM t1 WHERE a > ? AND a < ? ... +** +** then nEq should be passed 0. +** +** The returned value is an integer between 1 and 100, inclusive. A return +** value of 1 indicates that the proposed range scan is expected to visit +** approximately 1/100th (1%) of the rows selected by the nEq equality +** constraints (if any). A return value of 100 indicates that it is expected +** that the range scan will visit every row (100%) selected by the equality +** constraints. +** +** In the absence of sqlite_stat2 ANALYZE data, each range inequality +** reduces the search space by 2/3rds. Hence a single constraint (x>?) +** results in a return of 33 and a range constraint (x>? AND x<?) results +** in a return of 11. +*/ +static int whereRangeScanEst( + Parse *pParse, /* Parsing & code generating context */ + Index *p, /* The index containing the range-compared column; "x" */ + int nEq, /* index into p->aCol[] of the range-compared column */ + WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ + WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ + int *piEst /* OUT: Return value */ +){ + int rc = SQLITE_OK; + +#ifdef SQLITE_ENABLE_STAT2 + sqlite3 *db = pParse->db; + sqlite3_value *pLowerVal = 0; + sqlite3_value *pUpperVal = 0; + + if( nEq==0 && p->aSample ){ + int iEst; + int iLower = 0; + int iUpper = SQLITE_INDEX_SAMPLES; + u8 aff = p->pTable->aCol[0].affinity; + + if( pLower ){ + Expr *pExpr = pLower->pExpr->pRight; + rc = sqlite3ValueFromExpr(db, pExpr, SQLITE_UTF8, aff, &pLowerVal); + } + if( rc==SQLITE_OK && pUpper ){ + Expr *pExpr = pUpper->pExpr->pRight; + rc = sqlite3ValueFromExpr(db, pExpr, SQLITE_UTF8, aff, &pUpperVal); + } + + if( rc!=SQLITE_OK || (pLowerVal==0 && pUpperVal==0) ){ + sqlite3ValueFree(pLowerVal); + sqlite3ValueFree(pUpperVal); + goto range_est_fallback; + }else if( pLowerVal==0 ){ + rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper); + if( pLower ) iLower = iUpper/2; + }else if( pUpperVal==0 ){ + rc = whereRangeRegion(pParse, p, pLowerVal, &iLower); + if( pUpper ) iUpper = (iLower + SQLITE_INDEX_SAMPLES + 1)/2; + }else{ + rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper); + if( rc==SQLITE_OK ){ + rc = whereRangeRegion(pParse, p, pLowerVal, &iLower); + } + } + + iEst = iUpper - iLower; + testcase( iEst==SQLITE_INDEX_SAMPLES ); + assert( iEst<=SQLITE_INDEX_SAMPLES ); + if( iEst<1 ){ + iEst = 1; + } + + sqlite3ValueFree(pLowerVal); + sqlite3ValueFree(pUpperVal); + *piEst = (iEst * 100)/SQLITE_INDEX_SAMPLES; + return rc; + } +range_est_fallback: +#else + UNUSED_PARAMETER(pParse); + UNUSED_PARAMETER(p); + UNUSED_PARAMETER(nEq); +#endif + assert( pLower || pUpper ); + if( pLower && pUpper ){ + *piEst = 11; + }else{ + *piEst = 33; + } + return rc; +} + /* ** Find the query plan for accessing a particular table. Write the ** best query plan and its cost into the WhereCost object supplied as the ** last parameter. @@ -82610,352 +86308,356 @@ ** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table ** in the SELECT statement, then no indexes are considered. However, the ** selected plan may still take advantage of the tables built-in rowid ** index. */ -static void bestIndex( +static void bestBtreeIndex( Parse *pParse, /* The parsing context */ WhereClause *pWC, /* The WHERE clause */ struct SrcList_item *pSrc, /* The FROM clause term to search */ Bitmask notReady, /* Mask of cursors that are not available */ ExprList *pOrderBy, /* The ORDER BY clause */ WhereCost *pCost /* Lowest cost query plan */ ){ - WhereTerm *pTerm; /* A single term of the WHERE clause */ int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ Index *pProbe; /* An index we are evaluating */ - int rev; /* True to scan in reverse order */ - int wsFlags; /* Flags associated with pProbe */ - int nEq; /* Number of == or IN constraints */ - int eqTermMask; /* Mask of valid equality operators */ - double cost; /* Cost of using pProbe */ - double nRow; /* Estimated number of rows in result set */ - int i; /* Loop counter */ - Bitmask maskSrc; /* Bitmask for the pSrc table */ - - WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName,notReady)); - pProbe = pSrc->pTab->pIndex; - if( pSrc->notIndexed ){ - pProbe = 0; - } - - /* If the table has no indices and there are no terms in the where - ** clause that refer to the ROWID, then we will never be able to do - ** anything other than a full table scan on this table. We might as - ** well put it first in the join order. That way, perhaps it can be - ** referenced by other tables in the join. - */ - memset(pCost, 0, sizeof(*pCost)); - if( pProbe==0 && - findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 && - (pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){ - if( pParse->db->flags & SQLITE_ReverseOrder ){ - /* For application testing, randomly reverse the output order for - ** SELECT statements that omit the ORDER BY clause. This will help - ** to find cases where - */ - pCost->plan.wsFlags |= WHERE_REVERSE; - } - return; - } + Index *pIdx; /* Copy of pProbe, or zero for IPK index */ + int eqTermMask; /* Current mask of valid equality operators */ + int idxEqTermMask; /* Index mask of valid equality operators */ + Index sPk; /* A fake index object for the primary key */ + unsigned int aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ + int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ + int wsFlagMask; /* Allowed flags in pCost->plan.wsFlag */ + + /* Initialize the cost to a worst-case value */ + memset(pCost, 0, sizeof(*pCost)); pCost->rCost = SQLITE_BIG_DBL; - /* Check for a rowid=EXPR or rowid IN (...) constraints. If there was - ** an INDEXED BY clause attached to this table, skip this step. - */ - if( !pSrc->pIndex ){ - pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0); - if( pTerm ){ - Expr *pExpr; - pCost->plan.wsFlags = WHERE_ROWID_EQ; - if( pTerm->eOperator & WO_EQ ){ - /* Rowid== is always the best pick. Look no further. Because only - ** a single row is generated, output is always in sorted order */ - pCost->plan.wsFlags = WHERE_ROWID_EQ | WHERE_UNIQUE; - pCost->plan.nEq = 1; - WHERETRACE(("... best is rowid\n")); - pCost->rCost = 0; - pCost->nRow = 1; - return; - }else if( !ExprHasProperty((pExpr = pTerm->pExpr), EP_xIsSelect) - && pExpr->x.pList - ){ - /* Rowid IN (LIST): cost is NlogN where N is the number of list - ** elements. */ - pCost->rCost = pCost->nRow = pExpr->x.pList->nExpr; - pCost->rCost *= estLog(pCost->rCost); - }else{ - /* Rowid IN (SELECT): cost is NlogN where N is the number of rows - ** in the result of the inner select. We have no way to estimate - ** that value so make a wild guess. */ - pCost->nRow = 100; - pCost->rCost = 200; - } - WHERETRACE(("... rowid IN cost: %.9g\n", pCost->rCost)); - } - - /* Estimate the cost of a table scan. If we do not know how many - ** entries are in the table, use 1 million as a guess. - */ - cost = pProbe ? pProbe->aiRowEst[0] : 1000000; - WHERETRACE(("... table scan base cost: %.9g\n", cost)); - wsFlags = WHERE_ROWID_RANGE; - - /* Check for constraints on a range of rowids in a table scan. - */ - pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0); - if( pTerm ){ - if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){ - wsFlags |= WHERE_TOP_LIMIT; - cost /= 3; /* Guess that rowid<EXPR eliminates two-thirds of rows */ - } - if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){ - wsFlags |= WHERE_BTM_LIMIT; - cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */ - } - WHERETRACE(("... rowid range reduces cost to %.9g\n", cost)); - }else{ - wsFlags = 0; - } - nRow = cost; - - /* If the table scan does not satisfy the ORDER BY clause, increase - ** the cost by NlogN to cover the expense of sorting. */ - if( pOrderBy ){ - if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){ - wsFlags |= WHERE_ORDERBY|WHERE_ROWID_RANGE; - if( rev ){ - wsFlags |= WHERE_REVERSE; - } - }else{ - cost += cost*estLog(cost); - WHERETRACE(("... sorting increases cost to %.9g\n", cost)); - } - }else if( pParse->db->flags & SQLITE_ReverseOrder ){ - /* For application testing, randomly reverse the output order for - ** SELECT statements that omit the ORDER BY clause. This will help - ** to find cases where - */ - wsFlags |= WHERE_REVERSE; - } - - /* Remember this case if it is the best so far */ - if( cost<pCost->rCost ){ - pCost->rCost = cost; - pCost->nRow = nRow; - pCost->plan.wsFlags = wsFlags; - } - } - -#ifndef SQLITE_OMIT_OR_OPTIMIZATION - /* Search for an OR-clause that can be used to look up the table. - */ - maskSrc = getMask(pWC->pMaskSet, iCur); - for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ - WhereClause tempWC; - tempWC = *pWC; - if( pTerm->eOperator==WO_OR - && ((pTerm->prereqAll & ~maskSrc) & notReady)==0 - && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 ){ - WhereClause *pOrWC = &pTerm->u.pOrInfo->wc; - WhereTerm *pOrTerm; - int j; - int sortable = 0; - double rTotal = 0; - nRow = 0; - for(j=0, pOrTerm=pOrWC->a; j<pOrWC->nTerm; j++, pOrTerm++){ - WhereCost sTermCost; - WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", j,i)); - if( pOrTerm->eOperator==WO_AND ){ - WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc; - bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost); - }else if( pOrTerm->leftCursor==iCur ){ - tempWC.a = pOrTerm; - tempWC.nTerm = 1; - bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost); - }else{ - continue; - } - rTotal += sTermCost.rCost; - nRow += sTermCost.nRow; - if( rTotal>=pCost->rCost ) break; - } - if( pOrderBy!=0 ){ - if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) && !rev ){ - sortable = 1; - }else{ - rTotal += nRow*estLog(nRow); - WHERETRACE(("... sorting increases OR cost to %.9g\n", rTotal)); - } - } - WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", - rTotal, nRow)); - if( rTotal<pCost->rCost ){ - pCost->rCost = rTotal; - pCost->nRow = nRow; - pCost->plan.wsFlags = WHERE_MULTI_OR; - pCost->plan.u.pTerm = pTerm; - if( sortable ){ - pCost->plan.wsFlags = WHERE_ORDERBY|WHERE_MULTI_OR; - } - } - } - } -#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ - /* If the pSrc table is the right table of a LEFT JOIN then we may not ** use an index to satisfy IS NULL constraints on that table. This is ** because columns might end up being NULL if the table does not match - ** a circumstance which the index cannot help us discover. Ticket #2177. */ - if( (pSrc->jointype & JT_LEFT)!=0 ){ - eqTermMask = WO_EQ|WO_IN; - }else{ - eqTermMask = WO_EQ|WO_IN|WO_ISNULL; - } - - /* Look at each index. - */ + if( pSrc->jointype & JT_LEFT ){ + idxEqTermMask = WO_EQ|WO_IN; + }else{ + idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL; + } + if( pSrc->pIndex ){ - pProbe = pSrc->pIndex; - } - for(; pProbe; pProbe=(pSrc->pIndex ? 0 : pProbe->pNext)){ - double inMultiplier = 1; /* Number of equality look-ups needed */ - int inMultIsEst = 0; /* True if inMultiplier is an estimate */ - - WHERETRACE(("... index %s:\n", pProbe->zName)); - - /* Count the number of columns in the index that are satisfied - ** by x=EXPR constraints or x IN (...) constraints. For a term - ** of the form x=EXPR we only have to do a single binary search. - ** But for x IN (...) we have to do a number of binary searched - ** equal to the number of entries on the RHS of the IN operator. - ** The inMultipler variable with try to estimate the number of - ** binary searches needed. - */ - wsFlags = 0; - for(i=0; i<pProbe->nColumn; i++){ - int j = pProbe->aiColumn[i]; - pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pProbe); + /* An INDEXED BY clause specifies a particular index to use */ + pIdx = pProbe = pSrc->pIndex; + wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); + eqTermMask = idxEqTermMask; + }else{ + /* There is no INDEXED BY clause. Create a fake Index object to + ** represent the primary key */ + Index *pFirst; /* Any other index on the table */ + memset(&sPk, 0, sizeof(Index)); + sPk.nColumn = 1; + sPk.aiColumn = &aiColumnPk; + sPk.aiRowEst = aiRowEstPk; + aiRowEstPk[1] = 1; + sPk.onError = OE_Replace; + sPk.pTable = pSrc->pTab; + pFirst = pSrc->pTab->pIndex; + if( pSrc->notIndexed==0 ){ + sPk.pNext = pFirst; + } + /* The aiRowEstPk[0] is an estimate of the total number of rows in the + ** table. Get this information from the ANALYZE information if it is + ** available. If not available, assume the table 1 million rows in size. + */ + if( pFirst ){ + assert( pFirst->aiRowEst!=0 ); /* Allocated together with pFirst */ + aiRowEstPk[0] = pFirst->aiRowEst[0]; + }else{ + aiRowEstPk[0] = 1000000; + } + pProbe = &sPk; + wsFlagMask = ~( + WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE + ); + eqTermMask = WO_EQ|WO_IN; + pIdx = 0; + } + + /* Loop over all indices looking for the best one to use + */ + for(; pProbe; pIdx=pProbe=pProbe->pNext){ + const unsigned int * const aiRowEst = pProbe->aiRowEst; + double cost; /* Cost of using pProbe */ + double nRow; /* Estimated number of rows in result set */ + int rev; /* True to scan in reverse order */ + int wsFlags = 0; + Bitmask used = 0; + + /* The following variables are populated based on the properties of + ** scan being evaluated. They are then used to determine the expected + ** cost and number of rows returned. + ** + ** nEq: + ** Number of equality terms that can be implemented using the index. + ** + ** nInMul: + ** The "in-multiplier". This is an estimate of how many seek operations + ** SQLite must perform on the index in question. For example, if the + ** WHERE clause is: + ** + ** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6) + ** + ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is + ** set to 9. Given the same schema and either of the following WHERE + ** clauses: + ** + ** WHERE a = 1 + ** WHERE a >= 2 + ** + ** nInMul is set to 1. + ** + ** If there exists a WHERE term of the form "x IN (SELECT ...)", then + ** the sub-select is assumed to return 25 rows for the purposes of + ** determining nInMul. + ** + ** bInEst: + ** Set to true if there was at least one "x IN (SELECT ...)" term used + ** in determining the value of nInMul. + ** + ** nBound: + ** An estimate on the amount of the table that must be searched. A + ** value of 100 means the entire table is searched. Range constraints + ** might reduce this to a value less than 100 to indicate that only + ** a fraction of the table needs searching. In the absence of + ** sqlite_stat2 ANALYZE data, a single inequality reduces the search + ** space to 1/3rd its original size. So an x>? constraint reduces + ** nBound to 33. Two constraints (x>? AND x<?) reduce nBound to 11. + ** + ** bSort: + ** Boolean. True if there is an ORDER BY clause that will require an + ** external sort (i.e. scanning the index being evaluated will not + ** correctly order records). + ** + ** bLookup: + ** Boolean. True if for each index entry visited a lookup on the + ** corresponding table b-tree is required. This is always false + ** for the rowid index. For other indexes, it is true unless all the + ** columns of the table used by the SELECT statement are present in + ** the index (such an index is sometimes described as a covering index). + ** For example, given the index on (a, b), the second of the following + ** two queries requires table b-tree lookups, but the first does not. + ** + ** SELECT a, b FROM tbl WHERE a = 1; + ** SELECT a, b, c FROM tbl WHERE a = 1; + */ + int nEq; + int bInEst = 0; + int nInMul = 1; + int nBound = 100; + int bSort = 0; + int bLookup = 0; + + /* Determine the values of nEq and nInMul */ + for(nEq=0; nEq<pProbe->nColumn; nEq++){ + WhereTerm *pTerm; /* A single term of the WHERE clause */ + int j = pProbe->aiColumn[nEq]; + pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx); if( pTerm==0 ) break; - wsFlags |= WHERE_COLUMN_EQ; + wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ); if( pTerm->eOperator & WO_IN ){ Expr *pExpr = pTerm->pExpr; wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - inMultiplier *= 25; - inMultIsEst = 1; + nInMul *= 25; + bInEst = 1; }else if( pExpr->x.pList ){ - inMultiplier *= pExpr->x.pList->nExpr + 1; - } - } - } - nRow = pProbe->aiRowEst[i] * inMultiplier; - /* If inMultiplier is an estimate and that estimate results in an - ** nRow it that is more than half number of rows in the table, - ** then reduce inMultipler */ - if( inMultIsEst && nRow*2 > pProbe->aiRowEst[0] ){ - nRow = pProbe->aiRowEst[0]/2; - inMultiplier = nRow/pProbe->aiRowEst[i]; - } - cost = nRow + inMultiplier*estLog(pProbe->aiRowEst[0]); - nEq = i; - if( pProbe->onError!=OE_None && (wsFlags & WHERE_COLUMN_IN)==0 - && nEq==pProbe->nColumn ){ - wsFlags |= WHERE_UNIQUE; - } - WHERETRACE(("...... nEq=%d inMult=%.9g nRow=%.9g cost=%.9g\n", - nEq, inMultiplier, nRow, cost)); - - /* Look for range constraints. Assume that each range constraint - ** makes the search space 1/3rd smaller. - */ + nInMul *= pExpr->x.pList->nExpr + 1; + } + }else if( pTerm->eOperator & WO_ISNULL ){ + wsFlags |= WHERE_COLUMN_NULL; + } + used |= pTerm->prereqRight; + } + + /* Determine the value of nBound. */ if( nEq<pProbe->nColumn ){ int j = pProbe->aiColumn[nEq]; - pTerm = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe); - if( pTerm ){ - wsFlags |= WHERE_COLUMN_RANGE; - if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe) ){ + if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){ + WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx); + WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx); + whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &nBound); + if( pTop ){ wsFlags |= WHERE_TOP_LIMIT; - cost /= 3; - nRow /= 3; - } - if( findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe) ){ + used |= pTop->prereqRight; + } + if( pBtm ){ wsFlags |= WHERE_BTM_LIMIT; - cost /= 3; - nRow /= 3; - } - WHERETRACE(("...... range reduces nRow to %.9g and cost to %.9g\n", - nRow, cost)); - } - } - - /* Add the additional cost of sorting if that is a factor. - */ + used |= pBtm->prereqRight; + } + wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE); + } + }else if( pProbe->onError!=OE_None ){ + testcase( wsFlags & WHERE_COLUMN_IN ); + testcase( wsFlags & WHERE_COLUMN_NULL ); + if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ + wsFlags |= WHERE_UNIQUE; + } + } + + /* If there is an ORDER BY clause and the index being considered will + ** naturally scan rows in the required order, set the appropriate flags + ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index + ** will scan rows in a different order, set the bSort variable. */ if( pOrderBy ){ - if( (wsFlags & WHERE_COLUMN_IN)==0 && - isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){ - if( wsFlags==0 ){ - wsFlags = WHERE_COLUMN_RANGE; - } - wsFlags |= WHERE_ORDERBY; - if( rev ){ - wsFlags |= WHERE_REVERSE; - } - }else{ - cost += cost*estLog(cost); - WHERETRACE(("...... orderby increases cost to %.9g\n", cost)); - } - }else if( pParse->db->flags & SQLITE_ReverseOrder ){ - /* For application testing, randomly reverse the output order for - ** SELECT statements that omit the ORDER BY clause. This will help - ** to find cases where - */ - wsFlags |= WHERE_REVERSE; - } - - /* Check to see if we can get away with using just the index without - ** ever reading the table. If that is the case, then halve the - ** cost of this index. - */ - if( wsFlags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){ + if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 + && isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) + ){ + wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY; + wsFlags |= (rev ? WHERE_REVERSE : 0); + }else{ + bSort = 1; + } + } + + /* If currently calculating the cost of using an index (not the IPK + ** index), determine if all required column data may be obtained without + ** seeking to entries in the main table (i.e. if the index is a covering + ** index for this query). If it is, set the WHERE_IDX_ONLY flag in + ** wsFlags. Otherwise, set the bLookup variable to true. */ + if( pIdx && wsFlags ){ Bitmask m = pSrc->colUsed; int j; - for(j=0; j<pProbe->nColumn; j++){ - int x = pProbe->aiColumn[j]; + for(j=0; j<pIdx->nColumn; j++){ + int x = pIdx->aiColumn[j]; if( x<BMS-1 ){ m &= ~(((Bitmask)1)<<x); } } if( m==0 ){ wsFlags |= WHERE_IDX_ONLY; - cost /= 2; - WHERETRACE(("...... idx-only reduces cost to %.9g\n", cost)); - } - } - - /* If this index has achieved the lowest cost so far, then use it. - */ - if( wsFlags!=0 && cost < pCost->rCost ){ + }else{ + bLookup = 1; + } + } + + /**** Begin adding up the cost of using this index (Needs improvements) + ** + ** Estimate the number of rows of output. For an IN operator, + ** do not let the estimate exceed half the rows in the table. + */ + nRow = (double)(aiRowEst[nEq] * nInMul); + if( bInEst && nRow*2>aiRowEst[0] ){ + nRow = aiRowEst[0]/2; + nInMul = (int)(nRow / aiRowEst[nEq]); + } + + /* Assume constant cost to access a row and logarithmic cost to + ** do a binary search. Hence, the initial cost is the number of output + ** rows plus log2(table-size) times the number of binary searches. + */ + cost = nRow + nInMul*estLog(aiRowEst[0]); + + /* Adjust the number of rows and the cost downward to reflect rows + ** that are excluded by range constraints. + */ + nRow = (nRow * (double)nBound) / (double)100; + cost = (cost * (double)nBound) / (double)100; + + /* Add in the estimated cost of sorting the result + */ + if( bSort ){ + cost += cost*estLog(cost); + } + + /* If all information can be taken directly from the index, we avoid + ** doing table lookups. This reduces the cost by half. (Not really - + ** this needs to be fixed.) + */ + if( pIdx && bLookup==0 ){ + cost /= (double)2; + } + /**** Cost of using this index has now been computed ****/ + + WHERETRACE(( + "tbl=%s idx=%s nEq=%d nInMul=%d nBound=%d bSort=%d bLookup=%d" + " wsFlags=%d (nRow=%.2f cost=%.2f)\n", + pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"), + nEq, nInMul, nBound, bSort, bLookup, wsFlags, nRow, cost + )); + + /* If this index is the best we have seen so far, then record this + ** index and its cost in the pCost structure. + */ + if( (!pIdx || wsFlags) && cost<pCost->rCost ){ pCost->rCost = cost; pCost->nRow = nRow; - pCost->plan.wsFlags = wsFlags; + pCost->used = used; + pCost->plan.wsFlags = (wsFlags&wsFlagMask); pCost->plan.nEq = nEq; - assert( pCost->plan.wsFlags & WHERE_INDEXED ); - pCost->plan.u.pIdx = pProbe; - } - } - - /* Report the best result - */ + pCost->plan.u.pIdx = pIdx; + } + + /* If there was an INDEXED BY clause, then only that one index is + ** considered. */ + if( pSrc->pIndex ) break; + + /* Reset masks for the next index in the loop */ + wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); + eqTermMask = idxEqTermMask; + } + + /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag + ** is set, then reverse the order that the index will be scanned + ** in. This is used for application testing, to help find cases + ** where application behaviour depends on the (undefined) order that + ** SQLite outputs rows in in the absence of an ORDER BY clause. */ + if( !pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){ + pCost->plan.wsFlags |= WHERE_REVERSE; + } + + assert( pOrderBy || (pCost->plan.wsFlags&WHERE_ORDERBY)==0 ); + assert( pCost->plan.u.pIdx==0 || (pCost->plan.wsFlags&WHERE_ROWID_EQ)==0 ); + assert( pSrc->pIndex==0 + || pCost->plan.u.pIdx==0 + || pCost->plan.u.pIdx==pSrc->pIndex + ); + + WHERETRACE(("best index is: %s\n", + (pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk") + )); + + bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); pCost->plan.wsFlags |= eqTermMask; - WHERETRACE(("best index is %s, cost=%.9g, nrow=%.9g, wsFlags=%x, nEq=%d\n", - (pCost->plan.wsFlags & WHERE_INDEXED)!=0 ? - pCost->plan.u.pIdx->zName : "(none)", pCost->nRow, - pCost->rCost, pCost->plan.wsFlags, pCost->plan.nEq)); -} - +} + +/* +** Find the query plan for accessing table pSrc->pTab. Write the +** best query plan and its cost into the WhereCost object supplied +** as the last parameter. This function may calculate the cost of +** both real and virtual table scans. +*/ +static void bestIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + struct SrcList_item *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors that are not available */ + ExprList *pOrderBy, /* The ORDER BY clause */ + WhereCost *pCost /* Lowest cost query plan */ +){ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pSrc->pTab) ){ + sqlite3_index_info *p = 0; + bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, &p); + if( p->needToFreeIdxStr ){ + sqlite3_free(p->idxStr); + } + sqlite3DbFree(pParse->db, p); + }else +#endif + { + bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); + } +} /* ** Disable a term in the WHERE clause. Except, do not disable the term ** if it controls a LEFT OUTER JOIN and it did not originate in the ON ** or USING clause of that join. @@ -82992,21 +86694,23 @@ } } } /* -** Apply the affinities associated with the first n columns of index -** pIdx to the values in the n registers starting at base. -*/ -static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){ - if( n>0 ){ - Vdbe *v = pParse->pVdbe; - assert( v!=0 ); - sqlite3VdbeAddOp2(v, OP_Affinity, base, n); - sqlite3IndexAffinityStr(v, pIdx); - sqlite3ExprCacheAffinityChange(pParse, base, n); - } +** Code an OP_Affinity opcode to apply the column affinity string zAff +** to the n registers starting at base. +** +** Buffer zAff was allocated using sqlite3DbMalloc(). It is the +** responsibility of this function to arrange for it to be eventually +** freed using sqlite3DbFree(). +*/ +static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ + Vdbe *v = pParse->pVdbe; + assert( v!=0 ); + sqlite3VdbeAddOp2(v, OP_Affinity, base, n); + sqlite3VdbeChangeP4(v, -1, zAff, P4_DYNAMIC); + sqlite3ExprCacheAffinityChange(pParse, base, n); } /* ** Generate code for a single equality term of the WHERE clause. An equality @@ -83044,11 +86748,10 @@ assert( pX->op==TK_IN ); iReg = iTarget; eType = sqlite3FindInIndex(pParse, pX, 0); iTab = pX->iTable; sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); - VdbeComment((v, "%.*s", pX->span.n, pX->span.z)); assert( pLevel->plan.wsFlags & WHERE_IN_ABLE ); if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite3VdbeMakeLabel(v); } pLevel->u.in.nIn++; @@ -83094,26 +86797,43 @@ ** the index of that memory cell. The code that ** calls this routine will use that memory cell to store the termination ** key value of the loop. If one or more IN operators appear, then ** this routine allocates an additional nEq memory cells for internal ** use. +** +** Before returning, *pzAff is set to point to a buffer containing a +** copy of the column affinity string of the index allocated using +** sqlite3DbMalloc(). Except, entries in the copy of the string associated +** with equality constraints that use NONE affinity are set to +** SQLITE_AFF_NONE. This is to deal with SQL such as the following: +** +** CREATE TABLE t1(a TEXT PRIMARY KEY, b); +** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b; +** +** In the example above, the index on t1(a) has TEXT affinity. But since +** the right hand side of the equality constraint (t2.b) has NONE affinity, +** no conversion should be attempted before using a t2.b value as part of +** a key to search the index. Hence the first byte in the returned affinity +** string in this example would be set to SQLITE_AFF_NONE. */ static int codeAllEqualityTerms( Parse *pParse, /* Parsing context */ WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ WhereClause *pWC, /* The WHERE clause */ Bitmask notReady, /* Which parts of FROM have not yet been coded */ - int nExtraReg /* Number of extra registers to allocate */ + int nExtraReg, /* Number of extra registers to allocate */ + char **pzAff /* OUT: Set to point to affinity string */ ){ int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */ Vdbe *v = pParse->pVdbe; /* The vm under construction */ Index *pIdx; /* The index being used for this loop */ int iCur = pLevel->iTabCur; /* The cursor of the table */ WhereTerm *pTerm; /* A single constraint term */ int j; /* Loop counter */ int regBase; /* Base register */ int nReg; /* Number of registers to allocate */ + char *zAff; /* Affinity string to return */ /* This module is only called on query plans that use an index. */ assert( pLevel->plan.wsFlags & WHERE_INDEXED ); pIdx = pLevel->plan.u.pIdx; @@ -83120,10 +86840,15 @@ /* Figure out how many memory cells we will need then allocate them. */ regBase = pParse->nMem + 1; nReg = pLevel->plan.nEq + nExtraReg; pParse->nMem += nReg; + + zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx)); + if( !zAff ){ + pParse->db->mallocFailed = 1; + } /* Evaluate the equality constraints */ assert( pIdx->nColumn>=nEq ); for(j=0; j<nEq; j++){ @@ -83143,42 +86868,29 @@ } testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_IN ); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); - } - } - return regBase; -} - -/* -** Return TRUE if the WhereClause pWC contains no terms that -** are not virtual and which have not been coded. -** -** To put it another way, return TRUE if no additional WHERE clauses -** tests are required in order to establish that the current row -** should go to output and return FALSE if there are some terms of -** the WHERE clause that need to be validated before outputing the row. -*/ -static int whereRowReadyForOutput(WhereClause *pWC){ - WhereTerm *pTerm; - int j; - - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - if( (pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED))==0 ) return 0; - } - return 1; + if( zAff + && sqlite3CompareAffinity(pTerm->pExpr->pRight, zAff[j])==SQLITE_AFF_NONE + ){ + zAff[j] = SQLITE_AFF_NONE; + } + } + } + *pzAff = zAff; + return regBase; } /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ static Bitmask codeOneLoopStart( WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ - u8 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ + u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ Bitmask notReady /* Which tables are currently available */ ){ int j, k; /* Loop counters */ int iCur; /* The VDBE cursor for the table */ int addrNxt; /* Where to jump to continue with the next IN case */ @@ -83190,24 +86902,22 @@ Parse *pParse; /* Parsing context */ Vdbe *v; /* The prepared stmt under constructions */ struct SrcList_item *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ int addrCont; /* Jump here to continue with next cycle */ - int regRowSet; /* Write rowids to this RowSet if non-negative */ - int codeRowSetEarly; /* True if index fully constrains the search */ - + int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ + int iReleaseReg = 0; /* Temp register to free before returning */ pParse = pWInfo->pParse; v = pParse->pVdbe; pWC = pWInfo->pWC; pLevel = &pWInfo->a[iLevel]; pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; iCur = pTabItem->iCursor; bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0; - omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0; - regRowSet = pWInfo->regRowSet; - codeRowSetEarly = 0; + omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 + && (wctrlFlags & WHERE_FORCE_TABLE)==0; /* Create labels for the "break" and "continue" instructions ** for the current loop. Jump to addrBrk to break out of a loop. ** Jump to cont to go immediately to the next iteration of the ** loop. @@ -83242,24 +86952,20 @@ pVtabIdx->aConstraintUsage; const struct sqlite3_index_constraint *aConstraint = pVtabIdx->aConstraint; iReg = sqlite3GetTempRange(pParse, nConstraint+2); - pParse->disableColCache++; for(j=1; j<=nConstraint; j++){ for(k=0; k<nConstraint; k++){ if( aUsage[k].argvIndex==j ){ int iTerm = aConstraint[k].iTermOffset; - assert( pParse->disableColCache ); sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1); break; } } if( k==nConstraint ) break; } - assert( pParse->disableColCache ); - pParse->disableColCache--; sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr, pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); pVtabIdx->needToFreeIdxStr = 0; @@ -83270,15 +86976,10 @@ } } pLevel->op = OP_VNext; pLevel->p1 = iCur; pLevel->p2 = sqlite3VdbeCurrentAddr(v); - codeRowSetEarly = regRowSet>=0 ? whereRowReadyForOutput(pWC) : 0; - if( codeRowSetEarly ){ - sqlite3VdbeAddOp2(v, OP_VRowid, iCur, iReg); - sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, iReg); - } sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ if( pLevel->plan.wsFlags & WHERE_ROWID_EQ ){ @@ -83285,26 +86986,21 @@ /* Case 1: We can directly reference a single row using an ** equality comparison against the ROWID field. Or ** we reference multiple rows using a "rowid IN (...)" ** construct. */ - int r1; - int rtmp = sqlite3GetTempReg(pParse); + iReleaseReg = sqlite3GetTempReg(pParse); pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0); assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( pTerm->leftCursor==iCur ); assert( omitTable==0 ); - r1 = codeEqualityTerm(pParse, pTerm, pLevel, rtmp); + iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg); addrNxt = pLevel->addrNxt; - sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, addrNxt); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, r1); - codeRowSetEarly = (pWC->nTerm==1 && regRowSet>=0) ?1:0; - if( codeRowSetEarly ){ - sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1); - } - sqlite3ReleaseTempReg(pParse, rtmp); + sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); VdbeComment((v, "pk")); pLevel->op = OP_Noop; }else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){ /* Case 2: We have an inequality comparison against the ROWID field. */ @@ -83367,22 +87063,16 @@ start = sqlite3VdbeCurrentAddr(v); pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iCur; pLevel->p2 = start; pLevel->p5 = (pStart==0 && pEnd==0) ?1:0; - codeRowSetEarly = regRowSet>=0 ? whereRowReadyForOutput(pWC) : 0; - if( codeRowSetEarly || testOp!=OP_Noop ){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); - if( testOp!=OP_Noop ){ - sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, r1); - sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); - } - if( codeRowSetEarly ){ - sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1); - } - sqlite3ReleaseTempReg(pParse, r1); + if( testOp!=OP_Noop ){ + iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); + sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){ /* Case 3: A scan using an index. ** ** The WHERE clause may contain zero or more equality @@ -83441,10 +87131,11 @@ int nConstraint; /* Number of constraint terms */ Index *pIdx; /* The index we will be using */ int iIdxCur; /* The VDBE cursor for the index */ int nExtraReg = 0; /* Number of extra registers needed */ int op; /* Instruction opcode */ + char *zAff; pIdx = pLevel->plan.u.pIdx; iIdxCur = pLevel->iIdxCur; k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */ @@ -83480,13 +87171,14 @@ /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers ** starting at regBase. */ - regBase = codeAllEqualityTerms(pParse, pLevel, pWC, notReady, nExtraReg); - addrNxt = pLevel->addrNxt; - + regBase = codeAllEqualityTerms( + pParse, pLevel, pWC, notReady, nExtraReg, &zAff + ); + addrNxt = pLevel->addrNxt; /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). */ @@ -83503,25 +87195,29 @@ start_constraints = pRangeStart || nEq>0; /* Seek the index cursor to the start of the range. */ nConstraint = nEq; if( pRangeStart ){ - int dcc = pParse->disableColCache; - if( pRangeEnd ){ - pParse->disableColCache++; - } - sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq); - pParse->disableColCache = dcc; + Expr *pRight = pRangeStart->pExpr->pRight; + sqlite3ExprCode(pParse, pRight, regBase+nEq); sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); + if( zAff + && sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE + ){ + /* Since the comparison is to be performed with no conversions applied + ** to the operands, set the affinity to apply to pRight to + ** SQLITE_AFF_NONE. */ + zAff[nConstraint] = SQLITE_AFF_NONE; + } nConstraint++; }else if( isMinQuery ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); nConstraint++; startEq = 0; start_constraints = 1; } - codeApplyAffinity(pParse, regBase, nConstraint, pIdx); + codeApplyAffinity(pParse, regBase, nConstraint, zAff); op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); testcase( op==OP_Rewind ); testcase( op==OP_Last ); testcase( op==OP_SeekGt ); @@ -83534,13 +87230,24 @@ /* Load the value for the inequality constraint at the end of the ** range (if any). */ nConstraint = nEq; if( pRangeEnd ){ - sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq); + Expr *pRight = pRangeEnd->pExpr->pRight; + sqlite3ExprCacheRemove(pParse, regBase+nEq); + sqlite3ExprCode(pParse, pRight, regBase+nEq); sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); - codeApplyAffinity(pParse, regBase, nEq+1, pIdx); + zAff = sqlite3DbStrDup(pParse->db, zAff); + if( zAff + && sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE + ){ + /* Since the comparison is to be performed with no conversions applied + ** to the operands, set the affinity to apply to pRight to + ** SQLITE_AFF_NONE. */ + zAff[nConstraint] = SQLITE_AFF_NONE; + } + codeApplyAffinity(pParse, regBase, nEq+1, zAff); nConstraint++; } /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); @@ -83565,24 +87272,21 @@ testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ); if( pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1); sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont); } + sqlite3ReleaseTempReg(pParse, r1); /* Seek the table cursor, if required */ disableTerm(pLevel, pRangeStart); disableTerm(pLevel, pRangeEnd); - codeRowSetEarly = regRowSet>=0 ? whereRowReadyForOutput(pWC) : 0; - if( !omitTable || codeRowSetEarly ){ - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1); - if( codeRowSetEarly ){ - sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1); - }else{ - sqlite3VdbeAddOp2(v, OP_Seek, iCur, r1); /* Deferred seek */ - } - } - sqlite3ReleaseTempReg(pParse, r1); + if( !omitTable ){ + iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ + } /* Record the instruction used to terminate the loop. Disable ** WHERE clause terms made redundant by the index range scan. */ pLevel->op = bRev ? OP_Prev : OP_Next; @@ -83601,70 +87305,109 @@ ** CREATE INDEX i3 ON t1(c); ** ** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13) ** ** In the example, there are three indexed terms connected by OR. - ** The top of the loop is constructed by creating a RowSet object - ** and populating it. Then looping over elements of the rowset. - ** - ** Null 1 - ** # fill RowSet 1 with entries where a=5 using i1 - ** # fill Rowset 1 with entries where b=7 using i2 - ** # fill Rowset 1 with entries where c=11 and d=13 i3 and t1 - ** A: RowSetRead 1, B, 2 - ** Seek i, 2 - ** - ** The bottom of the loop looks like this: - ** - ** Goto 0, A - ** B: - */ - int regOrRowset; /* Register holding the RowSet object */ - int regNextRowid; /* Register holding next rowid */ + ** The top of the loop looks like this: + ** + ** Null 1 # Zero the rowset in reg 1 + ** + ** Then, for each indexed term, the following. The arguments to + ** RowSetTest are such that the rowid of the current row is inserted + ** into the RowSet. If it is already present, control skips the + ** Gosub opcode and jumps straight to the code generated by WhereEnd(). + ** + ** sqlite3WhereBegin(<term>) + ** RowSetTest # Insert rowid into rowset + ** Gosub 2 A + ** sqlite3WhereEnd() + ** + ** Following the above, code to terminate the loop. Label A, the target + ** of the Gosub above, jumps to the instruction right after the Goto. + ** + ** Null 1 # Zero the rowset in reg 1 + ** Goto B # The loop is finished. + ** + ** A: <loop body> # Return data, whatever. + ** + ** Return 2 # Jump back to the Gosub + ** + ** B: <after the loop> + ** + */ WhereClause *pOrWc; /* The OR-clause broken out into subterms */ - WhereTerm *pOrTerm; /* A single subterm within the OR-clause */ + WhereTerm *pFinal; /* Final subterm within the OR-clause. */ SrcList oneTab; /* Shortened table list */ + + int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ + int regRowset = 0; /* Register for RowSet object */ + int regRowid = 0; /* Register holding rowid */ + int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */ + int iRetInit; /* Address of regReturn init */ + int ii; pTerm = pLevel->plan.u.pTerm; assert( pTerm!=0 ); assert( pTerm->eOperator==WO_OR ); assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); pOrWc = &pTerm->u.pOrInfo->wc; - codeRowSetEarly = (regRowSet>=0 && pWC->nTerm==1) ?1:0; - - if( codeRowSetEarly ){ - regOrRowset = regRowSet; - }else{ - regOrRowset = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, regOrRowset); - } + pFinal = &pOrWc->a[pOrWc->nTerm-1]; + + /* Set up a SrcList containing just the table being scanned by this loop. */ oneTab.nSrc = 1; oneTab.nAlloc = 1; oneTab.a[0] = *pTabItem; - for(j=0, pOrTerm=pOrWc->a; j<pOrWc->nTerm; j++, pOrTerm++){ - WhereInfo *pSubWInfo; - if( pOrTerm->leftCursor!=iCur && pOrTerm->eOperator!=WO_AND ) continue; - pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0, - WHERE_FILL_ROWSET | WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE, - regOrRowset); - if( pSubWInfo ){ - sqlite3WhereEnd(pSubWInfo); - } - } - sqlite3VdbeResolveLabel(v, addrCont); - if( !codeRowSetEarly ){ - regNextRowid = sqlite3GetTempReg(pParse); - addrCont = - sqlite3VdbeAddOp3(v, OP_RowSetRead, regOrRowset,addrBrk,regNextRowid); - sqlite3VdbeAddOp2(v, OP_Seek, iCur, regNextRowid); - sqlite3ReleaseTempReg(pParse, regNextRowid); - /* sqlite3ReleaseTempReg(pParse, regOrRowset); // Preserve the RowSet */ - pLevel->op = OP_Goto; - pLevel->p2 = addrCont; - }else{ - pLevel->op = OP_Noop; - } + + /* Initialize the rowset register to contain NULL. An SQL NULL is + ** equivalent to an empty rowset. + ** + ** Also initialize regReturn to contain the address of the instruction + ** immediately following the OP_Return at the bottom of the loop. This + ** is required in a few obscure LEFT JOIN cases where control jumps + ** over the top of the loop into the body of it. In this case the + ** correct response for the end-of-loop code (the OP_Return) is to + ** fall through to the next instruction, just as an OP_Next does if + ** called on an uninitialized cursor. + */ + if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ + regRowset = ++pParse->nMem; + regRowid = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); + } + iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); + + for(ii=0; ii<pOrWc->nTerm; ii++){ + WhereTerm *pOrTerm = &pOrWc->a[ii]; + if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){ + WhereInfo *pSubWInfo; /* Info for single OR-term scan */ + /* Loop through table entries that match term pOrTerm. */ + pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0, + WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE); + if( pSubWInfo ){ + if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ + int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); + int r; + r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, + regRowid, 0); + sqlite3VdbeAddOp4(v, OP_RowSetTest, regRowset, + sqlite3VdbeCurrentAddr(v)+2, + r, SQLITE_INT_TO_PTR(iSet), P4_INT32); + } + sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); + + /* Finish the loop through table entries that match term pOrTerm. */ + sqlite3WhereEnd(pSubWInfo); + } + } + } + sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); + /* sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); + sqlite3VdbeResolveLabel(v, iLoopBody); + + pLevel->op = OP_Return; + pLevel->p1 = regReturn; disableTerm(pLevel, pTerm); }else #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ { @@ -83677,11 +87420,10 @@ assert( omitTable==0 ); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; - codeRowSetEarly = 0; } notReady &= ~getMask(pWC->pMaskSet, iCur); /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. @@ -83696,13 +87438,11 @@ pE = pTerm->pExpr; assert( pE!=0 ); if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } - pParse->disableColCache += k; - sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); - pParse->disableColCache -= k; + sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); k = 1; pTerm->wtFlags |= TERM_CODED; } /* For a LEFT OUTER JOIN, generate code that will record the fact that @@ -83710,12 +87450,11 @@ */ if( pLevel->iLeftJoin ){ pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); - sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur); - sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur); + sqlite3ExprCacheClear(pParse); for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ) continue; @@ -83722,28 +87461,11 @@ assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } } - - /* - ** If it was requested to store the results in a rowset and that has - ** not already been do, then do so now. - */ - if( regRowSet>=0 && !codeRowSetEarly ){ - int r1 = sqlite3GetTempReg(pParse); -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - sqlite3VdbeAddOp2(v, OP_VRowid, iCur, r1); - }else -#endif - { - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); - } - sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1); - sqlite3ReleaseTempReg(pParse, r1); - } + sqlite3ReleaseTempReg(pParse, iReleaseReg); return notReady; } #if defined(SQLITE_TEST) @@ -83766,11 +87488,11 @@ if( pWInfo ){ int i; for(i=0; i<pWInfo->nLevel; i++){ sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo; if( pInfo ){ - assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); + /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */ if( pInfo->needToFreeIdxStr ){ sqlite3_free(pInfo->idxStr); } sqlite3DbFree(db, pInfo); } @@ -83872,12 +87594,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ - u8 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ - int regRowSet /* Register hold RowSet if WHERE_FILL_ROWSET is set */ + u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */ ){ int i; /* Loop counter */ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ WhereInfo *pWInfo; /* Will become the return value of this function */ Vdbe *v = pParse->pVdbe; /* The virtual database engine */ @@ -83887,22 +87608,17 @@ struct SrcList_item *pTabItem; /* A single entry from pTabList */ WhereLevel *pLevel; /* A single level in the pWInfo list */ int iFrom; /* First unused FROM clause element */ int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */ sqlite3 *db; /* Database connection */ - ExprList *pOrderBy = 0; /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ if( pTabList->nSrc>BMS ){ sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); return 0; - } - - if( ppOrderBy ){ - pOrderBy = *ppOrderBy; } /* Allocate and initialize the WhereInfo structure that will become the ** return value. A single allocation is used to store the WhereInfo ** struct, the contents of WhereInfo.a[], the WhereClause structure @@ -83922,11 +87638,10 @@ } pWInfo->nLevel = pTabList->nSrc; pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); - pWInfo->regRowSet = (wctrlFlags & WHERE_FILL_ROWSET) ? regRowSet : -1; pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo]; pWInfo->wctrlFlags = wctrlFlags; pMaskSet = (WhereMaskSet*)&pWC[1]; /* Split the WHERE clause into separate subexpressions where each @@ -83953,13 +87668,24 @@ ** is (X-1). An expression from the ON clause of a LEFT JOIN can use ** its Expr.iRightJoinTable value to find the bitmask of the right table ** of the join. Subtracting one from the right table bitmask gives a ** bitmask for all tables to the left of the join. Knowing the bitmask ** for all tables to the left of a left join is important. Ticket #3015. - */ + ** + ** Configure the WhereClause.vmask variable so that bits that correspond + ** to virtual table cursors are set. This is used to selectively disable + ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful + ** with virtual tables. + */ + assert( pWC->vmask==0 && pMaskSet->n==0 ); for(i=0; i<pTabList->nSrc; i++){ createMask(pMaskSet, pTabList->a[i].iCursor); +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( ALWAYS(pTabList->a[i].pTab) && IsVirtual(pTabList->a[i].pTab) ){ + pWC->vmask |= ((Bitmask)1 << i); + } +#endif } #ifndef NDEBUG { Bitmask toTheLeft = 0; for(i=0; i<pTabList->nSrc; i++){ @@ -84002,64 +87728,88 @@ WHERETRACE(("*** Optimizer Start ***\n")); for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){ WhereCost bestPlan; /* Most efficient plan seen so far */ Index *pIdx; /* Index for FROM table at pTabItem */ int j; /* For looping over FROM tables */ - int bestJ = 0; /* The value of j */ + int bestJ = -1; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ - int once = 0; /* True when first table is seen */ + int isOptimal; /* Iterator for optimal/non-optimal search */ memset(&bestPlan, 0, sizeof(bestPlan)); bestPlan.rCost = SQLITE_BIG_DBL; - for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){ - int doNotReorder; /* True if this table should not be reordered */ - WhereCost sCost; /* Cost information from bestIndex() */ - - doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0; - if( once && doNotReorder ) break; - m = getMask(pMaskSet, pTabItem->iCursor); - if( (m & notReady)==0 ){ - if( j==iFrom ) iFrom++; - continue; - } - assert( pTabItem->pTab ); + + /* Loop through the remaining entries in the FROM clause to find the + ** next nested loop. The FROM clause entries may be iterated through + ** either once or twice. + ** + ** The first iteration, which is always performed, searches for the + ** FROM clause entry that permits the lowest-cost, "optimal" scan. In + ** this context an optimal scan is one that uses the same strategy + ** for the given FROM clause entry as would be selected if the entry + ** were used as the innermost nested loop. In other words, a table + ** is chosen such that the cost of running that table cannot be reduced + ** by waiting for other tables to run first. + ** + ** The second iteration is only performed if no optimal scan strategies + ** were found by the first. This iteration is used to search for the + ** lowest cost scan overall. + ** + ** Previous versions of SQLite performed only the second iteration - + ** the next outermost loop was always that with the lowest overall + ** cost. However, this meant that SQLite could select the wrong plan + ** for scripts such as the following: + ** + ** CREATE TABLE t1(a, b); + ** CREATE TABLE t2(c, d); + ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a; + ** + ** The best strategy is to iterate through table t1 first. However it + ** is not possible to determine this with a simple greedy algorithm. + ** However, since the cost of a linear scan through table t2 is the same + ** as the cost of a linear scan through table t1, a simple greedy + ** algorithm may choose to use t2 for the outer loop, which is a much + ** costlier approach. + */ + for(isOptimal=1; isOptimal>=0 && bestJ<0; isOptimal--){ + Bitmask mask = (isOptimal ? 0 : notReady); + assert( (pTabList->nSrc-iFrom)>1 || isOptimal ); + for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){ + int doNotReorder; /* True if this table should not be reordered */ + WhereCost sCost; /* Cost information from best[Virtual]Index() */ + ExprList *pOrderBy; /* ORDER BY clause for index to optimize */ + + doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0; + if( j!=iFrom && doNotReorder ) break; + m = getMask(pMaskSet, pTabItem->iCursor); + if( (m & notReady)==0 ){ + if( j==iFrom ) iFrom++; + continue; + } + pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); + + assert( pTabItem->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTabItem->pTab) ){ - sqlite3_index_info *pVtabIdx; /* Current virtual index */ - sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo; - sCost.rCost = bestVirtualIndex(pParse, pWC, pTabItem, notReady, - ppOrderBy ? *ppOrderBy : 0, i==0, - ppIdxInfo); - sCost.plan.wsFlags = WHERE_VIRTUALTABLE; - sCost.plan.u.pVtabIdx = pVtabIdx = *ppIdxInfo; - if( pVtabIdx && pVtabIdx->orderByConsumed ){ - sCost.plan.wsFlags = WHERE_VIRTUALTABLE | WHERE_ORDERBY; - } - sCost.plan.nEq = 0; - /* (double)2 In case of SQLITE_OMIT_FLOATING_POINT... */ - if( (SQLITE_BIG_DBL/((double)2))<sCost.rCost ){ - /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the - ** inital value of lowestCost in this loop. If it is, then - ** the (cost<lowestCost) test below will never be true. - */ - /* (double)2 In case of SQLITE_OMIT_FLOATING_POINT... */ - sCost.rCost = (SQLITE_BIG_DBL/((double)2)); - } - }else -#endif - { - bestIndex(pParse, pWC, pTabItem, notReady, - (i==0 && ppOrderBy) ? *ppOrderBy : 0, &sCost); - } - if( once==0 || sCost.rCost<bestPlan.rCost ){ - once = 1; - bestPlan = sCost; - bestJ = j; - } - if( doNotReorder ) break; - } - assert( once ); + if( IsVirtual(pTabItem->pTab) ){ + sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo; + bestVirtualIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost, pp); + }else +#endif + { + bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost); + } + assert( isOptimal || (sCost.used¬Ready)==0 ); + + if( (sCost.used¬Ready)==0 + && (j==iFrom || sCost.rCost<bestPlan.rCost) + ){ + bestPlan = sCost; + bestJ = j; + } + if( doNotReorder ) break; + } + } + assert( bestJ>=0 ); assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) ); WHERETRACE(("*** Optimizer selects table %d for loop %d\n", bestJ, pLevel-pWInfo->a)); if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){ *ppOrderBy = 0; @@ -84091,11 +87841,11 @@ assert( bestPlan.plan.u.pIdx==pIdx ); } } } WHERETRACE(("*** Optimizer Finished ***\n")); - if( db->mallocFailed ){ + if( pParse->nErr || db->mallocFailed ){ goto whereBeginError; } /* If the total query only selects a single row, then the ORDER BY ** clause is irrelevant. @@ -84152,17 +87902,17 @@ sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC); } #endif /* SQLITE_OMIT_EXPLAIN */ pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue; #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ + const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; - sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, - (const char*)pTab->pVtab, P4_VTAB); + sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); }else #endif if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 && (wctrlFlags & WHERE_OMIT_OPEN)==0 ){ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; @@ -84274,11 +88024,11 @@ SrcList *pTabList = pWInfo->pTabList; sqlite3 *db = pParse->db; /* Generate loop termination code. */ - sqlite3ExprClearColumnCache(pParse, -1); + sqlite3ExprCacheClear(pParse); for(i=pTabList->nSrc-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqlite3VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); @@ -84301,11 +88051,15 @@ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); if( pLevel->iIdxCur>=0 ){ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } - sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst); + if( pLevel->op==OP_Return ){ + sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); + }else{ + sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst); + } sqlite3VdbeJumpHere(v, addr); } } /* The "break" point is here, just past the end of the outer loop. @@ -84340,11 +88094,11 @@ ** sqlite3WhereEnd will have created code that references the table ** directly. This loop scans all that code looking for opcodes ** that reference the table and converts them into opcodes that ** reference the index. */ - if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){ + if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 && !db->mallocFailed){ int k, j, last; VdbeOp *pOp; Index *pIdx = pLevel->plan.u.pIdx; int useIndexOnly = pLevel->plan.wsFlags & WHERE_IDX_ONLY; @@ -84380,14 +88134,31 @@ /************** End of where.c ***********************************************/ /************** Begin file parse.c *******************************************/ /* Driver template for the LEMON parser generator. ** The author disclaims copyright to this source code. +** +** This version of "lempar.c" is modified, slightly, for use by SQLite. +** The only modifications are the addition of a couple of NEVER() +** macros to disable tests that are needed in the case of a general +** LALR(1) grammar but which are always false in the +** specific grammar used by SQLite. */ /* First off, code is included that follows the "include" declaration ** in the input grammar file. */ + +/* +** Disable all error recovery processing in the parser push-down +** automaton. +*/ +#define YYNOERRORRECOVERY 1 + +/* +** Make yytestcase() the same as testcase() +*/ +#define yytestcase(X) testcase(X) /* ** An instance of this structure holds information about the ** LIMIT clause of a SELECT statement. */ @@ -84419,10 +88190,72 @@ /* ** An instance of this structure holds the ATTACH key and the key type. */ struct AttachKey { int type; Token key; }; + + /* This is a utility routine used to set the ExprSpan.zStart and + ** ExprSpan.zEnd values of pOut so that the span covers the complete + ** range of text beginning with pStart and going to the end of pEnd. + */ + static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){ + pOut->zStart = pStart->z; + pOut->zEnd = &pEnd->z[pEnd->n]; + } + + /* Construct a new Expr object from a single identifier. Use the + ** new Expr to populate pOut. Set the span of pOut to be the identifier + ** that created the expression. + */ + static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){ + pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, pValue); + pOut->zStart = pValue->z; + pOut->zEnd = &pValue->z[pValue->n]; + } + + /* This routine constructs a binary expression node out of two ExprSpan + ** objects and uses the result to populate a new ExprSpan object. + */ + static void spanBinaryExpr( + ExprSpan *pOut, /* Write the result here */ + Parse *pParse, /* The parsing context. Errors accumulate here */ + int op, /* The binary operation */ + ExprSpan *pLeft, /* The left operand */ + ExprSpan *pRight /* The right operand */ + ){ + pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); + pOut->zStart = pLeft->zStart; + pOut->zEnd = pRight->zEnd; + } + + /* Construct an expression node for a unary postfix operator + */ + static void spanUnaryPostfix( + ExprSpan *pOut, /* Write the new expression node here */ + Parse *pParse, /* Parsing context to record errors */ + int op, /* The operator */ + ExprSpan *pOperand, /* The operand */ + Token *pPostOp /* The operand token for setting the span */ + ){ + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); + pOut->zStart = pOperand->zStart; + pOut->zEnd = &pPostOp->z[pPostOp->n]; + } + + /* Construct an expression node for a unary prefix operator + */ + static void spanUnaryPrefix( + ExprSpan *pOut, /* Write the new expression node here */ + Parse *pParse, /* Parsing context to record errors */ + int op, /* The operator */ + ExprSpan *pOperand, /* The operand */ + Token *pPreOp /* The operand token for setting the span */ + ){ + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); + pOut->zStart = pPreOp->z; + pOut->zEnd = pOperand->zEnd; + } /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ /* ** These constants (all generated automatically by the parser generator) @@ -84468,47 +88301,61 @@ ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. */ -#define YYCODETYPE unsigned short int -#define YYNOCODE 252 +#define YYCODETYPE unsigned char +#define YYNOCODE 254 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 65 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - Expr* yy72; - TriggerStep* yy145; - ExprList* yy148; - SrcList* yy185; - int yy194; - Select* yy243; - IdList* yy254; - struct TrigEvent yy332; - struct LimitVal yy354; - struct LikeOp yy392; - struct {int value; int mask;} yy497; + Select* yy3; + ExprList* yy14; + SrcList* yy65; + struct LikeOp yy96; + Expr* yy132; + u8 yy186; + int yy328; + ExprSpan yy346; + struct TrigEvent yy378; + IdList* yy408; + struct {int value; int mask;} yy429; + TriggerStep* yy473; + struct LimitVal yy476; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif #define sqlite3ParserARG_SDECL Parse *pParse; #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 616 -#define YYNRULE 323 +#define YYNSTATE 629 +#define YYNRULE 329 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) /* The yyzerominor constant is used to initialize instances of ** YYMINORTYPE objects to zero. */ static const YYMINORTYPE yyzerominor = { 0 }; + +/* Define the yytestcase() macro to be a no-op if is not already defined +** otherwise. +** +** Applications can choose to define yytestcase() in the %include section +** to a macro that can assist in verifying code coverage. For production +** code the yytestcase() macro should be turned off. But it is useful +** for testing. +*/ +#ifndef yytestcase +# define yytestcase(X) +#endif /* Next are the tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an @@ -84555,160 +88402,162 @@ ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { - /* 0 */ 304, 940, 176, 615, 2, 150, 214, 439, 24, 24, - /* 10 */ 24, 24, 488, 26, 26, 26, 26, 27, 27, 28, - /* 20 */ 28, 28, 29, 216, 413, 414, 212, 413, 414, 446, - /* 30 */ 452, 31, 26, 26, 26, 26, 27, 27, 28, 28, - /* 40 */ 28, 29, 216, 30, 483, 32, 134, 23, 22, 308, - /* 50 */ 456, 457, 453, 453, 25, 25, 24, 24, 24, 24, - /* 60 */ 436, 26, 26, 26, 26, 27, 27, 28, 28, 28, - /* 70 */ 29, 216, 304, 216, 311, 439, 512, 490, 45, 26, - /* 80 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 216, - /* 90 */ 413, 414, 416, 417, 156, 416, 417, 360, 363, 364, - /* 100 */ 311, 446, 452, 385, 514, 21, 186, 495, 365, 27, - /* 110 */ 27, 28, 28, 28, 29, 216, 413, 414, 415, 23, - /* 120 */ 22, 308, 456, 457, 453, 453, 25, 25, 24, 24, - /* 130 */ 24, 24, 555, 26, 26, 26, 26, 27, 27, 28, - /* 140 */ 28, 28, 29, 216, 304, 228, 504, 135, 468, 218, - /* 150 */ 548, 145, 132, 256, 358, 261, 359, 153, 416, 417, - /* 160 */ 241, 598, 331, 30, 265, 32, 134, 439, 596, 597, - /* 170 */ 230, 228, 490, 446, 452, 57, 506, 328, 132, 256, - /* 180 */ 358, 261, 359, 153, 416, 417, 435, 78, 408, 405, - /* 190 */ 265, 23, 22, 308, 456, 457, 453, 453, 25, 25, - /* 200 */ 24, 24, 24, 24, 342, 26, 26, 26, 26, 27, - /* 210 */ 27, 28, 28, 28, 29, 216, 304, 214, 534, 547, - /* 220 */ 307, 127, 489, 595, 30, 331, 32, 134, 345, 387, - /* 230 */ 429, 63, 331, 355, 415, 439, 507, 331, 415, 535, - /* 240 */ 328, 215, 193, 594, 593, 446, 452, 328, 18, 435, - /* 250 */ 85, 16, 328, 183, 190, 556, 435, 78, 309, 463, - /* 260 */ 464, 435, 85, 23, 22, 308, 456, 457, 453, 453, - /* 270 */ 25, 25, 24, 24, 24, 24, 436, 26, 26, 26, - /* 280 */ 26, 27, 27, 28, 28, 28, 29, 216, 304, 347, - /* 290 */ 221, 313, 595, 191, 378, 331, 472, 234, 345, 381, - /* 300 */ 324, 410, 220, 344, 592, 217, 213, 415, 112, 331, - /* 310 */ 328, 4, 594, 399, 211, 554, 529, 446, 452, 435, - /* 320 */ 79, 217, 553, 515, 328, 334, 513, 459, 459, 469, - /* 330 */ 441, 572, 432, 435, 78, 23, 22, 308, 456, 457, - /* 340 */ 453, 453, 25, 25, 24, 24, 24, 24, 436, 26, - /* 350 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 216, - /* 360 */ 304, 443, 443, 443, 156, 468, 218, 360, 363, 364, - /* 370 */ 331, 247, 395, 398, 217, 349, 331, 30, 365, 32, - /* 380 */ 134, 388, 282, 281, 39, 328, 41, 430, 545, 446, - /* 390 */ 452, 328, 214, 531, 435, 93, 542, 601, 1, 404, - /* 400 */ 435, 93, 413, 414, 495, 40, 536, 23, 22, 308, - /* 410 */ 456, 457, 453, 453, 25, 25, 24, 24, 24, 24, - /* 420 */ 573, 26, 26, 26, 26, 27, 27, 28, 28, 28, - /* 430 */ 29, 216, 304, 276, 331, 179, 508, 490, 210, 547, - /* 440 */ 319, 413, 414, 222, 192, 385, 320, 240, 415, 328, - /* 450 */ 557, 63, 413, 414, 415, 616, 408, 405, 435, 71, - /* 460 */ 415, 446, 452, 611, 572, 28, 28, 28, 29, 216, - /* 470 */ 416, 417, 436, 336, 463, 464, 401, 43, 436, 23, - /* 480 */ 22, 308, 456, 457, 453, 453, 25, 25, 24, 24, - /* 490 */ 24, 24, 495, 26, 26, 26, 26, 27, 27, 28, - /* 500 */ 28, 28, 29, 216, 304, 612, 209, 135, 511, 416, - /* 510 */ 417, 431, 233, 64, 388, 282, 281, 439, 66, 542, - /* 520 */ 416, 417, 413, 414, 156, 214, 403, 360, 363, 364, - /* 530 */ 547, 252, 490, 446, 452, 491, 217, 8, 365, 495, - /* 540 */ 436, 606, 63, 537, 299, 415, 492, 470, 546, 200, - /* 550 */ 196, 23, 22, 308, 456, 457, 453, 453, 25, 25, - /* 560 */ 24, 24, 24, 24, 386, 26, 26, 26, 26, 27, - /* 570 */ 27, 28, 28, 28, 29, 216, 304, 477, 254, 354, - /* 580 */ 528, 60, 517, 518, 436, 439, 389, 331, 356, 7, - /* 590 */ 416, 417, 331, 478, 328, 208, 197, 137, 460, 499, - /* 600 */ 447, 448, 328, 435, 9, 446, 452, 328, 479, 485, - /* 610 */ 519, 435, 72, 567, 415, 434, 435, 67, 486, 433, - /* 620 */ 520, 450, 451, 23, 22, 308, 456, 457, 453, 453, - /* 630 */ 25, 25, 24, 24, 24, 24, 331, 26, 26, 26, - /* 640 */ 26, 27, 27, 28, 28, 28, 29, 216, 304, 331, - /* 650 */ 449, 328, 268, 390, 461, 331, 65, 331, 368, 434, - /* 660 */ 435, 76, 310, 433, 328, 150, 427, 439, 473, 331, - /* 670 */ 328, 499, 328, 435, 97, 29, 216, 446, 452, 435, - /* 680 */ 96, 435, 101, 353, 328, 372, 415, 334, 154, 459, - /* 690 */ 459, 352, 569, 435, 99, 23, 22, 308, 456, 457, - /* 700 */ 453, 453, 25, 25, 24, 24, 24, 24, 331, 26, - /* 710 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 216, - /* 720 */ 304, 331, 248, 328, 264, 56, 334, 331, 459, 459, - /* 730 */ 861, 333, 435, 104, 376, 439, 328, 415, 331, 415, - /* 740 */ 565, 331, 328, 306, 564, 435, 105, 185, 265, 446, - /* 750 */ 452, 435, 126, 328, 570, 518, 328, 334, 377, 459, - /* 760 */ 459, 314, 435, 128, 194, 435, 59, 23, 22, 308, - /* 770 */ 456, 457, 453, 453, 25, 25, 24, 24, 24, 24, - /* 780 */ 331, 26, 26, 26, 26, 27, 27, 28, 28, 28, - /* 790 */ 29, 216, 304, 331, 136, 328, 242, 477, 436, 331, - /* 800 */ 350, 331, 609, 303, 435, 102, 201, 137, 328, 415, - /* 810 */ 454, 178, 331, 478, 328, 415, 328, 435, 77, 440, - /* 820 */ 249, 446, 452, 435, 100, 435, 68, 328, 479, 465, - /* 830 */ 341, 613, 931, 484, 931, 415, 435, 98, 467, 23, - /* 840 */ 22, 308, 456, 457, 453, 453, 25, 25, 24, 24, - /* 850 */ 24, 24, 331, 26, 26, 26, 26, 27, 27, 28, - /* 860 */ 28, 28, 29, 216, 304, 331, 397, 328, 164, 264, - /* 870 */ 205, 331, 264, 332, 610, 339, 435, 129, 407, 2, - /* 880 */ 328, 322, 175, 331, 415, 214, 328, 415, 415, 435, - /* 890 */ 130, 466, 466, 446, 452, 435, 131, 396, 328, 257, - /* 900 */ 334, 487, 459, 459, 436, 154, 229, 435, 69, 315, - /* 910 */ 258, 23, 33, 308, 456, 457, 453, 453, 25, 25, - /* 920 */ 24, 24, 24, 24, 331, 26, 26, 26, 26, 27, - /* 930 */ 27, 28, 28, 28, 29, 216, 304, 331, 497, 328, - /* 940 */ 151, 264, 412, 331, 264, 470, 337, 200, 435, 80, - /* 950 */ 250, 155, 328, 523, 524, 331, 415, 415, 328, 415, - /* 960 */ 306, 435, 81, 533, 532, 446, 452, 435, 70, 47, - /* 970 */ 328, 613, 930, 259, 930, 418, 419, 420, 316, 435, - /* 980 */ 82, 317, 206, 539, 22, 308, 456, 457, 453, 453, - /* 990 */ 25, 25, 24, 24, 24, 24, 331, 26, 26, 26, - /* 1000 */ 26, 27, 27, 28, 28, 28, 29, 216, 304, 331, - /* 1010 */ 209, 328, 529, 540, 610, 331, 436, 563, 375, 563, - /* 1020 */ 435, 83, 362, 538, 328, 155, 541, 331, 499, 526, - /* 1030 */ 328, 331, 575, 435, 84, 424, 543, 446, 452, 435, - /* 1040 */ 86, 290, 328, 415, 436, 267, 328, 155, 394, 141, - /* 1050 */ 415, 435, 87, 588, 411, 435, 88, 308, 456, 457, - /* 1060 */ 453, 453, 25, 25, 24, 24, 24, 24, 386, 26, - /* 1070 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 216, - /* 1080 */ 35, 338, 286, 3, 331, 270, 331, 327, 414, 421, - /* 1090 */ 382, 318, 276, 422, 325, 35, 338, 335, 3, 328, - /* 1100 */ 423, 328, 327, 414, 142, 144, 276, 415, 435, 73, - /* 1110 */ 435, 74, 335, 331, 6, 340, 425, 331, 326, 331, - /* 1120 */ 367, 415, 155, 437, 289, 472, 287, 274, 328, 272, - /* 1130 */ 340, 415, 328, 47, 328, 277, 276, 435, 89, 348, - /* 1140 */ 472, 435, 90, 435, 91, 38, 37, 243, 331, 582, - /* 1150 */ 244, 415, 426, 276, 36, 329, 330, 46, 245, 441, - /* 1160 */ 38, 37, 505, 328, 202, 203, 204, 415, 415, 36, - /* 1170 */ 329, 330, 435, 92, 441, 198, 568, 214, 155, 584, - /* 1180 */ 235, 236, 237, 143, 239, 346, 133, 581, 438, 246, - /* 1190 */ 443, 443, 443, 444, 445, 10, 585, 276, 20, 42, - /* 1200 */ 172, 415, 294, 331, 288, 443, 443, 443, 444, 445, - /* 1210 */ 10, 295, 415, 35, 338, 219, 3, 149, 328, 482, - /* 1220 */ 327, 414, 331, 170, 276, 572, 48, 435, 75, 169, - /* 1230 */ 335, 19, 171, 251, 442, 413, 414, 328, 331, 415, - /* 1240 */ 586, 343, 276, 177, 351, 496, 435, 17, 340, 415, - /* 1250 */ 481, 253, 255, 328, 276, 502, 415, 415, 472, 331, - /* 1260 */ 503, 357, 435, 94, 576, 415, 151, 231, 312, 415, - /* 1270 */ 577, 516, 54, 472, 328, 393, 291, 281, 38, 37, - /* 1280 */ 494, 305, 521, 435, 95, 232, 214, 36, 329, 330, - /* 1290 */ 526, 498, 441, 188, 189, 415, 500, 292, 522, 262, - /* 1300 */ 530, 260, 263, 513, 549, 269, 415, 441, 589, 400, - /* 1310 */ 54, 415, 525, 527, 415, 415, 271, 415, 273, 415, - /* 1320 */ 415, 275, 280, 443, 443, 443, 444, 445, 10, 107, - /* 1330 */ 380, 415, 383, 415, 384, 283, 415, 415, 443, 443, - /* 1340 */ 443, 284, 285, 580, 300, 415, 591, 415, 293, 415, - /* 1350 */ 415, 296, 297, 605, 226, 550, 415, 415, 415, 225, - /* 1360 */ 608, 415, 302, 415, 551, 227, 415, 415, 415, 301, - /* 1370 */ 544, 552, 369, 158, 373, 558, 159, 278, 371, 160, - /* 1380 */ 51, 207, 560, 561, 161, 140, 379, 117, 571, 163, - /* 1390 */ 391, 392, 181, 180, 321, 602, 578, 118, 119, 120, - /* 1400 */ 121, 123, 55, 587, 58, 603, 604, 607, 62, 174, - /* 1410 */ 103, 224, 111, 409, 238, 428, 199, 323, 657, 658, - /* 1420 */ 659, 146, 147, 455, 458, 34, 474, 462, 471, 182, - /* 1430 */ 195, 148, 475, 476, 480, 5, 12, 493, 44, 11, - /* 1440 */ 106, 138, 509, 510, 501, 223, 49, 361, 108, 109, - /* 1450 */ 152, 266, 50, 110, 157, 258, 370, 184, 559, 139, - /* 1460 */ 151, 113, 279, 162, 115, 374, 15, 574, 116, 165, - /* 1470 */ 52, 13, 366, 579, 53, 167, 168, 166, 583, 124, - /* 1480 */ 114, 122, 562, 566, 14, 61, 599, 600, 125, 173, - /* 1490 */ 298, 590, 187, 406, 941, 614, 941, 402, + /* 0 */ 309, 959, 178, 628, 2, 153, 216, 448, 24, 24, + /* 10 */ 24, 24, 497, 26, 26, 26, 26, 27, 27, 28, + /* 20 */ 28, 28, 29, 218, 422, 423, 214, 422, 423, 455, + /* 30 */ 461, 31, 26, 26, 26, 26, 27, 27, 28, 28, + /* 40 */ 28, 29, 218, 30, 492, 32, 137, 23, 22, 315, + /* 50 */ 465, 466, 462, 462, 25, 25, 24, 24, 24, 24, + /* 60 */ 445, 26, 26, 26, 26, 27, 27, 28, 28, 28, + /* 70 */ 29, 218, 309, 218, 318, 448, 521, 499, 45, 26, + /* 80 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 218, + /* 90 */ 422, 423, 425, 426, 159, 425, 426, 366, 369, 370, + /* 100 */ 318, 455, 461, 394, 523, 21, 188, 504, 371, 27, + /* 110 */ 27, 28, 28, 28, 29, 218, 422, 423, 424, 23, + /* 120 */ 22, 315, 465, 466, 462, 462, 25, 25, 24, 24, + /* 130 */ 24, 24, 564, 26, 26, 26, 26, 27, 27, 28, + /* 140 */ 28, 28, 29, 218, 309, 230, 513, 138, 477, 220, + /* 150 */ 557, 148, 135, 260, 364, 265, 365, 156, 425, 426, + /* 160 */ 245, 610, 337, 30, 269, 32, 137, 448, 608, 609, + /* 170 */ 233, 230, 499, 455, 461, 57, 515, 334, 135, 260, + /* 180 */ 364, 265, 365, 156, 425, 426, 444, 78, 417, 414, + /* 190 */ 269, 23, 22, 315, 465, 466, 462, 462, 25, 25, + /* 200 */ 24, 24, 24, 24, 348, 26, 26, 26, 26, 27, + /* 210 */ 27, 28, 28, 28, 29, 218, 309, 216, 543, 556, + /* 220 */ 486, 130, 498, 607, 30, 337, 32, 137, 351, 396, + /* 230 */ 438, 63, 337, 361, 424, 448, 487, 337, 424, 544, + /* 240 */ 334, 217, 195, 606, 605, 455, 461, 334, 18, 444, + /* 250 */ 85, 488, 334, 347, 192, 565, 444, 78, 316, 472, + /* 260 */ 473, 444, 85, 23, 22, 315, 465, 466, 462, 462, + /* 270 */ 25, 25, 24, 24, 24, 24, 445, 26, 26, 26, + /* 280 */ 26, 27, 27, 28, 28, 28, 29, 218, 309, 353, + /* 290 */ 223, 320, 607, 193, 238, 337, 481, 16, 351, 185, + /* 300 */ 330, 419, 222, 350, 604, 219, 215, 424, 112, 337, + /* 310 */ 334, 157, 606, 408, 213, 563, 538, 455, 461, 444, + /* 320 */ 79, 219, 562, 524, 334, 576, 522, 629, 417, 414, + /* 330 */ 450, 581, 441, 444, 78, 23, 22, 315, 465, 466, + /* 340 */ 462, 462, 25, 25, 24, 24, 24, 24, 445, 26, + /* 350 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 218, + /* 360 */ 309, 452, 452, 452, 159, 399, 311, 366, 369, 370, + /* 370 */ 337, 251, 404, 407, 219, 355, 556, 4, 371, 422, + /* 380 */ 423, 397, 286, 285, 244, 334, 540, 566, 63, 455, + /* 390 */ 461, 424, 216, 478, 444, 93, 28, 28, 28, 29, + /* 400 */ 218, 413, 477, 220, 578, 40, 545, 23, 22, 315, + /* 410 */ 465, 466, 462, 462, 25, 25, 24, 24, 24, 24, + /* 420 */ 582, 26, 26, 26, 26, 27, 27, 28, 28, 28, + /* 430 */ 29, 218, 309, 546, 337, 30, 517, 32, 137, 378, + /* 440 */ 326, 337, 874, 153, 194, 448, 1, 425, 426, 334, + /* 450 */ 422, 423, 422, 423, 29, 218, 334, 613, 444, 71, + /* 460 */ 210, 455, 461, 66, 581, 444, 93, 422, 423, 626, + /* 470 */ 949, 303, 949, 500, 479, 555, 202, 43, 445, 23, + /* 480 */ 22, 315, 465, 466, 462, 462, 25, 25, 24, 24, + /* 490 */ 24, 24, 436, 26, 26, 26, 26, 27, 27, 28, + /* 500 */ 28, 28, 29, 218, 309, 187, 211, 360, 520, 440, + /* 510 */ 246, 327, 622, 448, 397, 286, 285, 551, 425, 426, + /* 520 */ 425, 426, 334, 159, 337, 216, 366, 369, 370, 494, + /* 530 */ 556, 444, 9, 455, 461, 425, 426, 371, 495, 334, + /* 540 */ 445, 618, 63, 504, 198, 424, 501, 449, 444, 72, + /* 550 */ 474, 23, 22, 315, 465, 466, 462, 462, 25, 25, + /* 560 */ 24, 24, 24, 24, 395, 26, 26, 26, 26, 27, + /* 570 */ 27, 28, 28, 28, 29, 218, 309, 486, 445, 337, + /* 580 */ 537, 60, 224, 479, 343, 202, 398, 337, 439, 554, + /* 590 */ 199, 140, 337, 487, 334, 526, 527, 551, 516, 508, + /* 600 */ 456, 457, 334, 444, 67, 455, 461, 334, 488, 476, + /* 610 */ 528, 444, 76, 39, 424, 41, 444, 97, 579, 527, + /* 620 */ 529, 459, 460, 23, 22, 315, 465, 466, 462, 462, + /* 630 */ 25, 25, 24, 24, 24, 24, 337, 26, 26, 26, + /* 640 */ 26, 27, 27, 28, 28, 28, 29, 218, 309, 337, + /* 650 */ 458, 334, 272, 621, 307, 337, 312, 337, 374, 64, + /* 660 */ 444, 96, 317, 448, 334, 342, 472, 473, 469, 337, + /* 670 */ 334, 508, 334, 444, 101, 359, 252, 455, 461, 444, + /* 680 */ 99, 444, 104, 358, 334, 345, 424, 340, 157, 468, + /* 690 */ 468, 424, 493, 444, 105, 23, 22, 315, 465, 466, + /* 700 */ 462, 462, 25, 25, 24, 24, 24, 24, 337, 26, + /* 710 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 218, + /* 720 */ 309, 337, 181, 334, 499, 56, 139, 337, 219, 268, + /* 730 */ 384, 448, 444, 129, 382, 387, 334, 168, 337, 389, + /* 740 */ 508, 424, 334, 311, 424, 444, 131, 496, 269, 455, + /* 750 */ 461, 444, 59, 334, 424, 424, 391, 340, 8, 468, + /* 760 */ 468, 263, 444, 102, 390, 290, 321, 23, 22, 315, + /* 770 */ 465, 466, 462, 462, 25, 25, 24, 24, 24, 24, + /* 780 */ 337, 26, 26, 26, 26, 27, 27, 28, 28, 28, + /* 790 */ 29, 218, 309, 337, 138, 334, 416, 2, 268, 337, + /* 800 */ 389, 337, 443, 325, 444, 77, 442, 293, 334, 291, + /* 810 */ 7, 482, 337, 424, 334, 424, 334, 444, 100, 499, + /* 820 */ 339, 455, 461, 444, 68, 444, 98, 334, 254, 504, + /* 830 */ 232, 626, 948, 504, 948, 231, 444, 132, 47, 23, + /* 840 */ 22, 315, 465, 466, 462, 462, 25, 25, 24, 24, + /* 850 */ 24, 24, 337, 26, 26, 26, 26, 27, 27, 28, + /* 860 */ 28, 28, 29, 218, 309, 337, 280, 334, 256, 538, + /* 870 */ 362, 337, 258, 268, 622, 549, 444, 133, 203, 140, + /* 880 */ 334, 424, 548, 337, 180, 158, 334, 292, 424, 444, + /* 890 */ 134, 287, 552, 455, 461, 444, 69, 443, 334, 463, + /* 900 */ 340, 442, 468, 468, 427, 428, 429, 444, 80, 281, + /* 910 */ 322, 23, 33, 315, 465, 466, 462, 462, 25, 25, + /* 920 */ 24, 24, 24, 24, 337, 26, 26, 26, 26, 27, + /* 930 */ 27, 28, 28, 28, 29, 218, 309, 337, 406, 334, + /* 940 */ 212, 268, 550, 337, 268, 389, 329, 177, 444, 81, + /* 950 */ 542, 541, 334, 475, 475, 337, 424, 216, 334, 424, + /* 960 */ 424, 444, 70, 535, 368, 455, 461, 444, 82, 405, + /* 970 */ 334, 261, 392, 340, 445, 468, 468, 587, 323, 444, + /* 980 */ 83, 324, 262, 288, 22, 315, 465, 466, 462, 462, + /* 990 */ 25, 25, 24, 24, 24, 24, 337, 26, 26, 26, + /* 1000 */ 26, 27, 27, 28, 28, 28, 29, 218, 309, 337, + /* 1010 */ 211, 334, 294, 356, 340, 337, 468, 468, 532, 533, + /* 1020 */ 444, 84, 403, 144, 334, 574, 600, 337, 424, 573, + /* 1030 */ 334, 337, 420, 444, 86, 253, 234, 455, 461, 444, + /* 1040 */ 87, 430, 334, 383, 445, 431, 334, 274, 196, 331, + /* 1050 */ 424, 444, 88, 432, 145, 444, 73, 315, 465, 466, + /* 1060 */ 462, 462, 25, 25, 24, 24, 24, 24, 395, 26, + /* 1070 */ 26, 26, 26, 27, 27, 28, 28, 28, 29, 218, + /* 1080 */ 35, 344, 445, 3, 337, 394, 337, 333, 423, 278, + /* 1090 */ 388, 276, 280, 207, 147, 35, 344, 341, 3, 334, + /* 1100 */ 424, 334, 333, 423, 308, 623, 280, 424, 444, 74, + /* 1110 */ 444, 89, 341, 337, 6, 346, 338, 337, 421, 337, + /* 1120 */ 470, 424, 65, 332, 280, 481, 446, 445, 334, 247, + /* 1130 */ 346, 424, 334, 424, 334, 594, 280, 444, 90, 424, + /* 1140 */ 481, 444, 91, 444, 92, 38, 37, 625, 337, 410, + /* 1150 */ 47, 424, 237, 280, 36, 335, 336, 354, 248, 450, + /* 1160 */ 38, 37, 514, 334, 572, 381, 572, 596, 424, 36, + /* 1170 */ 335, 336, 444, 75, 450, 200, 506, 216, 154, 597, + /* 1180 */ 239, 240, 241, 146, 243, 249, 547, 593, 158, 433, + /* 1190 */ 452, 452, 452, 453, 454, 10, 598, 280, 20, 46, + /* 1200 */ 174, 412, 298, 337, 424, 452, 452, 452, 453, 454, + /* 1210 */ 10, 299, 424, 35, 344, 352, 3, 250, 334, 434, + /* 1220 */ 333, 423, 337, 172, 280, 581, 208, 444, 17, 171, + /* 1230 */ 341, 19, 173, 447, 424, 422, 423, 334, 337, 424, + /* 1240 */ 235, 280, 204, 205, 206, 42, 444, 94, 346, 435, + /* 1250 */ 136, 451, 221, 334, 308, 624, 424, 349, 481, 490, + /* 1260 */ 445, 152, 444, 95, 424, 424, 424, 236, 503, 491, + /* 1270 */ 507, 179, 424, 481, 424, 402, 295, 285, 38, 37, + /* 1280 */ 271, 310, 158, 424, 296, 424, 216, 36, 335, 336, + /* 1290 */ 509, 266, 450, 190, 191, 539, 267, 625, 558, 273, + /* 1300 */ 275, 48, 277, 522, 279, 424, 424, 450, 255, 409, + /* 1310 */ 424, 424, 257, 424, 424, 424, 284, 424, 386, 424, + /* 1320 */ 357, 584, 585, 452, 452, 452, 453, 454, 10, 259, + /* 1330 */ 393, 424, 289, 424, 592, 603, 424, 424, 452, 452, + /* 1340 */ 452, 297, 300, 301, 505, 424, 617, 424, 363, 424, + /* 1350 */ 424, 373, 577, 158, 158, 511, 424, 424, 424, 525, + /* 1360 */ 588, 424, 154, 589, 601, 54, 54, 620, 512, 306, + /* 1370 */ 319, 530, 531, 535, 264, 107, 228, 536, 534, 375, + /* 1380 */ 559, 304, 560, 561, 305, 227, 229, 553, 567, 161, + /* 1390 */ 162, 379, 377, 163, 51, 209, 569, 282, 164, 570, + /* 1400 */ 385, 143, 580, 116, 119, 183, 400, 590, 401, 121, + /* 1410 */ 122, 123, 124, 126, 599, 328, 614, 55, 58, 615, + /* 1420 */ 616, 619, 62, 418, 103, 226, 111, 176, 242, 182, + /* 1430 */ 437, 313, 201, 314, 670, 671, 672, 149, 150, 467, + /* 1440 */ 464, 34, 483, 471, 480, 184, 197, 502, 484, 5, + /* 1450 */ 485, 151, 489, 44, 141, 11, 106, 160, 225, 518, + /* 1460 */ 519, 49, 510, 108, 367, 270, 12, 155, 109, 50, + /* 1470 */ 110, 262, 376, 186, 568, 113, 142, 154, 165, 115, + /* 1480 */ 15, 283, 583, 166, 167, 380, 586, 117, 13, 120, + /* 1490 */ 372, 52, 53, 118, 591, 169, 114, 170, 595, 125, + /* 1500 */ 127, 571, 575, 602, 14, 128, 611, 612, 61, 175, + /* 1510 */ 189, 415, 302, 627, 960, 960, 960, 960, 411, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 19, 142, 143, 144, 145, 24, 116, 26, 75, 76, /* 10 */ 77, 78, 25, 80, 81, 82, 83, 84, 85, 86, /* 20 */ 87, 88, 89, 90, 26, 27, 160, 26, 27, 48, @@ -84729,282 +88578,286 @@ /* 170 */ 217, 90, 120, 48, 49, 50, 86, 165, 97, 98, /* 180 */ 99, 100, 101, 102, 94, 95, 174, 175, 1, 2, /* 190 */ 109, 66, 67, 68, 69, 70, 71, 72, 73, 74, /* 200 */ 75, 76, 77, 78, 191, 80, 81, 82, 83, 84, /* 210 */ 85, 86, 87, 88, 89, 90, 19, 116, 35, 150, - /* 220 */ 155, 24, 208, 150, 222, 150, 224, 225, 216, 128, - /* 230 */ 161, 162, 150, 221, 165, 94, 23, 150, 165, 56, + /* 220 */ 12, 24, 208, 150, 222, 150, 224, 225, 216, 128, + /* 230 */ 161, 162, 150, 221, 165, 94, 28, 150, 165, 56, /* 240 */ 165, 197, 160, 170, 171, 48, 49, 165, 204, 174, - /* 250 */ 175, 22, 165, 24, 185, 186, 174, 175, 169, 170, + /* 250 */ 175, 43, 165, 45, 185, 186, 174, 175, 169, 170, /* 260 */ 171, 174, 175, 66, 67, 68, 69, 70, 71, 72, /* 270 */ 73, 74, 75, 76, 77, 78, 194, 80, 81, 82, /* 280 */ 83, 84, 85, 86, 87, 88, 89, 90, 19, 214, - /* 290 */ 215, 108, 150, 25, 229, 150, 64, 148, 216, 234, + /* 290 */ 215, 108, 150, 25, 148, 150, 64, 22, 216, 24, /* 300 */ 146, 147, 215, 221, 231, 232, 152, 165, 154, 150, - /* 310 */ 165, 196, 170, 171, 160, 181, 182, 48, 49, 174, - /* 320 */ 175, 232, 188, 165, 165, 112, 94, 114, 115, 166, + /* 310 */ 165, 49, 170, 171, 160, 181, 182, 48, 49, 174, + /* 320 */ 175, 232, 188, 165, 165, 21, 94, 0, 1, 2, /* 330 */ 98, 55, 174, 174, 175, 66, 67, 68, 69, 70, /* 340 */ 71, 72, 73, 74, 75, 76, 77, 78, 194, 80, /* 350 */ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 360 */ 19, 129, 130, 131, 96, 84, 85, 99, 100, 101, - /* 370 */ 150, 226, 218, 231, 232, 216, 150, 222, 110, 224, - /* 380 */ 225, 105, 106, 107, 135, 165, 137, 172, 173, 48, - /* 390 */ 49, 165, 116, 183, 174, 175, 181, 242, 22, 245, - /* 400 */ 174, 175, 26, 27, 166, 136, 183, 66, 67, 68, + /* 360 */ 19, 129, 130, 131, 96, 61, 104, 99, 100, 101, + /* 370 */ 150, 226, 218, 231, 232, 216, 150, 196, 110, 26, + /* 380 */ 27, 105, 106, 107, 158, 165, 183, 161, 162, 48, + /* 390 */ 49, 165, 116, 166, 174, 175, 86, 87, 88, 89, + /* 400 */ 90, 247, 84, 85, 100, 136, 183, 66, 67, 68, /* 410 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, /* 420 */ 11, 80, 81, 82, 83, 84, 85, 86, 87, 88, - /* 430 */ 89, 90, 19, 150, 150, 23, 23, 25, 160, 150, - /* 440 */ 220, 26, 27, 205, 160, 150, 220, 158, 165, 165, - /* 450 */ 161, 162, 26, 27, 165, 0, 1, 2, 174, 175, - /* 460 */ 165, 48, 49, 23, 55, 86, 87, 88, 89, 90, - /* 470 */ 94, 95, 194, 169, 170, 171, 193, 136, 194, 66, + /* 430 */ 89, 90, 19, 183, 150, 222, 23, 224, 225, 237, + /* 440 */ 220, 150, 138, 24, 160, 26, 22, 94, 95, 165, + /* 450 */ 26, 27, 26, 27, 89, 90, 165, 244, 174, 175, + /* 460 */ 236, 48, 49, 22, 55, 174, 175, 26, 27, 22, + /* 470 */ 23, 163, 25, 120, 166, 167, 168, 136, 194, 66, /* 480 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - /* 490 */ 77, 78, 166, 80, 81, 82, 83, 84, 85, 86, - /* 500 */ 87, 88, 89, 90, 19, 65, 160, 95, 23, 94, - /* 510 */ 95, 173, 217, 22, 105, 106, 107, 26, 22, 181, - /* 520 */ 94, 95, 26, 27, 96, 116, 243, 99, 100, 101, - /* 530 */ 150, 205, 120, 48, 49, 120, 232, 22, 110, 166, - /* 540 */ 194, 161, 162, 183, 163, 165, 120, 166, 167, 168, - /* 550 */ 160, 66, 67, 68, 69, 70, 71, 72, 73, 74, + /* 490 */ 77, 78, 153, 80, 81, 82, 83, 84, 85, 86, + /* 500 */ 87, 88, 89, 90, 19, 196, 160, 150, 23, 173, + /* 510 */ 198, 220, 65, 94, 105, 106, 107, 181, 94, 95, + /* 520 */ 94, 95, 165, 96, 150, 116, 99, 100, 101, 31, + /* 530 */ 150, 174, 175, 48, 49, 94, 95, 110, 40, 165, + /* 540 */ 194, 161, 162, 166, 160, 165, 120, 166, 174, 175, + /* 550 */ 233, 66, 67, 68, 69, 70, 71, 72, 73, 74, /* 560 */ 75, 76, 77, 78, 218, 80, 81, 82, 83, 84, - /* 570 */ 85, 86, 87, 88, 89, 90, 19, 12, 205, 150, - /* 580 */ 23, 235, 190, 191, 194, 94, 240, 150, 86, 74, - /* 590 */ 94, 95, 150, 28, 165, 236, 206, 207, 23, 150, - /* 600 */ 48, 49, 165, 174, 175, 48, 49, 165, 43, 31, - /* 610 */ 45, 174, 175, 21, 165, 113, 174, 175, 40, 117, + /* 570 */ 85, 86, 87, 88, 89, 90, 19, 12, 194, 150, + /* 580 */ 23, 235, 205, 166, 167, 168, 240, 150, 172, 173, + /* 590 */ 206, 207, 150, 28, 165, 190, 191, 181, 23, 150, + /* 600 */ 48, 49, 165, 174, 175, 48, 49, 165, 43, 233, + /* 610 */ 45, 174, 175, 135, 165, 137, 174, 175, 190, 191, /* 620 */ 55, 69, 70, 66, 67, 68, 69, 70, 71, 72, /* 630 */ 73, 74, 75, 76, 77, 78, 150, 80, 81, 82, /* 640 */ 83, 84, 85, 86, 87, 88, 89, 90, 19, 150, - /* 650 */ 98, 165, 23, 61, 23, 150, 25, 150, 19, 113, - /* 660 */ 174, 175, 213, 117, 165, 24, 153, 26, 23, 150, - /* 670 */ 165, 150, 165, 174, 175, 89, 90, 48, 49, 174, - /* 680 */ 175, 174, 175, 19, 165, 237, 165, 112, 49, 114, - /* 690 */ 115, 27, 100, 174, 175, 66, 67, 68, 69, 70, + /* 650 */ 98, 165, 23, 250, 251, 150, 155, 150, 19, 22, + /* 660 */ 174, 175, 213, 26, 165, 169, 170, 171, 23, 150, + /* 670 */ 165, 150, 165, 174, 175, 19, 150, 48, 49, 174, + /* 680 */ 175, 174, 175, 27, 165, 228, 165, 112, 49, 114, + /* 690 */ 115, 165, 177, 174, 175, 66, 67, 68, 69, 70, /* 700 */ 71, 72, 73, 74, 75, 76, 77, 78, 150, 80, /* 710 */ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 720 */ 19, 150, 150, 165, 150, 24, 112, 150, 114, 115, - /* 730 */ 138, 19, 174, 175, 213, 94, 165, 165, 150, 165, - /* 740 */ 29, 150, 165, 104, 33, 174, 175, 196, 109, 48, - /* 750 */ 49, 174, 175, 165, 190, 191, 165, 112, 47, 114, - /* 760 */ 115, 187, 174, 175, 160, 174, 175, 66, 67, 68, + /* 720 */ 19, 150, 23, 165, 25, 24, 150, 150, 232, 150, + /* 730 */ 229, 94, 174, 175, 213, 234, 165, 25, 150, 150, + /* 740 */ 150, 165, 165, 104, 165, 174, 175, 177, 109, 48, + /* 750 */ 49, 174, 175, 165, 165, 165, 19, 112, 22, 114, + /* 760 */ 115, 177, 174, 175, 27, 16, 187, 66, 67, 68, /* 770 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, /* 780 */ 150, 80, 81, 82, 83, 84, 85, 86, 87, 88, - /* 790 */ 89, 90, 19, 150, 150, 165, 198, 12, 194, 150, - /* 800 */ 150, 150, 248, 249, 174, 175, 206, 207, 165, 165, - /* 810 */ 98, 23, 150, 28, 165, 165, 165, 174, 175, 166, - /* 820 */ 150, 48, 49, 174, 175, 174, 175, 165, 43, 233, - /* 830 */ 45, 22, 23, 177, 25, 165, 174, 175, 233, 66, + /* 790 */ 89, 90, 19, 150, 95, 165, 144, 145, 150, 150, + /* 800 */ 150, 150, 113, 213, 174, 175, 117, 58, 165, 60, + /* 810 */ 74, 23, 150, 165, 165, 165, 165, 174, 175, 120, + /* 820 */ 19, 48, 49, 174, 175, 174, 175, 165, 209, 166, + /* 830 */ 241, 22, 23, 166, 25, 187, 174, 175, 126, 66, /* 840 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* 850 */ 77, 78, 150, 80, 81, 82, 83, 84, 85, 86, - /* 860 */ 87, 88, 89, 90, 19, 150, 97, 165, 25, 150, - /* 870 */ 160, 150, 150, 150, 65, 228, 174, 175, 144, 145, - /* 880 */ 165, 246, 247, 150, 165, 116, 165, 165, 165, 174, - /* 890 */ 175, 129, 130, 48, 49, 174, 175, 128, 165, 98, - /* 900 */ 112, 177, 114, 115, 194, 49, 187, 174, 175, 187, - /* 910 */ 109, 66, 67, 68, 69, 70, 71, 72, 73, 74, + /* 860 */ 87, 88, 89, 90, 19, 150, 150, 165, 205, 182, + /* 870 */ 86, 150, 205, 150, 65, 166, 174, 175, 206, 207, + /* 880 */ 165, 165, 177, 150, 23, 25, 165, 138, 165, 174, + /* 890 */ 175, 241, 166, 48, 49, 174, 175, 113, 165, 98, + /* 900 */ 112, 117, 114, 115, 7, 8, 9, 174, 175, 193, + /* 910 */ 187, 66, 67, 68, 69, 70, 71, 72, 73, 74, /* 920 */ 75, 76, 77, 78, 150, 80, 81, 82, 83, 84, - /* 930 */ 85, 86, 87, 88, 89, 90, 19, 150, 23, 165, - /* 940 */ 25, 150, 150, 150, 150, 166, 167, 168, 174, 175, - /* 950 */ 209, 25, 165, 7, 8, 150, 165, 165, 165, 165, - /* 960 */ 104, 174, 175, 97, 98, 48, 49, 174, 175, 126, - /* 970 */ 165, 22, 23, 177, 25, 7, 8, 9, 187, 174, - /* 980 */ 175, 187, 160, 177, 67, 68, 69, 70, 71, 72, + /* 930 */ 85, 86, 87, 88, 89, 90, 19, 150, 97, 165, + /* 940 */ 160, 150, 177, 150, 150, 150, 248, 249, 174, 175, + /* 950 */ 97, 98, 165, 129, 130, 150, 165, 116, 165, 165, + /* 960 */ 165, 174, 175, 103, 178, 48, 49, 174, 175, 128, + /* 970 */ 165, 98, 242, 112, 194, 114, 115, 199, 187, 174, + /* 980 */ 175, 187, 109, 242, 67, 68, 69, 70, 71, 72, /* 990 */ 73, 74, 75, 76, 77, 78, 150, 80, 81, 82, /* 1000 */ 83, 84, 85, 86, 87, 88, 89, 90, 19, 150, - /* 1010 */ 160, 165, 182, 166, 65, 150, 194, 105, 106, 107, - /* 1020 */ 174, 175, 178, 23, 165, 25, 177, 150, 150, 103, - /* 1030 */ 165, 150, 199, 174, 175, 150, 166, 48, 49, 174, - /* 1040 */ 175, 209, 165, 165, 194, 23, 165, 25, 209, 6, - /* 1050 */ 165, 174, 175, 199, 149, 174, 175, 68, 69, 70, + /* 1010 */ 160, 165, 209, 150, 112, 150, 114, 115, 7, 8, + /* 1020 */ 174, 175, 209, 6, 165, 29, 199, 150, 165, 33, + /* 1030 */ 165, 150, 149, 174, 175, 150, 241, 48, 49, 174, + /* 1040 */ 175, 149, 165, 47, 194, 149, 165, 16, 160, 149, + /* 1050 */ 165, 174, 175, 13, 151, 174, 175, 68, 69, 70, /* 1060 */ 71, 72, 73, 74, 75, 76, 77, 78, 218, 80, /* 1070 */ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 1080 */ 19, 20, 16, 22, 150, 16, 150, 26, 27, 149, - /* 1090 */ 240, 213, 150, 149, 149, 19, 20, 36, 22, 165, - /* 1100 */ 13, 165, 26, 27, 151, 151, 150, 165, 174, 175, - /* 1110 */ 174, 175, 36, 150, 25, 54, 150, 150, 159, 150, - /* 1120 */ 23, 165, 25, 194, 58, 64, 60, 58, 165, 60, - /* 1130 */ 54, 165, 165, 126, 165, 193, 150, 174, 175, 123, - /* 1140 */ 64, 174, 175, 174, 175, 84, 85, 199, 150, 193, - /* 1150 */ 200, 165, 150, 150, 93, 94, 95, 124, 201, 98, - /* 1160 */ 84, 85, 86, 165, 105, 106, 107, 165, 165, 93, + /* 1080 */ 19, 20, 194, 22, 150, 150, 150, 26, 27, 58, + /* 1090 */ 240, 60, 150, 160, 151, 19, 20, 36, 22, 165, + /* 1100 */ 165, 165, 26, 27, 22, 23, 150, 165, 174, 175, + /* 1110 */ 174, 175, 36, 150, 25, 54, 150, 150, 150, 150, + /* 1120 */ 23, 165, 25, 159, 150, 64, 194, 194, 165, 199, + /* 1130 */ 54, 165, 165, 165, 165, 193, 150, 174, 175, 165, + /* 1140 */ 64, 174, 175, 174, 175, 84, 85, 65, 150, 193, + /* 1150 */ 126, 165, 217, 150, 93, 94, 95, 123, 200, 98, + /* 1160 */ 84, 85, 86, 165, 105, 106, 107, 193, 165, 93, /* 1170 */ 94, 95, 174, 175, 98, 5, 23, 116, 25, 193, - /* 1180 */ 10, 11, 12, 13, 14, 122, 150, 17, 203, 202, - /* 1190 */ 129, 130, 131, 132, 133, 134, 193, 150, 125, 135, - /* 1200 */ 30, 165, 32, 150, 138, 129, 130, 131, 132, 133, - /* 1210 */ 134, 41, 165, 19, 20, 227, 22, 118, 165, 157, - /* 1220 */ 26, 27, 150, 53, 150, 55, 104, 174, 175, 59, - /* 1230 */ 36, 22, 62, 210, 150, 26, 27, 165, 150, 165, - /* 1240 */ 193, 150, 150, 157, 121, 211, 174, 175, 54, 165, - /* 1250 */ 150, 210, 210, 165, 150, 211, 165, 165, 64, 150, - /* 1260 */ 211, 104, 174, 175, 23, 165, 25, 193, 46, 165, - /* 1270 */ 23, 176, 25, 64, 165, 105, 106, 107, 84, 85, - /* 1280 */ 150, 111, 176, 174, 175, 193, 116, 93, 94, 95, - /* 1290 */ 103, 150, 98, 84, 85, 165, 150, 193, 184, 150, - /* 1300 */ 150, 176, 150, 94, 150, 150, 165, 98, 23, 139, - /* 1310 */ 25, 165, 178, 176, 165, 165, 150, 165, 150, 165, - /* 1320 */ 165, 150, 150, 129, 130, 131, 132, 133, 134, 22, + /* 1180 */ 10, 11, 12, 13, 14, 201, 23, 17, 25, 150, + /* 1190 */ 129, 130, 131, 132, 133, 134, 193, 150, 125, 124, + /* 1200 */ 30, 245, 32, 150, 165, 129, 130, 131, 132, 133, + /* 1210 */ 134, 41, 165, 19, 20, 122, 22, 202, 165, 150, + /* 1220 */ 26, 27, 150, 53, 150, 55, 160, 174, 175, 59, + /* 1230 */ 36, 22, 62, 203, 165, 26, 27, 165, 150, 165, + /* 1240 */ 193, 150, 105, 106, 107, 135, 174, 175, 54, 150, + /* 1250 */ 150, 150, 227, 165, 22, 23, 165, 150, 64, 150, + /* 1260 */ 194, 118, 174, 175, 165, 165, 165, 193, 150, 157, + /* 1270 */ 150, 157, 165, 64, 165, 105, 106, 107, 84, 85, + /* 1280 */ 23, 111, 25, 165, 193, 165, 116, 93, 94, 95, + /* 1290 */ 150, 150, 98, 84, 85, 150, 150, 65, 150, 150, + /* 1300 */ 150, 104, 150, 94, 150, 165, 165, 98, 210, 139, + /* 1310 */ 165, 165, 210, 165, 165, 165, 150, 165, 150, 165, + /* 1320 */ 121, 150, 150, 129, 130, 131, 132, 133, 134, 210, /* 1330 */ 150, 165, 150, 165, 150, 150, 165, 165, 129, 130, - /* 1340 */ 131, 150, 150, 150, 179, 165, 150, 165, 150, 165, - /* 1350 */ 165, 150, 150, 150, 90, 176, 165, 165, 165, 230, - /* 1360 */ 23, 165, 25, 165, 176, 230, 165, 165, 165, 179, - /* 1370 */ 184, 176, 18, 156, 44, 157, 156, 238, 157, 156, - /* 1380 */ 135, 157, 157, 239, 156, 66, 157, 22, 189, 189, - /* 1390 */ 157, 18, 219, 219, 157, 39, 199, 192, 192, 192, - /* 1400 */ 192, 189, 241, 199, 241, 157, 157, 37, 244, 247, - /* 1410 */ 164, 180, 180, 1, 15, 23, 22, 250, 118, 118, - /* 1420 */ 118, 118, 118, 98, 113, 22, 11, 23, 23, 22, - /* 1430 */ 22, 25, 23, 23, 23, 34, 34, 120, 25, 25, - /* 1440 */ 22, 118, 23, 23, 27, 50, 22, 50, 22, 22, - /* 1450 */ 34, 23, 22, 22, 102, 109, 19, 24, 20, 38, - /* 1460 */ 25, 104, 138, 104, 22, 42, 5, 1, 108, 127, - /* 1470 */ 74, 22, 50, 1, 74, 16, 121, 119, 20, 108, - /* 1480 */ 51, 119, 57, 51, 22, 16, 23, 23, 127, 15, - /* 1490 */ 140, 128, 22, 3, 251, 4, 251, 63, + /* 1340 */ 131, 150, 150, 150, 211, 165, 150, 165, 104, 165, + /* 1350 */ 165, 23, 23, 25, 25, 211, 165, 165, 165, 176, + /* 1360 */ 23, 165, 25, 23, 23, 25, 25, 23, 211, 25, + /* 1370 */ 46, 176, 184, 103, 176, 22, 90, 176, 178, 18, + /* 1380 */ 176, 179, 176, 176, 179, 230, 230, 184, 157, 156, + /* 1390 */ 156, 44, 157, 156, 135, 157, 157, 238, 156, 239, + /* 1400 */ 157, 66, 189, 189, 22, 219, 157, 199, 18, 192, + /* 1410 */ 192, 192, 192, 189, 199, 157, 39, 243, 243, 157, + /* 1420 */ 157, 37, 246, 1, 164, 180, 180, 249, 15, 219, + /* 1430 */ 23, 252, 22, 252, 118, 118, 118, 118, 118, 113, + /* 1440 */ 98, 22, 11, 23, 23, 22, 22, 120, 23, 34, + /* 1450 */ 23, 25, 23, 25, 118, 25, 22, 102, 50, 23, + /* 1460 */ 23, 22, 27, 22, 50, 23, 34, 34, 22, 22, + /* 1470 */ 22, 109, 19, 24, 20, 104, 38, 25, 104, 22, + /* 1480 */ 5, 138, 1, 118, 34, 42, 27, 108, 22, 119, + /* 1490 */ 50, 74, 74, 127, 1, 16, 51, 121, 20, 119, + /* 1500 */ 108, 57, 51, 128, 22, 127, 23, 23, 16, 15, + /* 1510 */ 22, 3, 140, 4, 253, 253, 253, 253, 63, }; #define YY_SHIFT_USE_DFLT (-111) -#define YY_SHIFT_MAX 406 +#define YY_SHIFT_MAX 415 static const short yy_shift_ofst[] = { /* 0 */ 187, 1061, 1170, 1061, 1194, 1194, -2, 64, 64, -19, /* 10 */ 1194, 1194, 1194, 1194, 1194, 276, 1, 125, 1076, 1194, /* 20 */ 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, /* 30 */ 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, /* 40 */ 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, /* 50 */ 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, -48, - /* 60 */ 409, 1, 1, 141, 281, 281, -110, 53, 197, 269, + /* 60 */ 409, 1, 1, 141, 318, 318, -110, 53, 197, 269, /* 70 */ 341, 413, 485, 557, 629, 701, 773, 845, 773, 773, /* 80 */ 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, /* 90 */ 773, 773, 773, 773, 773, 773, 917, 989, 989, -67, - /* 100 */ -67, -1, -1, 55, 25, 379, 1, 1, 1, 1, - /* 110 */ 1, 639, 592, 1, 1, 1, 1, 1, 1, 1, - /* 120 */ 1, 1, 1, 1, 1, 1, 586, 141, -17, -111, - /* 130 */ -111, -111, 1209, 81, 376, 415, 426, 496, 90, 565, - /* 140 */ 565, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 100 */ -67, -1, -1, 55, 25, 310, 1, 1, 1, 1, + /* 110 */ 1, 639, 304, 1, 1, 1, 1, 1, 1, 1, + /* 120 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 365, + /* 130 */ 141, -17, -111, -111, -111, 1209, 81, 424, 353, 426, + /* 140 */ 441, 90, 565, 565, 1, 1, 1, 1, 1, 1, /* 150 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 160 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 170 */ 1, 1, 1, 1, 809, 949, 455, 641, 641, 641, - /* 180 */ 769, 101, -110, -110, -110, -111, -111, -111, 232, 232, - /* 190 */ 268, 428, 213, 575, 645, 785, 788, 412, 968, 502, - /* 200 */ 491, 52, 183, 183, 183, 614, 614, 711, 912, 614, - /* 210 */ 614, 614, 614, 229, 546, -13, 141, 762, 762, 249, - /* 220 */ 578, 578, 664, 578, 856, 578, 141, 578, 141, 926, - /* 230 */ 843, 664, 664, 843, 1043, 1043, 1043, 1043, 1087, 1087, - /* 240 */ 1089, -110, 1007, 1016, 1033, 1063, 1073, 1064, 1099, 1099, - /* 250 */ 1122, 1123, 1122, 1123, 1122, 1123, 1157, 1157, 1222, 1157, - /* 260 */ 1187, 1157, 1307, 1264, 1264, 1222, 1157, 1157, 1157, 1307, - /* 270 */ 1354, 1099, 1354, 1099, 1354, 1099, 1099, 1330, 1245, 1354, - /* 280 */ 1099, 1319, 1319, 1365, 1007, 1099, 1373, 1373, 1373, 1373, - /* 290 */ 1007, 1319, 1365, 1099, 1356, 1356, 1099, 1099, 1370, -111, - /* 300 */ -111, -111, -111, -111, 552, 1066, 1059, 1069, 712, 631, - /* 310 */ 915, 801, 946, 866, 1000, 1022, 1097, 1153, 1241, 1247, - /* 320 */ 1285, 515, 1337, 440, 1412, 1399, 1392, 1394, 1300, 1301, - /* 330 */ 1302, 1303, 1304, 1325, 1311, 1403, 1404, 1405, 1407, 1415, - /* 340 */ 1408, 1409, 1406, 1410, 1411, 1413, 1401, 1414, 1402, 1413, - /* 350 */ 1317, 1418, 1416, 1417, 1323, 1419, 1420, 1421, 1395, 1424, - /* 360 */ 1397, 1426, 1428, 1427, 1430, 1422, 1431, 1352, 1346, 1437, - /* 370 */ 1438, 1433, 1357, 1423, 1425, 1429, 1435, 1432, 1324, 1359, - /* 380 */ 1442, 1461, 1466, 1360, 1396, 1400, 1342, 1449, 1358, 1472, - /* 390 */ 1459, 1355, 1458, 1362, 1371, 1361, 1462, 1363, 1463, 1464, - /* 400 */ 1469, 1434, 1474, 1350, 1470, 1490, 1491, + /* 170 */ 1, 1, 1, 1, 1, 1, 447, 809, 327, 419, + /* 180 */ 419, 419, 841, 101, -110, -110, -110, -111, -111, -111, + /* 190 */ 232, 232, 268, 427, 575, 645, 788, 208, 861, 699, + /* 200 */ 897, 784, 637, 52, 183, 183, 183, 902, 902, 996, + /* 210 */ 1059, 902, 902, 902, 902, 275, 689, -13, 141, 824, + /* 220 */ 824, 478, 498, 498, 656, 498, 262, 498, 141, 498, + /* 230 */ 141, 860, 737, 712, 737, 656, 656, 712, 1017, 1017, + /* 240 */ 1017, 1017, 1040, 1040, 1089, -110, 1024, 1034, 1075, 1093, + /* 250 */ 1073, 1110, 1143, 1143, 1197, 1199, 1197, 1199, 1197, 1199, + /* 260 */ 1244, 1244, 1324, 1244, 1270, 1244, 1353, 1286, 1286, 1324, + /* 270 */ 1244, 1244, 1244, 1353, 1361, 1143, 1361, 1143, 1361, 1143, + /* 280 */ 1143, 1347, 1259, 1361, 1143, 1335, 1335, 1382, 1024, 1143, + /* 290 */ 1390, 1390, 1390, 1390, 1024, 1335, 1382, 1143, 1377, 1377, + /* 300 */ 1143, 1143, 1384, -111, -111, -111, -111, -111, -111, 552, + /* 310 */ 749, 1137, 1031, 1082, 1232, 801, 1097, 1153, 873, 1011, + /* 320 */ 853, 1163, 1257, 1328, 1329, 1337, 1340, 1341, 736, 1344, + /* 330 */ 1422, 1413, 1407, 1410, 1316, 1317, 1318, 1319, 1320, 1342, + /* 340 */ 1326, 1419, 1420, 1421, 1423, 1431, 1424, 1425, 1426, 1427, + /* 350 */ 1429, 1428, 1415, 1430, 1432, 1428, 1327, 1434, 1433, 1435, + /* 360 */ 1336, 1436, 1437, 1438, 1408, 1439, 1414, 1441, 1442, 1446, + /* 370 */ 1447, 1440, 1448, 1355, 1362, 1453, 1454, 1449, 1371, 1443, + /* 380 */ 1444, 1445, 1452, 1451, 1343, 1374, 1457, 1475, 1481, 1365, + /* 390 */ 1450, 1459, 1379, 1417, 1418, 1366, 1466, 1370, 1493, 1479, + /* 400 */ 1376, 1478, 1380, 1392, 1378, 1482, 1375, 1483, 1484, 1492, + /* 410 */ 1455, 1494, 1372, 1488, 1508, 1509, }; #define YY_REDUCE_USE_DFLT (-180) -#define YY_REDUCE_MAX 303 +#define YY_REDUCE_MAX 308 static const short yy_reduce_ofst[] = { /* 0 */ -141, 82, 154, 284, 12, 75, 69, 73, 142, -59, - /* 10 */ 145, 87, 159, 220, 226, 346, 289, 155, 429, 437, - /* 20 */ 442, 486, 499, 505, 507, 519, 558, 571, 577, 588, - /* 30 */ 591, 630, 643, 649, 651, 662, 702, 715, 721, 733, - /* 40 */ 774, 787, 793, 805, 846, 859, 865, 877, 881, 934, - /* 50 */ 936, 963, 967, 969, 998, 1053, 1072, 1088, 1109, -179, - /* 60 */ 850, 283, 380, 381, 89, 304, 390, 2, 2, 2, + /* 10 */ 145, 87, 159, 220, 291, 346, 226, 213, 357, 374, + /* 20 */ 429, 437, 442, 486, 499, 505, 507, 519, 558, 571, + /* 30 */ 577, 588, 630, 643, 649, 651, 662, 702, 715, 721, + /* 40 */ 733, 774, 787, 793, 805, 846, 859, 865, 877, 881, + /* 50 */ 934, 936, 963, 967, 969, 998, 1053, 1072, 1088, -179, + /* 60 */ 850, 956, 380, 308, 89, 496, 384, 2, 2, 2, /* 70 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 80 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 90 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - /* 100 */ 2, 2, 2, 215, 2, 2, 449, 574, 719, 722, - /* 110 */ 791, 134, 65, 942, 521, 794, -47, 878, 956, 986, - /* 120 */ 1003, 1047, 1074, 1092, 295, 1104, 2, 779, 2, 2, - /* 130 */ 2, 2, 158, 338, 572, 644, 650, 670, 723, 392, - /* 140 */ 564, 792, 885, 966, 1002, 1036, 723, 1084, 1091, 1100, - /* 150 */ 1130, 1141, 1146, 1149, 1150, 1152, 1154, 1155, 1166, 1168, - /* 160 */ 1171, 1172, 1180, 1182, 1184, 1185, 1191, 1192, 1193, 1196, - /* 170 */ 1198, 1201, 1202, 1203, 554, 554, 734, 238, 326, 373, - /* 180 */ -134, 278, 604, 710, 822, 44, 600, 635, -98, -70, - /* 190 */ -54, -36, -35, -35, -35, 13, -35, 14, 149, 115, - /* 200 */ 163, 14, 210, 223, 360, -35, -35, 359, 448, -35, - /* 210 */ -35, -35, -35, 513, 551, 598, 653, 596, 605, 647, - /* 220 */ 656, 724, 741, 796, 830, 806, 847, 849, 870, 844, - /* 230 */ 833, 832, 839, 854, 905, 940, 944, 945, 953, 954, - /* 240 */ 959, 929, 948, 950, 957, 987, 985, 988, 1062, 1086, - /* 250 */ 1023, 1034, 1041, 1044, 1042, 1049, 1095, 1106, 1114, 1125, - /* 260 */ 1134, 1137, 1165, 1129, 1135, 1186, 1179, 1188, 1195, 1190, - /* 270 */ 1217, 1218, 1220, 1221, 1223, 1224, 1225, 1139, 1144, 1228, - /* 280 */ 1229, 1199, 1200, 1173, 1197, 1233, 1205, 1206, 1207, 1208, - /* 290 */ 1204, 1212, 1174, 1237, 1161, 1163, 1248, 1249, 1164, 1246, - /* 300 */ 1231, 1232, 1162, 1167, + /* 100 */ 2, 2, 2, 416, 2, 2, 449, 579, 648, 723, + /* 110 */ 791, 134, 501, 716, 521, 794, 589, -47, 650, 590, + /* 120 */ 795, 942, 974, 986, 1003, 1047, 1074, 935, 1091, 2, + /* 130 */ 417, 2, 2, 2, 2, 158, 336, 526, 576, 863, + /* 140 */ 885, 966, 405, 428, 968, 1039, 1069, 1099, 1100, 966, + /* 150 */ 1101, 1107, 1109, 1118, 1120, 1140, 1141, 1145, 1146, 1148, + /* 160 */ 1149, 1150, 1152, 1154, 1166, 1168, 1171, 1172, 1180, 1182, + /* 170 */ 1184, 1185, 1191, 1192, 1193, 1196, 403, 403, 652, 377, + /* 180 */ 663, 667, -134, 780, 888, 933, 1066, 44, 672, 698, + /* 190 */ -98, -70, -54, -36, -35, -35, -35, 13, -35, 14, + /* 200 */ 146, 181, 227, 14, 203, 223, 250, -35, -35, 224, + /* 210 */ 202, -35, -35, -35, -35, 339, 309, 312, 381, 317, + /* 220 */ 376, 457, 515, 570, 619, 584, 687, 705, 709, 765, + /* 230 */ 726, 786, 730, 778, 741, 803, 813, 827, 883, 892, + /* 240 */ 896, 900, 903, 943, 964, 932, 930, 958, 984, 1015, + /* 250 */ 1030, 1025, 1112, 1114, 1098, 1133, 1102, 1144, 1119, 1157, + /* 260 */ 1183, 1195, 1188, 1198, 1200, 1201, 1202, 1155, 1156, 1203, + /* 270 */ 1204, 1206, 1207, 1205, 1233, 1231, 1234, 1235, 1237, 1238, + /* 280 */ 1239, 1159, 1160, 1242, 1243, 1213, 1214, 1186, 1208, 1249, + /* 290 */ 1217, 1218, 1219, 1220, 1215, 1224, 1210, 1258, 1174, 1175, + /* 300 */ 1262, 1263, 1176, 1260, 1245, 1246, 1178, 1179, 1181, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 621, 856, 939, 939, 856, 939, 939, 885, 885, 744, - /* 10 */ 854, 939, 939, 939, 939, 939, 939, 914, 939, 939, - /* 20 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 30 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 40 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 50 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 828, - /* 60 */ 939, 939, 939, 660, 885, 885, 748, 779, 939, 939, - /* 70 */ 939, 939, 939, 939, 939, 939, 780, 939, 858, 853, - /* 80 */ 849, 851, 850, 857, 781, 770, 777, 784, 759, 898, - /* 90 */ 786, 787, 793, 794, 915, 913, 816, 815, 834, 818, - /* 100 */ 840, 817, 827, 652, 819, 820, 939, 939, 939, 939, - /* 110 */ 939, 713, 647, 939, 939, 939, 939, 939, 939, 939, - /* 120 */ 939, 939, 939, 939, 939, 939, 821, 939, 822, 835, - /* 130 */ 836, 837, 939, 939, 939, 939, 939, 939, 939, 939, - /* 140 */ 939, 627, 939, 939, 939, 939, 939, 939, 939, 939, - /* 150 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 160 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 869, - /* 170 */ 939, 918, 920, 939, 939, 939, 621, 744, 744, 744, - /* 180 */ 939, 939, 939, 939, 939, 738, 748, 932, 939, 939, - /* 190 */ 704, 939, 939, 939, 939, 939, 939, 939, 629, 736, - /* 200 */ 662, 746, 939, 939, 939, 649, 725, 891, 939, 905, - /* 210 */ 903, 727, 789, 939, 736, 745, 939, 939, 939, 852, - /* 220 */ 773, 773, 761, 773, 683, 773, 939, 773, 939, 686, - /* 230 */ 783, 761, 761, 783, 626, 626, 626, 626, 637, 637, - /* 240 */ 703, 939, 783, 774, 776, 766, 778, 939, 752, 752, - /* 250 */ 760, 765, 760, 765, 760, 765, 715, 715, 700, 715, - /* 260 */ 686, 715, 862, 866, 866, 700, 715, 715, 715, 862, - /* 270 */ 644, 752, 644, 752, 644, 752, 752, 895, 897, 644, - /* 280 */ 752, 717, 717, 795, 783, 752, 724, 724, 724, 724, - /* 290 */ 783, 717, 795, 752, 917, 917, 752, 752, 925, 670, - /* 300 */ 688, 688, 932, 937, 939, 939, 939, 939, 939, 939, - /* 310 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 320 */ 939, 871, 939, 939, 939, 635, 939, 654, 802, 807, - /* 330 */ 803, 939, 804, 939, 730, 939, 939, 939, 939, 939, - /* 340 */ 939, 939, 939, 939, 939, 855, 939, 767, 939, 775, - /* 350 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 360 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 370 */ 939, 939, 939, 939, 939, 893, 894, 939, 939, 939, - /* 380 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 390 */ 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, - /* 400 */ 939, 924, 939, 939, 927, 622, 939, 617, 619, 620, - /* 410 */ 624, 625, 628, 654, 655, 657, 658, 659, 630, 631, - /* 420 */ 632, 633, 634, 636, 640, 638, 639, 641, 648, 650, - /* 430 */ 669, 671, 673, 734, 735, 799, 728, 729, 733, 656, - /* 440 */ 810, 801, 805, 806, 808, 809, 823, 824, 826, 832, - /* 450 */ 839, 842, 825, 830, 831, 833, 838, 841, 731, 732, - /* 460 */ 845, 663, 664, 667, 668, 881, 883, 882, 884, 666, - /* 470 */ 665, 811, 814, 847, 848, 906, 907, 908, 909, 910, - /* 480 */ 843, 753, 846, 829, 768, 771, 772, 769, 737, 747, - /* 490 */ 755, 756, 757, 758, 742, 743, 749, 764, 797, 798, - /* 500 */ 762, 763, 750, 751, 739, 740, 741, 844, 800, 812, - /* 510 */ 813, 674, 675, 807, 676, 677, 678, 716, 719, 720, - /* 520 */ 721, 679, 698, 701, 702, 680, 687, 681, 682, 689, - /* 530 */ 690, 691, 694, 695, 696, 697, 692, 693, 863, 864, - /* 540 */ 867, 865, 684, 685, 699, 672, 661, 653, 705, 708, - /* 550 */ 709, 710, 711, 712, 714, 706, 707, 651, 642, 645, - /* 560 */ 754, 887, 896, 892, 888, 889, 890, 646, 859, 860, - /* 570 */ 718, 791, 792, 886, 899, 901, 796, 902, 904, 900, - /* 580 */ 929, 643, 722, 723, 726, 868, 911, 782, 785, 788, - /* 590 */ 790, 870, 872, 874, 876, 877, 878, 879, 880, 873, - /* 600 */ 875, 912, 916, 919, 921, 922, 923, 926, 928, 933, - /* 610 */ 934, 935, 938, 936, 623, 618, + /* 0 */ 634, 869, 958, 958, 869, 958, 958, 898, 898, 757, + /* 10 */ 867, 958, 958, 958, 958, 958, 958, 932, 958, 958, + /* 20 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 30 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 40 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 50 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 841, + /* 60 */ 958, 958, 958, 673, 898, 898, 761, 792, 958, 958, + /* 70 */ 958, 958, 958, 958, 958, 958, 793, 958, 871, 866, + /* 80 */ 862, 864, 863, 870, 794, 783, 790, 797, 772, 911, + /* 90 */ 799, 800, 806, 807, 933, 931, 829, 828, 847, 831, + /* 100 */ 853, 830, 840, 665, 832, 833, 958, 958, 958, 958, + /* 110 */ 958, 726, 660, 958, 958, 958, 958, 958, 958, 958, + /* 120 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 834, + /* 130 */ 958, 835, 848, 849, 850, 958, 958, 958, 958, 958, + /* 140 */ 958, 958, 958, 958, 640, 958, 958, 958, 958, 958, + /* 150 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 160 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 170 */ 958, 882, 958, 936, 938, 958, 958, 958, 634, 757, + /* 180 */ 757, 757, 958, 958, 958, 958, 958, 751, 761, 950, + /* 190 */ 958, 958, 717, 958, 958, 958, 958, 958, 958, 958, + /* 200 */ 642, 749, 675, 759, 958, 958, 958, 662, 738, 904, + /* 210 */ 958, 923, 921, 740, 802, 958, 749, 758, 958, 958, + /* 220 */ 958, 865, 786, 786, 774, 786, 696, 786, 958, 786, + /* 230 */ 958, 699, 916, 796, 916, 774, 774, 796, 639, 639, + /* 240 */ 639, 639, 650, 650, 716, 958, 796, 787, 789, 779, + /* 250 */ 791, 958, 765, 765, 773, 778, 773, 778, 773, 778, + /* 260 */ 728, 728, 713, 728, 699, 728, 875, 879, 879, 713, + /* 270 */ 728, 728, 728, 875, 657, 765, 657, 765, 657, 765, + /* 280 */ 765, 908, 910, 657, 765, 730, 730, 808, 796, 765, + /* 290 */ 737, 737, 737, 737, 796, 730, 808, 765, 935, 935, + /* 300 */ 765, 765, 943, 683, 701, 701, 950, 955, 955, 958, + /* 310 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 320 */ 958, 958, 958, 958, 958, 958, 958, 958, 884, 958, + /* 330 */ 958, 648, 958, 667, 815, 820, 816, 958, 817, 958, + /* 340 */ 743, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 350 */ 958, 868, 958, 780, 958, 788, 958, 958, 958, 958, + /* 360 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 370 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 380 */ 958, 906, 907, 958, 958, 958, 958, 958, 958, 914, + /* 390 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 400 */ 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, + /* 410 */ 942, 958, 958, 945, 635, 958, 630, 632, 633, 637, + /* 420 */ 638, 641, 667, 668, 670, 671, 672, 643, 644, 645, + /* 430 */ 646, 647, 649, 653, 651, 652, 654, 661, 663, 682, + /* 440 */ 684, 686, 747, 748, 812, 741, 742, 746, 669, 823, + /* 450 */ 814, 818, 819, 821, 822, 836, 837, 839, 845, 852, + /* 460 */ 855, 838, 843, 844, 846, 851, 854, 744, 745, 858, + /* 470 */ 676, 677, 680, 681, 894, 896, 895, 897, 679, 678, + /* 480 */ 824, 827, 860, 861, 924, 925, 926, 927, 928, 856, + /* 490 */ 766, 859, 842, 781, 784, 785, 782, 750, 760, 768, + /* 500 */ 769, 770, 771, 755, 756, 762, 777, 810, 811, 775, + /* 510 */ 776, 763, 764, 752, 753, 754, 857, 813, 825, 826, + /* 520 */ 687, 688, 820, 689, 690, 691, 729, 732, 733, 734, + /* 530 */ 692, 711, 714, 715, 693, 700, 694, 695, 702, 703, + /* 540 */ 704, 707, 708, 709, 710, 705, 706, 876, 877, 880, + /* 550 */ 878, 697, 698, 712, 685, 674, 666, 718, 721, 722, + /* 560 */ 723, 724, 725, 727, 719, 720, 664, 655, 658, 767, + /* 570 */ 900, 909, 905, 901, 902, 903, 659, 872, 873, 731, + /* 580 */ 804, 805, 899, 912, 915, 917, 918, 919, 809, 920, + /* 590 */ 922, 913, 947, 656, 735, 736, 739, 881, 929, 795, + /* 600 */ 798, 801, 803, 883, 885, 887, 889, 890, 891, 892, + /* 610 */ 893, 886, 888, 930, 934, 937, 939, 940, 941, 944, + /* 620 */ 946, 951, 952, 953, 956, 957, 954, 636, 631, }; #define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0])) /* The next table maps tokens into fallback tokens. If a construct ** like the following: @@ -85081,86 +88934,10 @@ 26, /* VIEW => ID */ 26, /* VIRTUAL => ID */ 26, /* REINDEX => ID */ 26, /* RENAME => ID */ 26, /* CTIME_KW => ID */ - 0, /* ANY => nothing */ - 0, /* OR => nothing */ - 0, /* AND => nothing */ - 0, /* IS => nothing */ - 0, /* BETWEEN => nothing */ - 0, /* IN => nothing */ - 0, /* ISNULL => nothing */ - 0, /* NOTNULL => nothing */ - 0, /* NE => nothing */ - 0, /* EQ => nothing */ - 0, /* GT => nothing */ - 0, /* LE => nothing */ - 0, /* LT => nothing */ - 0, /* GE => nothing */ - 0, /* ESCAPE => nothing */ - 0, /* BITAND => nothing */ - 0, /* BITOR => nothing */ - 0, /* LSHIFT => nothing */ - 0, /* RSHIFT => nothing */ - 0, /* PLUS => nothing */ - 0, /* MINUS => nothing */ - 0, /* STAR => nothing */ - 0, /* SLASH => nothing */ - 0, /* REM => nothing */ - 0, /* CONCAT => nothing */ - 0, /* COLLATE => nothing */ - 0, /* UMINUS => nothing */ - 0, /* UPLUS => nothing */ - 0, /* BITNOT => nothing */ - 0, /* STRING => nothing */ - 0, /* JOIN_KW => nothing */ - 0, /* CONSTRAINT => nothing */ - 0, /* DEFAULT => nothing */ - 0, /* NULL => nothing */ - 0, /* PRIMARY => nothing */ - 0, /* UNIQUE => nothing */ - 0, /* CHECK => nothing */ - 0, /* REFERENCES => nothing */ - 0, /* AUTOINCR => nothing */ - 0, /* ON => nothing */ - 0, /* DELETE => nothing */ - 0, /* UPDATE => nothing */ - 0, /* INSERT => nothing */ - 0, /* SET => nothing */ - 0, /* DEFERRABLE => nothing */ - 0, /* FOREIGN => nothing */ - 0, /* DROP => nothing */ - 0, /* UNION => nothing */ - 0, /* ALL => nothing */ - 0, /* EXCEPT => nothing */ - 0, /* INTERSECT => nothing */ - 0, /* SELECT => nothing */ - 0, /* DISTINCT => nothing */ - 0, /* DOT => nothing */ - 0, /* FROM => nothing */ - 0, /* JOIN => nothing */ - 0, /* USING => nothing */ - 0, /* ORDER => nothing */ - 0, /* GROUP => nothing */ - 0, /* HAVING => nothing */ - 0, /* LIMIT => nothing */ - 0, /* WHERE => nothing */ - 0, /* INTO => nothing */ - 0, /* VALUES => nothing */ - 0, /* INTEGER => nothing */ - 0, /* FLOAT => nothing */ - 0, /* BLOB => nothing */ - 0, /* REGISTER => nothing */ - 0, /* VARIABLE => nothing */ - 0, /* CASE => nothing */ - 0, /* WHEN => nothing */ - 0, /* THEN => nothing */ - 0, /* ELSE => nothing */ - 0, /* INDEX => nothing */ - 0, /* ALTER => nothing */ - 0, /* ADD => nothing */ }; #endif /* YYFALLBACK */ /* The following structure represents a single element of the ** parser's stack. Information stored includes: @@ -85294,13 +89071,14 @@ "itemlist", "exprlist", "likeop", "escape", "between_op", "in_op", "case_operand", "case_exprlist", "case_else", "uniqueflag", "collate", "nmnum", "plus_opt", "number", "trigger_decl", "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", "when_clause", - "trigger_cmd", "database_kw_opt", "key_opt", "add_column_fullname", - "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg", - "vtabargtoken", "lp", "anylist", + "trigger_cmd", "trnm", "tridxby", "database_kw_opt", + "key_opt", "add_column_fullname", "kwcolumn_opt", "create_vtab", + "vtabarglist", "vtabarg", "vtabargtoken", "lp", + "anylist", }; #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. @@ -85589,48 +89367,54 @@ /* 280 */ "foreach_clause ::= FOR EACH ROW", /* 281 */ "when_clause ::=", /* 282 */ "when_clause ::= WHEN expr", /* 283 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", /* 284 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 285 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", - /* 286 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", - /* 287 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", - /* 288 */ "trigger_cmd ::= DELETE FROM nm where_opt", - /* 289 */ "trigger_cmd ::= select", - /* 290 */ "expr ::= RAISE LP IGNORE RP", - /* 291 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 292 */ "raisetype ::= ROLLBACK", - /* 293 */ "raisetype ::= ABORT", - /* 294 */ "raisetype ::= FAIL", - /* 295 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 296 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 297 */ "cmd ::= DETACH database_kw_opt expr", - /* 298 */ "key_opt ::=", - /* 299 */ "key_opt ::= KEY expr", - /* 300 */ "database_kw_opt ::= DATABASE", - /* 301 */ "database_kw_opt ::=", - /* 302 */ "cmd ::= REINDEX", - /* 303 */ "cmd ::= REINDEX nm dbnm", - /* 304 */ "cmd ::= ANALYZE", - /* 305 */ "cmd ::= ANALYZE nm dbnm", - /* 306 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 307 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 308 */ "add_column_fullname ::= fullname", - /* 309 */ "kwcolumn_opt ::=", - /* 310 */ "kwcolumn_opt ::= COLUMNKW", - /* 311 */ "cmd ::= create_vtab", - /* 312 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 313 */ "create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm", - /* 314 */ "vtabarglist ::= vtabarg", - /* 315 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 316 */ "vtabarg ::=", - /* 317 */ "vtabarg ::= vtabarg vtabargtoken", - /* 318 */ "vtabargtoken ::= ANY", - /* 319 */ "vtabargtoken ::= lp anylist RP", - /* 320 */ "lp ::= LP", - /* 321 */ "anylist ::=", - /* 322 */ "anylist ::= anylist ANY", + /* 285 */ "trnm ::= nm", + /* 286 */ "trnm ::= nm DOT nm", + /* 287 */ "tridxby ::=", + /* 288 */ "tridxby ::= INDEXED BY nm", + /* 289 */ "tridxby ::= NOT INDEXED", + /* 290 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 291 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt VALUES LP itemlist RP", + /* 292 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select", + /* 293 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 294 */ "trigger_cmd ::= select", + /* 295 */ "expr ::= RAISE LP IGNORE RP", + /* 296 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 297 */ "raisetype ::= ROLLBACK", + /* 298 */ "raisetype ::= ABORT", + /* 299 */ "raisetype ::= FAIL", + /* 300 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 301 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 302 */ "cmd ::= DETACH database_kw_opt expr", + /* 303 */ "key_opt ::=", + /* 304 */ "key_opt ::= KEY expr", + /* 305 */ "database_kw_opt ::= DATABASE", + /* 306 */ "database_kw_opt ::=", + /* 307 */ "cmd ::= REINDEX", + /* 308 */ "cmd ::= REINDEX nm dbnm", + /* 309 */ "cmd ::= ANALYZE", + /* 310 */ "cmd ::= ANALYZE nm dbnm", + /* 311 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 312 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 313 */ "add_column_fullname ::= fullname", + /* 314 */ "kwcolumn_opt ::=", + /* 315 */ "kwcolumn_opt ::= COLUMNKW", + /* 316 */ "cmd ::= create_vtab", + /* 317 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 318 */ "create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm", + /* 319 */ "vtabarglist ::= vtabarg", + /* 320 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 321 */ "vtabarg ::=", + /* 322 */ "vtabarg ::= vtabarg vtabargtoken", + /* 323 */ "vtabargtoken ::= ANY", + /* 324 */ "vtabargtoken ::= lp anylist RP", + /* 325 */ "lp ::= LP", + /* 326 */ "anylist ::=", + /* 327 */ "anylist ::= anylist LP anylist RP", + /* 328 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ #if YYSTACKDEPTH<=0 @@ -85708,26 +89492,18 @@ ** inside the C code. */ case 160: /* select */ case 194: /* oneselect */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy243)); +sqlite3SelectDelete(pParse->db, (yypminor->yy3)); } break; case 174: /* term */ case 175: /* expr */ - case 199: /* where_opt */ - case 201: /* having_opt */ - case 210: /* on_opt */ - case 215: /* sortitem */ case 223: /* escape */ - case 226: /* case_operand */ - case 228: /* case_else */ - case 239: /* when_clause */ - case 242: /* key_opt */ -{ -sqlite3ExprDelete(pParse->db, (yypminor->yy72)); +{ +sqlite3ExprDelete(pParse->db, (yypminor->yy346).pExpr); } break; case 179: /* idxlist_opt */ case 187: /* idxlist */ case 197: /* selcollist */ @@ -85739,37 +89515,49 @@ case 217: /* setlist */ case 220: /* itemlist */ case 221: /* exprlist */ case 227: /* case_exprlist */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy148)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); } break; case 193: /* fullname */ case 198: /* from */ case 206: /* seltablist */ case 207: /* stl_prefix */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy185)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy65)); +} + break; + case 199: /* where_opt */ + case 201: /* having_opt */ + case 210: /* on_opt */ + case 215: /* sortitem */ + case 226: /* case_operand */ + case 228: /* case_else */ + case 239: /* when_clause */ + case 244: /* key_opt */ +{ +sqlite3ExprDelete(pParse->db, (yypminor->yy132)); } break; case 211: /* using_opt */ case 213: /* inscollist */ case 219: /* inscollist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy254)); +sqlite3IdListDelete(pParse->db, (yypminor->yy408)); } break; case 235: /* trigger_cmd_list */ case 240: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy145)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy473)); } break; case 237: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy332).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy378).b); } break; default: break; /* If no destructor action specified: do nothing */ } } @@ -85784,11 +89572,13 @@ */ static int yy_pop_parser_stack(yyParser *pParser){ YYCODETYPE yymajor; yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; - if( pParser->yyidx<0 ) return 0; + /* There is no mechanism by which the parser stack can be popped below + ** empty in SQLite. */ + if( NEVER(pParser->yyidx<0) ) return 0; #ifndef NDEBUG if( yyTraceFILE && pParser->yyidx>=0 ){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); @@ -85815,11 +89605,13 @@ SQLITE_PRIVATE void sqlite3ParserFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ yyParser *pParser = (yyParser*)p; - if( pParser==0 ) return; + /* In SQLite, we never try to destroy a parser that was not successfully + ** created in the first place. */ + if( NEVER(pParser==0) ) return; while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); #if YYSTACKDEPTH<=0 free(pParser->yystack); #endif (*freeProc)((void*)pParser); @@ -85854,10 +89646,12 @@ return yy_default[stateno]; } assert( iLookAhead!=YYNOCODE ); i += iLookAhead; if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ + /* The user of ";" instead of "\000" as a statement terminator in SQLite + ** means that we always have a look-ahead token. */ if( iLookAhead>0 ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) && (iFallback = yyFallback[iLookAhead])!=0 ){ @@ -86283,48 +90077,54 @@ { 238, 3 }, { 239, 0 }, { 239, 2 }, { 235, 3 }, { 235, 2 }, - { 240, 6 }, + { 241, 1 }, + { 241, 3 }, + { 242, 0 }, + { 242, 3 }, + { 242, 2 }, + { 240, 7 }, { 240, 8 }, { 240, 5 }, - { 240, 4 }, + { 240, 5 }, { 240, 1 }, { 175, 4 }, { 175, 6 }, { 191, 1 }, { 191, 1 }, { 191, 1 }, { 147, 4 }, { 147, 6 }, { 147, 3 }, - { 242, 0 }, - { 242, 2 }, - { 241, 1 }, - { 241, 0 }, + { 244, 0 }, + { 244, 2 }, + { 243, 1 }, + { 243, 0 }, { 147, 1 }, { 147, 3 }, { 147, 1 }, { 147, 3 }, { 147, 6 }, { 147, 6 }, - { 243, 1 }, - { 244, 0 }, - { 244, 1 }, + { 245, 1 }, + { 246, 0 }, + { 246, 1 }, { 147, 1 }, { 147, 4 }, - { 245, 7 }, - { 246, 1 }, - { 246, 3 }, - { 247, 0 }, - { 247, 2 }, + { 247, 7 }, { 248, 1 }, { 248, 3 }, - { 249, 1 }, - { 250, 0 }, - { 250, 2 }, + { 249, 0 }, + { 249, 2 }, + { 250, 1 }, + { 250, 3 }, + { 251, 1 }, + { 252, 0 }, + { 252, 4 }, + { 252, 2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ /* @@ -86375,50 +90175,10 @@ ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ - case 0: /* input ::= cmdlist */ - case 1: /* cmdlist ::= cmdlist ecmd */ - case 2: /* cmdlist ::= ecmd */ - case 3: /* ecmd ::= SEMI */ - case 4: /* ecmd ::= explain cmdx SEMI */ - case 10: /* trans_opt ::= */ - case 11: /* trans_opt ::= TRANSACTION */ - case 12: /* trans_opt ::= TRANSACTION nm */ - case 20: /* savepoint_opt ::= SAVEPOINT */ - case 21: /* savepoint_opt ::= */ - case 25: /* cmd ::= create_table create_table_args */ - case 34: /* columnlist ::= columnlist COMMA column */ - case 35: /* columnlist ::= column */ - case 44: /* type ::= */ - case 51: /* signed ::= plus_num */ - case 52: /* signed ::= minus_num */ - case 53: /* carglist ::= carglist carg */ - case 54: /* carglist ::= */ - case 55: /* carg ::= CONSTRAINT nm ccons */ - case 56: /* carg ::= ccons */ - case 62: /* ccons ::= NULL onconf */ - case 89: /* conslist ::= conslist COMMA tcons */ - case 90: /* conslist ::= conslist tcons */ - case 91: /* conslist ::= tcons */ - case 92: /* tcons ::= CONSTRAINT nm */ - case 268: /* plus_opt ::= PLUS */ - case 269: /* plus_opt ::= */ - case 279: /* foreach_clause ::= */ - case 280: /* foreach_clause ::= FOR EACH ROW */ - case 300: /* database_kw_opt ::= DATABASE */ - case 301: /* database_kw_opt ::= */ - case 309: /* kwcolumn_opt ::= */ - case 310: /* kwcolumn_opt ::= COLUMNKW */ - case 314: /* vtabarglist ::= vtabarg */ - case 315: /* vtabarglist ::= vtabarglist COMMA vtabarg */ - case 317: /* vtabarg ::= vtabarg vtabargtoken */ - case 321: /* anylist ::= */ -{ -} - break; case 5: /* explain ::= */ { sqlite3BeginParse(pParse, 0); } break; case 6: /* explain ::= EXPLAIN */ { sqlite3BeginParse(pParse, 1); } @@ -86428,24 +90188,24 @@ break; case 8: /* cmdx ::= cmd */ { sqlite3FinishCoding(pParse); } break; case 9: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy194);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy328);} break; case 13: /* transtype ::= */ -{yygotominor.yy194 = TK_DEFERRED;} +{yygotominor.yy328 = TK_DEFERRED;} break; case 14: /* transtype ::= DEFERRED */ - case 15: /* transtype ::= IMMEDIATE */ - case 16: /* transtype ::= EXCLUSIVE */ - case 114: /* multiselect_op ::= UNION */ - case 116: /* multiselect_op ::= EXCEPT|INTERSECT */ -{yygotominor.yy194 = yymsp[0].major;} + case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15); + case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16); + case 114: /* multiselect_op ::= UNION */ yytestcase(yyruleno==114); + case 116: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==116); +{yygotominor.yy328 = yymsp[0].major;} break; case 17: /* cmd ::= COMMIT trans_opt */ - case 18: /* cmd ::= END trans_opt */ + case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18); {sqlite3CommitTransaction(pParse);} break; case 19: /* cmd ::= ROLLBACK trans_opt */ {sqlite3RollbackTransaction(pParse);} break; @@ -86464,51 +90224,51 @@ sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0); } break; case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy194,0,0,yymsp[-2].minor.yy194); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy328,0,0,yymsp[-2].minor.yy328); } break; case 27: /* createkw ::= CREATE */ { pParse->db->lookaside.bEnabled = 0; yygotominor.yy0 = yymsp[0].minor.yy0; } break; case 28: /* ifnotexists ::= */ - case 31: /* temp ::= */ - case 70: /* autoinc ::= */ - case 84: /* init_deferred_pred_opt ::= */ - case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - case 97: /* defer_subclause_opt ::= */ - case 108: /* ifexists ::= */ - case 119: /* distinct ::= ALL */ - case 120: /* distinct ::= */ - case 222: /* between_op ::= BETWEEN */ - case 225: /* in_op ::= IN */ -{yygotominor.yy194 = 0;} + case 31: /* temp ::= */ yytestcase(yyruleno==31); + case 70: /* autoinc ::= */ yytestcase(yyruleno==70); + case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); + case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); + case 97: /* defer_subclause_opt ::= */ yytestcase(yyruleno==97); + case 108: /* ifexists ::= */ yytestcase(yyruleno==108); + case 119: /* distinct ::= ALL */ yytestcase(yyruleno==119); + case 120: /* distinct ::= */ yytestcase(yyruleno==120); + case 222: /* between_op ::= BETWEEN */ yytestcase(yyruleno==222); + case 225: /* in_op ::= IN */ yytestcase(yyruleno==225); +{yygotominor.yy328 = 0;} break; case 29: /* ifnotexists ::= IF NOT EXISTS */ - case 30: /* temp ::= TEMP */ - case 71: /* autoinc ::= AUTOINCR */ - case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ - case 107: /* ifexists ::= IF EXISTS */ - case 118: /* distinct ::= DISTINCT */ - case 223: /* between_op ::= NOT BETWEEN */ - case 226: /* in_op ::= NOT IN */ -{yygotominor.yy194 = 1;} + case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); + case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71); + case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); + case 107: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==107); + case 118: /* distinct ::= DISTINCT */ yytestcase(yyruleno==118); + case 223: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==223); + case 226: /* in_op ::= NOT IN */ yytestcase(yyruleno==226); +{yygotominor.yy328 = 1;} break; case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ { sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0); } break; case 33: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy243); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); + sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy3); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3); } break; case 36: /* column ::= columnid type carglist */ { yygotominor.yy0.z = yymsp[-2].minor.yy0.z; @@ -86520,30 +90280,31 @@ sqlite3AddColumn(pParse,&yymsp[0].minor.yy0); yygotominor.yy0 = yymsp[0].minor.yy0; } break; case 38: /* id ::= ID */ - case 39: /* id ::= INDEXED */ - case 40: /* ids ::= ID|STRING */ - case 41: /* nm ::= id */ - case 42: /* nm ::= STRING */ - case 43: /* nm ::= JOIN_KW */ - case 46: /* typetoken ::= typename */ - case 49: /* typename ::= ids */ - case 126: /* as ::= AS nm */ - case 127: /* as ::= ids */ - case 137: /* dbnm ::= DOT nm */ - case 146: /* indexed_opt ::= INDEXED BY nm */ - case 251: /* collate ::= COLLATE ids */ - case 260: /* nmnum ::= plus_num */ - case 261: /* nmnum ::= nm */ - case 262: /* nmnum ::= ON */ - case 263: /* nmnum ::= DELETE */ - case 264: /* nmnum ::= DEFAULT */ - case 265: /* plus_num ::= plus_opt number */ - case 266: /* minus_num ::= MINUS number */ - case 267: /* number ::= INTEGER|FLOAT */ + case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39); + case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40); + case 41: /* nm ::= id */ yytestcase(yyruleno==41); + case 42: /* nm ::= STRING */ yytestcase(yyruleno==42); + case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43); + case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46); + case 49: /* typename ::= ids */ yytestcase(yyruleno==49); + case 126: /* as ::= AS nm */ yytestcase(yyruleno==126); + case 127: /* as ::= ids */ yytestcase(yyruleno==127); + case 137: /* dbnm ::= DOT nm */ yytestcase(yyruleno==137); + case 146: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==146); + case 251: /* collate ::= COLLATE ids */ yytestcase(yyruleno==251); + case 260: /* nmnum ::= plus_num */ yytestcase(yyruleno==260); + case 261: /* nmnum ::= nm */ yytestcase(yyruleno==261); + case 262: /* nmnum ::= ON */ yytestcase(yyruleno==262); + case 263: /* nmnum ::= DELETE */ yytestcase(yyruleno==263); + case 264: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==264); + case 265: /* plus_num ::= plus_opt number */ yytestcase(yyruleno==265); + case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266); + case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267); + case 285: /* trnm ::= nm */ yytestcase(yyruleno==285); {yygotominor.yy0 = yymsp[0].minor.yy0;} break; case 45: /* type ::= typetoken */ {sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);} break; @@ -86561,670 +90322,698 @@ break; case 50: /* typename ::= typename ids */ {yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);} break; case 57: /* ccons ::= DEFAULT term */ - case 59: /* ccons ::= DEFAULT PLUS term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy72);} + case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59); +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy346);} break; case 58: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy72);} +{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy346);} break; case 60: /* ccons ::= DEFAULT MINUS term */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy72, 0, 0); - sqlite3ExprSpan(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72->span); - sqlite3AddDefaultValue(pParse,p); + ExprSpan v; + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy346.pExpr, 0, 0); + v.zStart = yymsp[-1].minor.yy0.z; + v.zEnd = yymsp[0].minor.yy346.zEnd; + sqlite3AddDefaultValue(pParse,&v); } break; case 61: /* ccons ::= DEFAULT id */ { - Expr *p = sqlite3PExpr(pParse, TK_STRING, 0, 0, &yymsp[0].minor.yy0); - sqlite3AddDefaultValue(pParse,p); + ExprSpan v; + spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0); + sqlite3AddDefaultValue(pParse,&v); } break; case 63: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy194);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy328);} break; case 64: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy328,yymsp[0].minor.yy328,yymsp[-2].minor.yy328);} break; case 65: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy194,0,0,0,0);} +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy328,0,0,0,0);} break; case 66: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy72);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy346.pExpr);} break; case 67: /* ccons ::= REFERENCES nm idxlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy328);} break; case 68: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy194);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy328);} break; case 69: /* ccons ::= COLLATE ids */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 72: /* refargs ::= */ -{ yygotominor.yy194 = OE_Restrict * 0x010101; } +{ yygotominor.yy328 = OE_Restrict * 0x010101; } break; case 73: /* refargs ::= refargs refarg */ -{ yygotominor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; } +{ yygotominor.yy328 = (yymsp[-1].minor.yy328 & ~yymsp[0].minor.yy429.mask) | yymsp[0].minor.yy429.value; } break; case 74: /* refarg ::= MATCH nm */ -{ yygotominor.yy497.value = 0; yygotominor.yy497.mask = 0x000000; } +{ yygotominor.yy429.value = 0; yygotominor.yy429.mask = 0x000000; } break; case 75: /* refarg ::= ON DELETE refact */ -{ yygotominor.yy497.value = yymsp[0].minor.yy194; yygotominor.yy497.mask = 0x0000ff; } +{ yygotominor.yy429.value = yymsp[0].minor.yy328; yygotominor.yy429.mask = 0x0000ff; } break; case 76: /* refarg ::= ON UPDATE refact */ -{ yygotominor.yy497.value = yymsp[0].minor.yy194<<8; yygotominor.yy497.mask = 0x00ff00; } +{ yygotominor.yy429.value = yymsp[0].minor.yy328<<8; yygotominor.yy429.mask = 0x00ff00; } break; case 77: /* refarg ::= ON INSERT refact */ -{ yygotominor.yy497.value = yymsp[0].minor.yy194<<16; yygotominor.yy497.mask = 0xff0000; } +{ yygotominor.yy429.value = yymsp[0].minor.yy328<<16; yygotominor.yy429.mask = 0xff0000; } break; case 78: /* refact ::= SET NULL */ -{ yygotominor.yy194 = OE_SetNull; } +{ yygotominor.yy328 = OE_SetNull; } break; case 79: /* refact ::= SET DEFAULT */ -{ yygotominor.yy194 = OE_SetDflt; } +{ yygotominor.yy328 = OE_SetDflt; } break; case 80: /* refact ::= CASCADE */ -{ yygotominor.yy194 = OE_Cascade; } +{ yygotominor.yy328 = OE_Cascade; } break; case 81: /* refact ::= RESTRICT */ -{ yygotominor.yy194 = OE_Restrict; } +{ yygotominor.yy328 = OE_Restrict; } break; case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 98: /* defer_subclause_opt ::= defer_subclause */ - case 100: /* onconf ::= ON CONFLICT resolvetype */ - case 102: /* orconf ::= OR resolvetype */ - case 103: /* resolvetype ::= raisetype */ - case 175: /* insert_cmd ::= INSERT orconf */ -{yygotominor.yy194 = yymsp[0].minor.yy194;} + case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83); + case 98: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==98); + case 100: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==100); + case 103: /* resolvetype ::= raisetype */ yytestcase(yyruleno==103); +{yygotominor.yy328 = yymsp[0].minor.yy328;} break; case 87: /* conslist_opt ::= */ {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;} break; case 88: /* conslist_opt ::= COMMA conslist */ {yygotominor.yy0 = yymsp[-1].minor.yy0;} break; case 93: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy328,yymsp[-2].minor.yy328,0);} break; case 94: /* tcons ::= UNIQUE LP idxlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy148,yymsp[0].minor.yy194,0,0,0,0);} +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy328,0,0,0,0);} break; case 95: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy72);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy346.pExpr);} break; case 96: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy148, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[-1].minor.yy194); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy194); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy328); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy328); } break; case 99: /* onconf ::= */ +{yygotominor.yy328 = OE_Default;} + break; case 101: /* orconf ::= */ -{yygotominor.yy194 = OE_Default;} +{yygotominor.yy186 = OE_Default;} + break; + case 102: /* orconf ::= OR resolvetype */ +{yygotominor.yy186 = (u8)yymsp[0].minor.yy328;} break; case 104: /* resolvetype ::= IGNORE */ -{yygotominor.yy194 = OE_Ignore;} +{yygotominor.yy328 = OE_Ignore;} break; case 105: /* resolvetype ::= REPLACE */ - case 176: /* insert_cmd ::= REPLACE */ -{yygotominor.yy194 = OE_Replace;} +{yygotominor.yy328 = OE_Replace;} break; case 106: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy185, 0, yymsp[-1].minor.yy194); + sqlite3DropTable(pParse, yymsp[0].minor.yy65, 0, yymsp[-1].minor.yy328); } break; case 109: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */ { - sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy243, yymsp[-6].minor.yy194, yymsp[-4].minor.yy194); + sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy3, yymsp[-6].minor.yy328, yymsp[-4].minor.yy328); } break; case 110: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194); + sqlite3DropTable(pParse, yymsp[0].minor.yy65, 1, yymsp[-1].minor.yy328); } break; case 111: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy243, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); + sqlite3Select(pParse, yymsp[0].minor.yy3, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3); } break; case 112: /* select ::= oneselect */ -{yygotominor.yy243 = yymsp[0].minor.yy243;} +{yygotominor.yy3 = yymsp[0].minor.yy3;} break; case 113: /* select ::= select multiselect_op oneselect */ { - if( yymsp[0].minor.yy243 ){ - yymsp[0].minor.yy243->op = (u8)yymsp[-1].minor.yy194; - yymsp[0].minor.yy243->pPrior = yymsp[-2].minor.yy243; - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy243); - } - yygotominor.yy243 = yymsp[0].minor.yy243; + if( yymsp[0].minor.yy3 ){ + yymsp[0].minor.yy3->op = (u8)yymsp[-1].minor.yy328; + yymsp[0].minor.yy3->pPrior = yymsp[-2].minor.yy3; + }else{ + sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy3); + } + yygotominor.yy3 = yymsp[0].minor.yy3; } break; case 115: /* multiselect_op ::= UNION ALL */ -{yygotominor.yy194 = TK_ALL;} +{yygotominor.yy328 = TK_ALL;} break; case 117: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yygotominor.yy243 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy148,yymsp[-5].minor.yy185,yymsp[-4].minor.yy72,yymsp[-3].minor.yy148,yymsp[-2].minor.yy72,yymsp[-1].minor.yy148,yymsp[-7].minor.yy194,yymsp[0].minor.yy354.pLimit,yymsp[0].minor.yy354.pOffset); + yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy65,yymsp[-4].minor.yy132,yymsp[-3].minor.yy14,yymsp[-2].minor.yy132,yymsp[-1].minor.yy14,yymsp[-7].minor.yy328,yymsp[0].minor.yy476.pLimit,yymsp[0].minor.yy476.pOffset); } break; case 121: /* sclp ::= selcollist COMMA */ - case 247: /* idxlist_opt ::= LP idxlist RP */ -{yygotominor.yy148 = yymsp[-1].minor.yy148;} + case 247: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==247); +{yygotominor.yy14 = yymsp[-1].minor.yy14;} break; case 122: /* sclp ::= */ - case 150: /* orderby_opt ::= */ - case 158: /* groupby_opt ::= */ - case 240: /* exprlist ::= */ - case 246: /* idxlist_opt ::= */ -{yygotominor.yy148 = 0;} + case 150: /* orderby_opt ::= */ yytestcase(yyruleno==150); + case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158); + case 240: /* exprlist ::= */ yytestcase(yyruleno==240); + case 246: /* idxlist_opt ::= */ yytestcase(yyruleno==246); +{yygotominor.yy14 = 0;} break; case 123: /* selcollist ::= sclp expr as */ { - yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, yymsp[-1].minor.yy346.pExpr); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yygotominor.yy14,&yymsp[-1].minor.yy346); } break; case 124: /* selcollist ::= sclp STAR */ { - Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0); - yygotominor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p, 0); + Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy14, p); } break; case 125: /* selcollist ::= sclp nm DOT STAR */ { Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0); Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot, 0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, pDot); } break; case 128: /* as ::= */ {yygotominor.yy0.n = 0;} break; case 129: /* from ::= */ -{yygotominor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy185));} +{yygotominor.yy65 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy65));} break; case 130: /* from ::= FROM seltablist */ { - yygotominor.yy185 = yymsp[0].minor.yy185; - sqlite3SrcListShiftJoinType(yygotominor.yy185); + yygotominor.yy65 = yymsp[0].minor.yy65; + sqlite3SrcListShiftJoinType(yygotominor.yy65); } break; case 131: /* stl_prefix ::= seltablist joinop */ { - yygotominor.yy185 = yymsp[-1].minor.yy185; - if( yygotominor.yy185 && yygotominor.yy185->nSrc>0 ) yygotominor.yy185->a[yygotominor.yy185->nSrc-1].jointype = (u8)yymsp[0].minor.yy194; + yygotominor.yy65 = yymsp[-1].minor.yy65; + if( ALWAYS(yygotominor.yy65 && yygotominor.yy65->nSrc>0) ) yygotominor.yy65->a[yygotominor.yy65->nSrc-1].jointype = (u8)yymsp[0].minor.yy328; } break; case 132: /* stl_prefix ::= */ -{yygotominor.yy185 = 0;} +{yygotominor.yy65 = 0;} break; case 133: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yygotominor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); - sqlite3SrcListIndexedBy(pParse, yygotominor.yy185, &yymsp[-2].minor.yy0); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); + sqlite3SrcListIndexedBy(pParse, yygotominor.yy65, &yymsp[-2].minor.yy0); } break; case 134: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { - yygotominor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy243,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy3,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); } break; case 135: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { - if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){ - yygotominor.yy185 = yymsp[-4].minor.yy185; + if( yymsp[-6].minor.yy65==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy132==0 && yymsp[0].minor.yy408==0 ){ + yygotominor.yy65 = yymsp[-4].minor.yy65; }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy185); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy185,0,0,0,0,0,0,0); - yygotominor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy65); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy65,0,0,0,0,0,0,0); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); } } break; case 136: /* dbnm ::= */ - case 145: /* indexed_opt ::= */ + case 145: /* indexed_opt ::= */ yytestcase(yyruleno==145); {yygotominor.yy0.z=0; yygotominor.yy0.n=0;} break; case 138: /* fullname ::= nm dbnm */ -{yygotominor.yy185 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} +{yygotominor.yy65 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} break; case 139: /* joinop ::= COMMA|JOIN */ -{ yygotominor.yy194 = JT_INNER; } +{ yygotominor.yy328 = JT_INNER; } break; case 140: /* joinop ::= JOIN_KW JOIN */ -{ yygotominor.yy194 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } break; case 141: /* joinop ::= JOIN_KW nm JOIN */ -{ yygotominor.yy194 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } break; case 142: /* joinop ::= JOIN_KW nm nm JOIN */ -{ yygotominor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } break; case 143: /* on_opt ::= ON expr */ - case 154: /* sortitem ::= expr */ - case 161: /* having_opt ::= HAVING expr */ - case 168: /* where_opt ::= WHERE expr */ - case 183: /* expr ::= term */ - case 211: /* escape ::= ESCAPE expr */ - case 235: /* case_else ::= ELSE expr */ - case 237: /* case_operand ::= expr */ -{yygotominor.yy72 = yymsp[0].minor.yy72;} + case 154: /* sortitem ::= expr */ yytestcase(yyruleno==154); + case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161); + case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168); + case 235: /* case_else ::= ELSE expr */ yytestcase(yyruleno==235); + case 237: /* case_operand ::= expr */ yytestcase(yyruleno==237); +{yygotominor.yy132 = yymsp[0].minor.yy346.pExpr;} break; case 144: /* on_opt ::= */ - case 160: /* having_opt ::= */ - case 167: /* where_opt ::= */ - case 212: /* escape ::= */ - case 236: /* case_else ::= */ - case 238: /* case_operand ::= */ -{yygotominor.yy72 = 0;} + case 160: /* having_opt ::= */ yytestcase(yyruleno==160); + case 167: /* where_opt ::= */ yytestcase(yyruleno==167); + case 236: /* case_else ::= */ yytestcase(yyruleno==236); + case 238: /* case_operand ::= */ yytestcase(yyruleno==238); +{yygotominor.yy132 = 0;} break; case 147: /* indexed_opt ::= NOT INDEXED */ {yygotominor.yy0.z=0; yygotominor.yy0.n=1;} break; case 148: /* using_opt ::= USING LP inscollist RP */ - case 180: /* inscollist_opt ::= LP inscollist RP */ -{yygotominor.yy254 = yymsp[-1].minor.yy254;} + case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180); +{yygotominor.yy408 = yymsp[-1].minor.yy408;} break; case 149: /* using_opt ::= */ - case 179: /* inscollist_opt ::= */ -{yygotominor.yy254 = 0;} + case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179); +{yygotominor.yy408 = 0;} break; case 151: /* orderby_opt ::= ORDER BY sortlist */ - case 159: /* groupby_opt ::= GROUP BY nexprlist */ - case 239: /* exprlist ::= nexprlist */ -{yygotominor.yy148 = yymsp[0].minor.yy148;} + case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159); + case 239: /* exprlist ::= nexprlist */ yytestcase(yyruleno==239); +{yygotominor.yy14 = yymsp[0].minor.yy14;} break; case 152: /* sortlist ::= sortlist COMMA sortitem sortorder */ { - yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148,yymsp[-1].minor.yy72,0); - if( yygotominor.yy148 ) yygotominor.yy148->a[yygotominor.yy148->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy194; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14,yymsp[-1].minor.yy132); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; case 153: /* sortlist ::= sortitem sortorder */ { - yygotominor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy72,0); - if( yygotominor.yy148 && yygotominor.yy148->a ) yygotominor.yy148->a[0].sortOrder = (u8)yymsp[0].minor.yy194; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy132); + if( yygotominor.yy14 && ALWAYS(yygotominor.yy14->a) ) yygotominor.yy14->a[0].sortOrder = (u8)yymsp[0].minor.yy328; } break; case 155: /* sortorder ::= ASC */ - case 157: /* sortorder ::= */ -{yygotominor.yy194 = SQLITE_SO_ASC;} + case 157: /* sortorder ::= */ yytestcase(yyruleno==157); +{yygotominor.yy328 = SQLITE_SO_ASC;} break; case 156: /* sortorder ::= DESC */ -{yygotominor.yy194 = SQLITE_SO_DESC;} +{yygotominor.yy328 = SQLITE_SO_DESC;} break; case 162: /* limit_opt ::= */ -{yygotominor.yy354.pLimit = 0; yygotominor.yy354.pOffset = 0;} +{yygotominor.yy476.pLimit = 0; yygotominor.yy476.pOffset = 0;} break; case 163: /* limit_opt ::= LIMIT expr */ -{yygotominor.yy354.pLimit = yymsp[0].minor.yy72; yygotominor.yy354.pOffset = 0;} +{yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr; yygotominor.yy476.pOffset = 0;} break; case 164: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yygotominor.yy354.pLimit = yymsp[-2].minor.yy72; yygotominor.yy354.pOffset = yymsp[0].minor.yy72;} +{yygotominor.yy476.pLimit = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pOffset = yymsp[0].minor.yy346.pExpr;} break; case 165: /* limit_opt ::= LIMIT expr COMMA expr */ -{yygotominor.yy354.pOffset = yymsp[-2].minor.yy72; yygotominor.yy354.pLimit = yymsp[0].minor.yy72;} +{yygotominor.yy476.pOffset = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr;} break; case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy185,yymsp[0].minor.yy72); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy65, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy65,yymsp[0].minor.yy132); } break; case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy148,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy185,yymsp[-1].minor.yy148,yymsp[0].minor.yy72,yymsp[-5].minor.yy194); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy65, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy14,"set list"); + sqlite3Update(pParse,yymsp[-4].minor.yy65,yymsp[-1].minor.yy14,yymsp[0].minor.yy132,yymsp[-5].minor.yy186); } break; case 170: /* setlist ::= setlist COMMA nm EQ expr */ -{yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148,yymsp[0].minor.yy72,&yymsp[-2].minor.yy0);} +{ + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy346.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); +} break; case 171: /* setlist ::= nm EQ expr */ -{yygotominor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy72,&yymsp[-2].minor.yy0);} +{ + yygotominor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy346.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); +} break; case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */ -{sqlite3Insert(pParse, yymsp[-5].minor.yy185, yymsp[-1].minor.yy148, 0, yymsp[-4].minor.yy254, yymsp[-7].minor.yy194);} +{sqlite3Insert(pParse, yymsp[-5].minor.yy65, yymsp[-1].minor.yy14, 0, yymsp[-4].minor.yy408, yymsp[-7].minor.yy186);} break; case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */ -{sqlite3Insert(pParse, yymsp[-2].minor.yy185, 0, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy194);} +{sqlite3Insert(pParse, yymsp[-2].minor.yy65, 0, yymsp[0].minor.yy3, yymsp[-1].minor.yy408, yymsp[-4].minor.yy186);} break; case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ -{sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194);} +{sqlite3Insert(pParse, yymsp[-3].minor.yy65, 0, 0, yymsp[-2].minor.yy408, yymsp[-5].minor.yy186);} + break; + case 175: /* insert_cmd ::= INSERT orconf */ +{yygotominor.yy186 = yymsp[0].minor.yy186;} + break; + case 176: /* insert_cmd ::= REPLACE */ +{yygotominor.yy186 = OE_Replace;} break; case 177: /* itemlist ::= itemlist COMMA expr */ - case 241: /* nexprlist ::= nexprlist COMMA expr */ -{yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy72,0);} + case 241: /* nexprlist ::= nexprlist COMMA expr */ yytestcase(yyruleno==241); +{yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy346.pExpr);} break; case 178: /* itemlist ::= expr */ - case 242: /* nexprlist ::= expr */ -{yygotominor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy72,0);} + case 242: /* nexprlist ::= expr */ yytestcase(yyruleno==242); +{yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy346.pExpr);} break; case 181: /* inscollist ::= inscollist COMMA nm */ -{yygotominor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} +{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy408,&yymsp[0].minor.yy0);} break; case 182: /* inscollist ::= nm */ -{yygotominor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} +{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} + break; + case 183: /* expr ::= term */ + case 211: /* escape ::= ESCAPE expr */ yytestcase(yyruleno==211); +{yygotominor.yy346 = yymsp[0].minor.yy346;} break; case 184: /* expr ::= LP expr RP */ -{yygotominor.yy72 = yymsp[-1].minor.yy72; sqlite3ExprSpan(yygotominor.yy72,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } +{yygotominor.yy346.pExpr = yymsp[-1].minor.yy346.pExpr; spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);} break; case 185: /* term ::= NULL */ - case 190: /* term ::= INTEGER|FLOAT|BLOB */ - case 191: /* term ::= STRING */ -{yygotominor.yy72 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} + case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190); + case 191: /* term ::= STRING */ yytestcase(yyruleno==191); +{spanExpr(&yygotominor.yy346, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} break; case 186: /* expr ::= id */ - case 187: /* expr ::= JOIN_KW */ -{yygotominor.yy72 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);} + case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187); +{spanExpr(&yygotominor.yy346, pParse, TK_ID, &yymsp[0].minor.yy0);} break; case 188: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - yygotominor.yy72 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } break; case 189: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); - yygotominor.yy72 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); } break; case 192: /* expr ::= REGISTER */ -{yygotominor.yy72 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} +{ + /* When doing a nested parse, one can include terms in an expression + ** that look like this: #1 #2 ... These terms refer to registers + ** in the virtual machine. #N is the N-th register. */ + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = 0; + }else{ + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); + if( yygotominor.yy346.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy346.pExpr->iTable); + } + spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); +} break; case 193: /* expr ::= VARIABLE */ { - Token *pToken = &yymsp[0].minor.yy0; - Expr *pExpr = yygotominor.yy72 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); - sqlite3ExprAssignVarNumber(pParse, pExpr); + spanExpr(&yygotominor.yy346, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yygotominor.yy346.pExpr); + spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; case 194: /* expr ::= expr COLLATE ids */ { - yygotominor.yy72 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy72, &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0); + yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; case 195: /* expr ::= CAST LP expr AS typetoken RP */ { - yygotominor.yy72 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy72, 0, &yymsp[-1].minor.yy0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy346.pExpr, 0, &yymsp[-1].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } break; case 196: /* expr ::= ID LP distinct exprlist RP */ { - if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>SQLITE_MAX_FUNCTION_ARG ){ + if( yymsp[-1].minor.yy14 && yymsp[-1].minor.yy14->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } - yygotominor.yy72 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy194 && yygotominor.yy72 ){ - yygotominor.yy72->flags |= EP_Distinct; + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy328 && yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->flags |= EP_Distinct; } } break; case 197: /* expr ::= ID LP STAR RP */ { - yygotominor.yy72 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } break; case 198: /* term ::= CTIME_KW */ { /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are ** treated as functions that return constants */ - yygotominor.yy72 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0); - if( yygotominor.yy72 ){ - yygotominor.yy72->op = TK_CONST_FUNC; - yygotominor.yy72->span = yymsp[0].minor.yy0; - } + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->op = TK_CONST_FUNC; + } + spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; case 199: /* expr ::= expr AND expr */ - case 200: /* expr ::= expr OR expr */ - case 201: /* expr ::= expr LT|GT|GE|LE expr */ - case 202: /* expr ::= expr EQ|NE expr */ - case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - case 204: /* expr ::= expr PLUS|MINUS expr */ - case 205: /* expr ::= expr STAR|SLASH|REM expr */ - case 206: /* expr ::= expr CONCAT expr */ -{yygotominor.yy72 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy72,yymsp[0].minor.yy72,0);} + case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200); + case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201); + case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202); + case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203); + case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204); + case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205); + case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206); +{spanBinaryExpr(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy346);} break; case 207: /* likeop ::= LIKE_KW */ - case 209: /* likeop ::= MATCH */ -{yygotominor.yy392.eOperator = yymsp[0].minor.yy0; yygotominor.yy392.not = 0;} + case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209); +{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.not = 0;} break; case 208: /* likeop ::= NOT LIKE_KW */ - case 210: /* likeop ::= NOT MATCH */ -{yygotominor.yy392.eOperator = yymsp[0].minor.yy0; yygotominor.yy392.not = 1;} + case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210); +{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.not = 1;} + break; + case 212: /* escape ::= */ +{memset(&yygotominor.yy346,0,sizeof(yygotominor.yy346));} break; case 213: /* expr ::= expr likeop expr escape */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy72, 0); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy72, 0); - if( yymsp[0].minor.yy72 ){ - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy72, 0); - } - yygotominor.yy72 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy392.eOperator); - if( yymsp[-2].minor.yy392.not ) yygotominor.yy72 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72, &yymsp[-3].minor.yy72->span, &yymsp[-1].minor.yy72->span); - if( yygotominor.yy72 ) yygotominor.yy72->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy346.pExpr); + if( yymsp[0].minor.yy346.pExpr ){ + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr); + } + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy96.eOperator); + if( yymsp[-2].minor.yy96.not ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-3].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[-1].minor.yy346.zEnd; + if( yygotominor.yy346.pExpr ) yygotominor.yy346.pExpr->flags |= EP_InfixFunc; } break; case 214: /* expr ::= expr ISNULL|NOTNULL */ -{ - yygotominor.yy72 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-1].minor.yy72->span,&yymsp[0].minor.yy0); -} +{spanUnaryPostfix(&yygotominor.yy346,pParse,yymsp[0].major,&yymsp[-1].minor.yy346,&yymsp[0].minor.yy0);} break; case 215: /* expr ::= expr IS NULL */ -{ - yygotominor.yy72 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-2].minor.yy72->span,&yymsp[0].minor.yy0); -} +{spanUnaryPostfix(&yygotominor.yy346,pParse,TK_ISNULL,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy0);} break; case 216: /* expr ::= expr NOT NULL */ -{ - yygotominor.yy72 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-2].minor.yy72->span,&yymsp[0].minor.yy0); -} +{spanUnaryPostfix(&yygotominor.yy346,pParse,TK_NOTNULL,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy0);} break; case 217: /* expr ::= expr IS NOT NULL */ -{ - yygotominor.yy72 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-3].minor.yy72->span,&yymsp[0].minor.yy0); -} +{spanUnaryPostfix(&yygotominor.yy346,pParse,TK_NOTNULL,&yymsp[-3].minor.yy346,&yymsp[0].minor.yy0);} break; case 218: /* expr ::= NOT expr */ - case 219: /* expr ::= BITNOT expr */ -{ - yygotominor.yy72 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72->span); -} + case 219: /* expr ::= BITNOT expr */ yytestcase(yyruleno==219); +{spanUnaryPrefix(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; case 220: /* expr ::= MINUS expr */ -{ - yygotominor.yy72 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72->span); -} +{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UMINUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; case 221: /* expr ::= PLUS expr */ -{ - yygotominor.yy72 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy72->span); -} +{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UPLUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; case 224: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy72, 0); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy72, 0); - yygotominor.yy72 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy72, 0, 0); - if( yygotominor.yy72 ){ - yygotominor.yy72->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy194 ) yygotominor.yy72 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-4].minor.yy72->span,&yymsp[0].minor.yy72->span); + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd; } break; case 227: /* expr ::= expr in_op LP exprlist RP */ { - yygotominor.yy72 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy72, 0, 0); - if( yygotominor.yy72 ){ - yygotominor.yy72->x.pList = yymsp[-1].minor.yy148; - sqlite3ExprSetHeight(pParse, yygotominor.yy72); - }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); - } - if( yymsp[-3].minor.yy194 ) yygotominor.yy72 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-4].minor.yy72->span,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14; + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + }else{ + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + } + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; case 228: /* expr ::= LP select RP */ { - yygotominor.yy72 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( yygotominor.yy72 ){ - yygotominor.yy72->x.pSelect = yymsp[-1].minor.yy243; - ExprSetProperty(yygotominor.yy72, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy72); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy243); - } - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + }else{ + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); + } + yygotominor.yy346.zStart = yymsp[-2].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; case 229: /* expr ::= expr in_op LP select RP */ { - yygotominor.yy72 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy72, 0, 0); - if( yygotominor.yy72 ){ - yygotominor.yy72->x.pSelect = yymsp[-1].minor.yy243; - ExprSetProperty(yygotominor.yy72, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy72); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy243); - } - if( yymsp[-3].minor.yy194 ) yygotominor.yy72 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-4].minor.yy72->span,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + }else{ + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); + } + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; case 230: /* expr ::= expr in_op nm dbnm */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); - yygotominor.yy72 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy72, 0, 0); - if( yygotominor.yy72 ){ - yygotominor.yy72->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(yygotominor.yy72, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy72); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } - if( yymsp[-2].minor.yy194 ) yygotominor.yy72 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy72, 0, 0); - sqlite3ExprSpan(yygotominor.yy72,&yymsp[-3].minor.yy72->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0); + if( yymsp[-2].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-3].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]; } break; case 231: /* expr ::= EXISTS LP select RP */ { - Expr *p = yygotominor.yy72 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ - p->x.pSelect = yymsp[-1].minor.yy243; - ExprSetProperty(yygotominor.yy72, EP_xIsSelect); - sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); - sqlite3ExprSetHeight(pParse, yygotominor.yy72); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy243); - } + p->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(p, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, p); + }else{ + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); + } + yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; case 232: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yygotominor.yy72 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, yymsp[-1].minor.yy72, 0); - if( yygotominor.yy72 ){ - yygotominor.yy72->x.pList = yymsp[-2].minor.yy148; - sqlite3ExprSetHeight(pParse, yygotominor.yy72); - }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); - } - sqlite3ExprSpan(yygotominor.yy72, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy132, yymsp[-1].minor.yy132, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = yymsp[-2].minor.yy14; + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + }else{ + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); + } + yygotominor.yy346.zStart = yymsp[-4].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; case 233: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy72, 0); - yygotominor.yy148 = sqlite3ExprListAppend(pParse,yygotominor.yy148, yymsp[0].minor.yy72, 0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr); } break; case 234: /* case_exprlist ::= WHEN expr THEN expr */ { - yygotominor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy72, 0); - yygotominor.yy148 = sqlite3ExprListAppend(pParse,yygotominor.yy148, yymsp[0].minor.yy72, 0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr); } break; case 243: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */ { sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, - sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy148, yymsp[-9].minor.yy194, - &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy194); + sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy14, yymsp[-9].minor.yy328, + &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy328); } break; case 244: /* uniqueflag ::= UNIQUE */ - case 293: /* raisetype ::= ABORT */ -{yygotominor.yy194 = OE_Abort;} + case 298: /* raisetype ::= ABORT */ yytestcase(yyruleno==298); +{yygotominor.yy328 = OE_Abort;} break; case 245: /* uniqueflag ::= */ -{yygotominor.yy194 = OE_None;} +{yygotominor.yy328 = OE_None;} break; case 248: /* idxlist ::= idxlist COMMA nm collate sortorder */ { Expr *p = 0; if( yymsp[-1].minor.yy0.n>0 ){ - p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + p = sqlite3Expr(pParse->db, TK_COLUMN, 0); sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0); } - yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, p, &yymsp[-2].minor.yy0); - sqlite3ExprListCheckLength(pParse, yygotominor.yy148, "index"); - if( yygotominor.yy148 ) yygotominor.yy148->a[yygotominor.yy148->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy194; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, p); + sqlite3ExprListSetName(pParse,yygotominor.yy14,&yymsp[-2].minor.yy0,1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; case 249: /* idxlist ::= nm collate sortorder */ { Expr *p = 0; if( yymsp[-1].minor.yy0.n>0 ){ p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0); } - yygotominor.yy148 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0); - sqlite3ExprListCheckLength(pParse, yygotominor.yy148, "index"); - if( yygotominor.yy148 ) yygotominor.yy148->a[yygotominor.yy148->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy194; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, p); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; case 250: /* collate ::= */ {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;} break; case 252: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} +{sqlite3DropIndex(pParse, yymsp[0].minor.yy65, yymsp[-1].minor.yy328);} break; case 253: /* cmd ::= VACUUM */ - case 254: /* cmd ::= VACUUM nm */ + case 254: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==254); {sqlite3Vacuum(pParse);} break; case 255: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; @@ -87243,168 +91032,225 @@ case 270: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy473, &all); } break; case 271: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy328, yymsp[-4].minor.yy378.a, yymsp[-4].minor.yy378.b, yymsp[-2].minor.yy65, yymsp[0].minor.yy132, yymsp[-10].minor.yy328, yymsp[-8].minor.yy328); yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); } break; case 272: /* trigger_time ::= BEFORE */ - case 275: /* trigger_time ::= */ -{ yygotominor.yy194 = TK_BEFORE; } + case 275: /* trigger_time ::= */ yytestcase(yyruleno==275); +{ yygotominor.yy328 = TK_BEFORE; } break; case 273: /* trigger_time ::= AFTER */ -{ yygotominor.yy194 = TK_AFTER; } +{ yygotominor.yy328 = TK_AFTER; } break; case 274: /* trigger_time ::= INSTEAD OF */ -{ yygotominor.yy194 = TK_INSTEAD;} +{ yygotominor.yy328 = TK_INSTEAD;} break; case 276: /* trigger_event ::= DELETE|INSERT */ - case 277: /* trigger_event ::= UPDATE */ -{yygotominor.yy332.a = yymsp[0].major; yygotominor.yy332.b = 0;} + case 277: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==277); +{yygotominor.yy378.a = yymsp[0].major; yygotominor.yy378.b = 0;} break; case 278: /* trigger_event ::= UPDATE OF inscollist */ -{yygotominor.yy332.a = TK_UPDATE; yygotominor.yy332.b = yymsp[0].minor.yy254;} +{yygotominor.yy378.a = TK_UPDATE; yygotominor.yy378.b = yymsp[0].minor.yy408;} break; case 281: /* when_clause ::= */ - case 298: /* key_opt ::= */ -{ yygotominor.yy72 = 0; } + case 303: /* key_opt ::= */ yytestcase(yyruleno==303); +{ yygotominor.yy132 = 0; } break; case 282: /* when_clause ::= WHEN expr */ - case 299: /* key_opt ::= KEY expr */ -{ yygotominor.yy72 = yymsp[0].minor.yy72; } + case 304: /* key_opt ::= KEY expr */ yytestcase(yyruleno==304); +{ yygotominor.yy132 = yymsp[0].minor.yy346.pExpr; } break; case 283: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { -/* - if( yymsp[-2].minor.yy145 ){ - yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; - }else{ - yymsp[-2].minor.yy145 = yymsp[-1].minor.yy145; - } -*/ - assert( yymsp[-2].minor.yy145!=0 ); - yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; - yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; - yygotominor.yy145 = yymsp[-2].minor.yy145; + assert( yymsp[-2].minor.yy473!=0 ); + yymsp[-2].minor.yy473->pLast->pNext = yymsp[-1].minor.yy473; + yymsp[-2].minor.yy473->pLast = yymsp[-1].minor.yy473; + yygotominor.yy473 = yymsp[-2].minor.yy473; } break; case 284: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - /* if( yymsp[-1].minor.yy145 ) */ - assert( yymsp[-1].minor.yy145!=0 ); - yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; - yygotominor.yy145 = yymsp[-1].minor.yy145; -} - break; - case 285: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */ -{ yygotominor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-4].minor.yy194); } - break; - case 286: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */ -{yygotominor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy254, yymsp[-1].minor.yy148, 0, yymsp[-7].minor.yy194);} - break; - case 287: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */ -{yygotominor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, 0, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);} - break; - case 288: /* trigger_cmd ::= DELETE FROM nm where_opt */ -{yygotominor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy72);} - break; - case 289: /* trigger_cmd ::= select */ -{yygotominor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); } - break; - case 290: /* expr ::= RAISE LP IGNORE RP */ + assert( yymsp[-1].minor.yy473!=0 ); + yymsp[-1].minor.yy473->pLast = yymsp[-1].minor.yy473; + yygotominor.yy473 = yymsp[-1].minor.yy473; +} + break; + case 286: /* trnm ::= nm DOT nm */ +{ + yygotominor.yy0 = yymsp[0].minor.yy0; + sqlite3ErrorMsg(pParse, + "qualified table names are not allowed on INSERT, UPDATE, and DELETE " + "statements within triggers"); +} + break; + case 288: /* tridxby ::= INDEXED BY nm */ +{ + sqlite3ErrorMsg(pParse, + "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " + "within triggers"); +} + break; + case 289: /* tridxby ::= NOT INDEXED */ +{ + sqlite3ErrorMsg(pParse, + "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " + "within triggers"); +} + break; + case 290: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ +{ yygotominor.yy473 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy14, yymsp[0].minor.yy132, yymsp[-5].minor.yy186); } + break; + case 291: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt VALUES LP itemlist RP */ +{yygotominor.yy473 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy408, yymsp[-1].minor.yy14, 0, yymsp[-7].minor.yy186);} + break; + case 292: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */ +{yygotominor.yy473 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy408, 0, yymsp[0].minor.yy3, yymsp[-4].minor.yy186);} + break; + case 293: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ +{yygotominor.yy473 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy132);} + break; + case 294: /* trigger_cmd ::= select */ +{yygotominor.yy473 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy3); } + break; + case 295: /* expr ::= RAISE LP IGNORE RP */ +{ + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->affinity = OE_Ignore; + } + yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; +} + break; + case 296: /* expr ::= RAISE LP raisetype COMMA nm RP */ +{ + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); + if( yygotominor.yy346.pExpr ) { + yygotominor.yy346.pExpr->affinity = (char)yymsp[-3].minor.yy328; + } + yygotominor.yy346.zStart = yymsp[-5].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; +} + break; + case 297: /* raisetype ::= ROLLBACK */ +{yygotominor.yy328 = OE_Rollback;} + break; + case 299: /* raisetype ::= FAIL */ +{yygotominor.yy328 = OE_Fail;} + break; + case 300: /* cmd ::= DROP TRIGGER ifexists fullname */ { - yygotominor.yy72 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( yygotominor.yy72 ){ - yygotominor.yy72->affinity = OE_Ignore; - sqlite3ExprSpan(yygotominor.yy72, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); - } -} - break; - case 291: /* expr ::= RAISE LP raisetype COMMA nm RP */ + sqlite3DropTrigger(pParse,yymsp[0].minor.yy65,yymsp[-1].minor.yy328); +} + break; + case 301: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - yygotominor.yy72 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); - if( yygotominor.yy72 ) { - yygotominor.yy72->affinity = (char)yymsp[-3].minor.yy194; - sqlite3ExprSpan(yygotominor.yy72, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); - } -} - break; - case 292: /* raisetype ::= ROLLBACK */ -{yygotominor.yy194 = OE_Rollback;} - break; - case 294: /* raisetype ::= FAIL */ -{yygotominor.yy194 = OE_Fail;} - break; - case 295: /* cmd ::= DROP TRIGGER ifexists fullname */ + sqlite3Attach(pParse, yymsp[-3].minor.yy346.pExpr, yymsp[-1].minor.yy346.pExpr, yymsp[0].minor.yy132); +} + break; + case 302: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); -} - break; - case 296: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ -{ - sqlite3Attach(pParse, yymsp[-3].minor.yy72, yymsp[-1].minor.yy72, yymsp[0].minor.yy72); -} - break; - case 297: /* cmd ::= DETACH database_kw_opt expr */ -{ - sqlite3Detach(pParse, yymsp[0].minor.yy72); -} - break; - case 302: /* cmd ::= REINDEX */ + sqlite3Detach(pParse, yymsp[0].minor.yy346.pExpr); +} + break; + case 307: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 303: /* cmd ::= REINDEX nm dbnm */ + case 308: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 304: /* cmd ::= ANALYZE */ + case 309: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 305: /* cmd ::= ANALYZE nm dbnm */ + case 310: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 306: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 311: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); -} - break; - case 307: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy65,&yymsp[0].minor.yy0); +} + break; + case 312: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ { sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); } break; - case 308: /* add_column_fullname ::= fullname */ + case 313: /* add_column_fullname ::= fullname */ { pParse->db->lookaside.bEnabled = 0; - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); -} - break; - case 311: /* cmd ::= create_vtab */ + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy65); +} + break; + case 316: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 312: /* cmd ::= create_vtab LP vtabarglist RP */ + case 317: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 313: /* create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm */ + case 318: /* create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm */ { sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; - case 316: /* vtabarg ::= */ + case 321: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 318: /* vtabargtoken ::= ANY */ - case 319: /* vtabargtoken ::= lp anylist RP */ - case 320: /* lp ::= LP */ - case 322: /* anylist ::= anylist ANY */ + case 323: /* vtabargtoken ::= ANY */ + case 324: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==324); + case 325: /* lp ::= LP */ yytestcase(yyruleno==325); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} + break; + default: + /* (0) input ::= cmdlist */ yytestcase(yyruleno==0); + /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1); + /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2); + /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3); + /* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4); + /* (10) trans_opt ::= */ yytestcase(yyruleno==10); + /* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11); + /* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12); + /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20); + /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21); + /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25); + /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34); + /* (35) columnlist ::= column */ yytestcase(yyruleno==35); + /* (44) type ::= */ yytestcase(yyruleno==44); + /* (51) signed ::= plus_num */ yytestcase(yyruleno==51); + /* (52) signed ::= minus_num */ yytestcase(yyruleno==52); + /* (53) carglist ::= carglist carg */ yytestcase(yyruleno==53); + /* (54) carglist ::= */ yytestcase(yyruleno==54); + /* (55) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==55); + /* (56) carg ::= ccons */ yytestcase(yyruleno==56); + /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62); + /* (89) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==89); + /* (90) conslist ::= conslist tcons */ yytestcase(yyruleno==90); + /* (91) conslist ::= tcons */ yytestcase(yyruleno==91); + /* (92) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==92); + /* (268) plus_opt ::= PLUS */ yytestcase(yyruleno==268); + /* (269) plus_opt ::= */ yytestcase(yyruleno==269); + /* (279) foreach_clause ::= */ yytestcase(yyruleno==279); + /* (280) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==280); + /* (287) tridxby ::= */ yytestcase(yyruleno==287); + /* (305) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==305); + /* (306) database_kw_opt ::= */ yytestcase(yyruleno==306); + /* (314) kwcolumn_opt ::= */ yytestcase(yyruleno==314); + /* (315) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==315); + /* (319) vtabarglist ::= vtabarg */ yytestcase(yyruleno==319); + /* (320) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==320); + /* (322) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==322); + /* (326) anylist ::= */ yytestcase(yyruleno==326); + /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327); + /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328); break; }; yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; @@ -87433,10 +91279,11 @@ } /* ** The following code executes when the parse fails */ +#ifndef YYNOERRORRECOVERY static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ sqlite3ParserARG_FETCH; #ifndef NDEBUG @@ -87447,10 +91294,11 @@ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } +#endif /* YYNOERRORRECOVERY */ /* ** The following code executes when a syntax error first occurs. */ static void yy_syntax_error( @@ -87617,10 +91465,22 @@ yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); } } yypParser->yyerrcnt = 3; yyerrorhit = 1; +#elif defined(YYNOERRORRECOVERY) + /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax + ** error routine and continue going as if nothing had happened. + ** + ** Applications can set this macro (for example inside %include) if + ** they intend to abandon the parse upon the first syntax error seen. + */ + yy_syntax_error(yypParser,yymajor,yyminorunion); + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); + yymajor = YYNOCODE; + #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** ** * Report an error message, and throw away the input token. ** @@ -87661,11 +91521,11 @@ ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.155 2009/03/31 03:41:57 shane Exp $ +** $Id: tokenize.c,v 1.163 2009/07/03 22:54:37 drh Exp $ */ /* ** The charMap() macro maps alphabetic characters into their ** lower-case ASCII equivalent. On ASCII machines, this is just @@ -87714,11 +91574,11 @@ /************** Begin file keywordhash.h *************************************/ /***** This file contains automatically generated code ****** ** ** The code in this file has been automatically generated by ** -** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.37 2009/02/01 00:00:46 drh Exp $ +** $Header: /home/drh/sqlite/trans/cvs/sqlite/sqlite/tool/mkkeywordhash.c,v 1.38 2009/06/09 14:27:41 drh Exp $ ** ** The code in this file implements a function that determines whether ** or not a given identifier is really an SQL keyword. The same thing ** might be implemented more directly using a hand-written hash table. ** But by using this automatically generated code, the size of the code @@ -87849,129 +91709,129 @@ h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ - testcase( i==0 ); /* TK_REINDEX */ - testcase( i==1 ); /* TK_INDEXED */ - testcase( i==2 ); /* TK_INDEX */ - testcase( i==3 ); /* TK_DESC */ - testcase( i==4 ); /* TK_ESCAPE */ - testcase( i==5 ); /* TK_EACH */ - testcase( i==6 ); /* TK_CHECK */ - testcase( i==7 ); /* TK_KEY */ - testcase( i==8 ); /* TK_BEFORE */ - testcase( i==9 ); /* TK_FOREIGN */ - testcase( i==10 ); /* TK_FOR */ - testcase( i==11 ); /* TK_IGNORE */ - testcase( i==12 ); /* TK_LIKE_KW */ - testcase( i==13 ); /* TK_EXPLAIN */ - testcase( i==14 ); /* TK_INSTEAD */ - testcase( i==15 ); /* TK_ADD */ - testcase( i==16 ); /* TK_DATABASE */ - testcase( i==17 ); /* TK_AS */ - testcase( i==18 ); /* TK_SELECT */ - testcase( i==19 ); /* TK_TABLE */ - testcase( i==20 ); /* TK_JOIN_KW */ - testcase( i==21 ); /* TK_THEN */ - testcase( i==22 ); /* TK_END */ - testcase( i==23 ); /* TK_DEFERRABLE */ - testcase( i==24 ); /* TK_ELSE */ - testcase( i==25 ); /* TK_EXCEPT */ - testcase( i==26 ); /* TK_TRANSACTION */ - testcase( i==27 ); /* TK_ON */ - testcase( i==28 ); /* TK_JOIN_KW */ - testcase( i==29 ); /* TK_ALTER */ - testcase( i==30 ); /* TK_RAISE */ - testcase( i==31 ); /* TK_EXCLUSIVE */ - testcase( i==32 ); /* TK_EXISTS */ - testcase( i==33 ); /* TK_SAVEPOINT */ - testcase( i==34 ); /* TK_INTERSECT */ - testcase( i==35 ); /* TK_TRIGGER */ - testcase( i==36 ); /* TK_REFERENCES */ - testcase( i==37 ); /* TK_CONSTRAINT */ - testcase( i==38 ); /* TK_INTO */ - testcase( i==39 ); /* TK_OFFSET */ - testcase( i==40 ); /* TK_OF */ - testcase( i==41 ); /* TK_SET */ - testcase( i==42 ); /* TK_TEMP */ - testcase( i==43 ); /* TK_TEMP */ - testcase( i==44 ); /* TK_OR */ - testcase( i==45 ); /* TK_UNIQUE */ - testcase( i==46 ); /* TK_QUERY */ - testcase( i==47 ); /* TK_ATTACH */ - testcase( i==48 ); /* TK_HAVING */ - testcase( i==49 ); /* TK_GROUP */ - testcase( i==50 ); /* TK_UPDATE */ - testcase( i==51 ); /* TK_BEGIN */ - testcase( i==52 ); /* TK_JOIN_KW */ - testcase( i==53 ); /* TK_RELEASE */ - testcase( i==54 ); /* TK_BETWEEN */ - testcase( i==55 ); /* TK_NOTNULL */ - testcase( i==56 ); /* TK_NOT */ - testcase( i==57 ); /* TK_NULL */ - testcase( i==58 ); /* TK_LIKE_KW */ - testcase( i==59 ); /* TK_CASCADE */ - testcase( i==60 ); /* TK_ASC */ - testcase( i==61 ); /* TK_DELETE */ - testcase( i==62 ); /* TK_CASE */ - testcase( i==63 ); /* TK_COLLATE */ - testcase( i==64 ); /* TK_CREATE */ - testcase( i==65 ); /* TK_CTIME_KW */ - testcase( i==66 ); /* TK_DETACH */ - testcase( i==67 ); /* TK_IMMEDIATE */ - testcase( i==68 ); /* TK_JOIN */ - testcase( i==69 ); /* TK_INSERT */ - testcase( i==70 ); /* TK_MATCH */ - testcase( i==71 ); /* TK_PLAN */ - testcase( i==72 ); /* TK_ANALYZE */ - testcase( i==73 ); /* TK_PRAGMA */ - testcase( i==74 ); /* TK_ABORT */ - testcase( i==75 ); /* TK_VALUES */ - testcase( i==76 ); /* TK_VIRTUAL */ - testcase( i==77 ); /* TK_LIMIT */ - testcase( i==78 ); /* TK_WHEN */ - testcase( i==79 ); /* TK_WHERE */ - testcase( i==80 ); /* TK_RENAME */ - testcase( i==81 ); /* TK_AFTER */ - testcase( i==82 ); /* TK_REPLACE */ - testcase( i==83 ); /* TK_AND */ - testcase( i==84 ); /* TK_DEFAULT */ - testcase( i==85 ); /* TK_AUTOINCR */ - testcase( i==86 ); /* TK_TO */ - testcase( i==87 ); /* TK_IN */ - testcase( i==88 ); /* TK_CAST */ - testcase( i==89 ); /* TK_COLUMNKW */ - testcase( i==90 ); /* TK_COMMIT */ - testcase( i==91 ); /* TK_CONFLICT */ - testcase( i==92 ); /* TK_JOIN_KW */ - testcase( i==93 ); /* TK_CTIME_KW */ - testcase( i==94 ); /* TK_CTIME_KW */ - testcase( i==95 ); /* TK_PRIMARY */ - testcase( i==96 ); /* TK_DEFERRED */ - testcase( i==97 ); /* TK_DISTINCT */ - testcase( i==98 ); /* TK_IS */ - testcase( i==99 ); /* TK_DROP */ - testcase( i==100 ); /* TK_FAIL */ - testcase( i==101 ); /* TK_FROM */ - testcase( i==102 ); /* TK_JOIN_KW */ - testcase( i==103 ); /* TK_LIKE_KW */ - testcase( i==104 ); /* TK_BY */ - testcase( i==105 ); /* TK_IF */ - testcase( i==106 ); /* TK_ISNULL */ - testcase( i==107 ); /* TK_ORDER */ - testcase( i==108 ); /* TK_RESTRICT */ - testcase( i==109 ); /* TK_JOIN_KW */ - testcase( i==110 ); /* TK_JOIN_KW */ - testcase( i==111 ); /* TK_ROLLBACK */ - testcase( i==112 ); /* TK_ROW */ - testcase( i==113 ); /* TK_UNION */ - testcase( i==114 ); /* TK_USING */ - testcase( i==115 ); /* TK_VACUUM */ - testcase( i==116 ); /* TK_VIEW */ - testcase( i==117 ); /* TK_INITIALLY */ - testcase( i==118 ); /* TK_ALL */ + testcase( i==0 ); /* REINDEX */ + testcase( i==1 ); /* INDEXED */ + testcase( i==2 ); /* INDEX */ + testcase( i==3 ); /* DESC */ + testcase( i==4 ); /* ESCAPE */ + testcase( i==5 ); /* EACH */ + testcase( i==6 ); /* CHECK */ + testcase( i==7 ); /* KEY */ + testcase( i==8 ); /* BEFORE */ + testcase( i==9 ); /* FOREIGN */ + testcase( i==10 ); /* FOR */ + testcase( i==11 ); /* IGNORE */ + testcase( i==12 ); /* REGEXP */ + testcase( i==13 ); /* EXPLAIN */ + testcase( i==14 ); /* INSTEAD */ + testcase( i==15 ); /* ADD */ + testcase( i==16 ); /* DATABASE */ + testcase( i==17 ); /* AS */ + testcase( i==18 ); /* SELECT */ + testcase( i==19 ); /* TABLE */ + testcase( i==20 ); /* LEFT */ + testcase( i==21 ); /* THEN */ + testcase( i==22 ); /* END */ + testcase( i==23 ); /* DEFERRABLE */ + testcase( i==24 ); /* ELSE */ + testcase( i==25 ); /* EXCEPT */ + testcase( i==26 ); /* TRANSACTION */ + testcase( i==27 ); /* ON */ + testcase( i==28 ); /* NATURAL */ + testcase( i==29 ); /* ALTER */ + testcase( i==30 ); /* RAISE */ + testcase( i==31 ); /* EXCLUSIVE */ + testcase( i==32 ); /* EXISTS */ + testcase( i==33 ); /* SAVEPOINT */ + testcase( i==34 ); /* INTERSECT */ + testcase( i==35 ); /* TRIGGER */ + testcase( i==36 ); /* REFERENCES */ + testcase( i==37 ); /* CONSTRAINT */ + testcase( i==38 ); /* INTO */ + testcase( i==39 ); /* OFFSET */ + testcase( i==40 ); /* OF */ + testcase( i==41 ); /* SET */ + testcase( i==42 ); /* TEMP */ + testcase( i==43 ); /* TEMPORARY */ + testcase( i==44 ); /* OR */ + testcase( i==45 ); /* UNIQUE */ + testcase( i==46 ); /* QUERY */ + testcase( i==47 ); /* ATTACH */ + testcase( i==48 ); /* HAVING */ + testcase( i==49 ); /* GROUP */ + testcase( i==50 ); /* UPDATE */ + testcase( i==51 ); /* BEGIN */ + testcase( i==52 ); /* INNER */ + testcase( i==53 ); /* RELEASE */ + testcase( i==54 ); /* BETWEEN */ + testcase( i==55 ); /* NOTNULL */ + testcase( i==56 ); /* NOT */ + testcase( i==57 ); /* NULL */ + testcase( i==58 ); /* LIKE */ + testcase( i==59 ); /* CASCADE */ + testcase( i==60 ); /* ASC */ + testcase( i==61 ); /* DELETE */ + testcase( i==62 ); /* CASE */ + testcase( i==63 ); /* COLLATE */ + testcase( i==64 ); /* CREATE */ + testcase( i==65 ); /* CURRENT_DATE */ + testcase( i==66 ); /* DETACH */ + testcase( i==67 ); /* IMMEDIATE */ + testcase( i==68 ); /* JOIN */ + testcase( i==69 ); /* INSERT */ + testcase( i==70 ); /* MATCH */ + testcase( i==71 ); /* PLAN */ + testcase( i==72 ); /* ANALYZE */ + testcase( i==73 ); /* PRAGMA */ + testcase( i==74 ); /* ABORT */ + testcase( i==75 ); /* VALUES */ + testcase( i==76 ); /* VIRTUAL */ + testcase( i==77 ); /* LIMIT */ + testcase( i==78 ); /* WHEN */ + testcase( i==79 ); /* WHERE */ + testcase( i==80 ); /* RENAME */ + testcase( i==81 ); /* AFTER */ + testcase( i==82 ); /* REPLACE */ + testcase( i==83 ); /* AND */ + testcase( i==84 ); /* DEFAULT */ + testcase( i==85 ); /* AUTOINCREMENT */ + testcase( i==86 ); /* TO */ + testcase( i==87 ); /* IN */ + testcase( i==88 ); /* CAST */ + testcase( i==89 ); /* COLUMN */ + testcase( i==90 ); /* COMMIT */ + testcase( i==91 ); /* CONFLICT */ + testcase( i==92 ); /* CROSS */ + testcase( i==93 ); /* CURRENT_TIMESTAMP */ + testcase( i==94 ); /* CURRENT_TIME */ + testcase( i==95 ); /* PRIMARY */ + testcase( i==96 ); /* DEFERRED */ + testcase( i==97 ); /* DISTINCT */ + testcase( i==98 ); /* IS */ + testcase( i==99 ); /* DROP */ + testcase( i==100 ); /* FAIL */ + testcase( i==101 ); /* FROM */ + testcase( i==102 ); /* FULL */ + testcase( i==103 ); /* GLOB */ + testcase( i==104 ); /* BY */ + testcase( i==105 ); /* IF */ + testcase( i==106 ); /* ISNULL */ + testcase( i==107 ); /* ORDER */ + testcase( i==108 ); /* RESTRICT */ + testcase( i==109 ); /* OUTER */ + testcase( i==110 ); /* RIGHT */ + testcase( i==111 ); /* ROLLBACK */ + testcase( i==112 ); /* ROW */ + testcase( i==113 ); /* UNION */ + testcase( i==114 ); /* USING */ + testcase( i==115 ); /* VACUUM */ + testcase( i==116 ); /* VIEW */ + testcase( i==117 ); /* INITIALLY */ + testcase( i==118 ); /* ALL */ return aCode[i]; } } return TK_ID; } @@ -88037,10 +91897,15 @@ */ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ int i, c; switch( *z ){ case ' ': case '\t': case '\n': case '\f': case '\r': { + testcase( z[0]==' ' ); + testcase( z[0]=='\t' ); + testcase( z[0]=='\n' ); + testcase( z[0]=='\f' ); + testcase( z[0]=='\r' ); for(i=1; sqlite3Isspace(z[i]); i++){} *tokenType = TK_SPACE; return i; } case '-': { @@ -88149,10 +92014,13 @@ } case '`': case '\'': case '"': { int delim = z[0]; + testcase( delim=='`' ); + testcase( delim=='\'' ); + testcase( delim=='"' ); for(i=1; (c=z[i])!=0; i++){ if( c==delim ){ if( z[i+1]==delim ){ i++; }else{ @@ -88182,10 +92050,14 @@ /* If the next character is a digit, this is a floating point ** number that begins with ".". Fall thru into the next case */ } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { + testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); + testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); + testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); + testcase( z[0]=='9' ); *tokenType = TK_INTEGER; for(i=0; sqlite3Isdigit(z[i]); i++){} #ifndef SQLITE_OMIT_FLOATING_POINT if( z[i]=='.' ){ i++; @@ -88233,10 +92105,11 @@ case '$': #endif case '@': /* For compatibility with MS SQL Server */ case ':': { int n = 0; + testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' ); *tokenType = TK_VARIABLE; for(i=1; (c=z[i])!=0; i++){ if( IdChar(c) ){ n++; #ifndef SQLITE_OMIT_TCL_VARIABLE @@ -88260,10 +92133,11 @@ if( n==0 ) *tokenType = TK_ILLEGAL; return i; } #ifndef SQLITE_OMIT_BLOB_LITERAL case 'x': case 'X': { + testcase( z[0]=='x' ); testcase( z[0]=='X' ); if( z[1]=='\'' ){ *tokenType = TK_BLOB; for(i=2; (c=z[i])!=0 && c!='\''; i++){ if( !sqlite3Isxdigit(c) ){ *tokenType = TK_ILLEGAL; @@ -88310,19 +92184,18 @@ mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->activeVdbeCnt==0 ){ db->u1.isInterrupted = 0; } pParse->rc = SQLITE_OK; - pParse->zTail = pParse->zSql = zSql; + pParse->zTail = zSql; i = 0; assert( pzErrMsg!=0 ); pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); if( pEngine==0 ){ db->mallocFailed = 1; return SQLITE_NOMEM; } - assert( pParse->sLastToken.dyn==0 ); assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->nVarExpr==0 ); assert( pParse->nVarExprAlloc==0 ); @@ -88329,23 +92202,22 @@ assert( pParse->apVarExpr==0 ); enableLookaside = db->lookaside.bEnabled; if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; while( !db->mallocFailed && zSql[i]!=0 ){ assert( i>=0 ); - pParse->sLastToken.z = (u8*)&zSql[i]; - assert( pParse->sLastToken.dyn==0 ); + pParse->sLastToken.z = &zSql[i]; pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); i += pParse->sLastToken.n; if( i>mxSqlLen ){ pParse->rc = SQLITE_TOOBIG; break; } switch( tokenType ){ case TK_SPACE: { if( db->u1.isInterrupted ){ - pParse->rc = SQLITE_INTERRUPT; - sqlite3SetString(pzErrMsg, db, "interrupt"); + sqlite3ErrorMsg(pParse, "interrupt"); + pParse->rc = SQLITE_INTERRUPT; goto abort_parse; } break; } case TK_ILLEGAL: { @@ -88388,16 +92260,13 @@ pParse->rc = SQLITE_NOMEM; } if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); } + assert( pzErrMsg!=0 ); if( pParse->zErrMsg ){ - if( *pzErrMsg==0 ){ - *pzErrMsg = pParse->zErrMsg; - }else{ - sqlite3DbFree(db, pParse->zErrMsg); - } + *pzErrMsg = pParse->zErrMsg; pParse->zErrMsg = 0; nErr++; } if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ sqlite3VdbeDelete(pParse->pVdbe); @@ -88423,16 +92292,21 @@ } sqlite3DeleteTrigger(db, pParse->pNewTrigger); sqlite3DbFree(db, pParse->apVarExpr); sqlite3DbFree(db, pParse->aAlias); + while( pParse->pAinc ){ + AutoincInfo *p = pParse->pAinc; + pParse->pAinc = p->pNext; + sqlite3DbFree(db, p); + } while( pParse->pZombieTab ){ Table *p = pParse->pZombieTab; pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(p); } - if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ + if( nErr>0 && pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } return nErr; } @@ -88454,11 +92328,11 @@ ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** -** $Id: complete.c,v 1.7 2008/06/13 18:24:27 drh Exp $ +** $Id: complete.c,v 1.8 2009/04/28 04:46:42 drh Exp $ */ #ifndef SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. @@ -88549,11 +92423,11 @@ static const u8 trans[7][8] = { /* Token: */ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ /* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, }, /* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, }, - /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, }, + /* 2 EXPLAIN: */ { 0, 2, 2, 1, 3, 1, 1, 1, }, /* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, }, /* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, }, /* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, }, /* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, }, }; @@ -88730,12 +92604,10 @@ ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. -** -** $Id: main.c,v 1.536 2009/04/09 01:23:49 drh Exp $ */ #ifdef SQLITE_ENABLE_FTS3 /************** Include fts3.h in the middle of main.c ***********************/ /************** Begin file fts3.h ********************************************/ @@ -88839,10 +92711,11 @@ */ #ifndef SQLITE_AMALGAMATION SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; #endif SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } +SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) /* @@ -88929,17 +92802,19 @@ ** malloc subsystem - this implies that the allocation of a static ** mutex must not require support from the malloc subsystem. */ pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(pMaster); + sqlite3GlobalConfig.isMutexInit = 1; if( !sqlite3GlobalConfig.isMallocInit ){ rc = sqlite3MallocInit(); } if( rc==SQLITE_OK ){ sqlite3GlobalConfig.isMallocInit = 1; if( !sqlite3GlobalConfig.pInitMutex ){ - sqlite3GlobalConfig.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); + sqlite3GlobalConfig.pInitMutex = + sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){ rc = SQLITE_NOMEM; } } } @@ -88946,14 +92821,13 @@ if( rc==SQLITE_OK ){ sqlite3GlobalConfig.nRefInitMutex++; } sqlite3_mutex_leave(pMaster); - /* If unable to initialize the malloc subsystem, then return early. - ** There is little hope of getting SQLite to run if the malloc - ** subsystem cannot be initialized. - */ + /* If rc is not SQLITE_OK at this point, then either the malloc + ** subsystem could not be initialized or the system failed to allocate + ** the pInitMutex mutex. Return an error in either case. */ if( rc!=SQLITE_OK ){ return rc; } /* Do the rest of the initialization under the recursive mutex so @@ -88966,18 +92840,23 @@ if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); sqlite3GlobalConfig.inProgress = 1; memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); sqlite3RegisterGlobalFunctions(); - rc = sqlite3_os_init(); - if( rc==SQLITE_OK ){ + if( sqlite3GlobalConfig.isPCacheInit==0 ){ rc = sqlite3PcacheInitialize(); + } + if( rc==SQLITE_OK ){ + sqlite3GlobalConfig.isPCacheInit = 1; + rc = sqlite3OsInit(); + } + if( rc==SQLITE_OK ){ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); - } - sqlite3GlobalConfig.inProgress = 0; - sqlite3GlobalConfig.isInit = (rc==SQLITE_OK ? 1 : 0); + sqlite3GlobalConfig.isInit = 1; + } + sqlite3GlobalConfig.inProgress = 0; } sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex); /* Go back under the static mutex and clean up the recursive ** mutex to prevent a resource leak. @@ -89015,22 +92894,33 @@ /* ** Undo the effects of sqlite3_initialize(). Must not be called while ** there are outstanding database connections or memory allocations or ** while any part of SQLite is otherwise in use in any thread. This -** routine is not threadsafe. Not by a long shot. -*/ -SQLITE_API int sqlite3_shutdown(void){ - sqlite3GlobalConfig.isMallocInit = 0; - sqlite3PcacheShutdown(); +** routine is not threadsafe. But it is safe to invoke this routine +** on when SQLite is already shut down. If SQLite is already shut down +** when this routine is invoked, then this routine is a harmless no-op. +*/ +SQLITE_API int sqlite3_shutdown(void){ if( sqlite3GlobalConfig.isInit ){ sqlite3_os_end(); - } - sqlite3_reset_auto_extension(); - sqlite3MallocEnd(); - sqlite3MutexEnd(); - sqlite3GlobalConfig.isInit = 0; + sqlite3_reset_auto_extension(); + sqlite3GlobalConfig.isInit = 0; + } + if( sqlite3GlobalConfig.isPCacheInit ){ + sqlite3PcacheShutdown(); + sqlite3GlobalConfig.isPCacheInit = 0; + } + if( sqlite3GlobalConfig.isMallocInit ){ + sqlite3MallocEnd(); + sqlite3GlobalConfig.isMallocInit = 0; + } + if( sqlite3GlobalConfig.isMutexInit ){ + sqlite3MutexEnd(); + sqlite3GlobalConfig.isMutexInit = 0; + } + return SQLITE_OK; } /* ** This API allows applications to modify the global configuration of @@ -89110,19 +93000,19 @@ sqlite3GlobalConfig.szScratch = va_arg(ap, int); sqlite3GlobalConfig.nScratch = va_arg(ap, int); break; } case SQLITE_CONFIG_PAGECACHE: { - /* Designate a buffer for scratch memory space */ + /* Designate a buffer for page cache memory space */ sqlite3GlobalConfig.pPage = va_arg(ap, void*); sqlite3GlobalConfig.szPage = va_arg(ap, int); sqlite3GlobalConfig.nPage = va_arg(ap, int); break; } case SQLITE_CONFIG_PCACHE: { - /* Specify an alternative malloc implementation */ + /* Specify an alternative page cache implementation */ sqlite3GlobalConfig.pcache = *va_arg(ap, sqlite3_pcache_methods*); break; } case SQLITE_CONFIG_GETPCACHE: { @@ -89149,11 +93039,10 @@ memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m)); }else{ /* The heap pointer is not NULL, then install one of the ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor ** ENABLE_MEMSYS5 is defined, return an error. - ** the default case and return an error. */ #ifdef SQLITE_ENABLE_MEMSYS3 sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3(); #endif #ifdef SQLITE_ENABLE_MEMSYS5 @@ -89384,17 +93273,10 @@ if( !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); -#ifdef SQLITE_SSE - { - extern void sqlite3SseCleanup(sqlite3*); - sqlite3SseCleanup(db); - } -#endif - sqlite3ResetInternalSchema(db, 0); /* If a transaction is open, the ResetInternalSchema() call above ** will not have called the xDisconnect() method on any virtual ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() @@ -89538,41 +93420,45 @@ /* ** Return a static string that describes the kind of error specified in the ** argument. */ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ - const char *z; - switch( rc & 0xff ){ - case SQLITE_ROW: - case SQLITE_DONE: - case SQLITE_OK: z = "not an error"; break; - case SQLITE_ERROR: z = "SQL logic error or missing database"; break; - case SQLITE_PERM: z = "access permission denied"; break; - case SQLITE_ABORT: z = "callback requested query abort"; break; - case SQLITE_BUSY: z = "database is locked"; break; - case SQLITE_LOCKED: z = "database table is locked"; break; - case SQLITE_NOMEM: z = "out of memory"; break; - case SQLITE_READONLY: z = "attempt to write a readonly database"; break; - case SQLITE_INTERRUPT: z = "interrupted"; break; - case SQLITE_IOERR: z = "disk I/O error"; break; - case SQLITE_CORRUPT: z = "database disk image is malformed"; break; - case SQLITE_FULL: z = "database or disk is full"; break; - case SQLITE_CANTOPEN: z = "unable to open database file"; break; - case SQLITE_EMPTY: z = "table contains no data"; break; - case SQLITE_SCHEMA: z = "database schema has changed"; break; - case SQLITE_TOOBIG: z = "String or BLOB exceeded size limit"; break; - case SQLITE_CONSTRAINT: z = "constraint failed"; break; - case SQLITE_MISMATCH: z = "datatype mismatch"; break; - case SQLITE_MISUSE: z = "library routine called out of sequence";break; - case SQLITE_NOLFS: z = "large file support is disabled"; break; - case SQLITE_AUTH: z = "authorization denied"; break; - case SQLITE_FORMAT: z = "auxiliary database format error"; break; - case SQLITE_RANGE: z = "bind or column index out of range"; break; - case SQLITE_NOTADB: z = "file is encrypted or is not a database";break; - default: z = "unknown error"; break; - } - return z; + static const char* const aMsg[] = { + /* SQLITE_OK */ "not an error", + /* SQLITE_ERROR */ "SQL logic error or missing database", + /* SQLITE_INTERNAL */ 0, + /* SQLITE_PERM */ "access permission denied", + /* SQLITE_ABORT */ "callback requested query abort", + /* SQLITE_BUSY */ "database is locked", + /* SQLITE_LOCKED */ "database table is locked", + /* SQLITE_NOMEM */ "out of memory", + /* SQLITE_READONLY */ "attempt to write a readonly database", + /* SQLITE_INTERRUPT */ "interrupted", + /* SQLITE_IOERR */ "disk I/O error", + /* SQLITE_CORRUPT */ "database disk image is malformed", + /* SQLITE_NOTFOUND */ 0, + /* SQLITE_FULL */ "database or disk is full", + /* SQLITE_CANTOPEN */ "unable to open database file", + /* SQLITE_PROTOCOL */ 0, + /* SQLITE_EMPTY */ "table contains no data", + /* SQLITE_SCHEMA */ "database schema has changed", + /* SQLITE_TOOBIG */ "string or blob too big", + /* SQLITE_CONSTRAINT */ "constraint failed", + /* SQLITE_MISMATCH */ "datatype mismatch", + /* SQLITE_MISUSE */ "library routine called out of sequence", + /* SQLITE_NOLFS */ "large file support is disabled", + /* SQLITE_AUTH */ "authorization denied", + /* SQLITE_FORMAT */ "auxiliary database format error", + /* SQLITE_RANGE */ "bind or column index out of range", + /* SQLITE_NOTADB */ "file is encrypted or is not a database", + }; + rc &= 0xff; + if( ALWAYS(rc>=0) && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){ + return aMsg[rc]; + }else{ + return "unknown error"; + } } /* ** This routine implements a busy callback that sleeps and tries ** again until a timeout value is reached. The timeout value is @@ -89726,13 +93612,12 @@ if( zFunctionName==0 || (xFunc && (xFinal || xStep)) || (!xFunc && (xFinal && !xStep)) || (!xFunc && (!xFinal && xStep)) || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || - (255<(nName = sqlite3Strlen(db, zFunctionName))) ){ - sqlite3Error(db, SQLITE_ERROR, "bad parameters"); - return SQLITE_ERROR; + (255<(nName = sqlite3Strlen30( zFunctionName))) ){ + return SQLITE_MISUSE; } #ifndef SQLITE_OMIT_UTF16 /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the @@ -89852,11 +93737,11 @@ SQLITE_API int sqlite3_overload_function( sqlite3 *db, const char *zName, int nArg ){ - int nName = sqlite3Strlen(db, zName); + int nName = sqlite3Strlen30(zName); int rc; sqlite3_mutex_enter(db->mutex); if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, 0, sqlite3InvalidFunction, 0, 0); @@ -89962,33 +93847,55 @@ sqlite3_mutex_leave(db->mutex); return pRet; } /* +** This function returns true if main-memory should be used instead of +** a temporary file for transient pager files and statement journals. +** The value returned depends on the value of db->temp_store (runtime +** parameter) and the compile time value of SQLITE_TEMP_STORE. The +** following table describes the relationship between these two values +** and this functions return value. +** +** SQLITE_TEMP_STORE db->temp_store Location of temporary database +** ----------------- -------------- ------------------------------ +** 0 any file (return 0) +** 1 1 file (return 0) +** 1 2 memory (return 1) +** 1 0 file (return 0) +** 2 1 file (return 0) +** 2 2 memory (return 1) +** 2 0 memory (return 1) +** 3 any memory (return 1) +*/ +SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ +#if SQLITE_TEMP_STORE==1 + return ( db->temp_store==2 ); +#endif +#if SQLITE_TEMP_STORE==2 + return ( db->temp_store!=1 ); +#endif +#if SQLITE_TEMP_STORE==3 + return 1; +#endif +#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3 + return 0; +#endif +} + +/* ** This routine is called to create a connection to a database BTree ** driver. If zFilename is the name of a file, then that file is ** opened and used. If zFilename is the magic name ":memory:" then ** the database is stored in memory (and is thus forgotten as soon as ** the connection is closed.) If zFilename is NULL then the database ** is a "virtual" database for transient use only and is deleted as ** soon as the connection is closed. ** ** A virtual database can be either a disk file (that is automatically -** deleted when the file is closed) or it an be held entirely in memory, -** depending on the values of the SQLITE_TEMP_STORE compile-time macro and the -** db->temp_store variable, according to the following chart: -** -** SQLITE_TEMP_STORE db->temp_store Location of temporary database -** ----------------- -------------- ------------------------------ -** 0 any file -** 1 1 file -** 1 2 memory -** 1 0 file -** 2 1 file -** 2 2 memory -** 2 0 memory -** 3 any memory +** deleted when the file is closed) or it an be held entirely in memory. +** The sqlite3TempInMemory() function is used to determine which. */ SQLITE_PRIVATE int sqlite3BtreeFactory( const sqlite3 *db, /* Main database when opening aux otherwise 0 */ const char *zFilename, /* Name of the file containing the BTree database */ int omitJournal, /* if TRUE then do not journal this file */ @@ -90005,26 +93912,15 @@ btFlags |= BTREE_OMIT_JOURNAL; } if( db->flags & SQLITE_NoReadlock ){ btFlags |= BTREE_NO_READLOCK; } - if( zFilename==0 ){ -#if SQLITE_TEMP_STORE==0 - /* Do nothing */ -#endif #ifndef SQLITE_OMIT_MEMORYDB -#if SQLITE_TEMP_STORE==1 - if( db->temp_store==2 ) zFilename = ":memory:"; -#endif -#if SQLITE_TEMP_STORE==2 - if( db->temp_store!=1 ) zFilename = ":memory:"; -#endif -#if SQLITE_TEMP_STORE==3 + if( zFilename==0 && sqlite3TempInMemory(db) ){ zFilename = ":memory:"; -#endif -#endif /* SQLITE_OMIT_MEMORYDB */ - } + } +#endif if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){ vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; } rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags); @@ -90141,39 +94037,41 @@ ** and the encoding is enc. */ static int createCollation( sqlite3* db, const char *zName, - int enc, + u8 enc, + u8 collType, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDel)(void*) ){ CollSeq *pColl; int enc2; - int nName; + int nName = sqlite3Strlen30(zName); assert( sqlite3_mutex_held(db->mutex) ); /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. */ - enc2 = enc & ~SQLITE_UTF16_ALIGNED; - if( enc2==SQLITE_UTF16 ){ + enc2 = enc; + testcase( enc2==SQLITE_UTF16 ); + testcase( enc2==SQLITE_UTF16_ALIGNED ); + if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){ enc2 = SQLITE_UTF16NATIVE; } - if( (enc2&~3)!=0 ){ + if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){ return SQLITE_MISUSE; } /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ - nName = sqlite3Strlen(db, zName); - pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, nName, 0); + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); if( pColl && pColl->xCmp ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; @@ -90199,16 +94097,17 @@ } } } } - pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, nName, 1); + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1); if( pColl ){ pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->xDel = xDel; pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); + pColl->type = collType; } sqlite3Error(db, SQLITE_OK, 0); return SQLITE_OK; } @@ -90227,10 +94126,11 @@ SQLITE_MAX_VDBE_OP, SQLITE_MAX_FUNCTION_ARG, SQLITE_MAX_ATTACHED, SQLITE_MAX_LIKE_PATTERN_LENGTH, SQLITE_MAX_VARIABLE_NUMBER, + SQLITE_MAX_TRIGGER_DEPTH, }; /* ** Make sure the hard limits are set to reasonable values */ @@ -90261,10 +94161,13 @@ #if SQLITE_MAX_VARIABLE_NUMBER<1 # error SQLITE_MAX_VARIABLE_NUMBER must be at least 1 #endif #if SQLITE_MAX_COLUMN>32767 # error SQLITE_MAX_COLUMN must not exceed 32767 +#endif +#if SQLITE_MAX_TRIGGER_DEPTH<1 +# error SQLITE_MAX_TRIGGER_DEPTH must be at least 1 #endif /* ** Change the value of a limit. Report the old value. @@ -90302,13 +94205,13 @@ unsigned flags, /* Operational flags */ const char *zVfs /* Name of the VFS to use */ ){ sqlite3 *db; int rc; - CollSeq *pColl; int isThreadsafe; + *ppDb = 0; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); if( rc ) return rc; #endif @@ -90319,13 +94222,26 @@ }else if( flags & SQLITE_OPEN_FULLMUTEX ){ isThreadsafe = 1; }else{ isThreadsafe = sqlite3GlobalConfig.bFullMutex; } - - /* Remove harmful bits from the flags parameter */ + if( flags & SQLITE_OPEN_PRIVATECACHE ){ + flags &= ~SQLITE_OPEN_SHAREDCACHE; + }else if( sqlite3GlobalConfig.sharedCacheEnabled ){ + flags |= SQLITE_OPEN_SHAREDCACHE; + } + + /* Remove harmful bits from the flags parameter + ** + ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were + ** dealt with in the previous code block. Besides these, the only + ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY, + ** SQLITE_OPEN_READWRITE, and SQLITE_OPEN_CREATE. Silently mask + ** off all other flags. + */ flags &= ~( SQLITE_OPEN_DELETEONCLOSE | + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TRANSIENT_DB | SQLITE_OPEN_MAIN_JOURNAL | SQLITE_OPEN_TEMP_JOURNAL | @@ -90346,11 +94262,10 @@ goto opendb_out; } } sqlite3_mutex_enter(db->mutex); db->errMask = 0xff; - db->priorNewRowid = 0; db->nDb = 2; db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); @@ -90363,14 +94278,17 @@ | SQLITE_LegacyFileFmt #endif #ifdef SQLITE_ENABLE_LOAD_EXTENSION | SQLITE_LoadExtension #endif +#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS + | SQLITE_RecTriggers +#endif ; - sqlite3HashInit(&db->aCollSeq, 0); + sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3HashInit(&db->aModule, 0); + sqlite3HashInit(&db->aModule); #endif db->pVfs = sqlite3_vfs_find(zVfs); if( !db->pVfs ){ rc = SQLITE_ERROR; @@ -90380,29 +94298,27 @@ /* Add the default collation sequence BINARY. BINARY works for both UTF-8 ** and UTF-16, so add a version for each to avoid any unnecessary ** conversions. The only error that can occur here is a malloc() failure. */ - createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0); - createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0); - createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0); - createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF8, SQLITE_COLL_BINARY, 0, + binCollFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF16BE, SQLITE_COLL_BINARY, 0, + binCollFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF16LE, SQLITE_COLL_BINARY, 0, + binCollFunc, 0); + createCollation(db, "RTRIM", SQLITE_UTF8, SQLITE_COLL_USER, (void*)1, + binCollFunc, 0); if( db->mallocFailed ){ goto opendb_out; } - db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0); + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0); assert( db->pDfltColl!=0 ); /* Also add a UTF-8 case-insensitive collation sequence. */ - createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); - - /* Set flags on the built-in collating sequences */ - db->pDfltColl->type = SQLITE_COLL_BINARY; - pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0); - if( pColl ){ - pColl->type = SQLITE_COLL_NOCASE; - } + createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0, + nocaseCollatingFunc, 0); /* Open the backend database driver */ db->openFlags = flags; rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE, flags | SQLITE_OPEN_MAIN_DB, @@ -90421,14 +94337,12 @@ /* The default safety_level for the main database is 'full'; for the temp ** database it is 'NONE'. This matches the pager layer defaults. */ db->aDb[0].zName = "main"; db->aDb[0].safety_level = 3; -#ifndef SQLITE_OMIT_TEMPDB db->aDb[1].zName = "temp"; db->aDb[1].safety_level = 1; -#endif db->magic = SQLITE_MAGIC_OPEN; if( db->mallocFailed ){ goto opendb_out; } @@ -90441,12 +94355,13 @@ sqlite3RegisterBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ - (void)sqlite3AutoLoadExtensions(db); - if( sqlite3_errcode(db)!=SQLITE_OK ){ + sqlite3AutoLoadExtensions(db); + rc = sqlite3_errcode(db); + if( rc!=SQLITE_OK ){ goto opendb_out; } #ifdef SQLITE_ENABLE_FTS1 if( !db->mallocFailed ){ @@ -90580,11 +94495,11 @@ int(*xCompare)(void*,int,const void*,int,const void*) ){ int rc; sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); - rc = createCollation(db, zName, enc, pCtx, xCompare, 0); + rc = createCollation(db, zName, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } @@ -90600,11 +94515,11 @@ void(*xDel)(void*) ){ int rc; sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); - rc = createCollation(db, zName, enc, pCtx, xCompare, xDel); + rc = createCollation(db, zName, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, xDel); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } @@ -90623,11 +94538,11 @@ char *zName8; sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zName8 = sqlite3Utf16to8(db, zName, -1); if( zName8 ){ - rc = createCollation(db, zName8, enc, pCtx, xCompare, 0); + rc = createCollation(db, zName8, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0); sqlite3DbFree(db, zName8); } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; @@ -90960,11 +94875,11 @@ sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd); break; } /* - ** sqlite3_test_control(PENDING_BYTE, unsigned int X) + ** sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X) ** ** Set the PENDING byte to the value in the argument, if X>0. ** Make no changes if X==0. Return the value of the pending byte ** as it existing before this routine was called. ** @@ -90977,10 +94892,77 @@ unsigned int newVal = va_arg(ap, unsigned int); rc = sqlite3PendingByte; if( newVal ) sqlite3PendingByte = newVal; break; } + + /* + ** sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, int X) + ** + ** This action provides a run-time test to see whether or not + ** assert() was enabled at compile-time. If X is true and assert() + ** is enabled, then the return value is true. If X is true and + ** assert() is disabled, then the return value is zero. If X is + ** false and assert() is enabled, then the assertion fires and the + ** process aborts. If X is false and assert() is disabled, then the + ** return value is zero. + */ + case SQLITE_TESTCTRL_ASSERT: { + volatile int x = 0; + assert( (x = va_arg(ap,int))!=0 ); + rc = x; + break; + } + + + /* + ** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X) + ** + ** This action provides a run-time test to see how the ALWAYS and + ** NEVER macros were defined at compile-time. + ** + ** The return value is ALWAYS(X). + ** + ** The recommended test is X==2. If the return value is 2, that means + ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the + ** default setting. If the return value is 1, then ALWAYS() is either + ** hard-coded to true or else it asserts if its argument is false. + ** The first behavior (hard-coded to true) is the case if + ** SQLITE_TESTCTRL_ASSERT shows that assert() is disabled and the second + ** behavior (assert if the argument to ALWAYS() is false) is the case if + ** SQLITE_TESTCTRL_ASSERT shows that assert() is enabled. + ** + ** The run-time test procedure might look something like this: + ** + ** if( sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, 2)==2 ){ + ** // ALWAYS() and NEVER() are no-op pass-through macros + ** }else if( sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, 1) ){ + ** // ALWAYS(x) asserts that x is true. NEVER(x) asserts x is false. + ** }else{ + ** // ALWAYS(x) is a constant 1. NEVER(x) is a constant 0. + ** } + */ + case SQLITE_TESTCTRL_ALWAYS: { + int x = va_arg(ap,int); + rc = ALWAYS(x); + break; + } + + /* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N) + ** + ** Set the nReserve size to N for the main database on the database + ** connection db. + */ + case SQLITE_TESTCTRL_RESERVE: { + sqlite3 *db = va_arg(ap, sqlite3*); + int x = va_arg(ap,int); + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0); + sqlite3_mutex_leave(db->mutex); + break; + } + } va_end(ap); #endif /* SQLITE_OMIT_BUILTIN_TEST */ return rc; } @@ -99120,11 +103102,13 @@ iCol = pParse->iDefaultCol; iColLen = 0; for(ii=0; ii<pParse->nCol; ii++){ const char *zStr = pParse->azCol[ii]; int nStr = strlen(zStr); - if( nInput>nStr && zInput[nStr]==':' && memcmp(zStr, zInput, nStr)==0 ){ + if( nInput>nStr && zInput[nStr]==':' + && sqlite3_strnicmp(zStr, zInput, nStr)==0 + ){ iCol = ii; iColLen = ((zInput - z) + nStr + 1); break; } } @@ -99237,14 +103221,14 @@ } memset(pNot, 0, sizeof(Fts3Expr)); pNot->eType = FTSQUERY_NOT; pNot->pRight = p; if( pNotBranch ){ - pNotBranch->pLeft = p; - pNot->pRight = pNotBranch; + pNot->pLeft = pNotBranch; } pNotBranch = pNot; + p = pPrev; }else{ int eType = p->eType; assert( eType!=FTSQUERY_PHRASE || !p->pPhrase->isNot ); isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft); @@ -99322,11 +103306,15 @@ rc = SQLITE_OK; if( !sqlite3_fts3_enable_parentheses && pNotBranch ){ if( !pRet ){ rc = SQLITE_ERROR; }else{ - pNotBranch->pLeft = pRet; + Fts3Expr *pIter = pNotBranch; + while( pIter->pLeft ){ + pIter = pIter->pLeft; + } + pIter->pLeft = pRet; pRet = pNotBranch; } } } *pnConsumed = n - nIn; @@ -101212,11 +105200,11 @@ ** ************************************************************************* ** This file contains code for implementations of the r-tree and r*-tree ** algorithms packaged as an SQLite virtual table module. ** -** $Id: rtree.c,v 1.12 2008/12/22 15:04:32 danielk1977 Exp $ +** $Id: rtree.c,v 1.14 2009/08/06 18:36:47 danielk1977 Exp $ */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) /* @@ -103538,11 +107526,11 @@ #endif /* ** The xUpdate method for rtree module virtual tables. */ -int rtreeUpdate( +static int rtreeUpdate( sqlite3_vtab *pVtab, int nData, sqlite3_value **azData, sqlite_int64 *pRowid ){ @@ -103933,12 +107921,14 @@ if( zSql ){ zTmp = zSql; zSql = sqlite3_mprintf("%s);", zTmp); sqlite3_free(zTmp); } - if( !zSql || sqlite3_declare_vtab(db, zSql) ){ + if( !zSql ){ rc = SQLITE_NOMEM; + }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } sqlite3_free(zSql); } if( rc==SQLITE_OK ){
Modified src/sqlite3.h from [45a47b096b] to [67b66f4eca].
@@ -16,23 +16,21 @@ ** notice, and should not be referenced by programs that use SQLite. ** ** Some of the definitions that are in this file are marked as ** "experimental". Experimental interfaces are normally new ** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. +** to experimental interfaces but reserve the right to make minor changes +** if experience from use "in the wild" suggest such changes are prudent. ** ** The official C-language API documentation for SQLite is derived ** from comments in this file. This file is the authoritative source ** on how SQLite interfaces are suppose to operate. ** ** The name of this file under configuration management is "sqlite.h.in". ** The makefile makes some minor changes to this file (such as inserting ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. -** -** @(#) $Id: sqlite.h.in,v 1.440 2009/04/06 15:55:04 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include <stdarg.h> /* Needed for the definition of va_list */ @@ -49,14 +47,19 @@ */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif +#ifndef SQLITE_API +# define SQLITE_API +#endif + + /* ** These no-op macros are used in front of interfaces to mark those ** interfaces as either deprecated or experimental. New applications -** should not use deprecated intrfaces - they are support for backwards +** should not use deprecated interfaces - they are support for backwards ** compatibility only. Application writers should be aware that ** experimental interfaces are subject to change in point releases. ** ** These macros used to resolve to various kinds of compiler magic that ** would generate warning messages when they were used. But that @@ -82,55 +85,85 @@ ** ** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in ** the sqlite3.h file specify the version of SQLite with which ** that header file is associated. ** -** The "version" of SQLite is a string of the form "X.Y.Z". -** The phrase "alpha" or "beta" might be appended after the Z. -** The X value is major version number always 3 in SQLite3. -** The X value only changes when backwards compatibility is +** The "version" of SQLite is a string of the form "W.X.Y" or "W.X.Y.Z". +** The W value is major version number and is always 3 in SQLite3. +** The W value only changes when backwards compatibility is ** broken and we intend to never break backwards compatibility. -** The Y value is the minor version number and only changes when +** The X value is the minor version number and only changes when ** there are major feature enhancements that are forwards compatible ** but not backwards compatible. -** The Z value is the release number and is incremented with -** each release but resets back to 0 whenever Y is incremented. -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. +** The Y value is the release number and is incremented with +** each release but resets back to 0 whenever X is incremented. +** The Z value only appears on branch releases. +** +** The SQLITE_VERSION_NUMBER is an integer that is computed as +** follows: +** +** <blockquote><pre> +** SQLITE_VERSION_NUMBER = W*1000000 + X*1000 + Y +** </pre></blockquote> +** +** Since version 3.6.18, SQLite source code has been stored in the +** <a href="http://www.fossil-scm.org/">fossil configuration management +** system</a>. The SQLITE_SOURCE_ID +** macro is a string which identifies a particular check-in of SQLite +** within its configuration management system. The string contains the +** date and time of the check-in (UTC) and an SHA1 hash of the entire +** source tree. +** +** See also: [sqlite3_libversion()], +** [sqlite3_libversion_number()], [sqlite3_sourceid()], +** [sqlite_version()] and [sqlite_source_id()]. ** ** Requirements: [H10011] [H10014] */ -#define SQLITE_VERSION "3.6.13" -#define SQLITE_VERSION_NUMBER 3006013 +#define SQLITE_VERSION "3.6.18" +#define SQLITE_VERSION_NUMBER 3006018 +#define SQLITE_SOURCE_ID "2009-09-11 14:05:07 b084828a771ec40be85f07c590ca99de4f6c24ee" /* ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> ** KEYWORDS: sqlite3_version ** -** These features provide the same information as the [SQLITE_VERSION] -** and [SQLITE_VERSION_NUMBER] #defines in the header, but are associated -** with the library instead of the header file. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. +** These interfaces provide the same information as the [SQLITE_VERSION], +** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] #defines in the header, +** but are associated with the library instead of the header file. Cautious +** programmers might include assert() statements in their application to +** verify that values returned by these interfaces match the macros in +** the header, and thus insure that the application is +** compiled with matching library and header files. +** +** <blockquote><pre> +** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); +** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 ); +** assert( strcmp(sqlite3_libversion,SQLITE_VERSION)==0 ); +** </pre></blockquote> ** ** The sqlite3_libversion() function returns the same information as is ** in the sqlite3_version[] string constant. The function is provided ** for use in DLLs since DLL users usually do not have direct access to string -** constants within the DLL. +** constants within the DLL. Similarly, the sqlite3_sourceid() function +** returns the same information as is in the [SQLITE_SOURCE_ID] #define of +** the header file. +** +** See also: [sqlite_version()] and [sqlite_source_id()]. ** ** Requirements: [H10021] [H10022] [H10023] */ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); +SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} <S60100> ** ** SQLite can be compiled with or without mutexes. When -** the [SQLITE_THREADSAFE] C preprocessor macro 1 or 2, mutexes +** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes ** are enabled and SQLite is threadsafe. When the ** [SQLITE_THREADSAFE] macro is 0, ** the mutexes are omitted. Without the mutexes, it is not safe ** to use SQLite concurrently from more than one thread. ** @@ -137,11 +170,11 @@ ** Enabling mutexes incurs a measurable performance penalty. ** So if speed is of utmost importance, it makes sense to disable ** the mutexes. But for maximum safety, mutexes should be enabled. ** The default behavior is for mutexes to be enabled. ** -** This interface can be used by a program to make sure that the +** This interface can be used by an application to make sure that the ** version of SQLite that it is linking against was compiled with ** the desired setting of the [SQLITE_THREADSAFE] macro. ** ** This interface only reports on the compile-time mutex setting ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with @@ -154,11 +187,11 @@ ** ** See the [threading mode] documentation for additional information. ** ** Requirements: [H10101] [H10102] */ -int sqlite3_threadsafe(void); +SQLITE_API int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle {H12000} <S40200> ** KEYWORDS: {database connection} {database connections} ** @@ -235,11 +268,11 @@ ** [sqlite3_open_v2()], and not previously closed. ** ** Requirements: ** [H12011] [H12012] [H12013] [H12014] [H12015] [H12019] */ -int sqlite3_close(sqlite3 *); +SQLITE_API int sqlite3_close(sqlite3 *); /* ** The type for a callback function. ** This is legacy and deprecated. It is included for historical ** compatibility and is not documented. @@ -288,11 +321,11 @@ ** ** Requirements: ** [H12101] [H12102] [H12104] [H12105] [H12107] [H12110] [H12113] [H12116] ** [H12119] [H12122] [H12125] [H12131] [H12134] [H12137] [H12138] */ -int sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ void *, /* 1st argument to callback */ char **errmsg /* Error msg written here */ @@ -390,24 +423,26 @@ ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the xOpen method of the ** [sqlite3_vfs] object. */ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 -#define SQLITE_OPEN_NOMUTEX 0x00008000 -#define SQLITE_OPEN_FULLMUTEX 0x00010000 +#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ +#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ +#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ /* ** CAPI3REF: Device Characteristics {H10240} <H11120> ** ** The xDeviceCapabilities method of the [sqlite3_io_methods] @@ -471,12 +506,13 @@ #define SQLITE_SYNC_DATAONLY 0x00010 /* ** CAPI3REF: OS Interface Open File Handle {H11110} <S20110> ** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will +** An [sqlite3_file] object represents an open file in the +** [sqlite3_vfs | OS interface layer]. Individual OS interface +** implementations will ** want to subclass this object by appending additional fields ** for their own use. The pMethods entry is a pointer to an ** [sqlite3_io_methods] object that defines methods for performing ** I/O operations on the open file. */ @@ -491,10 +527,16 @@ ** Every file opened by the [sqlite3_vfs] xOpen method populates an ** [sqlite3_file] object (or, more commonly, a subclass of the ** [sqlite3_file] object) with a pointer to an instance of this object. ** This object defines the methods used to perform various operations ** against the open file represented by the [sqlite3_file] object. +** +** If the xOpen method sets the sqlite3_file.pMethods element +** to a non-NULL pointer, then the sqlite3_io_methods.xClose method +** may be invoked even if the xOpen reported that it failed. The +** only way to prevent a call to xClose following a failed xOpen +** is for the xOpen to set the sqlite3_file.pMethods element to NULL. ** ** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or ** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). ** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] ** flag may be ORed in to indicate that only the data of the file @@ -652,15 +694,15 @@ ** ** SQLite will guarantee that the zFilename parameter to xOpen ** is either a NULL pointer or string obtained ** from xFullPathname(). SQLite further guarantees that ** the string will be valid and unchanged until xClose() is -** called. Because of the previous sentense, +** called. Because of the previous sentence, ** the [sqlite3_file] can safely store a pointer to the ** filename if it needs to remember the filename for some reason. ** If the zFilename parameter is xOpen is a NULL pointer then xOpen -** must invite its own temporary name for the file. Whenever the +** must invent its own temporary name for the file. Whenever the ** xFilename parameter is NULL it will also be the case that the ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. ** ** The flags argument to xOpen() includes all bits set in ** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] @@ -700,18 +742,28 @@ ** ** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be ** deleted when it is closed. The [SQLITE_OPEN_DELETEONCLOSE] ** will be set for TEMP databases, journals and for subjournals. ** -** The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. +** The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction +** with the [SQLITE_OPEN_CREATE] flag, which are both directly +** analogous to the O_EXCL and O_CREAT flags of the POSIX open() +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** SQLITE_OPEN_CREATE, is used to indicate that file should always +** be created, and that it is an error if it already exists. +** It is <i>not</i> used to indicate the file should be opened +** for exclusive access. ** ** At least szOsFile bytes of memory are allocated by SQLite ** to hold the [sqlite3_file] structure passed as the third ** argument to xOpen. The xOpen method does not have to -** allocate the structure; it should just fill it in. +** allocate the structure; it should just fill it in. Note that +** the xOpen method must set the sqlite3_file.pMethods to either +** a valid [sqlite3_io_methods] object or to NULL. xOpen must do +** this even if the open fails. SQLite expects that the sqlite3_file.pMethods +** element will be valid after xOpen returns regardless of the success +** or failure of the xOpen call. ** ** The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] ** to test whether a file is at least readable. The file can be a @@ -789,10 +841,15 @@ ** the process, or if it is the first time sqlite3_initialize() is invoked ** following a call to sqlite3_shutdown(). Only an effective call ** of sqlite3_initialize() does any initialization. All other calls ** are harmless no-ops. ** +** A call to sqlite3_shutdown() is an "effective" call if it is the first +** call to sqlite3_shutdown() since the last sqlite3_initialize(). Only +** an effective call to sqlite3_shutdown() does any deinitialization. +** All other calls to sqlite3_shutdown() are harmless no-ops. +** ** Among other things, sqlite3_initialize() shall invoke ** sqlite3_os_init(). Similarly, sqlite3_shutdown() ** shall invoke sqlite3_os_end(). ** ** The sqlite3_initialize() routine returns [SQLITE_OK] on success. @@ -827,22 +884,23 @@ ** or sqlite3_os_end() directly. The application should only invoke ** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() ** interface is called automatically by sqlite3_initialize() and ** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate ** implementations for sqlite3_os_init() and sqlite3_os_end() -** are built into SQLite when it is compiled for unix, windows, or os/2. -** When built for other platforms (using the [SQLITE_OS_OTHER=1] compile-time +** are built into SQLite when it is compiled for Unix, Windows, or OS/2. +** When [custom builds | built for other platforms] +** (using the [SQLITE_OS_OTHER=1] compile-time ** option) the application must supply a suitable implementation for ** sqlite3_os_init() and sqlite3_os_end(). An application-supplied ** implementation of sqlite3_os_init() or sqlite3_os_end() ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -int sqlite3_initialize(void); -int sqlite3_shutdown(void); -int sqlite3_os_init(void); -int sqlite3_os_end(void); +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library {H14100} <S20000><S30200> ** EXPERIMENTAL ** @@ -873,11 +931,11 @@ ** Requirements: ** [H14103] [H14106] [H14120] [H14123] [H14126] [H14129] [H14132] [H14135] ** [H14138] [H14141] [H14144] [H14147] [H14150] [H14153] [H14156] [H14159] ** [H14162] [H14165] [H14168] */ -SQLITE_EXPERIMENTAL int sqlite3_config(int, ...); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections {H14200} <S20000> ** EXPERIMENTAL ** @@ -897,11 +955,11 @@ ** Additional arguments depend on the verb. ** ** Requirements: ** [H14203] [H14206] [H14209] [H14212] [H14215] */ -SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines {H10155} <S20120> ** EXPERIMENTAL ** @@ -909,42 +967,69 @@ ** and low-level memory allocation routines. ** ** This object is used in only one place in the SQLite interface. ** A pointer to an instance of this object is the argument to ** [sqlite3_config()] when the configuration option is -** [SQLITE_CONFIG_MALLOC]. By creating an instance of this object -** and passing it to [sqlite3_config()] during configuration, an -** application can specify an alternative memory allocation subsystem -** for SQLite to use for all of its dynamic memory needs. -** -** Note that SQLite comes with a built-in memory allocator that is -** perfectly adequate for the overwhelming majority of applications +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** By creating an instance of this object +** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) +** during configuration, an application can specify an alternative +** memory allocation subsystem for SQLite to use for all of its +** dynamic memory needs. +** +** Note that SQLite comes with several [built-in memory allocators] +** that are perfectly adequate for the overwhelming majority of applications ** and that this object is only useful to a tiny minority of applications ** with specialized memory allocation requirements. This object is ** also used during testing of SQLite in order to specify an alternative ** memory allocator that simulates memory out-of-memory conditions in ** order to verify that SQLite recovers gracefully from such ** conditions. ** -** The xMalloc, xFree, and xRealloc methods must work like the -** malloc(), free(), and realloc() functions from the standard library. +** The xMalloc and xFree methods must work like the +** malloc() and free() functions from the standard C library. +** The xRealloc method must work like realloc() from the standard C library +** with the exception that if the second argument to xRealloc is zero, +** xRealloc must be a no-op - it must not perform any allocation or +** deallocation. SQLite guaranteeds that the second argument to +** xRealloc is always a value returned by a prior call to xRoundup. +** And so in cases where xRoundup always returns a positive number, +** xRealloc can perform exactly as the standard library realloc() and +** still be in compliance with this specification. ** ** xSize should return the allocated size of a memory allocation ** previously obtained from xMalloc or xRealloc. The allocated size ** is always at least as big as the requested size but may be larger. ** ** The xRoundup method returns what would be the allocated size of ** a memory allocation given a particular requested size. Most memory ** allocators round up memory allocations at least to the next multiple ** of 8. Some allocators round up to a larger multiple or to a power of 2. +** Every memory allocation request coming in through [sqlite3_malloc()] +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** that causes the corresponding memory allocation to fail. ** ** The xInit method initializes the memory allocator. (For example, ** it might allocate any require mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite3_shutdown()] and should deallocate any resources acquired ** by xInit. The pAppData pointer is used as the only parameter to ** xInit and xShutdown. +** +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. For all other methods, SQLite +** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the +** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which +** it is by default) and so the methods are automatically serialized. +** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other +** methods must be threadsafe or else make their own arrangements for +** serialization. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). */ typedef struct sqlite3_mem_methods sqlite3_mem_methods; struct sqlite3_mem_methods { void *(*xMalloc)(int); /* Memory allocation function */ void (*xFree)(void*); /* Free a prior allocation */ @@ -1024,16 +1109,18 @@ ** </ul> ** </dd> ** ** <dt>SQLITE_CONFIG_SCRATCH</dt> ** <dd>This option specifies a static memory buffer that SQLite can use for -** scratch memory. There are three arguments: A pointer to the memory, the -** size of each scratch buffer (sz), and the number of buffers (N). The sz +** scratch memory. There are three arguments: A pointer an 8-byte +** aligned memory buffer from which the scrach allocations will be +** drawn, the size of each scratch allocation (sz), +** and the maximum number of scratch allocations (N). The sz ** argument must be a multiple of 16. The sz parameter should be a few bytes -** larger than the actual scratch space required due internal overhead. -** The first -** argument should point to an allocation of at least sz*N bytes of memory. +** larger than the actual scratch space required due to internal overhead. +** The first argument should pointer to an 8-byte aligned buffer +** of at least sz*N bytes of memory. ** SQLite will use no more than one scratch buffer at once per thread, so ** N should be set to the expected maximum number of threads. The sz ** parameter should be 6 times the size of the largest database page size. ** Scratch buffers are used as part of the btree balance operation. If ** The btree balancer needs additional memory beyond what is provided by @@ -1043,33 +1130,41 @@ ** <dt>SQLITE_CONFIG_PAGECACHE</dt> ** <dd>This option specifies a static memory buffer that SQLite can use for ** the database page cache with the default page cache implemenation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option. -** There are three arguments to this option: A pointer to the +** There are three arguments to this option: A pointer to 8-byte aligned ** memory, the size of each page buffer (sz), and the number of pages (N). -** The sz argument must be a power of two between 512 and 32768. The first +** The sz argument should be the size of the largest database page +** (a power of two between 512 and 32768) plus a little extra for each +** page header. The page header size is 20 to 40 bytes depending on +** the host architecture. It is harmless, apart from the wasted memory, +** to make sz a little too large. The first ** argument should point to an allocation of at least sz*N bytes of memory. ** SQLite will use the memory provided by the first argument to satisfy its ** memory needs for the first N pages that it adds to cache. If additional ** page cache memory is needed beyond what is provided by this option, then ** SQLite goes to [sqlite3_malloc()] for the additional storage space. ** The implementation might use one or more of the N buffers to hold -** memory accounting information. </dd> +** memory accounting information. The pointer in the first argument must +** be aligned to an 8-byte boundary or subsequent behavior of SQLite +** will be undefined.</dd> ** ** <dt>SQLITE_CONFIG_HEAP</dt> ** <dd>This option specifies a static memory buffer that SQLite will use ** for all of its dynamic memory allocation needs beyond those provided ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. -** There are three arguments: A pointer to the memory, the number of -** bytes in the memory buffer, and the minimum allocation size. If -** the first pointer (the memory pointer) is NULL, then SQLite reverts +** There are three arguments: An 8-byte aligned pointer to the memory, +** the number of bytes in the memory buffer, and the minimum allocation size. +** If the first pointer (the memory pointer) is NULL, then SQLite reverts ** to using its default memory allocator (the system malloc() implementation), ** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. If the ** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or ** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory -** allocator is engaged to handle all of SQLites memory allocation needs.</dd> +** allocator is engaged to handle all of SQLites memory allocation needs. +** The first pointer (the memory pointer) must be aligned to an 8-byte +** boundary or subsequent behavior of SQLite will be undefined.</dd> ** ** <dt>SQLITE_CONFIG_MUTEX</dt> ** <dd>This option takes a single argument which is a pointer to an ** instance of the [sqlite3_mutex_methods] structure. The argument specifies ** alternative low-level mutex routines to be used in place @@ -1084,13 +1179,16 @@ ** routines with a wrapper used to track mutex usage for performance ** profiling or testing, for example.</dd> ** ** <dt>SQLITE_CONFIG_LOOKASIDE</dt> ** <dd>This option takes two arguments that determine the default -** memory allcation lookaside optimization. The first argument is the +** memory allocation lookaside optimization. The first argument is the ** size of each lookaside buffer slot and the second is the number of -** slots allocated to each database connection.</dd> +** slots allocated to each database connection. This option sets the +** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** verb to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.</dd> ** ** <dt>SQLITE_CONFIG_PCACHE</dt> ** <dd>This option takes a single argument which is a pointer to ** an [sqlite3_pcache_methods] object. This object specifies the interface ** to a custom page cache implementation. SQLite makes a copy of the @@ -1136,16 +1234,19 @@ ** <dl> ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dd>This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. ** The first argument (the third parameter to [sqlite3_db_config()] is a -** pointer to a memory buffer to use for lookaside memory. The first -** argument may be NULL in which case SQLite will allocate the lookaside -** buffer itself using [sqlite3_malloc()]. The second argument is the +** pointer to an memory buffer to use for lookaside memory. +** The first argument may be NULL in which case SQLite will allocate the +** lookaside buffer itself using [sqlite3_malloc()]. The second argument is the ** size of each lookaside buffer slot and the third argument is the number of ** slots. The size of the buffer in the first argument must be greater than -** or equal to the product of the second and third arguments.</dd> +** or equal to the product of the second and third arguments. The buffer +** must be aligned to an 8-byte boundary. If the second argument is not +** a multiple of 8, it is internally rounded down to the next smaller +** multiple of 8. See also: [SQLITE_CONFIG_LOOKASIDE]</dd> ** ** </dl> */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ @@ -1158,11 +1259,11 @@ ** codes are disabled by default for historical compatibility considerations. ** ** Requirements: ** [H12201] [H12202] */ -int sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid {H12220} <S10700> ** ** Each entry in an SQLite table has a unique 64-bit signed @@ -1203,11 +1304,11 @@ ** function is running and thus changes the last insert [rowid], ** then the value returned by [sqlite3_last_insert_rowid()] is ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified {H12240} <S10600> ** ** This function returns the number of database rows that were changed @@ -1216,18 +1317,22 @@ ** Only changes that are directly specified by the [INSERT], [UPDATE], ** or [DELETE] statement are counted. Auxiliary changes caused by ** triggers are not counted. Use the [sqlite3_total_changes()] function ** to find the total number of changes including changes caused by triggers. ** +** Changes to a view that are simulated by an [INSTEAD OF trigger] +** are not counted. Only real table changes are counted. +** ** A "row change" is a change to a single row of a single table ** caused by an INSERT, DELETE, or UPDATE statement. Rows that -** are changed as side effects of REPLACE constraint resolution, -** rollback, ABORT processing, DROP TABLE, or by any other +** are changed as side effects of [REPLACE] constraint resolution, +** rollback, ABORT processing, [DROP TABLE], or by any other ** mechanisms do not count as direct row changes. ** ** A "trigger context" is a scope of execution that begins and -** ends with the script of a trigger. Most SQL statements are +** ends with the script of a [CREATE TRIGGER | trigger]. +** Most SQL statements are ** evaluated outside of any trigger. This is the "top level" ** trigger context. If a trigger fires from the top level, a ** new trigger context is entered for the duration of that one ** trigger. Subtriggers create subcontexts for their duration. ** @@ -1245,63 +1350,49 @@ ** changes in the most recently completed INSERT, UPDATE, or DELETE ** statement within the body of the same trigger. ** However, the number returned does not include changes ** caused by subtriggers since those have their own context. ** -** SQLite implements the command "DELETE FROM table" without a WHERE clause -** by dropping and recreating the table. Doing so is much faster than going -** through and deleting individual elements from the table. Because of this -** optimization, the deletions in "DELETE FROM table" are not row changes and -** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()] -** functions, regardless of the number of elements that were originally -** in the table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. Or recompile using the -** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the -** optimization on all queries. +** See also the [sqlite3_total_changes()] interface and the +** [count_changes pragma]. ** ** Requirements: ** [H12241] [H12243] ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -int sqlite3_changes(sqlite3*); +SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified {H12260} <S10600> ** -** This function returns the number of row changes caused by INSERT, -** UPDATE or DELETE statements since the [database connection] was opened. -** The count includes all changes from all trigger contexts. However, -** the count does not include changes used to implement REPLACE constraints, -** do rollbacks or ABORT processing, or DROP table processing. +** This function returns the number of row changes caused by [INSERT], +** [UPDATE] or [DELETE] statements since the [database connection] was opened. +** The count includes all changes from all +** [CREATE TRIGGER | trigger] contexts. However, +** the count does not include changes used to implement [REPLACE] constraints, +** do rollbacks or ABORT processing, or [DROP TABLE] processing. The +** count does not include rows of views that fire an [INSTEAD OF trigger], +** though if the INSTEAD OF trigger makes changes of its own, those changes +** are counted. ** The changes are counted as soon as the statement that makes them is ** completed (when the statement handle is passed to [sqlite3_reset()] or ** [sqlite3_finalize()]). ** -** SQLite implements the command "DELETE FROM table" without a WHERE clause -** by dropping and recreating the table. (This is much faster than going -** through and deleting individual elements from the table.) Because of this -** optimization, the deletions in "DELETE FROM table" are not row changes and -** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()] -** functions, regardless of the number of elements that were originally -** in the table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. Or recompile using the -** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the -** optimization on all queries. -** -** See also the [sqlite3_changes()] interface. +** See also the [sqlite3_changes()] interface and the +** [count_changes pragma]. ** ** Requirements: ** [H12261] [H12263] ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -int sqlite3_total_changes(sqlite3*); +SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query {H12270} <S30500> ** ** This function causes any pending database operation to abort and @@ -1322,48 +1413,66 @@ ** An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. ** If the interrupted SQL operation is an INSERT, UPDATE, or DELETE ** that is inside an explicit transaction, then the entire transaction ** will be rolled back automatically. ** -** A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. +** The sqlite3_interrupt(D) call is in effect until all currently running +** SQL statements on [database connection] D complete. Any new SQL statements +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been +** running prior to the sqlite3_interrupt() call. New SQL statements +** that are started after the running statement count reaches zero are +** not effected by the sqlite3_interrupt(). +** A call to sqlite3_interrupt(D) that occurs when there are no running +** SQL statements is a no-op and has no effect on SQL statements +** that are started after the sqlite3_interrupt() call returns. ** ** Requirements: ** [H12271] [H12272] ** ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -void sqlite3_interrupt(sqlite3*); +SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} <S70200> ** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or +** These routines are useful during command-line input to determine if the +** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string +** SQLite for parsing. These routines return 1 if the input string ** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon token and is not a fragment of a -** CREATE TRIGGER statement. Semicolons that are embedded within +** complete if it ends with a semicolon token and is not a prefix of a +** well-formed CREATE TRIGGER statement. Semicolons that are embedded within ** string literals or quoted identifier names or comments are not ** independent tokens (they are part of the token in which they are -** embedded) and thus do not count as a statement terminator. +** embedded) and thus do not count as a statement terminator. Whitespace +** and comments that follow the final semicolon are ignored. +** +** These routines return 0 if the statement is incomplete. If a +** memory allocation fails, then SQLITE_NOMEM is returned. ** ** These routines do not parse the SQL statements thus ** will not detect syntactically incorrect SQL. +** +** If SQLite has not been initialized using [sqlite3_initialize()] prior +** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked +** automatically by sqlite3_complete16(). If that initialization fails, +** then the return value from sqlite3_complete16() will be non-zero +** regardless of whether or not the input SQL is complete. ** ** Requirements: [H10511] [H10512] ** ** The input to [sqlite3_complete()] must be a zero-terminated ** UTF-8 string. ** ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {H12310} <S40400> ** ** This routine sets a callback function that might be invoked whenever @@ -1428,11 +1537,11 @@ ** [H12311] [H12312] [H12314] [H12316] [H12318] ** ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); +SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); /* ** CAPI3REF: Set A Busy Timeout {H12340} <S40410> ** ** This routine sets a [sqlite3_busy_handler | busy handler] that sleeps @@ -1451,11 +1560,11 @@ ** this routine, that other busy handler is cleared. ** ** Requirements: ** [H12341] [H12343] [H12344] */ -int sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries {H12370} <S10000> ** ** Definition: A <b>result table</b> is memory data structure created by the @@ -1524,24 +1633,24 @@ ** reflected in subsequent calls to [sqlite3_errcode()] or [sqlite3_errmsg()]. ** ** Requirements: ** [H12371] [H12373] [H12374] [H12376] [H12379] [H12382] */ -int sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ int *pnRow, /* Number of result rows written here */ int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -void sqlite3_free_table(char **result); +SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions {H17400} <S70000><S20000> ** -** These routines are workalikes of the "printf()" family of functions +** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. ** ** The sqlite3_mprintf() and sqlite3_vmprintf() routines write their ** results into memory obtained from [sqlite3_malloc()]. ** The strings returned by these two routines should be @@ -1629,13 +1738,13 @@ ** the result, [sqlite3_free()] is called on the input string. {END} ** ** Requirements: ** [H17403] [H17406] [H17407] */ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); /* ** CAPI3REF: Memory Allocation Subsystem {H17300} <S20000> ** ** The SQLite core uses these three routines for all of its own @@ -1714,13 +1823,13 @@ ** ** The application must not read or write any part of ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void sqlite3_free(void*); /* ** CAPI3REF: Memory Allocator Statistics {H17370} <S30210> ** ** SQLite provides these two interfaces for reporting on the status @@ -1728,12 +1837,12 @@ ** routines, which form the built-in memory allocation subsystem. ** ** Requirements: ** [H17371] [H17373] [H17374] [H17375] */ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator {H17390} <S20000> ** ** SQLite contains a high-quality pseudo-random number generator (PRNG) used to @@ -1752,11 +1861,11 @@ ** method. ** ** Requirements: ** [H17392] */ -void sqlite3_randomness(int N, void *P); +SQLITE_API void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks {H12500} <S70100> ** ** This routine registers a authorizer callback with a particular @@ -1777,24 +1886,29 @@ ** ** When the callback returns [SQLITE_OK], that means the operation ** requested is ok. When the callback returns [SQLITE_DENY], the ** [sqlite3_prepare_v2()] or equivalent call that triggered the ** authorizer will fail with an error message explaining that -** access is denied. If the authorizer code is [SQLITE_READ] -** and the callback returns [SQLITE_IGNORE] then the -** [prepared statement] statement is constructed to substitute -** a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] -** return can be used to deny an untrusted user access to individual -** columns of a table. +** access is denied. ** ** The first parameter to the authorizer callback is a copy of the third ** parameter to the sqlite3_set_authorizer() interface. The second parameter ** to the callback is an integer [SQLITE_COPY | action code] that specifies ** the particular action to be authorized. The third through sixth parameters ** to the callback are zero-terminated strings that contain additional ** details about the action to be authorized. +** +** If the action code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** If the action code is [SQLITE_DELETE] and the callback returns +** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the +** [truncate optimization] is disabled and all rows are deleted individually. ** ** An authorizer is used when [sqlite3_prepare | preparing] ** SQL statements from an untrusted source, to ensure that the SQL statements ** do not try to access data they are not allowed to see, or that they do not ** try to execute malicious statements that damage the database. For @@ -1819,23 +1933,25 @@ ** the database connection that invoked the authorizer callback. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** When [sqlite3_prepare_v2()] is used to prepare a statement, the -** statement might be reprepared during [sqlite3_step()] due to a +** statement might be re-prepared during [sqlite3_step()] due to a ** schema change. Hence, the application should ensure that the ** correct authorizer callback remains in place during the [sqlite3_step()]. ** ** Note that the authorizer callback is invoked only during ** [sqlite3_prepare()] or its variants. Authorization is not -** performed during statement evaluation in [sqlite3_step()]. +** performed during statement evaluation in [sqlite3_step()], unless +** as stated in the previous paragraph, sqlite3_step() invokes +** sqlite3_prepare_v2() to reprepare a statement after a schema change. ** ** Requirements: ** [H12501] [H12502] [H12503] [H12504] [H12505] [H12506] [H12507] [H12510] ** [H12511] [H12512] [H12520] [H12521] [H12522] */ -int sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData ); @@ -1929,12 +2045,12 @@ ** ** Requirements: ** [H12281] [H12282] [H12283] [H12284] [H12285] [H12287] [H12288] [H12289] ** [H12290] */ -SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* ** CAPI3REF: Query Progress Callbacks {H12910} <S60400> ** @@ -1955,11 +2071,11 @@ ** ** Requirements: ** [H12911] [H12912] [H12913] [H12914] [H12915] [H12916] [H12917] [H12918] ** */ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection {H12700} <S40200> ** ** These routines open an SQLite database file whose name is given by the @@ -1984,11 +2100,12 @@ ** ** The sqlite3_open_v2() interface works like sqlite3_open() ** except that it accepts two additional parameters for additional control ** over the new database connection. The flags parameter can take one of ** the following three values, optionally combined with the -** [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags: +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** and/or [SQLITE_OPEN_PRIVATECACHE] flags: ** ** <dl> ** <dt>[SQLITE_OPEN_READONLY]</dt> ** <dd>The database is opened in read-only mode. If the database does not ** already exist, an error is returned.</dd> @@ -2004,19 +2121,25 @@ ** sqlite3_open() and sqlite3_open16().</dd> ** </dl> ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** combinations shown above or one of the combinations shown above combined -** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags, +** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], +** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_SHAREDCACHE] flags, ** then the behavior is undefined. ** ** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection ** opens in the multi-thread [threading mode] as long as the single-thread ** mode has not been set at compile-time or start-time. If the ** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens ** in the serialized [threading mode] unless single-thread was ** previously selected at compile-time or start-time. +** The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. ** ** If the filename is ":memory:", then a private, temporary in-memory database ** is created for the connection. This in-memory database will vanish when ** the database connection is closed. Future versions of SQLite might ** make use of additional special filenames that begin with the ":" character. @@ -2041,19 +2164,19 @@ ** ** Requirements: ** [H12701] [H12702] [H12703] [H12704] [H12706] [H12707] [H12709] [H12711] ** [H12712] [H12713] [H12714] [H12717] [H12719] [H12721] [H12723] */ -int sqlite3_open( +SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -int sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -int sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ); @@ -2092,14 +2215,14 @@ ** error code and message may or may not be set. ** ** Requirements: ** [H12801] [H12802] [H12803] [H12807] [H12808] [H12809] */ -int sqlite3_errcode(sqlite3 *db); -int sqlite3_extended_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); /* ** CAPI3REF: SQL Statement Object {H13000} <H13010> ** KEYWORDS: {prepared statement} {prepared statements} ** @@ -2160,11 +2283,11 @@ ** New run-time limit categories may be added in future releases. ** ** Requirements: ** [H12762] [H12766] [H12769] */ -int sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories {H12790} <H12760> ** KEYWORDS: {limit category} {limit categories} ** @@ -2206,10 +2329,13 @@ ** [GLOB] operators.</dd> ** ** <dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt> ** <dd>The maximum number of variables in an SQL statement that can ** be bound.</dd> +** +** <dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt> +** <dd>The maximum depth of recursion for triggers.</dd> ** </dl> */ #define SQLITE_LIMIT_LENGTH 0 #define SQLITE_LIMIT_SQL_LENGTH 1 #define SQLITE_LIMIT_COLUMN 2 @@ -2218,10 +2344,11 @@ #define SQLITE_LIMIT_VDBE_OP 5 #define SQLITE_LIMIT_FUNCTION_ARG 6 #define SQLITE_LIMIT_ATTACHED 7 #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 #define SQLITE_LIMIT_VARIABLE_NUMBER 9 +#define SQLITE_LIMIT_TRIGGER_DEPTH 10 /* ** CAPI3REF: Compiling An SQL Statement {H13010} <S10000> ** KEYWORDS: {SQL statement compiler} ** @@ -2294,32 +2421,32 @@ ** ** Requirements: ** [H13011] [H13012] [H13013] [H13014] [H13015] [H13016] [H13019] [H13021] ** */ -int sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -int sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -int sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -int sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ @@ -2333,11 +2460,11 @@ ** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. ** ** Requirements: ** [H13101] [H13102] [H13103] */ -const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Dynamically Typed Value Object {H15000} <S20200> ** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} ** @@ -2394,22 +2521,23 @@ ** CAPI3REF: Binding Values To Prepared Statements {H13500} <S70300> ** KEYWORDS: {host parameter} {host parameters} {host parameter name} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} ** ** In the SQL strings input to [sqlite3_prepare_v2()] and its variants, -** literals may be replaced by a [parameter] in one of these forms: +** literals may be replaced by a [parameter] that matches one of following +** templates: ** ** <ul> ** <li> ? ** <li> ?NNN ** <li> :VVV ** <li> @VVV ** <li> $VVV ** </ul> ** -** In the parameter forms shown above NNN is an integer literal, -** and VVV is an alpha-numeric parameter name. The values of these +** In the templates above, NNN represents an integer literal, +** and VVV represents an alphanumeric identifer. The values of these ** parameters (also called "host parameter names" or "SQL parameters") ** can be set using the sqlite3_bind_*() routines defined here. ** ** The first argument to the sqlite3_bind_*() routines is always ** a pointer to the [sqlite3_stmt] object returned from @@ -2472,19 +2600,19 @@ ** Requirements: ** [H13506] [H13509] [H13512] [H13515] [H13518] [H13521] [H13524] [H13527] ** [H13530] [H13533] [H13536] [H13539] [H13542] [H13545] [H13548] [H13551] ** */ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters {H13600} <S70300> ** ** This routine can be used to find the number of [SQL parameters] @@ -2503,11 +2631,11 @@ ** [sqlite3_bind_parameter_index()]. ** ** Requirements: ** [H13601] */ -int sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter {H13620} <S70300> ** ** This routine returns a pointer to the name of the n-th @@ -2533,11 +2661,11 @@ ** [sqlite3_bind_parameter_index()]. ** ** Requirements: ** [H13621] */ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name {H13640} <S70300> ** ** Return the index of an SQL parameter given its name. The @@ -2552,11 +2680,11 @@ ** [sqlite3_bind_parameter_index()]. ** ** Requirements: ** [H13641] */ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement {H13660} <S70300> ** ** Contrary to the intuition of many, [sqlite3_reset()] does not reset @@ -2564,11 +2692,11 @@ ** Use this routine to reset all host parameters to NULL. ** ** Requirements: ** [H13661] */ -int sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set {H13710} <S10700> ** ** Return the number of columns in the result set returned by the @@ -2576,11 +2704,11 @@ ** statement that does not return data (for example an [UPDATE]). ** ** Requirements: ** [H13711] */ -int sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set {H13720} <S10700> ** ** These routines return the name assigned to a particular column @@ -2605,12 +2733,12 @@ ** one release of SQLite to the next. ** ** Requirements: ** [H13721] [H13723] [H13724] [H13725] [H13726] [H13727] */ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result {H13740} <S10700> ** ** These routines provide a means to determine what column of what @@ -2653,16 +2781,16 @@ ** If two or more threads call one or more ** [sqlite3_column_database_name | column metadata interfaces] ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result {H13760} <S10700> ** ** The first parameter is a [prepared statement]. @@ -2692,12 +2820,12 @@ ** used to hold those values. ** ** Requirements: ** [H13761] [H13762] [H13763] */ -const char *sqlite3_column_decltype(sqlite3_stmt*,int); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement {H13200} <S10000> ** ** After a [prepared statement] has been prepared using either @@ -2763,21 +2891,21 @@ ** by sqlite3_step(). The use of the "v2" interface is recommended. ** ** Requirements: ** [H13202] [H15304] [H15306] [H15308] [H15310] */ -int sqlite3_step(sqlite3_stmt*); +SQLITE_API int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set {H13770} <S10700> ** ** Returns the number of values in the current row of the result set. ** ** Requirements: ** [H13771] [H13772] */ -int sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes {H10265} <S10110><S10120> ** KEYWORDS: SQLITE_TEXT ** @@ -2963,20 +3091,20 @@ ** ** Requirements: ** [H13803] [H13806] [H13809] [H13812] [H13815] [H13818] [H13821] [H13824] ** [H13827] [H13830] */ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object {H13300} <S70300><S30100> ** ** The sqlite3_finalize() function is called to delete a [prepared statement]. @@ -2993,11 +3121,11 @@ ** [error code] returned will be [SQLITE_ABORT]. ** ** Requirements: ** [H11302] [H11304] */ -int sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object {H13330} <S70300> ** ** The sqlite3_reset() function is called to reset a [prepared statement] @@ -3019,11 +3147,11 @@ ** [sqlite3_reset(S)] returns an appropriate [error code]. ** ** {H11338} The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -int sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions {H16100} <S20200> ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} @@ -3047,18 +3175,21 @@ ** characters. Any attempt to create a function with a longer name ** will result in [SQLITE_ERROR] being returned. ** ** The third parameter (nArg) ** is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. +** aggregate takes. If this parameter is -1, then the SQL function or +** aggregate may take any number of arguments between 0 and the limit +** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third +** parameter is less than -1 or greater than 127 then the behavior is +** undefined. ** ** The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for ** its parameters. Any SQL function implementation should be able to work ** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to +** more efficient with one encoding than another. An application may ** invoke sqlite3_create_function() or sqlite3_create_function16() multiple ** times with the same function but with different values of eTextRep. ** When multiple implementations of the same function are available, SQLite ** will pick the one that involves the least amount of data conversion. ** If there is only a single implementation which does not care what text @@ -3076,11 +3207,11 @@ ** SQL function or aggregate, pass NULL for all three function callbacks. ** ** It is permitted to register multiple implementations of the same ** functions with the same name but with either differing numbers of ** arguments or differing preferred text encodings. SQLite will use -** the implementation most closely matches the way in which the +** the implementation that most closely matches the way in which the ** SQL function is used. A function implementation with a non-negative ** nArg parameter is a better match than a function implementation with ** a negative nArg. A function where the preferred text encoding ** matches the database encoding is a better ** match than a function where the encoding is different. @@ -3099,24 +3230,24 @@ ** SQLite interfaces. However, such calls must not ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. ** ** Requirements: -** [H16103] [H16106] [H16109] [H16112] [H16118] [H16121] [H16124] [H16127] +** [H16103] [H16106] [H16109] [H16112] [H16118] [H16121] [H16127] ** [H16130] [H16133] [H16136] [H16139] [H16142] */ -int sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, int eTextRep, void *pApp, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -int sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, void *pApp, @@ -3147,16 +3278,16 @@ ** to be supported. However, new applications should avoid ** the use of these functions. To help encourage people to avoid ** using these functions, we are not going to tell you what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); -SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); -SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_DEPRECATED int sqlite3_global_recover(void); -SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); -SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); #endif /* ** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} <S20200> ** @@ -3204,22 +3335,22 @@ ** ** Requirements: ** [H15103] [H15106] [H15109] [H15112] [H15115] [H15118] [H15121] [H15124] ** [H15127] [H15130] [H15133] [H15136] */ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context {H16210} <S20200> ** ** The implementation of aggregate SQL functions use this routine to allocate @@ -3243,11 +3374,11 @@ ** the aggregate SQL function is running. ** ** Requirements: ** [H16211] [H16213] [H16215] [H16217] */ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions {H16240} <S20200> ** ** The sqlite3_user_data() interface returns a copy of @@ -3260,11 +3391,11 @@ ** the application-defined function is running. ** ** Requirements: ** [H16243] */ -void *sqlite3_user_data(sqlite3_context*); +SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions {H16250} <S60600><S20200> ** ** The sqlite3_context_db_handle() interface returns a copy of @@ -3274,11 +3405,11 @@ ** registered the application defined function. ** ** Requirements: ** [H16253] */ -sqlite3 *sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data {H16270} <S20200> ** ** The following two functions may be used by scalar SQL functions to @@ -3321,12 +3452,12 @@ ** the SQL function is running. ** ** Requirements: ** [H16272] [H16274] [H16276] [H16277] [H16278] [H16279] */ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior {H10280} <S30100> ** @@ -3424,14 +3555,15 @@ ** function result. ** If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that ** function as the destructor on the text or BLOB result when it has ** finished using that result. -** If the 4th parameter to the sqlite3_result_text* interfaces or +** If the 4th parameter to the sqlite3_result_text* interfaces or to ** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite ** assumes that the text or BLOB result is in constant space and does not -** copy the it or call a destructor when it has finished using that result. +** copy the content of the parameter nor call a destructor on the content +** when it has finished using that result. ** If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT ** then SQLite makes a copy of the result into space obtained from ** from [sqlite3_malloc()] before it returns. ** @@ -3452,26 +3584,26 @@ ** Requirements: ** [H16403] [H16406] [H16409] [H16412] [H16415] [H16418] [H16421] [H16424] ** [H16427] [H16430] [H16433] [H16436] [H16439] [H16442] [H16445] [H16448] ** [H16451] [H16454] [H16457] [H16460] [H16463] */ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_error_code(sqlite3_context*, int); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences {H16600} <S20300> ** ** These functions are used to add new collation sequences to the @@ -3481,16 +3613,18 @@ ** for sqlite3_create_collation() and sqlite3_create_collation_v2() ** and a UTF-16 string for sqlite3_create_collation16(). In all cases ** the name is passed as the second function argument. ** ** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied +** [SQLITE_UTF16LE], or [SQLITE_UTF16BE], indicating that the user-supplied ** routine expects to be passed pointers to strings encoded using UTF-8, ** UTF-16 little-endian, or UTF-16 big-endian, respectively. The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that +** third argument might also be [SQLITE_UTF16] to indicate that the routine +** expects pointers to be UTF-16 strings in the native byte order, or the +** argument can be [SQLITE_UTF16_ALIGNED] if the ** the routine expects pointers to 16-bit word aligned strings -** of UTF-16 in the native byte order of the host computer. +** of UTF-16 in the native byte order. ** ** A pointer to the user supplied routine must be passed as the fifth ** argument. If it is NULL, this is the same as deleting the collation ** sequence (so that SQLite cannot call it anymore). ** Each time the application supplied function is invoked, it is passed @@ -3511,30 +3645,32 @@ ** of the sqlite3_create_collation_v2(). ** Collations are destroyed when they are overridden by later calls to the ** collation creation functions or when the [database connection] is closed ** using [sqlite3_close()]. ** +** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. +** ** Requirements: ** [H16603] [H16604] [H16606] [H16609] [H16612] [H16615] [H16618] [H16621] ** [H16624] [H16627] [H16630] */ -int sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void*, int(*xCompare)(void*,int,const void*,int,const void*) ); -int sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, void*, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -int sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, void*, int(*xCompare)(void*,int,const void*,int,const void*) @@ -3567,16 +3703,16 @@ ** [sqlite3_create_collation_v2()]. ** ** Requirements: ** [H16702] [H16704] [H16706] */ -int sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -int sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); @@ -3585,11 +3721,11 @@ ** called right after sqlite3_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ -int sqlite3_key( +SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); /* @@ -3598,11 +3734,11 @@ ** database is decrypted. ** ** The code to implement this API is not available in the public release ** of SQLite. */ -int sqlite3_rekey( +SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); /* @@ -3619,11 +3755,11 @@ ** SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. ** ** Requirements: [H10533] [H10536] */ -int sqlite3_sleep(int); +SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files {H10310} <S20000> ** ** If this global variable is made to point to a string which is @@ -3649,11 +3785,11 @@ ** using [sqlite3_free]. ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [temp_store_directory pragma] should be avoided. */ -SQLITE_EXTERN char *sqlite3_temp_directory; +SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory; /* ** CAPI3REF: Test For Auto-Commit Mode {H12930} <S60200> ** KEYWORDS: {autocommit mode} ** @@ -3674,11 +3810,11 @@ ** connection while this routine is running, then the return value ** is undefined. ** ** Requirements: [H12931] [H12932] [H12933] [H12934] */ -int sqlite3_get_autocommit(sqlite3*); +SQLITE_API int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement {H13120} <S60600> ** ** The sqlite3_db_handle interface returns the [database connection] handle @@ -3687,11 +3823,11 @@ ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. ** ** Requirements: [H13123] */ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Find the next prepared statement {H13140} <S60600> ** ** This interface returns a pointer to the next [prepared statement] after @@ -3704,21 +3840,21 @@ ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. ** ** Requirements: [H13143] [H13146] [H13149] [H13152] */ -sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks {H12950} <S60400> ** ** The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. +** function to be invoked whenever a transaction is [COMMIT | committed]. ** Any callback set by a previous call to sqlite3_commit_hook() ** for the same database connection is overridden. ** The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. +** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. ** Any callback set by a previous call to sqlite3_commit_hook() ** for the same database connection is overridden. ** The pArg argument is passed through to the callback. ** If the callback on a commit hook function returns non-zero, ** then the commit is converted into a rollback. @@ -3734,25 +3870,33 @@ ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** Registering a NULL function disables the callback. ** +** When the commit hook callback routine returns zero, the [COMMIT] +** operation is allowed to continue normally. If the commit hook +** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. +** The rollback hook is invoked on a rollback that results from a commit +** hook returning non-zero, just as it would be with any other rollback. +** ** For the purposes of this API, a transaction is said to have been ** rolled back if an explicit "ROLLBACK" statement is executed, or ** an error or constraint causes an implicit rollback to occur. ** The rollback callback is not invoked if a transaction is ** automatically rolled back because the database connection is closed. ** The rollback callback is not invoked if a transaction is ** rolled back because a commit callback returned non-zero. ** <todo> Check on this </todo> ** +** See also the [sqlite3_update_hook()] interface. +** ** Requirements: ** [H12951] [H12952] [H12953] [H12954] [H12955] ** [H12961] [H12962] [H12963] [H12964] */ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks {H12970} <S60400> ** ** The sqlite3_update_hook() interface registers a callback function @@ -3774,10 +3918,17 @@ ** In the case of an update, this is the [rowid] after the update takes place. ** ** The update hook is not invoked when internal system tables are ** modified (i.e. sqlite_master and sqlite_sequence). ** +** In the current implementation, the update hook +** is not invoked when duplication rows are deleted because of an +** [ON CONFLICT | ON CONFLICT REPLACE] clause. Nor is the update hook +** invoked when rows are deleted using the [truncate optimization]. +** The exceptions defined in this paragraph might change in a future +** release of SQLite. +** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the ** completion of the [sqlite3_step()] call that triggered the update hook. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their @@ -3784,22 +3935,25 @@ ** database connections for the meaning of "modify" in this paragraph. ** ** If another function was previously registered, its pArg value ** is returned. Otherwise NULL is returned. ** +** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] +** interfaces. +** ** Requirements: ** [H12971] [H12973] [H12975] [H12977] [H12979] [H12981] [H12983] [H12986] */ -void *sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* ); /* ** CAPI3REF: Enable Or Disable Shared Pager Cache {H10330} <S30900> -** KEYWORDS: {shared cache} {shared cache mode} +** KEYWORDS: {shared cache} ** ** This routine enables or disables the sharing of the database cache ** and schema data structures between [database connection | connections] ** to the same database. Sharing is enabled if the argument is true ** and disabled if the argument is false. @@ -3826,11 +3980,11 @@ ** ** See Also: [SQLite Shared-Cache Mode] ** ** Requirements: [H10331] [H10336] [H10337] [H10339] */ -int sqlite3_enable_shared_cache(int); +SQLITE_API int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory {H17340} <S30220> ** ** The sqlite3_release_memory() interface attempts to free N bytes @@ -3840,11 +3994,11 @@ ** sqlite3_release_memory() returns the number of bytes actually freed, ** which might be more or less than the amount requested. ** ** Requirements: [H17341] [H17342] */ -int sqlite3_release_memory(int); +SQLITE_API int sqlite3_release_memory(int); /* ** CAPI3REF: Impose A Limit On Heap Size {H17350} <S30220> ** ** The sqlite3_soft_heap_limit() interface places a "soft" limit @@ -3875,11 +4029,11 @@ ** individual threads. ** ** Requirements: ** [H16351] [H16352] [H16353] [H16354] [H16355] [H16358] */ -void sqlite3_soft_heap_limit(int); +SQLITE_API void sqlite3_soft_heap_limit(int); /* ** CAPI3REF: Extract Metadata About A Column Of A Table {H12850} <S60300> ** ** This routine returns metadata about a specific column of a specific @@ -3939,11 +4093,11 @@ ** in the [database connection] (to be retrieved using sqlite3_errmsg()). ** ** This API is only available if the library was compiled with the ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. */ -int sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ const char *zColumnName, /* Column name */ char const **pzDataType, /* OUTPUT: Declared data type */ @@ -3977,11 +4131,11 @@ ** ** {H12606} Extension loading must be enabled using ** [sqlite3_enable_load_extension()] prior to calling this API, ** otherwise an error will be returned. */ -int sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ); @@ -4000,11 +4154,11 @@ ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. ** ** {H12622} Extension loading is off by default. */ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load An Extensions {H12640} <S20500> ** ** This API can be invoked at program startup in order to register @@ -4027,11 +4181,11 @@ ** {H12643} This routine stores a pointer to the extension in an array ** that is obtained from [sqlite3_malloc()]. ** ** {H12644} Automatic extensions apply across all threads. */ -int sqlite3_auto_extension(void (*xEntryPoint)(void)); +SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading {H12660} <S20500> ** ** This function disables all previously registered automatic @@ -4041,11 +4195,11 @@ ** {H12661} This function disables all previously registered ** automatic extensions. ** ** {H12662} This function disables automatic extensions in all threads. */ -void sqlite3_reset_auto_extension(void); +SQLITE_API void sqlite3_reset_auto_extension(void); /* ****** EXPERIMENTAL - subject to change without notice ************** ** ** The interface to the virtual-table mechanism is currently considered @@ -4064,19 +4218,24 @@ typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; typedef struct sqlite3_module sqlite3_module; /* ** CAPI3REF: Virtual Table Object {H18000} <S20400> -** KEYWORDS: sqlite3_module -** EXPERIMENTAL -** -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. +** KEYWORDS: sqlite3_module {virtual table module} +** EXPERIMENTAL +** +** This structure, sometimes called a a "virtual table module", +** defines the implementation of a [virtual tables]. +** This structure consists mostly of methods for the module. +** +** A virtual table module is created by filling in a persistent +** instance of this structure and passing a pointer to that instance +** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. +** The registration remains valid until it is replaced by a different +** module or until the [database connection] closes. The content +** of this structure must not change while it is registered with +** any database connection. */ struct sqlite3_module { int iVersion; int (*xCreate)(sqlite3*, void *pAux, int argc, const char *const*argv, @@ -4110,12 +4269,12 @@ ** CAPI3REF: Virtual Table Indexing Information {H18100} <S20400> ** KEYWORDS: sqlite3_index_info ** EXPERIMENTAL ** ** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the +** pass information into and receive the reply from the [xBestIndex] +** method of a [virtual table module]. The fields under **Inputs** are the ** inputs to xBestIndex and are read-only. xBestIndex inserts its ** results into the **Outputs** fields. ** ** The aConstraint[] array records WHERE clause constraints of the form: ** @@ -4134,31 +4293,30 @@ ** form that refer to the particular virtual table being queried. ** ** Information about the ORDER BY clause is stored in aOrderBy[]. ** Each term of aOrderBy records a column of the ORDER BY clause. ** -** The xBestIndex method must fill aConstraintUsage[] with information +** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the ** virtual table and is not checked again by SQLite. ** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in +** The idxNum and idxPtr values are recorded and passed into the +** [xFilter] method. +** [sqlite3_free()] is used to free idxPtr if and only iff +** needToFreeIdxPtr is true. +** +** The orderByConsumed means that output from [xFilter]/[xNext] will occur in ** the correct order to satisfy the ORDER BY clause so that no separate ** sorting step is required. ** ** The estimatedCost value is an estimate of the cost of doing the ** particular lookup. A full scan of a table with N entries should have ** a cost of N. A binary search of a table of N entries should have a ** cost of approximately log(N). -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. */ struct sqlite3_index_info { /* Inputs */ int nConstraint; /* Number of entries in aConstraint */ struct sqlite3_index_constraint { @@ -4192,88 +4350,94 @@ /* ** CAPI3REF: Register A Virtual Table Implementation {H18200} <S20400> ** EXPERIMENTAL ** -** This routine is used to register a new module name with a -** [database connection]. Module names must be registered before -** creating new virtual tables on the module, or before using -** preexisting virtual tables of the module. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -SQLITE_EXPERIMENTAL int sqlite3_create_module( +** This routine is used to register a new [virtual table module] name. +** Module names must be registered before +** creating a new [virtual table] using the module, or before using a +** preexisting [virtual table] for the module. +** +** The module name is registered on the [database connection] specified +** by the first parameter. The name of the module is given by the +** second parameter. The third parameter is a pointer to +** the implementation of the [virtual table module]. The fourth +** parameter is an arbitrary client data pointer that is passed through +** into the [xCreate] and [xConnect] methods of the virtual table module +** when a new virtual table is be being created or reinitialized. +** +** This interface has exactly the same effect as calling +** [sqlite3_create_module_v2()] with a NULL client data destructor. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ ); /* ** CAPI3REF: Register A Virtual Table Implementation {H18210} <S20400> ** EXPERIMENTAL ** -** This routine is identical to the [sqlite3_create_module()] method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -SQLITE_EXPERIMENTAL int sqlite3_create_module_v2( +** This routine is identical to the [sqlite3_create_module()] method, +** except that it has an extra parameter to specify +** a destructor function for the client data pointer. SQLite will +** invoke the destructor function (if it is not NULL) when SQLite +** no longer needs the pClientData pointer. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ void(*xDestroy)(void*) /* Module destructor function */ ); /* ** CAPI3REF: Virtual Table Instance Object {H18010} <S20400> ** KEYWORDS: sqlite3_vtab ** EXPERIMENTAL ** -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will +** Every [virtual table module] implementation uses a subclass +** of the following structure to describe a particular instance +** of the [virtual table]. Each subclass will ** be tailored to the specific needs of the module implementation. ** The purpose of this superclass is to define certain fields that are ** common to all module implementations. ** ** Virtual tables methods can set an error message by assigning a ** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should ** take care that any prior string is freed by a call to [sqlite3_free()] ** prior to assigning a new string to zErrMsg. After the error message ** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. +** freed by sqlite3_free() and the zErrMsg field will be zeroed. */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ + int nRef; /* NO LONGER USED */ char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; /* ** CAPI3REF: Virtual Table Cursor Object {H18020} <S20400> -** KEYWORDS: sqlite3_vtab_cursor -** EXPERIMENTAL -** -** Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used +** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} +** EXPERIMENTAL +** +** Every [virtual table module] implementation uses a subclass of the +** following structure to describe cursors that point into the +** [virtual table] and are used ** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define +** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed +** by the [sqlite3_module.xClose | xClose] method. Cussors are used +** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods +** of the module. Each module implementation will define ** the content of a cursor structure to suit its own needs. ** ** This superclass exists in order to define fields of the cursor that ** are common to all implementations. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. */ struct sqlite3_vtab_cursor { sqlite3_vtab *pVtab; /* Virtual table of this cursor */ /* Virtual table implementations will typically add additional fields */ }; @@ -4280,39 +4444,35 @@ /* ** CAPI3REF: Declare The Schema Of A Virtual Table {H18280} <S20400> ** EXPERIMENTAL ** -** The xCreate and xConnect methods of a module use the following API +** The [xCreate] and [xConnect] methods of a +** [virtual table module] call this interface ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400> ** EXPERIMENTAL ** ** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions +** using the [xFindFunction] method of the [virtual table module]. +** But global versions of those functions ** must exist in order to be overloaded. ** ** This API makes sure a global version of a function with a particular ** name and number of parameters exists. If no such function exists ** before this API is called, a new function is created. The implementation ** of the new function always causes an exception to be thrown. So ** the new function is not good for anything by itself. Its only ** purpose is to be a placeholder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); +** by a [virtual table]. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up ** to a comment remarkably similar to this one) is currently considered ** to be experimental. The interface might change in incompatible ways. @@ -4347,24 +4507,27 @@ ** ** <pre> ** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow; ** </pre> {END} ** -** If the flags parameter is non-zero, the the BLOB is opened for read +** If the flags parameter is non-zero, then the BLOB is opened for read ** and write access. If it is zero, the BLOB is opened for read access. ** ** Note that the database name is not the filename that contains ** the database but rather the symbolic name of the database that ** is assigned when the database is connected using [ATTACH]. ** For the main database file, the database name is "main". ** For TEMP tables, the database name is "temp". ** ** On success, [SQLITE_OK] is returned and the new [BLOB handle] is written -** to *ppBlob. Otherwise an [error code] is returned and any value written -** to *ppBlob should not be used by the caller. +** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set +** to be a null pointer. ** This function sets the [database connection] error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related +** functions. Note that the *ppBlob variable is always initialized in a +** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob +** regardless of the success or failure of this routine. ** ** If the row that a BLOB handle points to is modified by an ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects ** then the BLOB handle is marked as "expired". ** This is true if any column of the row is changed, even a column @@ -4373,14 +4536,27 @@ ** a expired BLOB handle fail with an return code of [SQLITE_ABORT]. ** Changes written into a BLOB prior to the BLOB expiring are not ** rollback by the expiration of the BLOB. Such changes will eventually ** commit if the transaction continues to completion. ** +** Use the [sqlite3_blob_bytes()] interface to determine the size of +** the opened blob. The size of a blob may not be changed by this +** interface. Use the [UPDATE] SQL command to change the size of a +** blob. +** +** The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces +** and the built-in [zeroblob] SQL function can be used, if desired, +** to create an empty, zero-filled blob in which to read or write using +** this interface. +** +** To avoid a resource leak, every open [BLOB handle] should eventually +** be released by a call to [sqlite3_blob_close()]. +** ** Requirements: ** [H17813] [H17814] [H17816] [H17819] [H17821] [H17824] */ -int sqlite3_blob_open( +SQLITE_API int sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, const char *zColumn, sqlite3_int64 iRow, @@ -4395,35 +4571,45 @@ ** ** Closing a BLOB shall cause the current transaction to commit ** if there are no other BLOBs, no pending prepared statements, and the ** database connection is in [autocommit mode]. ** If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} +** until the close operation if they will fit. ** ** Closing the BLOB often forces the changes ** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {H17833} Any errors that occur during +** at the time when the BLOB is closed. Any errors that occur during ** closing are reported as a non-zero return value. ** ** The BLOB is closed unconditionally. Even if this routine returns ** an error code, the BLOB is still closed. ** +** Calling this routine with a null pointer (which as would be returned +** by failed call to [sqlite3_blob_open()]) is a harmless no-op. +** ** Requirements: ** [H17833] [H17836] [H17839] */ -int sqlite3_blob_close(sqlite3_blob *); +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB {H17840} <S30230> ** -** Returns the size in bytes of the BLOB accessible via the open -** []BLOB handle] in its only argument. +** Returns the size in bytes of the BLOB accessible via the +** successfully opened [BLOB handle] in its only argument. The +** incremental blob I/O routines can only read or overwriting existing +** blob content; they cannot change the size of a blob. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. ** ** Requirements: ** [H17843] */ -int sqlite3_blob_bytes(sqlite3_blob *); +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally {H17850} <S30230> ** ** This function is used to read data from an open [BLOB handle] into a @@ -4431,21 +4617,30 @@ ** from the open BLOB, starting at offset iOffset. ** ** If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is read. If N or iOffset is ** less than zero, [SQLITE_ERROR] is returned and no data is read. +** The size of the blob (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. ** ** An attempt to read from an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ** ** On success, SQLITE_OK is returned. ** Otherwise, an [error code] or an [extended error code] is returned. ** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_write()]. +** ** Requirements: ** [H17853] [H17856] [H17859] [H17862] [H17863] [H17865] [H17868] */ -int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally {H17870} <S30230> ** ** This function is used to write data into an open [BLOB handle] from a @@ -4459,10 +4654,12 @@ ** This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is written. If N is ** less than zero [SQLITE_ERROR] is returned and no data is written. +** The size of the BLOB (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. ** ** An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. Writes to the BLOB that occurred ** before the [BLOB handle] expired are not rolled back by the ** expiration of the handle, though of course those changes might @@ -4470,15 +4667,22 @@ ** or by other independent statements. ** ** On success, SQLITE_OK is returned. ** Otherwise, an [error code] or an [extended error code] is returned. ** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_read()]. +** ** Requirements: ** [H17873] [H17874] [H17875] [H17876] [H17877] [H17879] [H17882] [H17885] ** [H17888] */ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects {H11200} <S20100> ** ** A virtual filesystem (VFS) is an [sqlite3_vfs] object @@ -4508,13 +4712,13 @@ ** the default. The choice for the new VFS is arbitrary. ** ** Requirements: ** [H11203] [H11206] [H11209] [H11212] [H11215] [H11218] */ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes {H17000} <S20000> ** ** The SQLite core uses these routines for thread @@ -4574,11 +4778,11 @@ ** cases where it really needs one. {END} If a faster non-recursive mutex ** implementation is available on the host platform, the mutex subsystem ** might return such a mutex in response to SQLITE_MUTEX_FAST. ** ** {H17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are +** a pointer to a static preexisting mutex. {END} Six static mutexes are ** used by the current version of SQLite. Future versions of SQLite ** may add additional static mutexes. Static mutexes are for internal ** use by SQLite only. Applications that use SQLite mutexes should ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or ** SQLITE_MUTEX_RECURSIVE. @@ -4624,15 +4828,15 @@ ** sqlite3_mutex_leave() is a NULL pointer, then all three routines ** behave as no-ops. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object {H17120} <S20130> ** EXPERIMENTAL ** @@ -4680,10 +4884,25 @@ ** of a valid mutex handle. The implementations of the methods defined ** by this structure are not required to handle this case, the results ** of passing a NULL pointer instead of a valid mutex handle are undefined ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). +** +** The xMutexInit() method must be threadsafe. It must be harmless to +** invoke xMutexInit() mutiple times within the same process and without +** intervening calls to xMutexEnd(). Second and subsequent calls to +** xMutexInit() must be no-ops. +** +** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). Similarly, xMutexAlloc() must not use SQLite memory +** allocation for a static mutex. However xMutexAlloc() may use SQLite +** memory allocation for a fast or recursive mutex. +** +** SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is +** called, but only if the prior call to xMutexInit returned SQLITE_OK. +** If xMutexInit fails in any way, it is expected to clean up after itself +** prior to returning. */ typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; struct sqlite3_mutex_methods { int (*xMutexInit)(void); int (*xMutexEnd)(void); @@ -4723,12 +4942,12 @@ ** using mutexes. And we do not want the assert() containing the ** call to sqlite3_mutex_held() to fail, so a non-zero return is ** the appropriate thing to do. {H17086} The sqlite3_mutex_notheld() ** interface should also return 1 when given a NULL pointer. */ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); /* ** CAPI3REF: Mutex Types {H17001} <H17000> ** ** The [sqlite3_mutex_alloc()] interface takes a single argument @@ -4755,11 +4974,11 @@ ** serializes access to the [database connection] given in the argument ** when the [threading mode] is Serialized. ** If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ -sqlite3_mutex *sqlite3_db_mutex(sqlite3*); +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files {H11300} <S30800> ** ** {H11301} The [sqlite3_file_control()] interface makes a direct call to the @@ -4781,11 +5000,11 @@ ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. {END} ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface {H11400} <S30800> ** ** The sqlite3_test_control() interface is used to read out internal @@ -4800,11 +5019,11 @@ ** The details of the operation codes, their meanings, the parameters ** they take, and what they do are all subject to change without notice. ** Unlike most of the SQLite API, this function is not guaranteed to ** operate consistently from one release to the next. */ -int sqlite3_test_control(int op, ...); +SQLITE_API int sqlite3_test_control(int op, ...); /* ** CAPI3REF: Testing Interface Operation Codes {H11410} <H11400> ** ** These constants are the valid operation code parameters used @@ -4820,10 +5039,13 @@ #define SQLITE_TESTCTRL_PRNG_RESET 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 +#define SQLITE_TESTCTRL_ASSERT 12 +#define SQLITE_TESTCTRL_ALWAYS 13 +#define SQLITE_TESTCTRL_RESERVE 14 /* ** CAPI3REF: SQLite Runtime Status {H17200} <S60200> ** EXPERIMENTAL ** @@ -4842,20 +5064,20 @@ ** value. For these latter parameters nothing is written into *pCurrent. ** ** This routine returns SQLITE_OK on success and a non-zero ** [error code] on failure. ** -** This routine is threadsafe but is not atomic. This routine can +** This routine is threadsafe but is not atomic. This routine can be ** called while other threads are running the same or different SQLite ** interfaces. However the values returned in *pCurrent and ** *pHighwater reflect the status of SQLite at different points in time ** and it is possible that another thread might change the parameter ** in between the times when *pCurrent and *pHighwater are written. ** ** See also: [sqlite3_db_status()] */ -SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); /* ** CAPI3REF: Status Parameters {H17250} <H17200> ** EXPERIMENTAL @@ -4959,17 +5181,24 @@ ** the resetFlg is true, then the highest instantaneous value is ** reset back down to the current value. ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ -SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters for database connections {H17520} <H17500> ** EXPERIMENTAL ** -** Status verbs for [sqlite3_db_status()]. +** These constants are the available integer "verbs" that can be passed as +** the second argument to the [sqlite3_db_status()] interface. +** +** New verbs may be added in future releases of SQLite. Existing verbs +** might be discontinued. Applications should check the return code from +** [sqlite3_db_status()] to make sure that the call worked. +** The [sqlite3_db_status()] interface will return a non-zero error code +** if a discontinued or unsupported verb is invoked. ** ** <dl> ** <dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt> ** <dd>This parameter returns the number of lookaside memory slots currently ** checked out.</dd> @@ -5000,11 +5229,11 @@ ** If the resetFlg is true, then the counter is reset to zero after this ** interface call returns. ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements {H17570} <H17550> ** EXPERIMENTAL ** @@ -5043,99 +5272,113 @@ */ typedef struct sqlite3_pcache sqlite3_pcache; /* ** CAPI3REF: Application Defined Page Cache. +** KEYWORDS: {page cache} ** EXPERIMENTAL ** ** The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can ** register an alternative page cache implementation by passing in an ** instance of the sqlite3_pcache_methods structure. The majority of the -** heap memory used by sqlite is used by the page cache to cache data read +** heap memory used by SQLite is used by the page cache to cache data read ** from, or ready to be written to, the database file. By implementing a ** custom page cache using this API, an application can control more -** precisely the amount of memory consumed by sqlite, the way in which -** said memory is allocated and released, and the policies used to +** precisely the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to ** determine exactly which parts of a database file are cached and for ** how long. ** -** The contents of the structure are copied to an internal buffer by sqlite -** within the call to [sqlite3_config]. +** The contents of the sqlite3_pcache_methods structure are copied to an +** internal buffer by SQLite within the call to [sqlite3_config]. Hence +** the application may discard the parameter after the call to +** [sqlite3_config()] returns. ** ** The xInit() method is called once for each call to [sqlite3_initialize()] ** (usually only once during the lifetime of the process). It is passed ** a copy of the sqlite3_pcache_methods.pArg value. It can be used to set ** up global structures and mutexes required by the custom page cache -** implementation. The xShutdown() method is called from within -** [sqlite3_shutdown()], if the application invokes this API. It can be used -** to clean up any outstanding resources before process shutdown, if required. -** -** The xCreate() method is used to construct a new cache instance. The +** implementation. +** +** The xShutdown() method is called from within [sqlite3_shutdown()], +** if the application invokes this API. It can be used to clean up +** any outstanding resources before process shutdown, if required. +** +** SQLite holds a [SQLITE_MUTEX_RECURSIVE] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. All other methods must be threadsafe +** in multithreaded applications. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +** +** The xCreate() method is used to construct a new cache instance. SQLite +** will typically create one cache instance for each open database file, +** though this is not guaranteed. The ** first parameter, szPage, is the size in bytes of the pages that must -** be allocated by the cache. szPage will not be a power of two. The -** second argument, bPurgeable, is true if the cache being created will -** be used to cache database pages read from a file stored on disk, or +** be allocated by the cache. szPage will not be a power of two. szPage +** will the page size of the database file that is to be cached plus an +** increment (here called "R") of about 100 or 200. SQLite will use the +** extra R bytes on each page to store metadata about the underlying +** database page on disk. The value of R depends +** on the SQLite version, the target platform, and how SQLite was compiled. +** R is constant for a particular build of SQLite. The second argument to +** xCreate(), bPurgeable, is true if the cache being created will +** be used to cache database pages of a file stored on disk, or ** false if it is used for an in-memory database. The cache implementation -** does not have to do anything special based on the value of bPurgeable, -** it is purely advisory. +** does not have to do anything special based with the value of bPurgeable; +** it is purely advisory. On a cache where bPurgeable is false, SQLite will +** never invoke xUnpin() except to deliberately delete a page. +** In other words, a cache created with bPurgeable set to false will +** never contain any unpinned pages. ** ** The xCachesize() method may be called at any time by SQLite to set the ** suggested maximum cache-size (number of pages stored by) the cache ** instance passed as the first argument. This is the value configured using ** the SQLite "[PRAGMA cache_size]" command. As with the bPurgeable parameter, -** the implementation is not required to do anything special with this -** value, it is advisory only. +** the implementation is not required to do anything with this +** value; it is advisory only. ** ** The xPagecount() method should return the number of pages currently -** stored in the cache supplied as an argument. +** stored in the cache. ** ** The xFetch() method is used to fetch a page and return a pointer to it. ** A 'page', in this context, is a buffer of szPage bytes aligned at an ** 8-byte boundary. The page to be fetched is determined by the key. The ** mimimum key value is 1. After it has been retrieved using xFetch, the page -** is considered to be pinned. -** -** If the requested page is already in the page cache, then a pointer to -** the cached buffer should be returned with its contents intact. If the -** page is not already in the cache, then the expected behaviour of the -** cache is determined by the value of the createFlag parameter passed -** to xFetch, according to the following table: +** is considered to be "pinned". +** +** If the requested page is already in the page cache, then the page cache +** implementation must return a pointer to the page buffer with its content +** intact. If the requested page is not already in the cache, then the +** behavior of the cache implementation is determined by the value of the +** createFlag parameter passed to xFetch, according to the following table: ** ** <table border=1 width=85% align=center> -** <tr><th>createFlag<th>Expected Behaviour -** <tr><td>0<td>NULL should be returned. No new cache entry is created. -** <tr><td>1<td>If createFlag is set to 1, this indicates that -** SQLite is holding pinned pages that can be unpinned -** by writing their contents to the database file (a -** relatively expensive operation). In this situation the -** cache implementation has two choices: it can return NULL, -** in which case SQLite will attempt to unpin one or more -** pages before re-requesting the same page, or it can -** allocate a new page and return a pointer to it. If a new -** page is allocated, then the first sizeof(void*) bytes of -** it (at least) must be zeroed before it is returned. -** <tr><td>2<td>If createFlag is set to 2, then SQLite is not holding any -** pinned pages associated with the specific cache passed -** as the first argument to xFetch() that can be unpinned. The -** cache implementation should attempt to allocate a new -** cache entry and return a pointer to it. Again, the first -** sizeof(void*) bytes of the page should be zeroed before -** it is returned. If the xFetch() method returns NULL when -** createFlag==2, SQLite assumes that a memory allocation -** failed and returns SQLITE_NOMEM to the user. +** <tr><th> createFlag <th> Behaviour when page is not already in cache +** <tr><td> 0 <td> Do not allocate a new page. Return NULL. +** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +** <tr><td> 2 <td> Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. ** </table> +** +** SQLite will normally invoke xFetch() with a createFlag of 0 or 1. If +** a call to xFetch() with createFlag==1 returns NULL, then SQLite will +** attempt to unpin one or more cache pages by spilling the content of +** pinned pages to disk and synching the operating system disk cache. After +** attempting to unpin pages, the xFetch() method will be invoked again with +** a createFlag of 2. ** ** xUnpin() is called by SQLite with a pointer to a currently pinned page ** as its second argument. If the third parameter, discard, is non-zero, ** then the page should be evicted from the cache. In this case SQLite ** assumes that the next time the page is retrieved from the cache using ** the xFetch() method, it will be zeroed. If the discard parameter is ** zero, then the page is considered to be unpinned. The cache implementation -** may choose to reclaim (free or recycle) unpinned pages at any time. -** SQLite assumes that next time the page is retrieved from the cache -** it will either be zeroed, or contain the same data that it did when it -** was unpinned. +** may choose to evict unpinned pages at any time. ** ** The cache is not required to perform any reference counting. A single ** call to xUnpin() unpins the page regardless of the number of prior calls ** to xFetch(). ** @@ -5355,20 +5598,20 @@ ** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** APIs are not strictly speaking threadsafe. If they are invoked at the ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -sqlite3_backup *sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -int sqlite3_backup_step(sqlite3_backup *p, int nPage); -int sqlite3_backup_finish(sqlite3_backup *p); -int sqlite3_backup_remaining(sqlite3_backup *p); -int sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification ** EXPERIMENTAL ** @@ -5481,15 +5724,27 @@ ** by an sqlite3_step() call. If there is a blocking connection, then the ** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED. */ -int sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ ); + + +/* +** CAPI3REF: String Comparison +** EXPERIMENTAL +** +** The [sqlite3_strnicmp()] API allows applications and extensions to +** compare the contents of two buffers containing UTF-8 strings in a +** case-indendent fashion, using the same definition of case independence +** that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ @@ -5499,5 +5754,6 @@ #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif +
Modified src/style.c from [b19bc65e46] to [64c82161ee].
@@ -197,42 +197,42 @@ @ <nobr>$<project_name></nobr> @ </div> @ <div class="title">$<title></div> @ <div class="status"><nobr><th1> @ if {[info exists login]} { -@ html "Logged in as <a href='$baseurl/my'>$login</a>" +@ puts "Logged in as $login" @ } else { @ puts "Not logged in" @ } @ </th1></nobr></div> @ </div> @ <div class="mainmenu"><th1> -@ html "<a href='$baseurl$index_page'>Home</a>" +@ html "<a href='$baseurl$index_page'>Home</a> " @ if {[hascap h]} { -@ html "<a href='$baseurl/dir'>Files</a>" +@ html "<a href='$baseurl/dir'>Files</a> " @ } @ if {[hascap o]} { -@ html "<a href='$baseurl/leaves'>Leaves</a>" -@ html "<a href='$baseurl/timeline'>Timeline</a>" -@ html "<a href='$baseurl/brlist'>Branches</a>" -@ html "<a href='$baseurl/taglist'>Tags</a>" +@ html "<a href='$baseurl/leaves'>Leaves</a> " +@ html "<a href='$baseurl/timeline'>Timeline</a> " +@ html "<a href='$baseurl/brlist'>Branches</a> " +@ html "<a href='$baseurl/taglist'>Tags</a> " @ } @ if {[hascap r]} { -@ html "<a href='$baseurl/reportlist'>Tickets</a>" +@ html "<a href='$baseurl/reportlist'>Tickets</a> " @ } @ if {[hascap j]} { -@ html "<a href='$baseurl/wiki'>Wiki</a>" +@ html "<a href='$baseurl/wiki'>Wiki</a> " @ } @ if {[hascap s]} { -@ html "<a href='$baseurl/setup'>Admin</a>" +@ html "<a href='$baseurl/setup'>Admin</a> " @ } elseif {[hascap a]} { -@ html "<a href='$baseurl/setup_ulist'>Users</a>" +@ html "<a href='$baseurl/setup_ulist'>Users</a> " @ } @ if {[info exists login]} { -@ html "<a href='$baseurl/login'>Logout</a>" +@ html "<a href='$baseurl/login'>Logout</a> " @ } else { -@ html "<a href='$baseurl/login'>Login</a>" +@ html "<a href='$baseurl/login'>Login</a> " @ } @ </th1></div> ; /* @@ -392,11 +392,10 @@ @ @ div.miniform { @ font-size: smaller; @ margin: 8px; @ } -@ @ table.fossil_db_generic_query_view { @ border-spacing: 0px; @ border: 1px solid black; @ } @ table.fossil_db_generic_query_view td { @@ -413,10 +412,13 @@ @ table.fossil_db_generic_query_view tr.header { @ background: #558195; @ font-size: 1.5em; @ color: #ffffff; @ } +@ +@ /* addeitions to support creole parser */ +@ @ .creoletable { @ border: 1px solid #666666; @ border-spacing: 0; @ margin: 1.5em 2em 1.8em 2em; @ } @@ -452,10 +454,13 @@ /* ** WEBPAGE: test_env */ void page_test_env(void){ style_header("Environment Test"); +#if !defined(__MINGW32__) + @ uid=%d(getuid()), gid=%d(getgid())<br> +#endif @ g.zBaseURL = %h(g.zBaseURL)<br> @ g.zTop = %h(g.zTop)<br> cgi_print_all(); style_footer(); }
Modified src/sync.c from [e1f5588a66] to [312506edea].
@@ -83,11 +83,11 @@ if( zUrl==0 ){ if( urlOptional ) exit(0); usage("URL"); } url_parse(zUrl); - db_set("last-sync-url", zUrl, 0); + db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : zUrl, 0); user_select(); if( g.argc==2 ){ if( g.urlPort!=g.urlDfltPort ){ printf("Server: %s://%s:%d%s\n", g.urlProtocol, g.urlName, g.urlPort, g.urlPath); @@ -101,26 +101,16 @@ /* ** COMMAND: pull ** ** Usage: %fossil pull ?URL? ?-R|--respository REPOSITORY? ** -** Pull changes in a remote repository into the local repository. -** The repository is identified by the -R or --repository option. -** If there is no such option then the open repository is used. -** The URL of the remote server is specified on the command line -** If no URL is specified then the URL used by the most recent -** "pull", "push", or "sync" command is used. -** -** The URL is of the following form: -** -** http://USER@HOST:PORT/PATH -** -** The "USER@" and ":PORT" substrings are optional. -** The "USER" substring specifies the login user. You will be -** prompted for the password on the command-line. The PORT -** specifies the TCP port of the server. The default port is -** 80. +** Pull changes from a remote repository into the local repository. +** +** If the URL is not specified, then the URL from the most recent +** clone, push, pull, remote-url, or sync command is used. +** +** See also: clone, push, sync, remote-url */ void pull_cmd(void){ process_sync_args(); client_sync(0,1,0,0,0); } @@ -129,11 +119,15 @@ ** COMMAND: push ** ** Usage: %fossil push ?URL? ?-R|--repository REPOSITORY? ** ** Push changes in the local repository over into a remote repository. -** See the "pull" command for additional information. +** +** If the URL is not specified, then the URL from the most recent +** clone, push, pull, remote-url, or sync command is used. +** +** See also: clone, pull, sync, remote-url */ void push_cmd(void){ process_sync_args(); client_sync(1,0,0,0,0); } @@ -144,11 +138,64 @@ ** ** Usage: %fossil sync ?URL? ?-R|--repository REPOSITORY? ** ** Synchronize the local repository with a remote repository. This is ** the equivalent of running both "push" and "pull" at the same time. -** See the "pull" command for additional information. +** +** If a user-id and password are required, specify them as follows: +** +** http://userid:password@www.domain.com:1234/path +** +** If the URL is not specified, then the URL from the most recent successful +** clone, push, pull, remote-url, or sync command is used. +** +** See also: clone, push, pull, remote-url */ void sync_cmd(void){ process_sync_args(); client_sync(1,1,0,0,0); +} + +/* +** COMMAND: remote-url +** +** Usage: %fossil remote-url ?URL|off? --show-pw +** +** Query and/or change the default server URL used by the "pull", "push", +** and "sync" commands. +** +** The userid and password are of the URL are not printed unless +** the --show-pw option is used on the command-line. +** +** The remote-url is set automatically by a "clone" command or by any +** "sync", "push", or "pull" command that specifies an explicit URL. +** The default remote-url is used by auto-syncing and by "sync", "push", +** "pull" that omit the server URL. +** +** See also: clone, push, pull, sync +*/ +void remote_url_cmd(void){ + char *zUrl; + int showPw = find_option("show-pw",0,0)!=0; + db_find_and_open_repository(1); + if( g.argc!=2 && g.argc!=3 ){ + usage("remote-url ?URL|off?"); + } + if( g.argc==3 ){ + if( strcmp(g.argv[2],"off")==0 ){ + db_unset("last-sync-url", 0); + }else{ + url_parse(g.argv[2]); + db_set("last-sync-url", g.urlCanonical, 0); + } + } + zUrl = db_get("last-sync-url", 0); + if( zUrl==0 ){ + printf("off\n"); + return; + }else if( showPw ){ + g.urlCanonical = zUrl; + }else{ + url_parse(zUrl); + } + printf("%s\n", g.urlCanonical); }
Modified src/tag.c from [3c286a5a05] to [bc765b3a20].
@@ -142,11 +142,11 @@ } /* ** Insert a tag into the database. */ -void tag_insert( +int tag_insert( const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */ int tagtype, /* 0:cancel 1:singleton 2:propagated */ const char *zValue, /* Value if the tag is really a property */ int srcId, /* Artifact that contains this tag */ double mtime, /* Timestamp. Use default if <=0.0 */ @@ -170,11 +170,11 @@ db_bind_double(&s, ":mtime", mtime); rc = db_step(&s); db_finalize(&s); if( rc==SQLITE_ROW ){ /* Another entry that is more recent already exists. Do nothing */ - return; + return tagid; } db_prepare(&s, "REPLACE INTO tagxref(tagid,tagtype,srcId,origid,value,mtime,rid)" " VALUES(%d,%d,%d,%d,%Q,:mtime,%d)", tagid, tagtype, srcId, rid, zValue, rid @@ -201,13 +201,18 @@ } } if( zCol ){ db_multi_exec("UPDATE event SET %s=%Q WHERE objid=%d", zCol, zValue, rid); } + if( tagid==TAG_DATE ){ + db_multi_exec("UPDATE event SET mtime=julianday(%Q) WHERE objid=%d", + zValue, rid); + } if( tagtype==0 || tagtype==2 ){ tag_propagate(rid, tagid, tagtype, rid, zValue, mtime); } + return tagid; } /* ** COMMAND: test-tag @@ -238,10 +243,11 @@ } rid = name_to_rid(g.argv[3]); if( rid==0 ){ fossil_fatal("no such object: %s", g.argv[3]); } + g.markPrivate = content_is_private(rid); zValue = g.argc==5 ? g.argv[4] : 0; db_begin_transaction(); tag_insert(zTag, tagtype, zValue, -1, 0.0, rid); db_end_transaction(0); } @@ -272,10 +278,11 @@ if( name_to_uuid(&uuid, 9) ){ fossil_fatal("%s", g.zErrMsg); return; } rid = name_to_rid(blob_str(&uuid)); + g.markPrivate = content_is_private(rid); blob_zero(&ctrl); #if 0 if( validate16(zTagname, strlen(zTagname)) ){ fossil_fatal(
Deleted src/tagview.c version [c5f7f1444b]
Modified src/timeline.c from [146af37c0f] to [f95beac657].
@@ -54,11 +54,11 @@ ){ char zShortUuid[UUID_SIZE+1]; sprintf(zShortUuid, "%.10s", zUuid); if( g.okHistory ){ @ <a onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")' - @ href="%s(g.zBaseURL)/ci/%s(zUuid)">[%s(zShortUuid)]</a> + @ href="%s(g.zBaseURL)/vinfo/%s(zUuid)">[%s(zShortUuid)]</a> }else{ @ <b onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'> @ [%s(zShortUuid)]</b> } } @@ -71,10 +71,40 @@ if( zV2==0 ){ @ <a href="%s(g.zBaseURL)/diff?v2=%s(zV1)">[diff]</a> }else{ @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a> } + } +} + +/* +** Generate a hyperlink to a date & time. +*/ +void hyperlink_to_date(const char *zDate, const char *zSuffix){ + if( zSuffix==0 ) zSuffix = ""; + if( g.okHistory ){ + @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix) + }else{ + @ %s(zDate)%s(zSuffix) + } +} + +/* +** Generate a hyperlink to a user. This will link to a timeline showing +** events by that user. If the date+time is specified, then the timeline +** is centered on that date+time. +*/ +void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ + if( zSuf==0 ) zSuf = ""; + if( g.okHistory ){ + if( zD && zD[0] ){ + @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf) + }else{ + @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf) + } + }else{ + @ %s(zU) } } /* ** Count the number of primary non-branch children for the given check-in. @@ -102,10 +132,11 @@ ** Allowed flags for the tmFlags argument to www_print_timeline */ #if INTERFACE #define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */ #define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */ +#define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */ #endif /* ** Output a timeline in the web format given a query. The query ** should return these columns: @@ -117,24 +148,28 @@ ** 4. User ** 5. Number of non-merge children ** 6. Number of parents ** 7. True if is a leaf ** 8. background color -** 9. type ("ci", "w") +** 9. type ("ci", "w", "t") ** 10. list of symbolic tags. +** 11. tagid for ticket or wiki +** 12. Short comment to user for repeated tickets and wiki */ void www_print_timeline( Stmt *pQuery, /* Query to implement the timeline */ int tmFlags, /* Flags controlling display behavior */ void (*xExtra)(int) /* Routine to call on each line of display */ ){ int wikiFlags; int mxWikiLen; Blob comment; + int prevTagid = 0; + int suppressCnt = 0; char zPrevDate[20]; - zPrevDate[0] = 0; - + + zPrevDate[0] = 0; mxWikiLen = db_get_int("timeline-max-comment", 0); if( db_get_boolean("timeline-block-markup", 0) ){ wikiFlags = WIKI_INLINE; }else{ wikiFlags = WIKI_INLINE | WIKI_NOBLOCK; @@ -155,10 +190,33 @@ const char *zBgClr = db_column_text(pQuery, 8); const char *zDate = db_column_text(pQuery, 2); const char *zType = db_column_text(pQuery, 9); const char *zUser = db_column_text(pQuery, 4); const char *zTagList = db_column_text(pQuery, 10); + int tagid = db_column_int(pQuery, 11); + int commentColumn = 3; /* Column containing comment text */ + if( tagid ){ + if( tagid==prevTagid ){ + if( tmFlags & TIMELINE_BRIEF ){ + suppressCnt++; + continue; + }else{ + commentColumn = 12; + } + } + } + prevTagid = tagid; + if( suppressCnt ){ + @ <tr><td><td><td> + @ <small><i>... %d(suppressCnt) similar + @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr> + suppressCnt = 0; + } + if( strcmp(zType,"div")==0 ){ + @ <tr><td colspan=3><hr></td></tr> + continue; + } db_multi_exec("INSERT OR IGNORE INTO seen VALUES(%d)", rid); if( memcmp(zDate, zPrevDate, 10) ){ sprintf(zPrevDate, "%.10s", zDate); @ <tr><td colspan=3> @ <div class="divider">%s(zPrevDate)</div> @@ -205,11 +263,11 @@ } } }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ hyperlink_to_uuid(zUuid); } - db_column_blob(pQuery, 3, &comment); + db_column_blob(pQuery, commentColumn, &comment); if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ Blob truncated; blob_zero(&truncated); blob_append(&truncated, blob_buffer(&comment), mxWikiLen); blob_append(&truncated, "...", 3); @@ -246,11 +304,13 @@ @ nchild INTEGER, @ nparent INTEGER, @ isleaf BOOLEAN, @ bgcolor TEXT, @ etype TEXT, - @ taglist TEXT + @ taglist TEXT, + @ tagid INTEGER, + @ short TEXT @ ) ; db_multi_exec(zSql); } @@ -277,11 +337,13 @@ @ WHERE tagid=%d AND rid=plink.cid), 'trunk')), @ bgcolor, @ event.type, @ (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid - @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) + @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0), + @ tagid, + @ brief @ FROM event JOIN blob @ WHERE blob.rid=event.objid ; if( zBase==0 ){ zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH); @@ -301,17 +363,38 @@ ){ style_submenu_element(zMenuName, zMenuName, "%s", url_render(pUrl, zParam, zValue, zRemove, 0)); } + +/* +** zDate is a localtime date. Insert records into the +** "timeline" table to cause <hr> to be inserted before and after +** entries of that date. +*/ +static void timeline_add_dividers(const char *zDate){ + db_multi_exec( + "INSERT INTO timeline(rid,timestamp,etype)" + "VALUES(-1,datetime(%Q,'-1 second') || '.9','div')", + zDate + ); + db_multi_exec( + "INSERT INTO timeline(rid,timestamp,etype)" + "VALUES(-2,datetime(%Q) || '.1','div')", + zDate + ); +} + + /* ** WEBPAGE: timeline ** ** Query parameters: ** ** a=TIMESTAMP after this date ** b=TIMESTAMP before this date. +** c=TIMESTAMP "circa" this date. ** n=COUNT number of events in output ** p=RID artifact RID and up to COUNT parents and ancestors ** d=RID artifact RID and up to COUNT descendants ** t=TAGID show only check-ins with the given tagid ** u=USER only if belonging to this user @@ -334,22 +417,29 @@ int d_rid = atoi(PD("d","0")); /* artifact d and its descendants */ const char *zUser = P("u"); /* All entries by this user if not NULL */ const char *zType = PD("y","all"); /* Type of events. All if NULL */ const char *zAfter = P("a"); /* Events after this time */ const char *zBefore = P("b"); /* Events before this time */ + const char *zCirca = P("c"); /* Events near this time */ const char *zTagName = P("t"); /* Show events with this tag */ HQuery url; /* URL for various branch links */ int tagid; /* Tag ID */ + int tmFlags; /* Timeline flags */ /* To view the timeline, must have permission to read project data. */ login_check_credentials(); if( !g.okRead ){ login_needed(); return; } if( zTagName ){ tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName); }else{ tagid = 0; + } + if( zType[0]=='a' ){ + tmFlags = TIMELINE_BRIEF; + }else{ + tmFlags = 0; } style_header("Timeline"); login_anonymous_available(); timeline_temp_table(); @@ -360,41 +450,54 @@ if( p_rid || d_rid ){ /* If p= or d= is present, ignore all other parameters other than n= */ char *zUuid; int np, nd; - if( p_rid && d_rid && p_rid!=d_rid ) p_rid = d_rid; + if( p_rid && d_rid ){ + if( p_rid!=d_rid ) p_rid = d_rid; + if( P("n")==0 ) nEntry = 10; + } db_multi_exec( "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY)" ); zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", p_rid ? p_rid : d_rid); blob_appendf(&sql, " AND event.objid IN ok"); nd = 0; if( d_rid ){ - compute_descendants(d_rid, nEntry); + compute_descendants(d_rid, nEntry+1); nd = db_int(0, "SELECT count(*)-1 FROM ok"); if( nd>0 ){ db_multi_exec("%s", blob_str(&sql)); blob_appendf(&desc, "%d descendants", nd); } + timeline_add_dividers( + db_text("1","SELECT datetime(mtime,'localtime') FROM event" + " WHERE objid=%d", d_rid) + ); db_multi_exec("DELETE FROM ok"); } if( p_rid ){ - compute_ancestors(p_rid, nEntry); + compute_ancestors(p_rid, nEntry+1); np = db_int(0, "SELECT count(*)-1 FROM ok"); if( np>0 ){ if( nd>0 ) blob_appendf(&desc, " and "); blob_appendf(&desc, "%d ancestors", np); db_multi_exec("%s", blob_str(&sql)); } + if( d_rid==0 ){ + timeline_add_dividers( + db_text("1","SELECT datetime(mtime,'localtime') FROM event" + " WHERE objid=%d", p_rid) + ); + } } if( g.okHistory ){ blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>", g.zBaseURL, zUuid, zUuid); }else{ - blob_appendf(&desc, " of [%.10s]", zUuid); + blob_appendf(&desc, " of check-in [%.10s]", zUuid); } }else{ int n; const char *zEType = "event"; char *zDate; @@ -442,10 +545,32 @@ " ORDER BY event.mtime DESC", zBefore); url_add_parameter(&url, "b", zBefore); }else{ zBefore = 0; } + }else if( zCirca ){ + while( isspace(zCirca[0]) ){ zCirca++; } + if( zCirca[0] ){ + double rCirca = db_double(0.0, "SELECT julianday(%Q, 'utc')", zCirca); + Blob sql2; + blob_init(&sql2, blob_str(&sql), -1); + blob_appendf(&sql2, + " AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d", + rCirca, (nEntry+1)/2 + ); + db_multi_exec("%s", blob_str(&sql2)); + blob_reset(&sql2); + blob_appendf(&sql, + " AND event.mtime>=%f ORDER BY event.mtime ASC", + rCirca + ); + nEntry -= (nEntry+1)/2; + timeline_add_dividers(zCirca); + url_add_parameter(&url, "c", zCirca); + }else{ + zCirca = 0; + } }else{ blob_appendf(&sql, " ORDER BY event.mtime DESC"); } blob_appendf(&sql, " LIMIT %d", nEntry); db_multi_exec("%s", blob_str(&sql)); @@ -452,11 +577,11 @@ n = db_int(0, "SELECT count(*) FROM timeline"); if( n<nEntry && zAfter ){ cgi_redirect(url_render(&url, "a", 0, "b", 0)); } - if( zAfter==0 && zBefore==0 ){ + if( zAfter==0 && zBefore==0 && zCirca==0 ){ blob_appendf(&desc, "%d most recent %ss", n, zEType); }else{ blob_appendf(&desc, "%d %ss", n, zEType); } if( zUser ){ @@ -467,10 +592,12 @@ } if( zAfter ){ blob_appendf(&desc, " occurring on or after %h.<br>", zAfter); }else if( zBefore ){ blob_appendf(&desc, " occurring on or before %h.<br>", zBefore); + }else if( zCirca ){ + blob_appendf(&desc, " occurring around %h.<br>", zCirca); } if( g.okHistory ){ if( zAfter || n==nEntry ){ zDate = db_text(0, "SELECT min(timestamp) FROM timeline"); timeline_submenu(&url, "Older", "b", zDate, "a"); @@ -504,11 +631,11 @@ } blob_zero(&sql); db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC"); @ <h2>%b(&desc)</h2> blob_reset(&desc); - www_print_timeline(&q, 0, 0); + www_print_timeline(&q, tmFlags, 0); db_finalize(&q); @ <script> @ var parentof = new Object(); @ var childof = new Object();
Modified src/tkt.c from [a24e654e39] to [98960a5cdc].
@@ -197,11 +197,11 @@ ** work of trying to create it. ** ** Return TRUE if a new TICKET entry was created and FALSE if an ** existing entry was revised. */ -int ticket_insert(Manifest *p, int createFlag, int checkTime){ +int ticket_insert(const Manifest *p, int createFlag, int checkTime){ Blob sql; Stmt q; int i; const char *zSep; int rc = 0; @@ -218,11 +218,12 @@ for(i=0; i<p->nField; i++){ const char *zName = p->aField[i].zName; if( zName[0]=='+' ){ zName++; if( fieldId(zName)<0 ) continue; - blob_appendf(&sql,", %s=%s || %Q", zName, zName, p->aField[i].zValue); + blob_appendf(&sql,", %s=coalesce(%s,'') || %Q", + zName, zName, p->aField[i].zValue); }else{ if( fieldId(zName)<0 ) continue; blob_appendf(&sql,", %s=%Q", zName, p->aField[i].zValue); } } @@ -264,10 +265,11 @@ while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); content_get(rid, &content); manifest_parse(&manifest, &content); ticket_insert(&manifest, createFlag, 0); + manifest_ticket_event(rid, &manifest, createFlag, tagid); manifest_clear(&manifest); createFlag = 0; } db_finalize(&q); } @@ -456,11 +458,13 @@ }else{ rid = content_put(&tktchng, 0, 0); if( rid==0 ){ fossil_panic("trouble committing ticket: %s", g.zErrMsg); } + manifest_crosslink_begin(); manifest_crosslink(rid, &tktchng); + manifest_crosslink_end(); } return TH_RETURN; } @@ -689,14 +693,15 @@ char *zDate = db_text(0, "SELECT datetime(%.12f)", m.rDate); char zUuid[12]; memcpy(zUuid, zChngUuid, 10); zUuid[10] = 0; @ - @ <p>%s(zDate) + @ Ticket change @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zUuid)</a>]</a> - @ by %h(m.zUser):</p> - @ + @ (rid %d(rid)) by + hyperlink_to_user(m.zUser,zDate," on"); + hyperlink_to_date(zDate, ":"); free(zDate); ticket_output_change_artifact(&m); } manifest_clear(&m); }
Modified src/update.c from [e7d09d9291] to [053193c6c1].
@@ -187,11 +187,15 @@ /* The file is unedited. Change it to the target version */ printf("UPDATE %s\n", zName); undo_save(zName); vfile_to_disk(0, idt, 0); }else if( idt==0 && idv>0 ){ - if( chnged ){ + if( ridv==0 ){ + /* Added in current checkout. Continue to hold the file as + ** as an addition */ + db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv); + }else if( chnged ){ printf("CONFLICT %s\n", zName); }else{ char *zFullPath; printf("REMOVE %s\n", zName); undo_save(zName);
Modified src/url.c from [6c8a641bd1] to [c5cf8d9b2a].
@@ -27,17 +27,21 @@ #include "url.h" /* ** Parse the given URL. Populate variables in the global "g" structure. ** -** g.urlIsFile True if this is a file URL -** g.urlName Hostname for HTTP:. Filename for FILE: -** g.urlPort Port name for HTTP. -** g.urlPath Path name for HTTP. +** g.urlIsFile True if FILE: +** g.urlIsHttps True if HTTPS: +** g.urlProtocol "http" or "https" or "file" +** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE: +** g.urlPort TCP port number for HTTP or HTTPS. +** g.urlDfltPort Default TCP port number (80 or 443). +** g.urlPath Path name for HTTP or HTTPS. ** g.urlUser Userid. ** g.urlPasswd Password. -** g.urlCanonical The URL in canonical form +** g.urlHostname HOST:PORT or just HOST if port is the default. +** g.urlCanonical The URL in canonical form, omitting userid/password ** ** HTTP url format is: ** ** http://userid:password@host:port/path?query#fragment ** @@ -87,12 +91,17 @@ g.urlHostname = g.urlName; } g.urlPath = mprintf(&zUrl[i]); dehttpize(g.urlName); dehttpize(g.urlPath); - g.urlCanonical = mprintf("%s://%T:%d%T", - g.urlProtocol, g.urlName, g.urlPort, g.urlPath); + if( g.urlDfltPort==g.urlPort ){ + g.urlCanonical = mprintf("%s://%T%T", + g.urlProtocol, g.urlName, g.urlPath); + }else{ + g.urlCanonical = mprintf("%s://%T:%d%T", + g.urlProtocol, g.urlName, g.urlPort, g.urlPath); + } }else if( strncmp(zUrl, "file:", 5)==0 ){ g.urlIsFile = 1; if( zUrl[5]=='/' && zUrl[6]=='/' ){ i = 7; }else{ @@ -154,32 +163,38 @@ } } } /* -** Proxy specified on the command-line. +** Proxy specified on the command-line using the --proxy option. +** If there is no --proxy option on the command-line then this +** variable holds a NULL pointer. */ static const char *zProxyOpt = 0; /* -** Extra any proxy options from the command-line. +** Extract any proxy options from the command-line. ** ** --proxy URL|off ** +** This also happens to be a convenient function to use to look for +** the --nosync option that will temporarily disable the "autosync" +** feature. */ void url_proxy_options(void){ zProxyOpt = find_option("proxy", 0, 1); if( find_option("nosync",0,0) ) g.fNoSync = 1; } /* -** If the "proxy" setting is defined, then change the URL to refer -** to the proxy server. +** If the "proxy" setting is defined, then change the URL settings +** (initialized by a prior call to url_parse()) so that the HTTP +** header will be appropriate for the proxy and so that the TCP/IP +** connection will be opened to the proxy rather than to the server. ** -** If the protocol is "https://" then start stunnel to handle the SSL -** and make the url setting refer to stunnel rather than the original -** destination. +** If zMsg is not NULL and a proxy is used, then print zMsg followed +** by the canonical name of the proxy (with userid and password suppressed). */ void url_enable_proxy(const char *zMsg){ const char *zProxy; zProxy = zProxyOpt; if( zProxy==0 ){ @@ -189,14 +204,26 @@ } } if( zProxy && zProxy[0] && !is_false(zProxy) ){ char *zOriginalUrl = g.urlCanonical; char *zOriginalHost = g.urlHostname; - if( zMsg ) printf("%s%s\n", zMsg, zProxy); + char *zOriginalUser = g.urlUser; + char *zOriginalPasswd = g.urlPasswd; + g.urlUser = 0; + g.urlPasswd = ""; url_parse(zProxy); + if( zMsg ) printf("%s%s\n", zMsg, g.urlCanonical); g.urlPath = zOriginalUrl; g.urlHostname = zOriginalHost; + if( g.urlUser ){ + char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd); + char *zCredentials2 = encode64(zCredentials1, -1); + g.urlProxyAuth = mprintf("Basic %z", zCredentials2); + free(zCredentials1); + } + g.urlUser = zOriginalUser; + g.urlPasswd = zOriginalPasswd; } } #if INTERFACE /*
Modified src/user.c from [d521e5caee] to [29b52a5fb9].
@@ -316,12 +316,14 @@ if( attempt_user(db_get("default-user", 0)) ) return; if( attempt_user(getenv("USER")) ) return; - db_prepare(&s, "SELECT uid, login FROM user" - " WHERE login NOT IN ('anonymous','nobody')"); + db_prepare(&s, + "SELECT uid, login FROM user" + " WHERE login NOT IN ('anonymous','nobody','reader','developer')" + ); if( db_step(&s)==SQLITE_ROW ){ g.userUid = db_column_int(&s, 0); g.zLogin = mprintf("%s", db_column_text(&s, 1)); } db_finalize(&s);
Modified src/vfile.c from [eb6d72e4f4] to [5504b327f7].
@@ -259,11 +259,11 @@ ** of pPath when inserting into the SFILE table. ** ** Subdirectories are scanned recursively. ** Omit files named in VFILE.vid */ -void vfile_scan(int vid, Blob *pPath, int nPrefix){ +void vfile_scan(int vid, Blob *pPath, int nPrefix, int allFlag){ DIR *d; int origSize; const char *zDir; struct dirent *pEntry; static const char *zSql = "SELECT 1 FROM vfile " @@ -273,15 +273,19 @@ zDir = blob_str(pPath); d = opendir(zDir); if( d ){ while( (pEntry=readdir(d))!=0 ){ char *zPath; - if( pEntry->d_name[0]=='.' ) continue; + if( pEntry->d_name[0]=='.' ){ + if( !allFlag ) continue; + if( pEntry->d_name[1]==0 ) continue; + if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue; + } blob_appendf(pPath, "/%s", pEntry->d_name); zPath = blob_str(pPath); if( file_isdir(zPath)==1 ){ - vfile_scan(vid, pPath, nPrefix); + vfile_scan(vid, pPath, nPrefix, allFlag); }else if( file_isfile(zPath) && !db_exists(zSql, &zPath[nPrefix+1]) ){ db_multi_exec("INSERT INTO sfile VALUES(%Q)", &zPath[nPrefix+1]); } blob_resize(pPath, origSize); }
Modified src/wiki.c from [2ebc00b129] to [8af938a182].
@@ -50,25 +50,32 @@ if( i<3 || i>100 ) return 0; return 1; } /* +** Output rules for well-formed wiki pages +*/ +static void well_formed_wiki_name_rules(void){ + @ <ul> + @ <li> Must not begin or end with a space. + @ <li> Must not contain any control characters, including tab or + @ newline. + @ <li> Must not have two or more spaces in a row internally. + @ <li> Must be between 3 and 100 characters in length. + @ </ul> +} + +/* ** Check a wiki name. If it is not well-formed, then issue an error ** and return true. If it is well-formed, return false. */ static int check_name(const char *z){ if( !wiki_name_is_wellformed(z) ){ style_header("Wiki Page Name Error"); @ The wiki name "<b>%h(z)</b>" is not well-formed. Rules for @ wiki page names: - @ <ul> - @ <li> Must not begin or end with a space. - @ <li> Must not contain any control characters, including tab or - @ newline. - @ <li> Must not have two or more spaces in a row internally. - @ <li> Must be between 3 and 100 characters in length. - @ </ul> + well_formed_wiki_name_rules(); style_footer(); return 1; } return 0; } @@ -119,11 +126,10 @@ int rid = 0; int isSandbox; Blob wiki; Manifest m; const char *zPageName; - char *zHtmlPageName; char *zBody = mprintf("%s","<i>Empty Page</i>"); login_check_credentials(); if( !g.okRdWiki ){ login_needed(); return; } zPageName = P("name"); @@ -130,20 +136,23 @@ if( zPageName==0 ){ style_header("Wiki"); @ <ul> { char *zHomePageName = db_get("project-name",0); if( zHomePageName ){ - @ <li> <a href="%s(g.zBaseURL)/wiki?name=%s(zHomePageName)"> - @ %s(zHomePageName)</a> wiki home page.</li> + @ <li> <a href="%s(g.zBaseURL)/wiki?name=%t(zHomePageName)"> + @ %h(zHomePageName)</a> wiki home page.</li> } } @ <li> <a href="%s(g.zBaseURL)/timeline?y=w">Recent changes</a> to wiki @ pages. </li> @ <li> <a href="%s(g.zBaseURL)/wiki_rules">Formatting rules</a> for @ wiki.</li> @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> @ to experiment.</li> + if( g.okNewWiki ){ + @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> + } @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> @ available on this server.</li> @ </ul> style_footer(); return; @@ -183,12 +192,11 @@ if( g.okHistory ){ style_submenu_element("History", "History", "%s/whistory?name=%T", g.zTop, zPageName); } } - zHtmlPageName = mprintf("%h", zPageName); - style_header(zHtmlPageName); + style_header(zPageName); blob_init(&wiki, zBody, -1); wiki_convert(&wiki, 0, 0); blob_reset(&wiki); if( !isSandbox ){ manifest_clear(&m); @@ -291,11 +299,11 @@ return; } if( zBody==0 ){ zBody = mprintf("<i>Empty Page</i>"); } - zHtmlPageName = mprintf("Edit: %h", zPageName); + zHtmlPageName = mprintf("Edit: %s", zPageName); style_header(zHtmlPageName); if( P("preview")!=0 ){ blob_zero(&wiki); blob_append(&wiki, zBody, -1); @ Preview:<hr> @@ -321,10 +329,45 @@ if( !isSandbox ){ manifest_clear(&m); } style_footer(); } + +/* +** WEBPAGE: wikinew +** URL /wikinew +** +** Prompt the user to enter the name of a new wiki page. Then redirect +** to the wikiedit screen for that new page. +*/ +void wikinew_page(void){ + const char *zName; + login_check_credentials(); + if( !g.okNewWiki ){ + login_needed(); + return; + } + zName = PD("name",""); + if( zName[0] && wiki_name_is_wellformed(zName) ){ + cgi_redirectf("wikiedit?name=%T", zName); + } + style_header("Create A New Wiki Page"); + @ <p>Rules for wiki page names: + well_formed_wiki_name_rules(); + @ </p> + @ <form method="POST" action="%s(g.zBaseURL)/wikinew"> + @ <p>Name of new wiki page: + @ <input type="text" width="35" name="name" value="%h(zName)"> + @ <input type="submit" value="Create"> + @ </p></form> + if( zName[0] ){ + @ <p><b><font color="red"> + @ "%h(zName)" is not a valid wiki page name!</font></b></p> + } + style_footer(); +} + /* ** Append the wiki text for an remark to the end of the given BLOB. */ static void appendRemark(Blob *p){ @@ -432,11 +475,11 @@ } if( P("cancel")!=0 ){ cgi_redirectf("wiki?name=%T", zPageName); return; } - zHtmlPageName = mprintf("Append Comment To: %h", zPageName); + zHtmlPageName = mprintf("Append Comment To: %s", zPageName); style_header(zHtmlPageName); if( P("preview")!=0 ){ Blob preview; blob_zero(&preview); appendRemark(&preview); @@ -461,10 +504,23 @@ @ </form> style_footer(); } /* +** Name of the wiki history page being generated +*/ +static const char *zWikiPageName; + +/* +** Function called to output extra text at the end of each line in +** a wiki history listing. +*/ +static void wiki_history_extra(int rid){ + @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a> +} + +/* ** WEBPAGE: whistory ** URL: /whistory?name=PAGENAME ** ** Show the complete change history for a single wiki page. */ @@ -474,11 +530,11 @@ char *zSQL; const char *zPageName; login_check_credentials(); if( !g.okHistory ){ login_needed(); return; } zPageName = PD("name",""); - zTitle = mprintf("History Of %h", zPageName); + zTitle = mprintf("History Of %s", zPageName); style_header(zTitle); free(zTitle); zSQL = mprintf("%s AND event.objid IN " " (SELECT rid FROM tagxref WHERE tagid=" @@ -485,12 +541,66 @@ "(SELECT tagid FROM tag WHERE tagname='wiki-%q'))" "ORDER BY mtime DESC", timeline_query_for_www(), zPageName); db_prepare(&q, zSQL); free(zSQL); - www_print_timeline(&q, TIMELINE_ARTID, 0); + zWikiPageName = zPageName; + www_print_timeline(&q, TIMELINE_ARTID, wiki_history_extra); db_finalize(&q); + style_footer(); +} + +/* +** WEBPAGE: wdiff +** URL: /whistory?name=PAGENAME&a=RID1&b=RID2 +** +** Show the difference between two wiki pages. +*/ +void wdiff_page(void){ + char *zTitle; + int rid1, rid2; + const char *zPageName; + Blob content1, content2; + Manifest m1, m2; + Blob w1, w2, d; + + login_check_credentials(); + rid1 = atoi(PD("a","0")); + if( !g.okHistory ){ login_needed(); return; } + if( rid1==0 ) fossil_redirect_home(); + rid2 = atoi(PD("b","0")); + zPageName = PD("name",""); + zTitle = mprintf("Changes To %s", zPageName); + style_header(zTitle); + free(zTitle); + + if( rid2==0 ){ + rid2 = db_int(0, + "SELECT objid FROM event JOIN tagxref ON objid=rid AND tagxref.tagid=" + "(SELECT tagid FROM tag WHERE tagname='wiki-%q')" + " WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)" + " ORDER BY event.mtime DESC LIMIT 1", + zPageName, rid1 + ); + } + content_get(rid1, &content1); + manifest_parse(&m1, &content1); + if( m1.type!=CFTYPE_WIKI ) fossil_redirect_home(); + blob_init(&w1, m1.zWiki, -1); + blob_zero(&w2); + if( rid2 ){ + content_get(rid2, &content2); + manifest_parse(&m2, &content2); + if( m2.type==CFTYPE_WIKI ){ + blob_init(&w2, m2.zWiki, -1); + } + } + blob_zero(&d); + text_diff(&w2, &w1, &d, 5); + @ <pre> + @ %h(blob_str(&d)) + @ </pre> style_footer(); } /* ** WEBPAGE: wcontent @@ -691,20 +801,21 @@ /* ** COMMAND: wiki ** ** Usage: %fossil wiki (export|create|commit|list) WikiName ** -** Run various subcommands to fetch wiki entries. +** Run various subcommands to work with wiki entries. ** ** %fossil wiki export PAGENAME ?FILE? ** ** Sends the latest version of the PAGENAME wiki ** entry to the given file or standard output. ** ** %fossil wiki commit PAGENAME ?FILE? ** -** Commit changes to a wiki page from FILE or from standard. +** Commit changes to a wiki page from FILE or from standard +** input. ** ** %fossil wiki create PAGENAME ?FILE? ** ** Create a new wiki page with initial content taken from ** FILE or from standard input.
Modified src/wikiformat.c from [7abff38b1d] to [3654a443f2].
@@ -918,10 +918,25 @@ ** close the markup. ** ** Actually, this routine might or might not append the hyperlink, depending ** on current rendering rules: specifically does the current user have ** "History" permission. +** +** [http://www.fossil-scm.org/] +** [https://www.fossil-scm.org/] +** [ftp://www.fossil-scm.org/] +** [mailto:fossil-users@lists.fossil-scm.org] +** +** [/path] +** +** [./relpath] +** +** [WikiPageName] +** +** [0123456789abcdef] +** +** [#fragment] */ static void openHyperlink( Renderer *p, /* Rendering context */ const char *zTarget, /* Hyperlink traget; text within [...] */ char *zClose, /* Write hyperlink closing text here */ @@ -940,18 +955,18 @@ if( 1 /* g.okHistory */ ){ blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zBaseURL, zTarget); }else{ zTerm = ""; } - }else if( zTarget[0]=='.' ){ + }else if( zTarget[0]=='.' || zTarget[0]=='#' ){ if( 1 /* g.okHistory */ ){ blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); }else{ zTerm = ""; } }else if( is_valid_uuid(zTarget) ){ - int isClosed; + int isClosed = 0; if( is_ticket(zTarget, &isClosed) ){ /* Special display processing for tickets. Display the hyperlink ** as crossed out if the ticket is closed. */ if( isClosed ){ @@ -1351,10 +1366,36 @@ if( g.argc!=3 ) usage("FILE"); blob_zero(&out); blob_read_from_file(&in, g.argv[2]); wiki_convert(&in, &out, 0); blob_write_to_file(&out, "-"); +} + +/* +** Search for a <title>...</title> at the beginning of a wiki page. +** Return true (nonzero) if a title is found. Return zero if there is +** not title. +** +** If a title is found, initialize the pTitle blob to be the content +** of the title and initialize pTail to be the text that follows the +** title. +*/ +int wiki_find_title(Blob *pIn, Blob *pTitle, Blob *pTail){ + char *z; + int i; + int iStart; + z = blob_str(pIn); + for(i=0; isspace(z[i]); i++){} + if( z[i]!='<' ) return 0; + i++; + if( strncmp(&z[i],"title>", 6)!=0 ) return 0; + iStart = i+6; + for(i=iStart; z[i] && (z[i]!='<' || strncmp(&z[i],"</title>",8)!=0); i++){} + if( z[i]!='<' ) return 0; + blob_init(pTitle, &z[iStart], i-iStart); + blob_init(pTail, &z[i+8], -1); + return 1; } /* ** Additions to support creole parser
Modified src/winhttp.c from [2ef98f5c31] to [f308305b21].
@@ -109,15 +109,15 @@ } wanted -= got; } fclose(out); out = 0; - sprintf(zCmd, "%s http \"%s\" %s %s %s", + sprintf(zCmd, "\"%s\" http \"%s\" %s %s %s", g.argv[0], g.zRepositoryName, zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr) ); - system(zCmd); + portable_system(zCmd); in = fopen(zReplyFName, "rb"); if( in ){ while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){ send(p->s, zHdr, got, 0); } @@ -177,11 +177,11 @@ zTempPrefix = mprintf("fossil_server_P%d_", iPort); printf("Listening for HTTP requests on TCP port %d\n", iPort); if( zBrowser ){ zBrowser = mprintf(zBrowser, iPort); printf("Launch webbrowser: %s\n", zBrowser); - system(zBrowser); + portable_system(zBrowser); } printf("Type Ctrl-C to stop the HTTP server\n"); for(;;){ SOCKET client; SOCKADDR_IN client_addr;
Modified src/xfer.c from [0df98a4b53] to [0008bf7842].
@@ -97,10 +97,13 @@ ** If DELTASRC exists, then the CONTENT is a delta against the ** content of DELTASRC. ** ** If any error occurs, write a message into pErr which has already ** be initialized to an empty string. +** +** Any artifact successfully received by this routine is considered to +** be public and is therefore removed from the "private" table. */ static void xfer_accept_file(Xfer *pXfer){ int n; int rid; int srcid = 0; @@ -125,14 +128,14 @@ } if( pXfer->nToken==4 ){ Blob src; srcid = rid_from_uuid(&pXfer->aToken[2], 1); if( content_get(srcid, &src)==0 ){ - content_put(&content, blob_str(&pXfer->aToken[1]), srcid); - blob_appendf(pXfer->pOut, "gimme %b\n", &pXfer->aToken[2]); - pXfer->nGimmeSent++; + rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid); pXfer->nDanglingFile++; + db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); + content_make_public(rid); return; } pXfer->nDeltaRcvd++; blob_delta_apply(&src, &content, &content); blob_reset(&src); @@ -146,11 +149,11 @@ rid = content_put(&content, blob_str(&hash), 0); blob_reset(&hash); if( rid==0 ){ blob_appendf(&pXfer->err, "%s", g.zErrMsg); }else{ - /* db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); */ + content_make_public(rid); manifest_crosslink(rid, &content); } remote_has(rid); } @@ -157,10 +160,12 @@ /* ** Try to send a file as a delta against its parent. ** If successful, return the number of bytes in the delta. ** If we cannot generate an appropriate delta, then send ** nothing and return zero. +** +** Never send a delta against a private artifact. */ static int send_delta_parent( Xfer *pXfer, /* The transfer context */ int rid, /* record id of the file to send */ Blob *pContent, /* The content of the file to send */ @@ -185,11 +190,11 @@ int srcId = 0; for(i=0; srcId==0 && i<count(azQuery); i++){ srcId = db_int(0, azQuery[i], rid); } - if( srcId>0 && content_get(srcId, &src) ){ + if( srcId>0 && !content_is_private(srcId) && content_get(srcId, &src) ){ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcId); blob_delta_create(&src, pContent, &delta); size = blob_size(&delta); if( size>=blob_size(pContent)-50 ){ size = 0; @@ -210,10 +215,12 @@ /* ** Try to send a file as a native delta. ** If successful, return the number of bytes in the delta. ** If we cannot generate an appropriate delta, then send ** nothing and return zero. +** +** Never send a delta against a private artifact. */ static int send_delta_native( Xfer *pXfer, /* The transfer context */ int rid, /* record id of the file to send */ Blob *pUuid /* The UUID of the file to send */ @@ -221,11 +228,11 @@ Blob src, delta; int size = 0; int srcId; srcId = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", rid); - if( srcId>0 ){ + if( srcId>0 && !content_is_private(srcId) ){ blob_zero(&src); db_blob(&src, "SELECT uuid FROM blob WHERE rid=%d", srcId); if( uuid_is_shunned(blob_str(&src)) ){ blob_reset(&src); return 0; @@ -251,15 +258,20 @@ ** The pUuid can be NULL in which case the correct UUID is computed ** from the rid. ** ** Try to send the file as a native delta if nativeDelta is true, or ** as a parent delta if nativeDelta is false. +** +** It should never be the case that rid is a private artifact. But +** as a precaution, this routine does check on rid and if it is private +** this routine becomes a no-op. */ static void send_file(Xfer *pXfer, int rid, Blob *pUuid, int nativeDelta){ Blob content, uuid; int size = 0; + if( content_is_private(rid) ) return; if( db_exists("SELECT 1 FROM onremote WHERE rid=%d", rid) ){ return; } blob_zero(&uuid); db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid); @@ -309,16 +321,20 @@ blob_reset(&uuid); } /* ** Send a gimme message for every phantom. +** +** It should not be possible to have a private phantom. But just to be +** sure, take care not to send any "gimme" messagse on private artifacts. */ static void request_phantoms(Xfer *pXfer, int maxReq){ Stmt q; db_prepare(&q, "SELECT uuid FROM phantom JOIN blob USING(rid)" " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" + " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)" ); while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ const char *zUuid = db_column_text(&q, 0); blob_appendf(pXfer->pOut, "gimme %s\n", zUuid); pXfer->nGimmeSent++; @@ -366,13 +382,19 @@ ** Signature generation on the client side is handled by the ** http_exchange() routine. */ void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){ Stmt q; - int rc; - - db_prepare(&q, "SELECT pw, cap, uid FROM user WHERE login=%B", pLogin); + int rc = -1; + + db_prepare(&q, + "SELECT pw, cap, uid FROM user" + " WHERE login=%B" + " AND login NOT IN ('anonymous','nobody','developer','reader')" + " AND length(pw)>0", + pLogin + ); if( db_step(&q)==SQLITE_ROW ){ Blob pw, combined, hash; blob_zero(&pw); db_ephemeral_blob(&q, 0, &pw); blob_zero(&combined); @@ -391,10 +413,15 @@ g.zLogin = mprintf("%b", pLogin); g.zNonce = mprintf("%b", pNonce); } } db_finalize(&q); + + if( rc==0 ){ + /* If the login was successful. */ + login_set_anon_nobody_capabilities(); + } } /* ** Send the content of all files in the unsent table. ** @@ -402,11 +429,11 @@ ** unsent table, all the right files will still get transferred. ** It just might require an extra round trip or two. */ static void send_unsent(Xfer *pXfer){ Stmt q; - db_prepare(&q, "SELECT rid FROM unsent"); + db_prepare(&q, "SELECT rid FROM unsent EXCEPT SELECT rid FROM private"); while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); send_file(pXfer, rid, 0, 0); } db_finalize(&q); @@ -421,10 +448,17 @@ */ static void create_cluster(void){ Blob cluster, cksum; Stmt q; int nUncl; + + /* We should not ever get any private artifacts in the unclustered table. + ** But if we do (because of a bug) now is a good time to delete them. */ + db_multi_exec( + "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)" + ); + nUncl = db_int(0, "SELECT count(*) FROM unclustered" " WHERE NOT EXISTS(SELECT 1 FROM phantom" " WHERE rid=unclustered.rid)"); if( nUncl<100 ){ return; @@ -456,10 +490,11 @@ Stmt q; int cnt = 0; db_prepare(&q, "SELECT uuid FROM unclustered JOIN blob USING(rid)" " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" + " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)" ); while( db_step(&q)==SQLITE_ROW ){ blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0)); cnt++; } @@ -473,10 +508,11 @@ static void send_all(Xfer *pXfer){ Stmt q; db_prepare(&q, "SELECT uuid FROM blob " " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" + " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)" ); while( db_step(&q)==SQLITE_ROW ){ blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0)); } db_finalize(&q); @@ -532,10 +568,13 @@ int isClone = 0; int nGimme = 0; int size; int recvConfig = 0; + if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ + fossil_redirect_home(); + } memset(&xfer, 0, sizeof(xfer)); blobarray_zero(xfer.aToken, count(xfer.aToken)); cgi_set_content_type(g.zContentType); blob_zero(&xfer.err); xfer.pIn = &g.cgiIn; @@ -545,10 +584,11 @@ db_begin_transaction(); db_multi_exec( "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" ); + manifest_crosslink_begin(); while( blob_line(xfer.pIn, &xfer.line) ){ if( blob_buffer(&xfer.line)[0]=='#' ) continue; xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); /* file UUID SIZE \n CONTENT @@ -796,10 +836,11 @@ send_unclustered(&xfer); } if( recvConfig ){ configure_finalize_receive(); } + manifest_crosslink_end(); db_end_transaction(0); } /* ** COMMAND: test-xfer @@ -863,16 +904,22 @@ int nFileSend = 0; int origConfigRcvMask; /* Original value of configRcvMask */ int nFileRecv; /* Number of files received */ int mxPhantomReq = 200; /* Max number of phantoms to request per comm */ const char *zCookie; /* Server cookie */ + int nSent, nRcvd; /* Bytes sent and received (after compression) */ Blob send; /* Text we are sending to the server */ Blob recv; /* Reply we got back from the server */ Xfer xfer; /* Transfer data */ const char *zSCode = db_get("server-code", "x"); const char *zPCode = db_get("project-code", 0); + if( db_get_boolean("dont-push", 0) ) pushFlag = 0; + if( pushFlag + pullFlag + cloneFlag == 0 + && configRcvMask==0 && configSendMask==0 ) return; + + transport_stats(0, 0, 1); socket_global_init(); memset(&xfer, 0, sizeof(xfer)); xfer.pIn = &recv; xfer.pOut = &send; xfer.mxSend = db_get_int("max-upload", 250000); @@ -905,10 +952,11 @@ } if( pushFlag ){ blob_appendf(&send, "push %s %s\n", zSCode, zPCode); nCard++; } + manifest_crosslink_begin(); printf(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas"); while( go ){ int newPhantom = 0; char *zRandomness; @@ -958,15 +1006,13 @@ } configSendMask = 0; } /* Append randomness to the end of the message */ -#if 1 /* Enable this after all servers have upgraded */ zRandomness = db_text(0, "SELECT hex(randomblob(20))"); blob_appendf(&send, "# %s\n", zRandomness); free(zRandomness); -#endif /* Exchange messages with the server */ nFileSend = xfer.nFileSent + xfer.nDeltaSent; printf(zValueFormat, "Send:", blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent, @@ -1037,11 +1083,13 @@ if( xfer.nToken==2 && blob_eq(&xfer.aToken[0], "igot") && blob_is_uuid(&xfer.aToken[1]) ){ int rid = rid_from_uuid(&xfer.aToken[1], 0); - if( rid==0 && (pullFlag || cloneFlag) ){ + if( rid>0 ){ + content_make_public(rid); + }else if( pullFlag || cloneFlag ){ rid = content_new(blob_str(&xfer.aToken[1])); if( rid ) newPhantom = 1; } remote_has(rid); }else @@ -1134,10 +1182,16 @@ blob_appendf(&xfer.err, "server says: %s", zMsg); }else /* Unknown message */ { + if( blob_str(&xfer.aToken[0])[0]=='<' ){ + fossil_fatal( + "server replies with HTML instead of fossil sync protocol:\n%b", + &recv + ); + } blob_appendf(&xfer.err, "unknown command: %b", &xfer.aToken[0]); } if( blob_size(&xfer.err) ){ fossil_fatal("%b", &xfer.err); @@ -1175,10 +1229,14 @@ */ if( xfer.nFileSent+xfer.nDeltaSent>0 ){ go = 1; } }; + transport_stats(&nSent, &nRcvd, 1); + printf("Total network traffic: %d bytes sent, %d bytes received\n", + nSent, nRcvd); transport_close(); socket_global_shutdown(); db_multi_exec("DROP TABLE onremote"); + manifest_crosslink_end(); db_end_transaction(0); }
Modified src/zip.c from [f641ace2a3] to [8c1776ca5d].
@@ -48,10 +48,13 @@ static Blob body; /* The body of the ZIP archive */ static Blob toc; /* The table of contents */ static int nEntry; /* Number of files */ static int dosTime; /* DOS-format time */ static int dosDate; /* DOS-format date */ +static int unixTime; /* Seconds since 1970 */ +static int nDir; /* Number of entries in azDir[] */ +static char **azDir; /* Directory names already added to the archive */ /* ** Initialize a new ZIP archive. */ void zip_open(void){ @@ -58,10 +61,11 @@ blob_zero(&body); blob_zero(&toc); nEntry = 0; dosTime = 0; dosDate = 0; + unixTime = 0; } /* ** Set the date and time values from an ISO8601 date string. */ @@ -84,10 +88,37 @@ */ void zip_set_timedate(double rDate){ char *zDate = db_text(0, "SELECT datetime(%.17g)", rDate); zip_set_timedate_from_str(zDate); free(zDate); + unixTime = (rDate - 2440587.5)*86400.0; +} + +/* +** If the given filename includes one or more directory entries, make +** sure the directories are already in the archive. If they are not +** in the archive, add them. +*/ +void zip_add_folders(char *zName){ + int i, c; + int j; + for(i=0; zName[i]; i++){ + if( zName[i]=='/' ){ + c = zName[i+1]; + zName[i+1] = 0; + for(j=0; j<nDir; j++){ + if( strcmp(zName, azDir[j])==0 ) break; + } + if( j>=nDir ){ + nDir++; + azDir = realloc(azDir, sizeof(azDir[0])*nDir); + azDir[j] = mprintf("%s", zName); + zip_add_file(zName, 0); + } + zName[i+1] = c; + } + } } /* ** Append a single file to a growing ZIP archive. ** @@ -98,110 +129,135 @@ z_stream stream; int nameLen; int skip; int toOut; int iStart; - int iCRC; - int nByte; - int nByteCompr; + int iCRC = 0; + int nByte = 0; + int nByteCompr = 0; + int nBlob; /* Size of the blob */ + int iMethod; /* Compression method. */ + int iMode = 0644; /* Access permissions */ char *z; char zHdr[30]; + char zExTime[13]; char zBuf[100]; char zOutBuf[100000]; /* Fill in as much of the header as we know. */ + nBlob = pFile ? blob_size(pFile) : 0; + if( nBlob>0 ){ + iMethod = 8; + iMode = 0100644; + }else{ + iMethod = 0; + iMode = 040755; + } nameLen = strlen(zName); + memset(zHdr, 0, sizeof(zHdr)); put32(&zHdr[0], 0x04034b50); - put16(&zHdr[4], 0x0014); + put16(&zHdr[4], 0x000a); put16(&zHdr[6], 0); - put16(&zHdr[8], 8); + put16(&zHdr[8], iMethod); put16(&zHdr[10], dosTime); put16(&zHdr[12], dosDate); put16(&zHdr[26], nameLen); - put16(&zHdr[28], 0); + put16(&zHdr[28], 13); + + put16(&zExTime[0], 0x5455); + put16(&zExTime[2], 9); + zExTime[4] = 3; + put32(&zExTime[5], unixTime); + put32(&zExTime[9], unixTime); + /* Write the header and filename. */ iStart = blob_size(&body); blob_append(&body, zHdr, 30); blob_append(&body, zName, nameLen); - - /* The first two bytes that come out of the deflate compressor are - ** some kind of header that ZIP does not use. So skip the first two - ** output bytes. - */ - skip = 2; - - /* Write the compressed file. Compute the CRC as we progress. - */ - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = 0; - stream.avail_in = blob_size(pFile); - stream.next_in = (unsigned char*)blob_buffer(pFile); - stream.avail_out = sizeof(zOutBuf); - stream.next_out = (unsigned char*)zOutBuf; - deflateInit(&stream, 9); - iCRC = crc32(0, stream.next_in, stream.avail_in); - while( stream.avail_in>0 ){ - deflate(&stream, 0); - toOut = sizeof(zOutBuf) - stream.avail_out; - if( toOut>skip ){ - blob_append(&body, &zOutBuf[skip], toOut - skip); - skip = 0; - }else{ - skip -= toOut; - } + blob_append(&body, zExTime, 13); + + if( nBlob>0 ){ + /* The first two bytes that come out of the deflate compressor are + ** some kind of header that ZIP does not use. So skip the first two + ** output bytes. + */ + skip = 2; + + /* Write the compressed file. Compute the CRC as we progress. + */ + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = 0; + stream.avail_in = blob_size(pFile); + stream.next_in = (unsigned char*)blob_buffer(pFile); stream.avail_out = sizeof(zOutBuf); stream.next_out = (unsigned char*)zOutBuf; - } - do{ - stream.avail_out = sizeof(zOutBuf); - stream.next_out = (unsigned char*)zOutBuf; - deflate(&stream, Z_FINISH); - toOut = sizeof(zOutBuf) - stream.avail_out; - if( toOut>skip ){ - blob_append(&body, &zOutBuf[skip], toOut - skip); - skip = 0; - }else{ - skip -= toOut; + deflateInit(&stream, 9); + iCRC = crc32(0, stream.next_in, stream.avail_in); + while( stream.avail_in>0 ){ + deflate(&stream, 0); + toOut = sizeof(zOutBuf) - stream.avail_out; + if( toOut>skip ){ + blob_append(&body, &zOutBuf[skip], toOut - skip); + skip = 0; + }else{ + skip -= toOut; + } + stream.avail_out = sizeof(zOutBuf); + stream.next_out = (unsigned char*)zOutBuf; } - }while( stream.avail_out==0 ); - nByte = stream.total_in; - nByteCompr = stream.total_out - 2; - deflateEnd(&stream); - - /* Go back and write the header, now that we know the compressed file size. - */ - z = &blob_buffer(&body)[iStart]; - put32(&z[14], iCRC); - put32(&z[18], nByteCompr); - put32(&z[22], nByte); + do{ + stream.avail_out = sizeof(zOutBuf); + stream.next_out = (unsigned char*)zOutBuf; + deflate(&stream, Z_FINISH); + toOut = sizeof(zOutBuf) - stream.avail_out; + if( toOut>skip ){ + blob_append(&body, &zOutBuf[skip], toOut - skip); + skip = 0; + }else{ + skip -= toOut; + } + }while( stream.avail_out==0 ); + nByte = stream.total_in; + nByteCompr = stream.total_out - 2; + deflateEnd(&stream); + + /* Go back and write the header, now that we know the compressed file size. + */ + z = &blob_buffer(&body)[iStart]; + put32(&z[14], iCRC); + put32(&z[18], nByteCompr); + put32(&z[22], nByte); + } /* Make an entry in the tables of contents */ memset(zBuf, 0, sizeof(zBuf)); put32(&zBuf[0], 0x02014b50); put16(&zBuf[4], 0x0317); - put16(&zBuf[6], 0x0014); + put16(&zBuf[6], 0x000a); put16(&zBuf[8], 0); - put16(&zBuf[10], 0x0008); + put16(&zBuf[10], iMethod); put16(&zBuf[12], dosTime); put16(&zBuf[14], dosDate); put32(&zBuf[16], iCRC); put32(&zBuf[20], nByteCompr); put32(&zBuf[24], nByte); put16(&zBuf[28], nameLen); - put16(&zBuf[30], 0); + put16(&zBuf[30], 9); put16(&zBuf[32], 0); - put16(&zBuf[34], 1); + put16(&zBuf[34], 0); put16(&zBuf[36], 0); - put32(&zBuf[38], ((unsigned)(0100000 | 0644))<<16); + put32(&zBuf[38], ((unsigned)iMode)<<16); put32(&zBuf[42], iStart); blob_append(&toc, zBuf, 46); blob_append(&toc, zName, nameLen); + put16(&zExTime[2], 5); + blob_append(&toc, zExTime, 9); nEntry++; } /* @@ -208,10 +264,11 @@ ** Write the ZIP archive into the given BLOB. */ void zip_close(Blob *pZip){ int iTocStart; int iTocEnd; + int i; char zBuf[30]; iTocStart = blob_size(&body); blob_append(&body, blob_buffer(&toc), blob_size(&toc)); iTocEnd = blob_size(&body); @@ -228,10 +285,16 @@ blob_append(&body, zBuf, 22); blob_reset(&toc); *pZip = body; blob_zero(&body); nEntry = 0; + for(i=0; i<nDir; i++){ + free(azDir[i]); + } + free(azDir); + nDir = 0; + azDir = 0; } /* ** COMMAND: test-filezip ** @@ -296,27 +359,33 @@ blob_appendf(&filename, "%s/", zDir); } nPrefix = blob_size(&filename); if( manifest_parse(&m, &mfile) ){ + char *zName; zip_set_timedate(m.rDate); blob_append(&filename, "manifest", -1); - zip_add_file(blob_str(&filename), &file); + zName = blob_str(&filename); + zip_add_folders(zName); + zip_add_file(zName, &file); sha1sum_blob(&file, &hash); blob_reset(&file); blob_append(&hash, "\n", 1); blob_resize(&filename, nPrefix); blob_append(&filename, "manifest.uuid", -1); - zip_add_file(blob_str(&filename), &hash); + zName = blob_str(&filename); + zip_add_file(zName, &hash); blob_reset(&hash); for(i=0; i<m.nFile; i++){ int fid = uuid_to_rid(m.aFile[i].zUuid, 0); if( fid ){ content_get(fid, &file); blob_resize(&filename, nPrefix); blob_append(&filename, m.aFile[i].zName, -1); - zip_add_file(blob_str(&filename), &file); + zName = blob_str(&filename); + zip_add_folders(zName); + zip_add_file(zName, &file); blob_reset(&file); } } manifest_clear(&m); }else{
Deleted todo-ak.txt version [25be5322be]
Deleted todo.txt version [5e00e8293a]
Deleted wiki_and_ticket_ideas.txt version [210e4ddb28]
Deleted win32.txt version [43b1765726]
Modified www/branching.wiki from [fb37090eee] to [73c9169a7e].
@@ -1,5 +1,6 @@ +<title>Fossil Documentation</title> <h1 align="center"> Branching, Forking, Merging, and Tagging </h1> In a simple and perfect world, the development of a project would proceed
Modified www/bugtheory.wiki from [d140a990b1] to [953206fd82].
@@ -1,5 +1,6 @@ +<title>Fossil Documentation</title> <h1>Bug-Tracking In <a href="index.wiki">Fossil</a></h1> A bug-report in fossil is called a "ticket". Tickets are tracked separately from code check-ins.
Modified www/build.wiki from [bd5f08e8f5] to [a81964674b].
@@ -1,7 +1,7 @@ -<nowiki> -<h1>Installing Fossil</h1> +<title>Building and Installing Fossil</title> +<nowiki> <p>This page describes how to build and install Fossil. The whole process is designed to be very easy.</p> <h2>0.0 Using A Pre-compiled Binary</h2> @@ -34,13 +34,27 @@ <li><p>Select a version of of fossil you want to download. Click on its link. Note that you must successfully log in as "anonymous" in step 1 above in order to see the link to the detailed version information.</p></li> -<li><p>On the version information page, click on the +<li><p>On the version information page, click on the "[details]" hyperlink +that appears right after the check-in comment at the top of the page.</p> + +<li><p>Finally, click on the "Zip Archive" link. This link will build a ZIP archive of the -complete source code and download it to your browser.</p></li> +complete source code and download it to your browser. + +<blockquote><i> +Note to Mac users: The ZIP archive constructed by Fossil is a well-formed +ZIP archive. However, the unarchiver that is built into the Mac has a bug +in that it does not understand all well-formed ZIP archives. So you may +get an error when the Mac goes to automatically extract the downloaded ZIP +archive. We are still trying to figure out what it is about Fossil-generated +ZIP archives that the Mac doesn't like. Until we do, +your work-around is to manually extract the ZIP archive using the +"unzip" command from a command-line shell. +</i></blockquote> </ol> <h2>2.0 Compiling</h2> <p>Follow these steps to compile:</p>
Modified www/concepts.wiki from [37b66fe58e] to [846a2562a2].
@@ -1,69 +1,66 @@ -<nowiki> -<h1 align="center"> -Fossil Concepts -</h1> +<title>Fossil Concepts</title> +<h1 align="center">Fossil Concepts</h1> <h2>1.0 Introduction</h2> -<p> -<a href="index.html">Fossil</a> is a -<a href="http://en.wikipedia.org/wiki/Software_configuration_management"> -software configuration management</a> system. + +[./index.wiki | Fossil] is a +[http://en.wikipedia.org/wiki/Software_configuration_management | software configuration management] system. Fossil is software that is designed to control and track the development of a software project and to record the history of the project. There are many such systems in use today. Fossil strives to distinguish itself from the others by being extremely simple -to setup and operate.</p> - -<p>This document is intended as a quick introduction to the concepts -behind fossil.</p> +to setup and operate. + +This document is intended as a quick introduction to the concepts +behind fossil. <h2>2.0 Composition Of A Project</h2> <img src="concept1.gif" align="right" hspace="10"> -<p>A software project normally consists of a "source tree". +A software project normally consists of a "source tree". A source tree is a hierarchy of files that are used to generate the end product. The source tree changes over time as the software grows and expands and as features are added and bugs are fixed. A snapshot of the source tree at any point in time is called a "version" or "revision" or a "baseline" of the product. -In fossil, we use the name "check-in".</p> - -<p>A "repository" is a database that contains copies of all historical +In fossil, we use the name "check-in". + +A "repository" is a database that contains copies of all historical check-ins for a project. Check-ins are normally stored in the repository in a highly space-efficient compressed format (delta encoding). But that is an implementation detail that you the user need not worry over. Think of the repository as a safe place where all your old check-ins are securely stored away and available for retrieval whenever you need -them.</p> - -<p>A repository in fossil is a single file on your disk. This file +them. + +A repository in fossil is a single file on your disk. This file might be rather large (dozens or hundreds of megabytes for a large or long running project) but it is nevertheless just a file. You can move it around, rename it, write it out to a memory stick, or -do anything else you normally do with files.</p> - -<p>Each source tree that is controlled by fossil is associated with +do anything else you normally do with files. + +Each source tree that is controlled by fossil is associated with a single repository on the local disk drive. You can tie two or more source trees to a single repository if you want (though one tree per repository is the most common configuration.) So a single repository can be associated with many source trees, but -each source tree is associated with only one repository.</p> - -<p>Fossil source trees may not overlap. A fossil source tree is identified +each source tree is associated with only one repository. + +Fossil source trees may not overlap. A fossil source tree is identified by a file named "_FOSSIL_" in the root directory of the source tree. Every file that is a sibling of _FOSSIL_ and every file in every subfolder is considered potentially a part of the source tree. The _FOSSIL_ file contains (among other things) the pathname of the repository with which the source tree is associated. On the other hand, the repository has no record of its source trees. So you are free to delete a source tree or move it around without consequence. But if you move or rename or delete a repository, then any source trees associated with that repository -will no longer be able to locate their repository and will stop working.</p> - -<p>When multiple developers are working on the same project, each +will no longer be able to locate their repository and will stop working. + +When multiple developers are working on the same project, each developer typically has his or her own local repository and an associated source tree in which to work. Developers share their work by "syncing" the content of their local repositories either directly or through a central server. Changes can "push" from the local repository into a remote repository. Or changes can "pull" from a @@ -70,71 +67,74 @@ remote repository into a local repository. Or one can do a "sync" which is a shortcut for doing both a push and a pull at the same time. Fossil also has the concept of "cloning". A "clone" is like a "pull", except that instead of beginning with an existing local repository, a clone begins with nothing and creates a new local repository that -is a duplicate of a remote repository.</p> - -<p>Communication between repositories is via HTTP. Remote +is a duplicate of a remote repository. + +Communication between repositories is via HTTP. Remote repositories are identified by URL. You can also point a web browser at a repository and get human-readable status, history, and tracking -information about the project.</p> +information about the project. <h3>2.1 Identification Of Artifacts</h3> -<p>A particular version of a particular file is called an "artifact". +A particular version of a particular file is called an "artifact". Each artifact has a universally unique name which is the <a href="http://en.wikipedia.org/wiki/SHA">SHA1</a> hash of the content of that file expressed as 40 characters of lower-case hexadecimal. Such a hash is referred to as the Artifact Identifier or Artifact ID for the artifact. The SHA1 algorithm is created with the purpose of providing a highly forgery-resistant identifier for a file. Given any file it is simple to find the artifact ID for that file. But given a artifact ID it is computationally intractable to generate a file that will -have that Artifact ID.</p> - - -<p>Artifact IDs look something like this:</p> +have that Artifact ID. + +Artifact IDs look something like this: <blockquote><b> 6089f0b563a9db0a6d90682fe47fd7161ff867c8<br> 59712614a1b3ccfd84078a37fa5b606e28434326<br> 19dbf73078be9779edd6a0156195e610f81c94f9<br> b4104959a67175f02d6b415480be22a239f1f077<br> 997c9d6ae03ad114b2b57f04e9eeef17dcb82788 </b></blockquote> -<p>When referring to an artifact using fossil, you can use a unique +When referring to an artifact using fossil, you can use a unique prefix of the artifact ID that is four characters or longer. This saves a lot of typing. When displaying artifact IDs, fossil will usually only show the first 10 digits since that is normally enough to uniquely -identify a file.</p> - -<p>Changing (or adding or removing) a single byte in a file results +identify a file. + +Changing (or adding or removing) a single byte in a file results in a completely different artifact ID. And since the artifact ID is the name of the artifact, making any change to a file results in a new artifact. -In this way, artifacts are immutable.</p> - -<p>A repository is really just an unordered collection of +In this way, artifacts are immutable. + +A repository is really just an unordered collection of artifacts. New artifacts can be added to the repository, but -existing artifacts can never be removed. Fossil is designed in +existing artifacts can never be removed. (Well, almost never. There +is a [./shunning.wiki | "shunning"] mechanism that allows spam or other +inappropriate content to be removed if absolutely necessary, but such +removal is discouraged.) +Fossil is designed in such a way that it can be handed a set of artifacts in any order and it can figure out the relationship between those artifacts and reconstruct the complete development history of -a software project.</p> +a software project. <h3>2.2 Manifests</h3> -<p>At the root of a source tree is a special file called the +At the root of a source tree is a special file called the "manifest". The manifest is a listing of all other files in that source tree. The manifest contains the (complete) artifact ID of the file and the name of the file as it appears on disk, and thus serves as a mapping from artifact ID to disk name. The artifact ID of the manifest is the identifier for the entire check-in. When you look at a "timeline" of changes in fossil, the ID associated with each check-in or commit is really just the artifact ID of the -manifest for that check-in.</p> +manifest for that check-in. <p>Fossil automatically generates a manifest whenever you "commit" a new check-in. So this is not something that you, the developer, need to worry with. The format of a manifest is intentionally designed to be simple to parse, so that if @@ -148,11 +148,12 @@ and links to other check-ins from which the current check-in is derived. There is also a couple of checksums used to verify the integrity of the check-in. And the whole manifest might be PGP clearsigned.</p> -<h3><a name="keyconc">2.3</a> Key concepts</h3> +<a name="keyconc"></a> +<h3>2.3 Key concepts</h3> <ul> <li>A <b>check-in</b> is a set of files arranged in a hierarchy.</li> <li>A <b>repository</b> keeps a record of historical check-ins.</li> @@ -166,17 +167,20 @@ <li>The artifact ID of the manifest is the identifier of the check-in.</li> </ul> <h2>3.0 Fossil - The Program</h2> -<p>Fossil is software. The implementation of fossil is in the form -of a single executable named "fossil". To install fossil on your system, +Fossil is software. The implementation of fossil is in the form +of a single executable named "fossil" (or "fossil.exe" on windows). +To install fossil on your system, all you have to do is obtain a copy of this one executable file (either -by downloading a pre-compiled version or compiling it yourself) and then -putting that file somewhere on your PATH.</p> - -<p>Fossil is completely self-contained. It is not necessary to +by downloading a +<a href="http://www.fossil-scm.org/download.html">pre-compiled version</a> +or [./build.wiki | compiling it yourself]) and then +putting that file somewhere on your PATH. + +Fossil is completely self-contained. It is not necessary to install any other software in order to use fossil. You do <u>not</u> need CVS, gzip, diff, rsync, Python, Perl, Tcl, Java, apache, PostgreSQL, MySQL, SQLite, patch, or any similar software on your system in order to use fossil effectively. You will want to have some kind of text editor for entering check-in comments. Fossil will use whatever text editor @@ -183,252 +187,267 @@ is identified by your VISUAL environment variable. Fossil will also use GPG to clearsign your manifests if you happen to have it installed, but fossil will skip that step if GPG missing from your system. You can optionally set up fossil to use external "diff" programs, though fossil has an excellent built-in "diff" algorithm that works -fine for most people.</p> - -<p>To uninstall fossil, simply delete the executable.</p> - -<p>To upgrade an older version of fossil to a newer version, just +fine for most people. + +To uninstall fossil, simply delete the executable. + +To upgrade an older version of fossil to a newer version, just replace the old executable with the new one. You might need to -run a one-time command to restructure your repositories after -an upgrade. Check the instructions that come with the upgrade -for details.</p> - -<p>To use fossil, simply type the name of the executable in your +run "<b>fossil all rebuild</b>" to restructure your repositories after +an upgrade. Running "all rebuild" never hurts, so when upgrading it +is a good policy to run it even if it is not strictly necessary. + +To use fossil, simply type the name of the executable in your shell, followed by one of the various built-in commands and -arguments appropriate for that command. For example:</p> +arguments appropriate for that command. For example: <blockquote><b> fossil help </b></blockquote> -<p>In the next section, when we say things like "use the <b>help</b> +In the next section, when we say things like "use the <b>help</b> command" we mean to use the command name "help" as the first -token after the name of the fossil executable, as shown above.</p> - +token after the name of the fossil executable, as shown above. + +<a name="workflow"></a> <h2>4.0 Workflow</h2> <img src="concept2.gif" align="right" hspace="10"> -<p>Fossil has two modes of operation: "autosync" and "non-autosync". -Autosync mode works something like CVS or SVN in that it automatically -keeps your work in sync with the central server. Non-autosync is -more like GIT or Bitkeeper in that your local repository develops -independently of your coworkers and you share your changes manually. +Fossil has two modes of operation: <i>"autosync"</i> and +<i>"manual-merge"</i> +Autosync mode is reminiscent of CVS or SVN in that it automatically +keeps your changes in synchronization with your co-workers through +the use of a central server. The manual-merge mode is the standard workflow +for GIT or Mercurial in that your local repository develops +independently of your coworkers and you share and merge your changes manually. An interesting feature of fossil is that it supports both autosync -and non-autosync work flows.</p> - -<p>The default setting for fossil is to be in autosync mode. You +and manual-merge work flows. + +The default setting for fossil is to be in autosync mode. You can change the autosync setting or check the current autosync -setting using commands like:</p> +setting using commands like: <blockquote> <b>fossil setting autosync on<br> fossil setting autosync off<br> <b>fossil settings</b> </blockquote> -<p>By default, fossil runs with autosync mode turned on. The -authors find that projects run more smoothly when autosync is only -disabled when off-network.</p> +By default, fossil runs with autosync mode turned on. The +authors finds that projects run more smoothly in autosync mode since +autosync helps to prevent pointless forking and merge and helps keeps +all collaborators working on exactly the same code rather than on their +own personal forks of the code. In the author's view, manual-merge mode +should be reserved for disconnected operation. <h3>4.1 Autosync Workflow</h3> <ol> -<li><p> +<li> Establish a local repository using either the <b>new</b> command to start a new project, or the <b>clone</b> command to make a clone of a repository for an existing project. -</p></li> - -<li><p> -Establish one or more source trees by changing your working directory -to where you want the root of the source tree to be, then issuing +</li> + +<li> +Establish one or more source trees using the <b>open</b> command with the name of the repository file as its argument. -</p></li> - -<li><p> +</li> + +<li> The <b>open</b> command in the previous step populates your local source tree with a copy of the latest check-in. Usually this is what you want. In the rare cases where it is not, use the <b>update</b> command to -switch to a new check-in. Use the <b>timeline</b> or <b>leaves</b> commands +switch to a different check-in. +Use the <b>timeline</b> or <b>leaves</b> commands to identify alternative check-ins to switch to. -</p></li> - -<li><p> +</li> + +<li> Edit the code. Add new files to the source tree using the <b>add</b> command. Omit files from future check-ins using the <b>rm</b> command. (Even when you remove files from future check-ins, those files continue to exist in historical check-ins.) Test your changes. -</p></li> - -<li><p> +</li> + +<li> Create a new check-in using the <b>commit</b> command. You will be prompted for a check-in comment and also for your GPG key if you have GPG installed. The commit copies the edits you have made in your local source tree into your local repository. After your commit completes, fossil will automatically <b>push</b> your changes back to the server you cloned from or whatever server you most recently synced with. -</p></li> - -<li><p> +</li> + +<li> When your coworkers make their own changes, you can merge those changes into your local local source tree using the <b>update</b> command. In autosync mode, <b>update</b> will first go back to the server you cloned from or with which you most recently synced, and pull down all recent changes into your local repository. Then it will merge recent changes into your local source tree. If you do an <b>update</b> and find that it messes something up in your source tree (perhaps a co-worker checked in incompatible changes) you can use the <b>undo</b> command to back out the changes. -</p></li> - -<li><p> +</li> + +<li> Repeat all of the above until you have generated great software. -</p></li> +</li> </ol> -<h3>4.2 Non-Autosync Workflow</h3> - -<p>When autosync is disabled, the <b>commit</b> command is decoupled from +<h3>4.2 Manual-Merge Workflow</h3> + +When autosync is disabled, the <b>commit</b> command is decoupled from <b>push</b> and the <b>update</b> command is decoupled from <b>pull</b>. That means you have to do a few extra steps in order to accomplish the -<b>push</b> and <b>pull</b> tasks manually.</p> +<b>push</b> and <b>pull</b> tasks manually. <ol> -<li><p> +<li> Establish a local repository using either the <b>new</b> command to start a new project, or the <b>clone</b> command to make a clone of a repository for an existing project. The default setting for a new repository is with autosync on, so you will need to turn it off using the <b>setting autosync off</b> command with a <b>-R</b> option to specify the repository. -</p></li> - -<li><p> +</li> + +<li> Establish one or more source trees by changing your working directory to where you want the root of the source tree to be, then issuing the <b>open</b> command with the name of the repository file as its argument. -</p></li> - -<li><p> +</li> + +<li> The <b>open</b> command in the previous step populates your local source tree with a copy of the latest check-in. Usually this is what you want. In the rare cases where it is not, use the <b>update</b> command to -switch to a new check-in. Use the <b>timeline</b> or <b>leaves</b> commands +switch to a different check-in. +Use the <b>timeline</b> or <b>leaves</b> commands to identify alternative check-ins to switch to. -</p></li> - -<li><p> +</li> + +<li> Edit the code. Add new files to the source tree using the <b>add</b> command. Omit files from future check-ins using the <b>rm</b> command. (Even when you remove files from future check-ins, those files continue to exist in historical check-ins.) Test your changes. -</p></li> - -<li><p> +</li> + +<li> Create a new check-in using the <b>commit</b> command. You will be prompted for a check-in comment and also for your GPG key if you have GPG installed. The commit copies the edits you have made in your local source tree into your local repository. -</p></li> - -<li><p>Use the <b>push</b> command to push your changes out to a server +</li> + +<li> +Use the <b>push</b> command to push your changes out to a server where your co-workers can access them. -</p></li> - -<li><p> +</li> + +<li> When co-workers make their own changes, use the <b>pull</b> command to pull those changes into your local repository. Note that <b>pull</b> does not move the changes into your local source tree, only into your local repository. -</p></li> - -<li><p> +</li> + +<li> Once changes are in your local repository, use use the <b>update</b> command to merge them to your local source tree. If you merge in some changes and find that the changes do not work out or are not to your liking, you can back out the changes using the <b>undo</b> command. -</p></li> - -<li><p> +</li> + +<li> +If two or more people ran "commit" against the same check-in, this will +result in a [./branching.wiki | fork] which you may want to resolve by +running <b>merge</b> followed by another <b>commit</b>. +</li> + +<li> Repeat all of the above until you have generated great software. -</p></li> +</li> </ol> <h2>5.0 Setting Up A Fossil Server</h2> -<p>With other configuration management software, setting up a server is +With other configuration management software, setting up a server is a lot of work and normally takes time, patience, and a lot of system knowledge. Fossil is designed to avoid this frustration. Setting up a server with fossil is ridiculously easy. You have three options:</p> <ol> -<li><p><b><a name="saserv">S</a>etting up a stand-alone server</b></p> - -<p>From within your source tree just use the <b>server</b> command and +<li><b><a name="saserv"></a>Setting up a stand-alone server</b> + +From within your source tree just use the <b>server</b> command and fossil will start listening for incoming requests on TCP port 8080. You can point your web browser at <a href="http://localhost:8080/"> http://localhost:8080/</a> and begin exploring. Or your coworkers can do pushes or pulls against your server. Use the <b>--port</b> option to the server command to specify a different TCP port. If you do not have a local source tree, use the <b>-R</b> command-line -option to specify the repository file.</p> +option to specify the repository file. -<p>A stand-alone server is a great way to set of transient connections +A stand-alone server is a great way to set of transient connections between coworkers for doing quick pushes or pulls. But you can also set up a permanent stand-alone server if you prefer. Just make arrangements for fossil to be launched with appropriate arguments -after every reboot.</p> +after every reboot. -<p>If you just want a server to browse the built-in fossil website +If you just want a server to browse the built-in fossil website locally, use the <b>ui</b> command in place of <b>server</b>. The <b>ui</b> command starts up a local server too, but it also takes the additional step of automatically launching your webbrowser and -pointing at the new server.</p> +pointing at the new server. </li> -<li><p><b>Setting up a CGI server</b></p> +<li><b>Setting up a CGI server</b> -<p>If you have a webserver running on your machine already, you can +If you have a web-server running on your machine already, you can set up fossil to be run from CGI. Simply create an executable script -that looks something like this:</p> +that looks something like this: <blockquote><pre> #!/usr/local/bin/fossil repository: /home/me/bigproject.fossil </pre></blockquote> -<p>Edit this script to use whatever pathnames are appropriate for +Edit this script to use whatever pathnames are appropriate for your project. Then point your web browser at the script and off you -go.</p></li> +go. The [./selfhost.wiki | self-hosting fossil repositories] are +all set up this way.</li> -<li><p><b>Setting up an inetd server</b></p> +<li><b>Setting up an inetd server</b> -<p>If you have inetd or xinetd running on your system, you can set +If you have inetd or xinetd running on your system, you can set those services up to launch fossil to deal with inbound TCP/IP connections on whatever port you want. Set up inetd or xinetd to launch fossil -like this:</p> +like this: <blockquote><pre> /usr/local/bin/fossil http /home/me/bigproject.fossil </pre></blockquote> -<p>As before, change the filenames to whatever is appropriate for +As before, change the filenames to whatever is appropriate for your system. You can have fossil run as any user that has write permission on the repository and on the directory that contains the repository. But it is safer to run fossil as root. When fossil sees that it is running as root, it automatically puts itself into a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> and drops all privileges prior to reading any information from the client. Since fossil is a stand-alone program, you do not need to put anything -in the chroot jail with fossil in order for it to do its job.</p> +in the chroot jail with fossil in order for it to do its job. </li> </ol> <h2>6.0 Review Of Key Concepts</h2>
Modified www/embeddeddoc.wiki from [43544f7566] to [989355d07b].
@@ -1,5 +1,6 @@ +<title>Managing Project Documentation</title> <h1 align="center">Managing Project Documentation</h1> Fossil provides a built-in <a href="wikitheory.wiki">wiki</a> that can be used to store the documentation for a project. This is sufficient for many projects. @@ -47,12 +48,12 @@ the check-in containing the documentation you want to access. Or <i><version></i> can be the name of a [./branching.wiki | branch] in order to show the documentation for the latest version of that branch. Or <i><version></i> can be one of the keywords "<b>tip</b>" or -"<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recently -checked-in. This is useful if you want to see the very latest +"<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent +check-in. This is useful if you want to see the very latest version of the documentation. The "<b>ckout</b>" keywords means to pull the documentation file from the local source tree on disk, not from the any check-in. The "<b>ckout</b>" keyword normally only works when you start your server using the "<b>fossil server</b>" or "<b>fossil ui</b>" @@ -68,11 +69,11 @@ different file suffixes, including all the popular ones such as ".css", ".gif", ".htm", ".html", ".jpg", ".jpeg", ".png", and ".txt". Documentation files whose names end in ".wiki" use the [/wiki_rules | same markup as wiki pages] - -a safe subset of HTML together with some rules for paragraph +a safe subset of HTML together with some wiki rules for paragraph breaks, lists, and hyperlinks. The ".wiki" and ".txt" pages are rendered with the standard fossil header and footer added. All other mimetypes are delivered directly to the requesting web browser without interpretation, additions, or changes.
Modified www/faq.tcl from [b788977002] to [032c2fe5ed].
@@ -66,23 +66,61 @@ faq { How do I create a private branch that won't get pushed back to the main repository. } { - You cannot. All branches in fossil are public in the sense that - are all pushed and pulled together. There is no way to tell fossil - to only push or pull a subset of branches. + Use the <b>--private</b> command-line option on the + <b>commit</b> command. The result will be a check-in which exists on + your local repository only and is never pushed to other repositories. + All descendents of a private check-in are also private. + + Unless you specify something different using the <b>--branch</b> and/or + <b>--bgcolor</b> options, the new private check-in will be put on a branch + named "private" with an orange background color. + + You can merge from the trunk into your private branch in order to keep + your private branch in sync with the latest changes on the trunk. Once + you have everything in your private branch the way you want it, you can + then merge your private branch back into the trunk and push. Only the + final merge operation will appear in other repositories. It will seem + as if all the changes that occurred on your private branch occurred in + a single check-in. + Of course, you can also keep your branch private forever simply + by not merging the changes in the private branch back into the trunk. +} - Of course, as long as you never push, you can make as many private - changes as you want. +faq { + How can I delete inappropriate content from my fossil repository? +} { + See the article on [./shunning.wiki | "shunning"] for details. } - +faq { + How do I make a clone of the fossil self-hosting repository? +} { + Any of the following commands should work: + <blockquote><pre> + fossil clone http://www.fossil-scm.org/ fossil.fossil<br> + fossil clone http://www2.fossil-scm.org/ fossil.fossil<br> + fossil clone http://www.hwaci.com/cgi-bin/fossil fossil.fossil + </pre></blockquote> + Once you have the repository cloned, you can open a local check-out + as follows: + <blockquote><pre> + mkdir src; cd src; fossil open ../fossil.fossil + </pre></blockquote> + Thereafter you should be able to keep your local check-out up to date + with the latest code in the public repository by typing: + <blockquote><pre> + fossil update + </pre></blockquote> +} ############################################################################# # Code to actually generate the FAQ # +puts "<title>Fossil FAQ</title>" puts "<h1 align=\"center\">Frequently Asked Questions</h1>\n" puts "<p>Note: See also <a href=\"qandc.wiki\">Questions and Criticisms</a>.\n" puts {<ol>} for {set i 1} {$i<$cnt} {incr i} {
Modified www/faq.wiki from [4f2f594a41] to [26afb3550c].
@@ -1,5 +1,6 @@ +<title>Fossil FAQ</title> <h1 align="center">Frequently Asked Questions</h1> <p>Note: See also <a href="qandc.wiki">Questions and Criticisms</a>. <ol> @@ -6,10 +7,12 @@ <li><a href="#q1">What GUIs are available for fossil?</a></li> <li><a href="#q2">What is the difference between a "branch" and a "fork"?</a></li> <li><a href="#q3">How do I create a new branch in fossil?</a></li> <li><a href="#q4">How do I create a private branch that won't get pushed back to the main repository.</a></li> +<li><a href="#q5">How can I delete inappropriate content from my fossil repository?</a></li> +<li><a href="#q6">How do I make a clone of the fossil self-hosting repository?</a></li> </ol> <hr> <a name="q1"></a> <p><b>(1) What GUIs are available for fossil?</b></p> @@ -64,13 +67,50 @@ <a name="q4"></a> <p><b>(4) How do I create a private branch that won't get pushed back to the main repository.</b></p> -<blockquote>You cannot. All branches in fossil are public in the sense that -are all pushed and pulled together. There is no way to tell fossil -to only push or pull a subset of branches. +<blockquote>Use the <b>--private</b> command-line option on the +<b>commit</b> command. The result will be a check-in which exists on +your local repository only and is never pushed to other repositories. +All descendents of a private check-in are also private. + +Unless you specify something different using the <b>--branch</b> and/or +<b>--bgcolor</b> options, the new private check-in will be put on a branch +named "private" with an orange background color. + +You can merge from the trunk into your private branch in order to keep +your private branch in sync with the latest changes on the trunk. Once +you have everything in your private branch the way you want it, you can +then merge your private branch back into the trunk and push. Only the +final merge operation will appear in other repositories. It will seem +as if all the changes that occurred on your private branch occurred in +a single check-in. +Of course, you can also keep your branch private forever simply +by not merging the changes in the private branch back into the trunk.</blockquote></li> + +<a name="q5"></a> +<p><b>(5) How can I delete inappropriate content from my fossil repository?</b></p> + +<blockquote>See the article on [./shunning.wiki | "shunning"] for details.</blockquote></li> + +<a name="q6"></a> +<p><b>(6) How do I make a clone of the fossil self-hosting repository?</b></p> -Of course, as long as you never push, you can make as many private -changes as you want.</blockquote></li> +<blockquote>Any of the following commands should work: +<blockquote><pre> +fossil clone http://www.fossil-scm.org/ fossil.fossil<br> +fossil clone http://www2.fossil-scm.org/ fossil.fossil<br> +fossil clone http://www.hwaci.com/cgi-bin/fossil fossil.fossil +</pre></blockquote> +Once you have the repository cloned, you can open a local check-out +as follows: +<blockquote><pre> +mkdir src; cd src; fossil open ../fossil.fossil +</pre></blockquote> +Thereafter you should be able to keep your local check-out up to date +with the latest code in the public repository by typing: +<blockquote><pre> +fossil update +</pre></blockquote></blockquote></li> </ol>
Modified www/fileformat.wiki from [9924363ba6] to [ab44da6d91].
@@ -156,17 +156,10 @@ always readable and writable. This can be expressed by "w" permission if desired but is optional. The optional 4th argument is the name of the same file as it existed in the parent check-in. If the name of the file is unchanged from its parent, then the 4th argument is omitted. -</p> - -<p> -A manifest has zero or more N-cards. Each N card records a name changes -to one of the files in the manifest. The first argument to the N code is -the name of the file in the parent check-in. The second argument is the -name of the file in the check-in defined by the manifest. </p> <p> A manifest has zero or one P-cards. Most manifests have one P-card. The P-card has a varying number of arguments that
Added www/fossil.eps version [672ae62970]
@@ -1,1 +1,129 @@ - +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 249 284 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginProlog +%%BeginResource: procset SDRes-Prolog 1.0 0 +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02835 0.02837 s +0 -10008 t +/tm matrix currentmatrix def +tm setmatrix +-4875 -2599 t +1 1 s +0.500 c 7207 8311 m 7036 8281 6990 7727 7105 7073 ct 7221 6420 7453 5915 7625 5945 ct +7796 5975 7842 6529 7727 7183 ct 7612 7836 7379 8342 7207 8311 ct p ef +7607 10301 m 7445 10335 7221 9926 7107 9387 ct 6992 8847 7030 8382 7192 8348 ct +7354 8313 7578 8723 7693 9262 ct 7807 9802 7769 10267 7607 10301 ct p ef +8749 11736 m 8626 11826 8289 11574 7995 11173 ct 7701 10773 7563 10375 7686 10285 ct +7809 10195 8146 10446 8440 10847 ct 8734 11248 8872 11645 8749 11736 ct p ef +10691 12070 m 10668 12234 10205 12303 9658 12223 ct 9111 12143 8686 11946 8710 11782 ct +8734 11618 9197 11550 9744 11629 ct 10291 11709 10715 11906 10691 12070 ct p ef +10761 12053 m 10721 11951 11064 11722 11526 11541 ct 11989 11360 12396 11296 12436 11398 ct +12476 11500 12134 11729 11671 11910 ct 11208 12091 10801 12155 10761 12053 ct +p ef +12410 11353 m 12365 11314 12499 11087 12709 10847 ct 12920 10607 13126 10444 13171 10483 ct +13216 10522 13082 10749 12872 10989 ct 12662 11230 12455 11392 12410 11353 ct +p ef +7901 12525 m 7790 12525 7700 12212 7700 11826 ct 7700 11440 7790 11127 7901 11127 ct +8012 11127 8102 11440 8102 11826 ct 8102 12212 8012 12525 7901 12525 ct p ef +7826 12575 m 7765 12668 7415 12547 7044 12306 ct 6672 12064 6420 11793 6480 11700 ct +6541 11607 6891 11728 7262 11970 ct 7634 12211 7886 12482 7826 12575 ct p ef +6460 11694 m 6435 11723 6333 11673 6234 11584 ct 6134 11494 6073 11399 6099 11371 ct +6124 11343 6225 11392 6325 11482 ct 6425 11571 6485 11666 6460 11694 ct p ef +13183 10437 m 13129 10414 13185 10157 13309 9863 ct 13433 9569 13579 9350 13633 9373 ct +13688 9396 13632 9653 13508 9947 ct 13384 10241 13238 10460 13183 10437 ct p ef +9900 11524 m 9790 11524 9701 11211 9701 10825 ct 9701 10439 9790 10126 9900 10126 ct +10009 10126 10098 10439 10098 10825 ct 10098 11211 10009 11524 9900 11524 ct +p ef +9828 11574 m 9767 11667 9417 11546 9046 11305 ct 8674 11063 8422 10792 8482 10699 ct +8543 10606 8893 10727 9264 10969 ct 9636 11210 9888 11481 9828 11574 ct p ef +6085 9230 m 5976 9131 6097 8819 6357 8533 ct 6616 8247 6915 8095 7024 8194 ct +7133 8293 7012 8605 6752 8892 ct 6493 9178 6194 9329 6085 9230 ct p ef +5910 9182 m 5805 9210 5629 8884 5516 8456 ct 5403 8027 5396 7657 5501 7629 ct +5605 7601 5782 7927 5895 8356 ct 6008 8784 6014 9154 5910 9182 ct p ef +8630 9345 m 8548 9270 8691 8978 8951 8692 ct 9210 8406 9487 8234 9569 8309 ct +9651 8383 9507 8675 9248 8961 ct 8989 9247 8712 9419 8630 9345 ct p ef +8566 9556 m 8478 9624 8188 9394 7918 9043 ct 7647 8692 7499 8352 7587 8285 ct +7675 8217 7965 8447 8235 8798 ct 8506 9149 8654 9489 8566 9556 ct p ef +6579 11626 m 6549 11638 6480 11543 6425 11413 ct 6371 11283 6352 11167 6382 11154 ct +6412 11141 6481 11237 6535 11367 ct 6590 11497 6609 11613 6579 11626 ct p ef +5952 11674 m 5959 11642 6081 11642 6223 11674 ct 6366 11707 6475 11759 6468 11791 ct +6461 11823 6339 11823 6197 11790 ct 6054 11758 5945 11706 5952 11674 ct p ef +5384 7615 m 5359 7644 5257 7594 5158 7505 ct 5058 7415 4997 7320 5023 7292 ct +5048 7264 5149 7313 5249 7403 ct 5349 7492 5409 7587 5384 7615 ct p ef +5503 7547 m 5473 7559 5404 7464 5349 7334 ct 5295 7204 5276 7088 5306 7075 ct +5336 7062 5405 7158 5459 7288 ct 5514 7418 5533 7534 5503 7547 ct p ef +4875 7595 m 4882 7562 5004 7563 5147 7595 ct 5289 7628 5399 7680 5392 7712 ct +5385 7744 5263 7744 5120 7711 ct 4977 7679 4868 7627 4875 7595 ct p ef +9764 8248 m 9739 8220 9798 8125 9898 8036 ct 9997 7946 10097 7897 10123 7925 ct +10148 7952 10088 8047 9989 8137 ct 9890 8226 9789 8276 9764 8248 ct p ef +9641 8179 m 9611 8167 9631 8051 9685 7920 ct 9740 7790 9809 7694 9839 7707 ct +9869 7720 9850 7836 9795 7966 ct 9741 8097 9672 8192 9641 8179 ct p ef +10269 8227 m 10276 8259 10167 8311 10024 8343 ct 9882 8375 9760 8375 9753 8343 ct +9746 8311 9856 8259 9998 8227 ct 10141 8195 10262 8195 10269 8227 ct p ef +9749 10085 m 9724 10113 9623 10064 9523 9974 ct 9424 9885 9363 9790 9389 9762 ct +9414 9734 9515 9783 9615 9872 ct 9714 9961 9775 10057 9749 10085 ct p ef +9868 10017 m 9838 10029 9770 9934 9715 9804 ct 9661 9674 9641 9558 9671 9545 ct +9702 9533 9770 9628 9824 9758 ct 9879 9888 9898 10004 9868 10017 ct p ef +9242 10064 m 9249 10032 9371 10032 9513 10064 ct 9656 10097 9765 10149 9758 10181 ct +9751 10213 9629 10213 9487 10180 ct 9344 10148 9235 10096 9242 10064 ct p ef +6841 4401 m 6726 4212 7272 3670 8061 3191 ct 8849 2711 9581 2475 9696 2664 ct +9811 2853 9265 3395 8477 3875 ct 7688 4355 6956 4590 6841 4401 ct p ef +9097 6042 m 8862 6353 8161 6221 7532 5745 ct 6902 5270 6583 4632 6818 4321 ct +7053 4009 7754 4142 8384 4617 ct 9013 5092 9333 5730 9097 6042 ct p ef +7880 5222 m 7747 5124 7957 4611 8349 4075 ct 8742 3540 9168 3185 9302 3283 ct +9435 3381 9225 3894 8833 4430 ct 8440 4965 8014 5320 7880 5222 ct p ef +9003 6100 m 8784 6059 8750 5255 8927 4303 ct 9103 3351 9423 2612 9642 2652 ct +9861 2693 9895 3498 9719 4450 ct 9543 5401 9222 6140 9003 6100 ct p ef +0 10008 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF
Added www/fossil.gif version [590c4da59e]
cannot compute difference between binary files
Added www/fossil2.eps version [d8e0aba6ac]
@@ -1,1 +1,215 @@ - +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 555 735 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02833 0.02833 s +0 -25940 t +/tm matrix currentmatrix def +gs +tm setmatrix +-1000 -1000 t +1 1 s +1000 1000 m 20589 1000 l 20589 26939 l 1000 26939 l 1000 1000 l eoclip newpath +gs +1000 1000 m 20589 1000 l 20589 26939 l 1000 26939 l 1000 1000 l eoclip newpath +1000 1000 m 20590 1000 l 20590 26940 l 1000 26940 l 1000 1000 l eoclip newpath +0.500 c 7207 8311 m 7036 8281 6989 7726 7104 7073 ct 7220 6420 7453 5913 7624 5944 ct +7796 5974 7842 6529 7727 7182 ct 7612 7835 7378 8341 7207 8311 ct p ef +7607 10301 m 7446 10335 7220 9925 7106 9386 ct 6991 8847 7030 8381 7191 8347 ct +7353 8312 7578 8723 7693 9262 ct 7807 9800 7768 10267 7607 10301 ct p ef +8749 11736 m 8627 11825 8288 11574 7995 11173 ct 7701 10772 7562 10374 7685 10284 ct +7808 10194 8146 10446 8440 10847 ct 8734 11247 8872 11646 8749 11736 ct p ef +10683 12127 m 10664 12260 10204 12303 9657 12224 ct 9111 12145 8683 11972 8702 11840 ct +8721 11707 9181 11664 9727 11743 ct 10274 11822 10702 11995 10683 12127 ct p ef +10761 12053 m 10721 11951 11064 11721 11526 11540 ct 11989 11359 12397 11296 12437 11397 ct +12477 11499 12134 11729 11671 11910 ct 11209 12091 10801 12154 10761 12053 ct +p ef +12410 11353 m 12366 11314 12500 11087 12710 10847 ct 12920 10607 13127 10444 13171 10483 ct +13216 10522 13082 10749 12872 10989 ct 12662 11229 12455 11392 12410 11353 ct +p ef +7901 12525 m 7790 12525 7700 12212 7700 11826 ct 7700 11440 7790 11127 7901 11127 ct +8012 11127 8102 11440 8102 11826 ct 8102 12212 8012 12525 7901 12525 ct p ef +7825 12576 m 7765 12669 7414 12548 7043 12306 ct 6671 12065 6419 11793 6479 11700 ct +6540 11607 6891 11728 7262 11969 ct 7633 12211 7886 12483 7825 12576 ct p ef +6460 11695 m 6434 11723 6333 11674 6233 11584 ct 6133 11495 6072 11399 6098 11371 ct +6123 11342 6225 11392 6325 11481 ct 6425 11571 6485 11666 6460 11695 ct p ef +13184 10437 m 13129 10414 13185 10156 13309 9862 ct 13434 9569 13580 9349 13634 9372 ct +13688 9395 13632 9653 13508 9947 ct 13384 10240 13238 10460 13184 10437 ct p ef +9899 11524 m 9790 11524 9700 11211 9700 10825 ct 9700 10439 9790 10126 9899 10126 ct +10008 10126 10098 10439 10098 10825 ct 10098 11211 10008 11524 9899 11524 ct +p ef +9827 11575 m 9767 11668 9416 11547 9045 11305 ct 8673 11064 8421 10792 8481 10699 ct +8542 10606 8893 10727 9264 10968 ct 9635 11210 9888 11482 9827 11575 ct p ef +6085 9230 m 5976 9132 6098 8819 6357 8533 ct 6616 8247 6915 8096 7024 8194 ct +7133 8293 7012 8605 6753 8892 ct 6493 9178 6194 9329 6085 9230 ct p ef +5910 9183 m 5806 9210 5629 8885 5516 8456 ct 5403 8028 5396 7658 5501 7630 ct +5605 7602 5782 7928 5895 8357 ct 6008 8785 6014 9155 5910 9183 ct p ef +8630 9344 m 8547 9270 8691 8977 8950 8691 ct 9209 8405 9486 8234 9568 8308 ct +9650 8383 9507 8675 9248 8961 ct 8989 9247 8712 9419 8630 9344 ct p ef +8566 9557 m 8478 9625 8187 9395 7917 9044 ct 7646 8693 7498 8353 7586 8285 ct +7674 8217 7965 8448 8235 8799 ct 8505 9150 8654 9490 8566 9557 ct p ef +6578 11626 m 6548 11638 6479 11543 6424 11413 ct 6370 11283 6351 11166 6381 11153 ct +6412 11141 6481 11236 6535 11366 ct 6589 11496 6609 11613 6578 11626 ct p ef +5952 11673 m 5959 11641 6081 11641 6224 11674 ct 6366 11706 6476 11759 6469 11791 ct +6462 11823 6340 11823 6197 11791 ct 6055 11758 5945 11706 5952 11673 ct p ef +5384 7616 m 5358 7644 5257 7595 5157 7505 ct 5057 7416 4996 7320 5022 7292 ct +5047 7263 5149 7313 5249 7402 ct 5349 7492 5409 7587 5384 7616 ct p ef +5502 7547 m 5472 7559 5403 7464 5348 7334 ct 5294 7204 5275 7087 5305 7074 ct +5336 7062 5405 7157 5459 7287 ct 5513 7417 5533 7534 5502 7547 ct p ef +4875 7594 m 4882 7562 5004 7562 5147 7594 ct 5289 7627 5399 7679 5392 7712 ct +5385 7744 5263 7744 5120 7711 ct 4978 7679 4868 7626 4875 7594 ct p ef +9763 8248 m 9738 8220 9798 8124 9897 8035 ct 9996 7946 10097 7896 10122 7924 ct +10147 7951 10087 8047 9988 8136 ct 9889 8225 9787 8275 9763 8248 ct p ef +9639 8179 m 9608 8166 9628 8050 9682 7920 ct 9737 7790 9806 7694 9836 7707 ct +9867 7719 9847 7836 9793 7966 ct 9739 8096 9669 8192 9639 8179 ct p ef +10269 8228 m 10277 8260 10166 8312 10024 8344 ct 9881 8376 9759 8376 9752 8344 ct +9745 8311 9855 8259 9998 8227 ct 10140 8195 10262 8196 10269 8228 ct p ef +9749 10085 m 9724 10113 9622 10064 9523 9975 ct 9424 9886 9363 9791 9388 9762 ct +9414 9734 9516 9784 9615 9872 ct 9714 9961 9774 10057 9749 10085 ct p ef +9868 10017 m 9839 10029 9770 9933 9715 9803 ct 9661 9673 9642 9557 9671 9544 ct +9701 9532 9770 9628 9824 9758 ct 9879 9888 9898 10004 9868 10017 ct p ef +9242 10063 m 9249 10031 9371 10031 9514 10064 ct 9656 10096 9766 10149 9759 10181 ct +9752 10213 9630 10213 9487 10181 ct 9345 10148 9235 10096 9242 10063 ct p ef +6841 4401 m 6726 4212 7272 3669 8060 3190 ct 8848 2710 9581 2475 9696 2664 ct +9811 2853 9265 3396 8477 3875 ct 7689 4354 6956 4590 6841 4401 ct p ef +9098 6041 m 8863 6352 8161 6220 7532 5745 ct 6903 5271 6583 4632 6818 4321 ct +7053 4009 7755 4142 8384 4617 ct 9013 5091 9333 5730 9098 6041 ct p ef +7879 5222 m 7746 5124 7956 4610 8348 4075 ct 8740 3540 9167 3185 9300 3283 ct +9433 3380 9224 3895 8832 4430 ct 8440 4964 8012 5319 7879 5222 ct p ef +9004 6100 m 8786 6059 8751 5255 8927 4303 ct 9103 3351 9424 2612 9642 2652 ct +9861 2693 9896 3498 9719 4449 ct 9543 5401 9222 6140 9004 6100 ct p ef +106 lw 1 lj 9435 13668 m 9429 13652 l 9421 13637 l 9412 13622 l 9401 13607 l +9390 13593 l 9377 13579 l 9363 13565 l 9347 13552 l 9331 13539 l 9313 13526 l +9295 13515 l 9275 13503 l 9254 13493 l 9233 13482 l 9211 13473 l 9188 13464 l +9164 13456 l 9139 13448 l 9114 13441 l 9088 13435 l 9062 13430 l 9035 13425 l +9008 13422 l 8981 13419 l 8953 13416 l 8925 13415 l 8898 13414 l 8870 13414 l +8842 13415 l 8814 13417 l 8787 13419 l 8759 13422 l 8732 13426 l 8706 13431 l +8680 13437 l 8654 13443 l 8629 13450 l 8605 13458 l 8581 13466 l 8558 13475 l +8536 13485 l 8514 13495 l 8494 13506 l 8475 13517 l 8456 13529 l 8439 13542 l +8423 13555 l 8408 13568 l 8394 13582 l 8381 13596 l 8370 13611 l 8360 13626 l +8351 13641 l 8344 13656 l 8338 13672 l 8333 13687 l 8330 13703 l 8328 13719 l +8327 13735 l 8328 13751 l 8330 13767 l 8334 13783 l 8338 13798 l 8345 13814 l +8352 13829 l 8361 13844 l 8372 13859 l 8383 13874 l 8396 13888 l 8410 13902 l +8425 13915 l 8441 13928 l 8459 13940 l 8477 13952 l 8497 13964 l 8517 13974 l +8539 13985 l 8561 13994 l 8584 14003 l 8608 14011 l 8632 14019 l 8657 14026 l +8683 14032 l 8709 14037 l 8736 14042 l 8763 14046 l 8790 14049 l 8818 14052 l +8846 14053 l 8873 14054 l 8901 14054 l 8929 14053 l 8957 14051 l ps +8347 14443 m 8354 14459 l 8362 14474 l 8371 14489 l 8382 14504 l 8394 14518 l +8407 14533 l 8421 14546 l 8436 14560 l 8453 14573 l 8471 14585 l 8490 14597 l +8510 14608 l 8530 14619 l 8552 14629 l 8575 14639 l 8598 14647 l 8622 14656 l +8647 14663 l 8673 14670 l 8699 14676 l 8725 14681 l 8752 14685 l 8779 14689 l +8807 14692 l 8835 14694 l 8863 14695 l 8891 14696 l 8919 14696 l 8947 14695 l +8975 14693 l 9002 14690 l 9030 14687 l 9057 14682 l 9083 14677 l 9109 14672 l +9135 14665 l 9160 14658 l 9184 14650 l 9208 14641 l 9231 14632 l 9253 14622 l +9274 14612 l 9294 14600 l 9313 14589 l 9332 14576 l 9349 14564 l 9364 14550 l +9379 14537 l 9393 14523 l 9405 14508 l 9416 14494 l 9425 14479 l 9434 14463 l +9441 14448 l 9446 14432 l 9451 14416 l 9453 14400 l 9455 14384 l 9455 14368 l +9453 14352 l 9451 14336 l 9446 14320 l 9441 14305 l 9434 14289 l 9426 14274 l +9416 14259 l 9405 14244 l 9393 14230 l 9380 14216 l 9365 14202 l 9349 14189 l +9332 14176 l 9314 14164 l 9295 14152 l 9275 14141 l 9254 14130 l 9232 14120 l +9209 14111 l 9185 14102 l 9161 14094 l 9136 14087 l 9110 14081 l 9084 14075 l +9057 14070 l 9030 14066 l 9003 14062 l 8975 14059 l 8948 14057 l ps +10974 13668 m 10968 13652 l 10960 13637 l 10951 13622 l 10940 13607 l +10929 13593 l 10916 13579 l 10902 13565 l 10886 13552 l 10870 13539 l +10853 13526 l 10834 13515 l 10814 13503 l 10794 13493 l 10772 13482 l +10750 13473 l 10727 13464 l 10703 13456 l 10679 13448 l 10653 13441 l +10628 13435 l 10602 13430 l 10575 13425 l 10548 13422 l 10521 13419 l +10493 13416 l 10465 13415 l 10438 13414 l 10410 13414 l 10382 13415 l +10354 13417 l 10327 13419 l 10300 13422 l 10273 13426 l 10246 13431 l +10220 13437 l 10194 13443 l 10169 13450 l 10145 13458 l 10121 13466 l +10098 13475 l 10076 13485 l 10055 13495 l 10035 13506 l 10015 13517 l +9997 13529 l 9980 13542 l 9964 13555 l 9949 13568 l 9935 13582 l 9922 13596 l +9911 13611 l 9901 13626 l 9892 13641 l 9885 13656 l 9879 13672 l 9874 13687 l +9871 13703 l 9869 13719 l 9868 13735 l 9869 13751 l 9871 13767 l 9875 13783 l +9879 13798 l 9886 13814 l 9893 13829 l 9902 13844 l 9912 13859 l 9924 13874 l +9937 13888 l 9951 13902 l 9966 13915 l 9982 13928 l 10000 13940 l +10018 13952 l 10037 13964 l 10058 13974 l 10079 13985 l 10101 13994 l +10124 14003 l 10148 14011 l 10173 14019 l 10198 14026 l 10223 14032 l +10250 14037 l 10276 14042 l 10303 14046 l 10330 14049 l 10358 14052 l +10386 14053 l 10413 14054 l 10441 14054 l 10469 14053 l 10497 14051 l +ps +9888 14443 m 9895 14459 l 9903 14474 l 9912 14489 l 9923 14504 l 9934 14518 l +9948 14533 l 9962 14546 l 9977 14560 l 9994 14573 l 10012 14585 l +10031 14597 l 10050 14608 l 10071 14619 l 10093 14629 l 10115 14639 l +10139 14647 l 10163 14656 l 10188 14663 l 10213 14670 l 10239 14676 l +10265 14681 l 10292 14685 l 10320 14689 l 10347 14692 l 10375 14694 l +10403 14695 l 10431 14696 l 10459 14696 l 10487 14695 l 10514 14693 l +10542 14690 l 10569 14687 l 10596 14682 l 10623 14677 l 10649 14672 l +10675 14665 l 10700 14658 l 10724 14650 l 10748 14641 l 10770 14632 l +10792 14622 l 10813 14612 l 10834 14600 l 10853 14589 l 10871 14576 l +10888 14564 l 10904 14550 l 10918 14537 l 10932 14523 l 10944 14508 l +10955 14494 l 10965 14479 l 10973 14463 l 10980 14448 l 10985 14432 l +10990 14416 l 10992 14400 l 10994 14384 l 10994 14368 l 10992 14352 l +10990 14336 l 10986 14320 l 10980 14305 l 10973 14289 l 10965 14274 l +10955 14259 l 10944 14244 l 10932 14230 l 10919 14216 l 10904 14202 l +10888 14189 l 10871 14176 l 10853 14164 l 10834 14152 l 10814 14141 l +10793 14130 l 10771 14120 l 10748 14111 l 10725 14102 l 10700 14094 l +10675 14087 l 10650 14081 l 10624 14075 l 10597 14070 l 10570 14066 l +10543 14062 l 10515 14059 l 10488 14057 l ps +7205 14684 m 6849 14684 6559 14412 6559 14078 ct 6559 13744 6849 13472 7205 13472 ct +7561 13472 7851 13744 7851 14078 ct 7851 14412 7561 14684 7205 14684 ct pc +5427 13589 m 5427 14657 l ps +5374 13560 m 6242 13560 l ps +5374 13914 m 6090 13914 l ps +11776 13397 m 11776 14697 l ps +12625 13414 m 12625 14680 l ps +12577 14640 m 13493 14640 l ps +gr +gs +1000 1000 m 20589 1000 l 20589 26939 l 1000 26939 l 1000 1000 l eoclip newpath +gr +gr +0 25940 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF
Added www/fossil2.gif version [f64284050b]
cannot compute difference between binary files
Added www/fossil3.gif version [0fa38d6065]
cannot compute difference between binary files
Added www/fossil_logo_small.gif version [b47a93e56e]
cannot compute difference between binary files
Added www/fossil_logo_small2.gif version [2a25c3c9b9]
cannot compute difference between binary files
Added www/fossil_logo_small3.gif version [6c2768dcb6]
cannot compute difference between binary files
Modified www/index.wiki from [7ee83e7ec9] to [5f5f3d2cbf].
@@ -1,96 +1,128 @@ -<h1>Fossil: Distributed Revision Control, Wiki, and Bug-Tracking</h1> +<title>Fossil Home Page</title> + + +<p align="center"> +<font size="5"> +<b>Fossil:</b> +<i>Simple, high-reliability, distributed software configuration management</i> +</font> +</p> + + +<h3>Why Use Fossil?</h3> + +<table border="0" cellpadding="1" bgcolor="#558195" align="right" hspace="10"> +<tr><td> +<table border="0" cellpadding="10" bgcolor="white"> +<tr><td> +<h3>Quick Links</h3> +<ul> +<li> [./quickstart.wiki | Quick Start] +<li> [http://www.fossil-scm.org/download.html | Download] +<li> [./build.wiki | Install] +<li> [../COPYRIGHT-GPL2.txt | License] +<li> [/timeline | Recent changes] +<li> [./faq.wiki | FAQ] +</ul> +</td></tr> +<tr><td> +<center><img src="fossil3.gif"></center> +</td></tr> +</table> +</table> + +There are plenty of open-source version control systems available on the +internet these days. What makes Fossil worthy of attention? + + 1. <b>Bug Tracking And Wiki</b> - + In addition to doing [./concepts.wiki | distributed version control] + like Git and Mercurial, + Fossil also supports [./bugtheory.wiki | distributed bug tracking] and + [./wikitheory.wiki | distributed wiki] all in a single + integrated package. + + 2. <b>Web Interface</b> - + Fossil has a built-in and easy-to-use [./webui.wiki | web interface] + that simplifies project tracking and promotes situational awareness. + Simply type "fossil ui" from within any check-out and Fossil + automatically opens your web browser in a page that gives detailed + history and status information on that project. + + 3. <b>Autosync</b> - + Fossil supports [./concepts.wiki#workflow | "autosync" mode] + which helps to keep projects moving + forward by reducing the amount of needless + [./branching.wiki | forking and merging] often + associated distributed projects. + + 4. <b>Self-Contained</b> - + Fossil is a single stand-alone executable that contains everything + needed to do configuration management. + Installation is trivial: simply download a + <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> + for Linux, Mac, or Windows and put it on your $PATH. + [./build.wiki | Easy-to-compile source code] is available for + users on other platforms. Fossil sources are also mostly self-contained, + requiring only the "zlib" library and the standard C library to build. -Fossil is a -[http://en.wikipedia.org/wiki/Revision_control | distributed software version control system] -that includes an integrated -[./wikitheory.wiki | distributed wiki] and an integrated -[./bugtheory.wiki | distributed bug-tracking system] all in a single, -easy-to-use, stand-alone executable. -Fossil is [http://www.fossil-scm.org/ | self-hosting] -since 2007-07-21 on -[http://www.hwaci.com/cgi-bin/fossil | two separate servers]. -You can download the [/timeline?y=ci | latest sources] and -[./build.wiki | compile it yourself]. -Or you can grab -[http://www.fossil-scm.org/download.html | pre-compiled binaries]. + 5. <b>Simple Networking</b> - + Fossil uses plain old HTTP (with + [./quickstart.wiki#proxy | proxy support]) + for all network communications, meaning that it works fine from behind + restrictive firewalls. The protocol is + [./stats.wiki | bandwidth efficient] to the point that Fossil can be + used comfortably over a dial-up internet connection. + 6. <b>CGI Enabled</b> - + No server is required to use fossil. But a + server does make collaboration easier. Fossil supports three different + yet simple [./quickstart.wiki#serversetup | server configurations]. + The most popular is a 2-line CGI script. This is the approach + used by the [./selfhost.wiki | self-hosting fossil repositories]. -<b>Feature Summary:</b> + 7. <b>Robust & Reliable</b> - + Fossil stores content in an SQLite database so that transactions are + atomic even if interrupted by a power loss or system crash. Furthermore, + automatic [./selfcheck.wiki | self-checks] verify that all aspects of + the repository are consistent prior to each commit. In over two years + of operation, no work has ever been lost after having been committed to + a Fossil repository. - * Flexible workflow:<ul> - <li>Disconnected, distributed development like - <a href="http://kerneltrap.org/node/4982">git</a>, - <a href="http://www.monotone.ca/">monotone</a>, - <a href="http://www.selenic.com/mercurial/wiki/index.cgi">mercurial</a>, - and <a href="http://www.bitkeeper.com/">bitkeeper</a> - <li>Or, client/server operation like - <a href="http://www.nongnu.org/cvs/">CVS</a> and - <a href="http://subversion.tigris.org/">subversion</a>, - <li>Or, operations on local repositories, - <li>Or, all of the above at the same time</ul> - * Integrated, [./bugtheory.wiki | distributed bug tracking] and - [./wikitheory.wiki | distributed wiki]. - * Built-in [./webui.wiki | web interface] that supports deep - archaeological digs through the project history. - * All network communication via HTTP with - [./quickstart.wiki#proxy | proxy support] - so that everything works from behind restrictive firewalls. - * Everything (client, server, and utilities) is included in a - single self-contained executable - trivial to install - * Server runs as [./quickstart.wiki#cgiserver | CGI], using - [./quickstart.wiki#inetdserver | inetd/xinetd] - or using its own - [./quickstart.wiki#serversetup | built-in, stand alone web server]. - * An entire project contained in single disk file - (an [http://www.sqlite.org/ | SQLite] database.) - * Uses an [./fileformat.wiki | enduring file format] that is - designed to be readable, searchable, and extensible by people - not yet born. - * Automatic [./selfcheck.wiki | self-check] - on repository changes makes it exceedingly - unlikely that data will ever be lost because of a software bug. - * Ridiculously easy to [./build.wiki | install] and - [./quickstart.wiki | operate]. - * License: [../COPYRIGHT-GPL2.txt | GPL] +<hr> +<h3>Links For Fossil Users:</h3> -<b>User Links:</b> - + * [./reviews.wiki | Testimonials] from satisfied fossil users. * [./faq.wiki | FAQ] * The [./concepts.wiki | concepts] behind fossil * [./quickstart.wiki | Quick Start] guide to using fossil - * [./reviews.wiki | Testimonials] from fossil users. * [./qandc.wiki | Questions & Criticisms] directed at fossil. * [./build.wiki | Building And Installing] * Fossil supports [./embeddeddoc.wiki | embedded documentation] that is versioned along with project source code. + * Fossil uses an [./fileformat.wiki | enduring file format] that is + designed to be readable, searchable, and extensible by people + not yet born. * A tutorial on [./branching.wiki | branching], what it means and how to do it using fossil. * The [./selfcheck.wiki | automatic self-check] mechanism helps insure project integrity. * Fossil contains a [./wikitheory.wiki | built-in wiki]. * There is a [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] available for discussing fossil issues. + * [./stats.wiki | Performance statistics] taken from real-world projects + hosted on fossil. + * How to [./shunning.wiki | delete content] from a fossil repository. * Some (unfinished but expanding) extended [./reference.wiki | reference documentation] for the fossil command line. -<b>Developer Links:</b> +<h3>Links For Fossil Developer:</h3> * [./pop.wiki | Principles Of Operation] * The [./fileformat.wiki | file format] used by every content file stored in the repository. * The [./delta_format.wiki | format of deltas] used to efficiently store changes between file revisions. * The [./delta_encoder_algorithm.wiki | encoder algorithm] used to efficiently generate deltas. * The [./sync.wiki | synchronization protocol]. - -<b>Competing Projects:</b> - - * [http://www.ditrack.org/ | DITrace] - A Distributed Issue Tracker - * [http://www.distract.wellquite.org/ | DisTract] - - Another distributed issue tracker based on - [http://www.monotone.ca/ | monotone]. - * [http://www.monotone.ca/ | Monotone] - distributed - SCM in a single-file executable with a single-file SQLite - database repository.
Modified www/mkdownload.tcl from [10dc1e9e78] to [d83e6610b9].
@@ -4,31 +4,41 @@ # # puts \ {<html> <head> -<title>Fossil Download</title> +<title>Fossil: Downloads</title> +<link rel="stylesheet" href="/fossil/style.css" type="text/css" + media="screen"> </head> <body> -<h1>Fossil Download</h1> +<div class="header"> + <div class="logo"> + <img src="/fossil/doc/tip/www/fossil_logo_small.gif" alt="logo"> + </div> + <div class="title">Fossil Downloads</div> +</div> +<div class="mainmenu"><a href='/fossil/doc/tip/www/index.wiki'>Home</a><a href='/fossil/leaves'>Leaves</a><a href='/fossil/timeline'>Timeline</a><a href='/fossil/brlist'>Branches</a><a href='/fossil/taglist'>Tags</a><a href='/fossil/reportlist'>Tickets</a><a href='/fossil/wiki'>Wiki</a><a href='/fossil/login'>Login</a></div> +<div class="content"> +<p> <p> -This page contains prebuilt binaries for -<a href="index.html">fossil</a> for various architectures. -The source code is available in the -<a href="http://www.fossil-scm.org/fossil/timeline">self-hosting -fossil repository</a>. +Click on links below to download prebuilt binaries and source tarballs for +recent versions of <a href="/fossil">Fossil</a>. +The historical source code is also available in the +<a href="/fossil/doc/tip/www/selfhost.wiki">self-hosting +Fossil repositories</a>. </p> <table cellpadding="5"> } proc Product {pattern desc} { set flist [glob -nocomplain download/$pattern] foreach file [lsort -dict $flist] { set file [file tail $file] - if {![regexp -- {-([a-f0-9]{10})[^a-f0-9]} $file all version]} continue + if {![regexp -- {-([0-9]+)\.} $file all version]} continue set mtime [file mtime download/$file] set date [clock format $mtime -format {%Y-%m-%d %H:%M:%S UTC} -gmt 1] set size [file size download/$file] set units bytes if {$size>1024*1024} { @@ -46,20 +56,25 @@ puts "<td valign=\"top\">[string trim $d2].<br>Size: $size $units.<br>" puts "Created: $date</td></tr>" } } -Product fossil-linux-x86-*.gz { +Product fossil-linux-x86-*.zip { Prebuilt fossil binary version [VERSION] for Linux on x86 } -Product fossil-macosx-x86-*.gz { +Product fossil-linux-amd64-*.zip { + Prebuilt fossil binary version [VERSION] for Linux on amd64 +} +Product fossil-macosx-x86-*.zip { Prebuilt fossil binary version [VERSION] for MacOSX on x86 } Product fossil-w32-*.zip { Prebuilt fossil binary version [VERSION] for windows } - +Product fossil-src-*.tar.gz { + Source code tarball for fossil version [VERSION] +} puts {</table> </body> </html> }
Modified www/quickstart.wiki from [a7f1c75cf3] to [9f4eaca262].
@@ -1,5 +1,6 @@ +<title>Fossil Quick Start Guide</title> <nowiki> <h1 align="center">Fossil Quick Start</h1> <p>This is a guide to get you started using fossil quickly and painlessly.</p> @@ -11,13 +12,13 @@ <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> or <a href="build.wiki">build it yourself</a> from sources. Install fossil by putting the fossil binary someplace on your PATH environment variable.</p> - </blockquote> - <a name="#fslclone"><h2>Cloning An Existing Repository</h2></a> - <blockquote> +</blockquote> +<a name="fslclone"></a> +<h2>Cloning An Existing Repository</h2><blockquote> <p>Most fossil operations interact with a repository that is on the local disk drive, not on a remote system. Hence, before accessing a remote repository it is necessary to make a local copy of that repository. Making a local copy of a remote repository is called @@ -106,11 +107,11 @@ <b>fossil status</b><br> <b>fossil changes</b><br> <b>fossil timeline</b><br> <b>fossil leaves</b><br> <b>fossil ls</b><br> - <b>fossil branches</b><br> + <b>fossil branch list</b><br> </blockquote> </blockquote><h2>Making Changes</h2><blockquote> <p>To add new files to your project, or remove old files, use these
Modified www/reference.wiki from [65e06e5538] to [820ff3080a].
@@ -489,11 +489,11 @@ The default is "gpg --clearsign -o ". mtime-changes Use file modification times (mtimes) to detect when files have been modified. - proxy URL of the HTTP proxy. If undefined or "off" then + proxy URL of the HTTP proxy. If undefined or "on" then the "http_proxy" environment variable is consulted. If the http_proxy environment variable is undefined then a direct HTTP connection is used. web-browser A shell command used to launch your preferred
Modified www/selfcheck.wiki from [4eea53cd1b] to [87d27f0d70].
@@ -1,61 +1,49 @@ -<nowiki> -<h1 align="center"> -Fossil Repository Integrity Self-Checks -</h1> - -<p> -Even though fossil is a relatively new project and still contains -many bugs, it is designed with features to give it a high level -of integrity so that you can have confidence that you will not -lose your files. This note describes the defensive measures that -fossil uses to help prevent file loss due to bugs. -</p> - -<p><i>Follow-up as of 2007-11-24:</i> -<i>Reiterated on 2008-05-16 and again on 2008-10-04:</i> +<title>Fossil Repository Integrity Self-Checks</title> + +<h1 align="center">Fossil Repository Integrity Self-Checks</h1> + +Fossil is designed with features to give it a high level +of integrity so that users can have confidence that content will +never be mangled or lost by Fossil. +This note describes the defensive measures that +Fossil uses to help prevent information loss due to bugs. + Fossil has been hosting itself and many other projects for -months now. Many bugs have been encountered. But, thanks in large +years now. Many bugs have been encountered. But, thanks in large part to the defensive measures described here, no data has been lost. The integrity checks are doing their job well.</p> <h2>Atomic Check-ins With Rollback</h2> -<p> The fossil repository is an <a href="http://www.sqlite.org/">SQLite version 3</a> database file. SQLite is very mature and stable and has been in wide-spread use for many years, so we are confident it will not cause repository corruption. SQLite databases do not corrupt even if a program or system crash or power failure occurs in the middle of the update. If some kind of crash does occur in the middle of a change, then all the changes are rolled back the next time that the database is accessed. -</p> - -<p> + A check-in operation in fossil makes many changes to the repository database. But all these changes happen within a single transaction. If something goes wrong in the middle of the commit, then the transaction is rolled back and the database is unchanged. -</p> <h2>Verification Of Delta Encodings Prior To Transaction Commit</h2> -<p> The content files that comprise the global state of a fossil respository are stored in the repository as a tree. The leaves of the tree are stored as zlib-compressed BLOBs. Interior nodes are deltas from their decendants. A lot of encoding is going on. There is zlib-compression which is relatively well-tested but still might cause corruption if used improperly. And there is the relatively new delta-encoding mechanism designed expressly for fossil. We want to make sure that bugs in these encoding mechanisms do not lead to loss of data. -</p> - -<p> + To increase our confidence that everything in the repository is recoverable, fossil makes sure it can extract an exact replicate of every content file that it changes just prior to transaction commit. So during the course of check-in (or other repository operation) many different files @@ -66,23 +54,19 @@ file. Then just before transaction commit, fossil re-extracts the original content of all files that were written, computes the SHA1 checksum again, and verifies that the checksums match. If anything does not match up, an error message is printed and the transaction rolls back. -</p> - -<p> + So, in other words, fossil always checks to make sure it can re-extract a file before it commits a change to that file. Hence bugs in fossil are unlikely to corrupt the repository in a way that prevents us from extracting historical versions of files. -</p> <h2>Checksum Over All Files In A Check-in</h2> -<p> Manifest artifacts that define a check-in have two fields (the R-card and Z-card) that record MD5 hashs of the manifest itself and of all other files in the manifest. Prior to any check-in commit, these checksums are verified to ensure that the check-in checked in agrees exactly with what is on disk. Similarly, @@ -89,6 +73,33 @@ the repository checksum is verified after a checkout to make sure that the entire repository was checked out correctly. Note that these added checks use a different hash (MD5 instead of SHA1) in order to avoid common-mode failures in the hash algorithm implementation. -</p> + + +<h2>Checksums On Control Artifacts And Deltas</h2> + +Every [./fileformat.wiki | control artifact] in a fossil repository +contains a "Z-card" bearing an MD5 checksum over the rest of the +artifact. Any mismatch causes the control artifact to be ignored. + +The [./delta_format.wiki | file delta format] includes a 32-bit +checksum of the target file. Whenever a file is reconstructed from +a delta, that checksum is verified to make sure the reconstruction +was done correctly. + +<h2>Reliability Versus Performance</h2> + +Some version control systems make a big deal out of being "high performance" +or the "fastest version control system". Fossil makes no such claims and has +no such ambition. Indeed, profiling indicates that fossil bears a +substantial performance cost for +doing all of the checksumming and verification outlined above. +Fossil takes the philosophy of the +<a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: +reliability is more important than raw speed. The developers of +fossil see no merit in getting the wrong answer quickly. + +Fossil may not be the fastest versioning system, but it is "fast enough". +Fossil runs quickly enough to stay out of the developers way. +Most operations complete in under a second.
Added www/selfhost.wiki version [712cb7df6c]
@@ -1,1 +1,66 @@ +<title>Fossil Self-Hosting Repositories</title> +<h1 align="center">Fossil Self-Hosting Repositories</h1> + +Fossil has self-hosted since 2007-07-21. As of this writing (2009-08-24) +there are three publicly accessible repositories for the Fossil source code: + + 1. [http://www.fossil-scm.org/] + 2. [http://www.hwaci.com/cgi-bin/fossil] + 3. [http://www2.fossil-scm.org/] + + +The canonical repository is (1). Repositories (2) and (3) automatically +stay in synchronization with (1) via a +<a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes +"fossil sync" at regular intervals. + +Note that the two secondary repositories are more than just read-only mirrors. +All three servers support full read/write capabilities. +Changes (such as new tickets or wiki or check-ins) can be implemented +on any of the three servers and those changes automatically propagate to the +other two servers. + +Server (1) runs as a CGI script on a +<a href="http://www.linode.com/">Linode 720</a> located in Dallas, TX +- on the same virtual machine that +hosts <a href="http://www.sqlite.org/">SQLite</a> and over a +dozen other smaller projects. This demonstrates that Fossil does not +require much server power. +Multiple fossil-based projects can easily be hosted on the same machine, +even if that machine is itself one of several dozen virtual machines on +single physical box. The CGI script that runs the canonical Fossil +self-hosting repository is as follows: + +<blockquote><pre> +#!/usr/bin/fossil +repository: /fossil/fossil.fossil +</pre></blockquote> + +Server (2) runs as a CGI script on a shared hosting account at +<a href="http://www.he.net/">Hurricane Electric</a> in San Jose and +Fremont, CA. This server demonstrates the ability of +Fossil to run on an economical shared-host web account with no +privileges beyond port 80 HTTP access and CGI. It is not necessary +to have a dedicated server to run Fossil. As far as we are aware, +Fossil is the only full-featured configuration management system +that can run in +such a restricted environment. The CGI script that runs on the +Hurricane Electric server is the same as the CGI script shown above, +except that the pathnames are modified to suite the environment: + +<blockquote><pre> +#!/home/hwaci/bin/fossil +repository: /home/hwaci/fossil/fossil.fossil +</pre></blockquote> + +Server (2) is synchronized with the canonical server (1) by running +the following command via cron: + +<blockquote><pre> +/home/hwaci/bin/fossil sync -R /home/hwaci/fossil/fossil.fossil +</pre></blockquote> +Server (3) is a +<a href="http://www.linode.com/">Linode 360</a> located in Atlanta, GA +and set up just like the canonical server (1) with the addition of a +cron job for synchronization as in server (2).
Added www/shunning.wiki version [7b6d5703dc]
@@ -1,1 +1,80 @@ +<title>Deleting Content From Fossil</title> +<h1 align="center">Deleting Content From Fossil</h1> + +Fossil is designed to keep all historical content forever. Users +of Fossil are discouraged from "deleting" content simply because it +has become obsolete. Old content is part of the historical record +(part of the "fossil record") and should be maintained indefinitely. +Such is the design intent of Fossil. + +Nevertheless, there may occasionally arise legitimate reasons for +deleting content. Such reasons might include: + + * Spammers have inserted inappropriate content into a wiki page + or ticket that needs to be removed. + + * A file that contains trade secrets or that is under copyright + may have been accidentally committed and needs to be backed + out. + + * A malformed control artifact may have been inserted and is + disrupting the operation of Fossil. + +<h2>Shunning</h2> + +Fossil provides a mechanism called "shunning" for removing content from +a repository. + +Every Fossil repository maintains a list of the SHA1 hash names of +"shunned" artifacts. +Fossil will refuse to push or pull any shunned artifact. +Furthermore, all shunned artifacts (but not the shunning list +itself) are removed from the +repository whenever the repository is reconstructed using the +"rebuild" command. + +<h3>Shunning lists are local state</h3> + +The shunning list is part of the local state of a Fossil repository. +In other words, shunning does not propagate using the normal "sync" +mechanism. An artifact can be +shunned from one repository but be allowed to exist in another. The fact that +the shunning list does not propagate is a security feature. If the +shunning list propagated then a malecious user (or +a bug in the fossil code) might introduce a shun record that would +propagate through all respositories in a network and permanently +destroy vital information. By refusing to propagate the shunning list, +Fossil insures that no remote user will ever be able to remove +information from your personal repositories without your permission. + +The shunning list does not propagate by the normal "sync" mechanism, +but it is still possible to copy shuns from one repository to another +using the "configuration" command: + + <b>fossil configuration pull shun</b> <i>remote-url</i><br> + <b>fossil configuration push shun</b> <i>remote-url</i> + +The two command above will pull or push shunning lists from or to +the <i>remote-url</i> indicated and merge the lists on the receiving +end. "Admin" privilege on the remote server is required in order to +push a shun list. + +Note that the shunning list remains in the respository even after the +shunned artifact has been removed. This is to prevent the artifact +from being reintroduced into the repository the next time it syncs with +another repository that has not shunned the artifact. + +<h3>Managing the shunning list</h3> + +The complete shunning list for a repository can be viewed by a user +with "admin" privilege on the "/shunned" URL of the web interface to Fossil. +That URL is accessible under the "Admin" button on the default menu +bar. Items can be added to or removed from the shunning list. "Sync" +operations are inhibited as soon as the artifact is added to the +shunning list, but the content of the artifact is not actually removed +from the responstory until the next time the repository is rebuilt. +When viewing individual artifacts with the web interface, "admin" +users will usually see a "Shun" option in the submenu that will take +them directly to the shunning page and enable that artifact to be +shunned with a single additional mouse click.
Added www/stats.wiki version [f1a2de8646]
@@ -1,1 +1,165 @@ +<title>Fossil Performance</title> +<h1 align="center">Performance Statistics</h1> + +The questions will inevitably arise: How does Fossil perform? +Does it use a lot of disk space or bandwidth? Is it scalable? + +In an attempt to answers these questions, this report looks at five +projects that use fossil for configuration management and examines how +well they are working. The following table is a summary of the results. +Explanation and analysis follows the table. + +<table border=1> +<tr> +<th>Project</th> +<th>Number Of Artifacts</th> +<th>Number Of Check-ins</th> +<th>Project Duration<br>(as of 2009-08-23)</th> +<th>Average Check-ins Per Day</th> +<th>Uncompressed Size</th> +<th>Repository Size</th> +<th>Compression Ratio</th> +<th>Clone Bandwidth</th> +</tr> + +<tr align="center"> +<td>SQLite +<td>28643 +<td>6755 +<td>3373 days<br>9.24 yrs +<td>2.00 +<td>1.27 GB +<td>35.4 MB +<td>35:1 +<td>982 KB up<br>12.4 MB down +</tr> + +<tr align="center"> +<td>Fossil +<td>4981 +<td>1272 +<td>764 days<br>2.1 yrs +<td>1.66 +<td>144 MB +<td>8.74 MB +<td>16:1 +<td>128 KB up<br>4.49 MB down +</tr> + +<tr align="center"> +<td>SLT +<td>2062 +<td>67 +<td>266 days +<td>0.25 +<td>1.76 GB +<td>147 MB +<td>11:1 +<td>1.1 MB up<br>141 MB down +</tr> + +<tr align="center"> +<td>TH3 +<td>1999 +<td>429 +<td>331 days +<td>1.30 +<td>70.5 MB +<td>6.3 MB +<td>11:1 +<td>55 KB up<br>4.66 MB down +</tr> + +<tr align="center"> +<td>SQLite Docs +<td>1787 +<td>444 +<td>650 days<br>1.78 yrs +<td>0.68 +<td>43 MB +<td>4.9 MB +<td>8:1 +<td>46 KB up<br>3.35 MB down +</tr> + +</table> + +<h2>The Five Projects</h2> + +The five projects listed above were chosen because they have been in +existance for a long time (relative to the age of fossil) or because +they have larges amounts of content. The most important project using +fossil is SQLite. Fossil itself +is built on top of SQLite and so obviously SQLite has to predate fossil. +SQLite was originally versioned using CVS, but recently the entire 9-year +and 320-MB CVS history of SQLite was converted over to Fossil. This is +an important datapoint because it demonstrates fossil's ability to manage +a significant and long-running project. +The next-longest running fossil project is fossil itself, at 2.1 years. +The documentation for SQLite +(identified above as "SQLite Docs") was split off of the main SQLite +source tree and into its own fossil repository about 1.75 years ago. +The "SQL Logic Test" or "SLT" project is a massive +collection of SQL statements and their output used to compare the +processing of SQLite against MySQL, PostgreSQL, Microsoft SQL Server, +and Oracle. +Finally "TH3" is a proprietary set of test cases for SQLite used to give +100% branch test coverage of SQLite on embedded platforms. All projects +except for TH3 are open-source. + +<h2>Measured Attributes</h2> + +In fossil, every version of every file, every wiki page, every change to +every ticket, and every check-in is a separate "artifact". One way to +think of a fossil project is as a bag of artifacts. Of course, there is +a lot more than this going on in fossil. Many of the artifacts have meaning +and are related to other artifacts. But at a low level (for example when +synchronizing two instances of the same project) the only thing that matters +is the unordered collection of artifacts. In fact, one of the key +characteristics of fossil is that the entire project history can be +reconstructed simply by scanning the artifacts in an arbitrary order. + +The number of check-ins is the number of times that the "commit" command +has been run. A single check-in might change a 3 or 4 files, or it might +change several dozen different files. Regardless of the number of files +changed, it still only counts as one check-in. + +The "Uncompressed Size" is the total size of all the artifacts within +the fossil repository assuming they were all uncompressed and stored +separately on the disk. Fossil makes use of delta compression between related +versions of the same file, and then uses zlib compression on the resulting +deltas. The total resulting repository size is shown after the uncompressed +size. + +On the right end of the table, we show the "Clone Bandwidth". This is the +total number of bytes sent from client to server ("uplink") and from server +back to client ("downlink") in order to clone a repository. These byte counts +include HTTP protocol overhead. + +In the table and throughout this article, +"GB" means gigabytes (10<sup><small>9</small></sup> bytes) +not <a href="http://en.wikipedia.org/wiki/Gibibyte">gibibytes</a> +(2<sup><small>30</small></sup> bytes). Similarly, "MB" and "KB" +means megabytes and kilobytes, not mebibytes and kibibytes. + +<h2>Analysis And Supplimental Data</h2> + +Perhaps the two most interesting datapoints in the above table are SQLite +and SLT. SQLite is a long-running project with long revision chains. +Some of the files in SQLite have been edited close to a thousand times. +Each of these edits is stored as a delta, and hence the SQLite project +gets excellent 35:1 compression. SLT, on the other hand, consists of +many large (megabyte-sized) SQL scripts that have one or maybe two +versions. There is very little delta compression occurring and so the +overall repository compression ratio is much lower. Note also that +quite a bit more bandwidth is required to clone SLT than SQLite. +For the first nine years of its development, SQLite was versioned by CVS. +The resulting CVS repository measured over 320MB in size. So, the +developers were +pleasently surprised to see that this entire project could be cloned in +fossil using only about 13MB of network traffic. The "sync" protocol +used by fossil has turned out to be surprisingly efficient. A typical +check-in on SQLite might use 3 or 4KB of network bandwidth total. Hardly +worth measuring. The sync protocol is efficient enough that, once cloned, +fossil could easily be used over a dial-up connection.
Modified www/sync.wiki from [7118e0761e] to [e571cf1d85].
@@ -384,20 +384,20 @@ <li>The client sends a cookie card if it has previously received a cookie. <li>The client sends gimme cards for every phantom that it holds. <hr> <li>The server checks the login password and rejects the session if the user does not have permission to pull. -<li>If the number entries in the unclustered table on the server is +<li>If the number of entries in the unclustered table on the server is greater than 100, then the server constructs a new cluster artifact to cover all those unclustered entries. <li>The server sends file cards for every gimme card it received from the client. -<li>The server sends ihave cards for every artifact in its unclustered +<li>The server sends igot cards for every artifact in its unclustered table that is not a phantom. <hr> <li>The client adds the content of file cards to its repository. -<li>The client creates a phantom for every ihave card in the server reply +<li>The client creates a phantom for every igot card in the server reply that mentions an artifact that the client does not possess. <li>The client creates a phantom for the delta source of file cards when the delta source is an artifact that the client does not possess. </ol>