/ Check-in [6c3f0902]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge recent trunk enhancements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1:6c3f09028f070b2612c00466ec3f01e2098b818d
User & Date: drh 2017-02-04 15:29:05
Context
2017-02-08
16:55
Merge the 3.17.0beta changes from trunk. check-in: 92dbd875 user: drh tags: apple-osx
2017-02-04
15:29
Merge recent trunk enhancements. check-in: 6c3f0902 user: drh tags: apple-osx
14:24
In RTREE, use an sqlite3_blob object rather than an sqlite3_stmt object for reading content out of the %_node shadow table. check-in: 97ccf3e4 user: drh tags: trunk
2017-01-27
16:39
Merge all recent trunk enhancements into the apple-osx branch. check-in: 0e14fe1b user: drh tags: apple-osx
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.msc.

    19     19   # <</mark>>
    20     20   
    21     21   # Set this non-0 to enable full warnings (-W4, etc) when compiling.
    22     22   #
    23     23   !IFNDEF USE_FULLWARN
    24     24   USE_FULLWARN = 0
    25     25   !ENDIF
           26  +
           27  +# Set this non-0 to enable treating warnings as errors (-WX, etc) when
           28  +# compiling.
           29  +#
           30  +!IFNDEF USE_FATAL_WARN
           31  +USE_FATAL_WARN = 0
           32  +!ENDIF
    26     33   
    27     34   # Set this non-0 to enable full runtime error checks (-RTC1, etc).  This
    28     35   # has no effect if (any) optimizations are enabled.
    29     36   #
    30     37   !IFNDEF USE_RUNTIME_CHECKS
    31     38   USE_RUNTIME_CHECKS = 0
    32     39   !ENDIF
................................................................................
   488    495   # same unless your are cross-compiling.)
   489    496   #
   490    497   !IF $(USE_FULLWARN)!=0
   491    498   TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
   492    499   !ELSE
   493    500   TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
   494    501   !ENDIF
          502  +
          503  +# Check if warnings should be treated as errors when compiling.
          504  +#
          505  +!IF $(USE_FATAL_WARN)!=0
          506  +TCC = $(TCC) -WX
          507  +!ENDIF
   495    508   
   496    509   TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
   497    510   RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
   498    511   
   499    512   # Check if we want to use the "stdcall" calling convention when compiling.
   500    513   # This is not supported by the compilers for non-x86 platforms.  It should
   501    514   # also be noted here that building any target with these "stdcall" options

Changes to autoconf/Makefile.msc.

    19     19   
    20     20   
    21     21   # Set this non-0 to enable full warnings (-W4, etc) when compiling.
    22     22   #
    23     23   !IFNDEF USE_FULLWARN
    24     24   USE_FULLWARN = 0
    25     25   !ENDIF
           26  +
           27  +# Set this non-0 to enable treating warnings as errors (-WX, etc) when
           28  +# compiling.
           29  +#
           30  +!IFNDEF USE_FATAL_WARN
           31  +USE_FATAL_WARN = 0
           32  +!ENDIF
    26     33   
    27     34   # Set this non-0 to enable full runtime error checks (-RTC1, etc).  This
    28     35   # has no effect if (any) optimizations are enabled.
    29     36   #
    30     37   !IFNDEF USE_RUNTIME_CHECKS
    31     38   USE_RUNTIME_CHECKS = 0
    32     39   !ENDIF
................................................................................
   449    456   # same unless your are cross-compiling.)
   450    457   #
   451    458   !IF $(USE_FULLWARN)!=0
   452    459   TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
   453    460   !ELSE
   454    461   TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
   455    462   !ENDIF
          463  +
          464  +# Check if warnings should be treated as errors when compiling.
          465  +#
          466  +!IF $(USE_FATAL_WARN)!=0
          467  +TCC = $(TCC) -WX
          468  +!ENDIF
   456    469   
   457    470   TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise
   458    471   RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
   459    472   
   460    473   # Check if we want to use the "stdcall" calling convention when compiling.
   461    474   # This is not supported by the compilers for non-x86 platforms.  It should
   462    475   # also be noted here that building any target with these "stdcall" options

Changes to ext/fts3/fts3.c.

  1359   1359     p->db = db;
  1360   1360     p->nColumn = nCol;
  1361   1361     p->nPendingData = 0;
  1362   1362     p->azColumn = (char **)&p[1];
  1363   1363     p->pTokenizer = pTokenizer;
  1364   1364     p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
  1365   1365     p->bHasDocsize = (isFts4 && bNoDocsize==0);
  1366         -  p->bHasStat = isFts4;
  1367         -  p->bFts4 = isFts4;
  1368         -  p->bDescIdx = bDescIdx;
         1366  +  p->bHasStat = (u8)isFts4;
         1367  +  p->bFts4 = (u8)isFts4;
         1368  +  p->bDescIdx = (u8)bDescIdx;
  1369   1369     p->nAutoincrmerge = 0xff;   /* 0xff means setting unknown */
  1370   1370     p->zContentTbl = zContent;
  1371   1371     p->zLanguageid = zLanguageid;
  1372   1372     zContent = 0;
  1373   1373     zLanguageid = 0;
  1374   1374     TESTONLY( p->inTransaction = -1 );
  1375   1375     TESTONLY( p->mxSavepoint = -1 );
................................................................................
  3418   3418       char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
  3419   3419       if( zSql ){
  3420   3420         sqlite3_stmt *pStmt = 0;
  3421   3421         rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
  3422   3422         if( rc==SQLITE_OK ){
  3423   3423           int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
  3424   3424           rc = sqlite3_finalize(pStmt);
  3425         -        if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
         3425  +        if( rc==SQLITE_OK ) p->bHasStat = (u8)bHasStat;
  3426   3426         }
  3427   3427         sqlite3_free(zSql);
  3428   3428       }else{
  3429   3429         rc = SQLITE_NOMEM;
  3430   3430       }
  3431   3431     }
  3432   3432     return rc;

Added ext/misc/sha1.c.

            1  +/*
            2  +** 2017-01-27
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +******************************************************************************
           12  +**
           13  +** This SQLite extension implements a functions that compute SHA1 hashes.
           14  +** Two SQL functions are implemented:
           15  +**
           16  +**     sha1(X)
           17  +**     sha1_query(Y)
           18  +**
           19  +** The sha1(X) function computes the SHA1 hash of the input X, or NULL if
           20  +** X is NULL.
           21  +**
           22  +** The sha1_query(Y) function evalutes all queries in the SQL statements of Y
           23  +** and returns a hash of their results.
           24  +*/
           25  +#include "sqlite3ext.h"
           26  +SQLITE_EXTENSION_INIT1
           27  +#include <assert.h>
           28  +#include <string.h>
           29  +#include <stdarg.h>
           30  +
           31  +/******************************************************************************
           32  +** The Hash Engine
           33  +*/
           34  +/* Context for the SHA1 hash */
           35  +typedef struct SHA1Context SHA1Context;
           36  +struct SHA1Context {
           37  +  unsigned int state[5];
           38  +  unsigned int count[2];
           39  +  unsigned char buffer[64];
           40  +};
           41  +
           42  +
           43  +#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
           44  +/*
           45  + * GCC by itself only generates left rotates.  Use right rotates if
           46  + * possible to be kinder to dinky implementations with iterative rotate
           47  + * instructions.
           48  + */
           49  +#define SHA_ROT(op, x, k) \
           50  +        ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
           51  +#define rol(x,k) SHA_ROT("roll", x, k)
           52  +#define ror(x,k) SHA_ROT("rorl", x, k)
           53  +
           54  +#else
           55  +/* Generic C equivalent */
           56  +#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
           57  +#define rol(x,k) SHA_ROT(x,k,32-(k))
           58  +#define ror(x,k) SHA_ROT(x,32-(k),k)
           59  +#endif
           60  +
           61  +
           62  +#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
           63  +    |(rol(block[i],8)&0x00FF00FF))
           64  +#define blk0be(i) block[i]
           65  +#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
           66  +    ^block[(i+2)&15]^block[i&15],1))
           67  +
           68  +/*
           69  + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
           70  + *
           71  + * Rl0() for little-endian and Rb0() for big-endian.  Endianness is
           72  + * determined at run-time.
           73  + */
           74  +#define Rl0(v,w,x,y,z,i) \
           75  +    z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
           76  +#define Rb0(v,w,x,y,z,i) \
           77  +    z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
           78  +#define R1(v,w,x,y,z,i) \
           79  +    z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
           80  +#define R2(v,w,x,y,z,i) \
           81  +    z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
           82  +#define R3(v,w,x,y,z,i) \
           83  +    z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
           84  +#define R4(v,w,x,y,z,i) \
           85  +    z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
           86  +
           87  +/*
           88  + * Hash a single 512-bit block. This is the core of the algorithm.
           89  + */
           90  +void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
           91  +  unsigned int qq[5]; /* a, b, c, d, e; */
           92  +  static int one = 1;
           93  +  unsigned int block[16];
           94  +  memcpy(block, buffer, 64);
           95  +  memcpy(qq,state,5*sizeof(unsigned int));
           96  +
           97  +#define a qq[0]
           98  +#define b qq[1]
           99  +#define c qq[2]
          100  +#define d qq[3]
          101  +#define e qq[4]
          102  +
          103  +  /* Copy p->state[] to working vars */
          104  +  /*
          105  +  a = state[0];
          106  +  b = state[1];
          107  +  c = state[2];
          108  +  d = state[3];
          109  +  e = state[4];
          110  +  */
          111  +
          112  +  /* 4 rounds of 20 operations each. Loop unrolled. */
          113  +  if( 1 == *(unsigned char*)&one ){
          114  +    Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
          115  +    Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
          116  +    Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
          117  +    Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
          118  +  }else{
          119  +    Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
          120  +    Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
          121  +    Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
          122  +    Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
          123  +  }
          124  +  R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
          125  +  R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
          126  +  R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
          127  +  R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
          128  +  R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
          129  +  R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
          130  +  R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
          131  +  R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
          132  +  R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
          133  +  R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
          134  +  R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
          135  +  R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
          136  +  R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
          137  +  R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
          138  +  R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
          139  +  R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
          140  +
          141  +  /* Add the working vars back into context.state[] */
          142  +  state[0] += a;
          143  +  state[1] += b;
          144  +  state[2] += c;
          145  +  state[3] += d;
          146  +  state[4] += e;
          147  +
          148  +#undef a
          149  +#undef b
          150  +#undef c
          151  +#undef d
          152  +#undef e
          153  +}
          154  +
          155  +
          156  +/* Initialize a SHA1 context */
          157  +static void hash_init(SHA1Context *p){
          158  +  /* SHA1 initialization constants */
          159  +  p->state[0] = 0x67452301;
          160  +  p->state[1] = 0xEFCDAB89;
          161  +  p->state[2] = 0x98BADCFE;
          162  +  p->state[3] = 0x10325476;
          163  +  p->state[4] = 0xC3D2E1F0;
          164  +  p->count[0] = p->count[1] = 0;
          165  +}
          166  +
          167  +/* Add new content to the SHA1 hash */
          168  +static void hash_step(
          169  +  SHA1Context *p,                 /* Add content to this context */
          170  +  const unsigned char *data,      /* Data to be added */
          171  +  unsigned int len                /* Number of bytes in data */
          172  +){
          173  +  unsigned int i, j;
          174  +
          175  +  j = p->count[0];
          176  +  if( (p->count[0] += len << 3) < j ){
          177  +    p->count[1] += (len>>29)+1;
          178  +  }
          179  +  j = (j >> 3) & 63;
          180  +  if( (j + len) > 63 ){
          181  +    (void)memcpy(&p->buffer[j], data, (i = 64-j));
          182  +    SHA1Transform(p->state, p->buffer);
          183  +    for(; i + 63 < len; i += 64){
          184  +      SHA1Transform(p->state, &data[i]);
          185  +    }
          186  +    j = 0;
          187  +  }else{
          188  +    i = 0;
          189  +  }
          190  +  (void)memcpy(&p->buffer[j], &data[i], len - i);
          191  +}
          192  +
          193  +/* Compute a string using sqlite3_vsnprintf() and hash it */
          194  +static void hash_step_vformat(
          195  +  SHA1Context *p,                 /* Add content to this context */
          196  +  const char *zFormat,
          197  +  ...
          198  +){
          199  +  va_list ap;
          200  +  int n;
          201  +  char zBuf[50];
          202  +  va_start(ap, zFormat);
          203  +  sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
          204  +  va_end(ap);
          205  +  n = (int)strlen(zBuf);
          206  +  hash_step(p, (unsigned char*)zBuf, n);
          207  +}
          208  +
          209  +
          210  +/* Add padding and compute the message digest.  Render the
          211  +** message digest as lower-case hexadecimal and put it into
          212  +** zOut[].  zOut[] must be at least 41 bytes long. */
          213  +static void hash_finish(
          214  +  SHA1Context *p,           /* The SHA1 context to finish and render */
          215  +  char *zOut                /* Store hexadecimal hash here */
          216  +){
          217  +  unsigned int i;
          218  +  unsigned char finalcount[8];
          219  +  unsigned char digest[20];
          220  +  static const char zEncode[] = "0123456789abcdef";
          221  +
          222  +  for (i = 0; i < 8; i++){
          223  +    finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
          224  +       >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
          225  +  }
          226  +  hash_step(p, (const unsigned char *)"\200", 1);
          227  +  while ((p->count[0] & 504) != 448){
          228  +    hash_step(p, (const unsigned char *)"\0", 1);
          229  +  }
          230  +  hash_step(p, finalcount, 8);  /* Should cause a SHA1Transform() */
          231  +  for (i = 0; i < 20; i++){
          232  +    digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
          233  +  }
          234  +  for(i=0; i<20; i++){
          235  +    zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
          236  +    zOut[i*2+1] = zEncode[digest[i] & 0xf];
          237  +  }
          238  +  zOut[i*2]= 0;
          239  +}
          240  +/* End of the hashing logic
          241  +*****************************************************************************/
          242  +
          243  +/*
          244  +** Implementation of the sha1(X) function.
          245  +**
          246  +** Return a lower-case hexadecimal rendering of the SHA1 hash of the
          247  +** argument X.  If X is a BLOB, it is hashed as is.  For all other
          248  +** types of input, X is converted into a UTF-8 string and the string
          249  +** is hash without the trailing 0x00 terminator.  The hash of a NULL
          250  +** value is NULL.
          251  +*/
          252  +static void sha1Func(
          253  +  sqlite3_context *context,
          254  +  int argc,
          255  +  sqlite3_value **argv
          256  +){
          257  +  SHA1Context cx;
          258  +  int eType = sqlite3_value_type(argv[0]);
          259  +  int nByte = sqlite3_value_bytes(argv[0]);
          260  +  char zOut[44];
          261  +
          262  +  assert( argc==1 );
          263  +  if( eType==SQLITE_NULL ) return;
          264  +  hash_init(&cx);
          265  +  if( eType==SQLITE_BLOB ){
          266  +    hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
          267  +  }else{
          268  +    hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
          269  +  }
          270  +  hash_finish(&cx, zOut);
          271  +  sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
          272  +}
          273  +
          274  +/*
          275  +** Implementation of the sha1_query(SQL) function.
          276  +**
          277  +** This function compiles and runs the SQL statement(s) given in the
          278  +** argument. The results are hashed using SHA1 and that hash is returned.
          279  +**
          280  +** The original SQL text is included as part of the hash.
          281  +**
          282  +** The hash is not just a concatenation of the outputs.  Each query
          283  +** is delimited and each row and value within the query is delimited,
          284  +** with all values being marked with their datatypes.
          285  +*/
          286  +static void sha1QueryFunc(
          287  +  sqlite3_context *context,
          288  +  int argc,
          289  +  sqlite3_value **argv
          290  +){
          291  +  sqlite3 *db = sqlite3_context_db_handle(context);
          292  +  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
          293  +  sqlite3_stmt *pStmt = 0;
          294  +  int nCol;                   /* Number of columns in the result set */
          295  +  int i;                      /* Loop counter */
          296  +  int rc;
          297  +  int n;
          298  +  const char *z;
          299  +  SHA1Context cx;
          300  +  char zOut[44];
          301  +
          302  +  assert( argc==1 );
          303  +  if( zSql==0 ) return;
          304  +  hash_init(&cx);
          305  +  while( zSql[0] ){
          306  +    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
          307  +    if( rc ){
          308  +      char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
          309  +                                   zSql, sqlite3_errmsg(db));
          310  +      sqlite3_finalize(pStmt);
          311  +      sqlite3_result_error(context, zMsg, -1);
          312  +      sqlite3_free(zMsg);
          313  +      return;
          314  +    }
          315  +    if( !sqlite3_stmt_readonly(pStmt) ){
          316  +      char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
          317  +      sqlite3_finalize(pStmt);
          318  +      sqlite3_result_error(context, zMsg, -1);
          319  +      sqlite3_free(zMsg);
          320  +      return;
          321  +    }
          322  +    nCol = sqlite3_column_count(pStmt);
          323  +    z = sqlite3_sql(pStmt);
          324  +    n = (int)strlen(z);
          325  +    hash_step_vformat(&cx,"S%d:",n);
          326  +    hash_step(&cx,(unsigned char*)z,n);
          327  +
          328  +    /* Compute a hash over the result of the query */
          329  +    while( SQLITE_ROW==sqlite3_step(pStmt) ){
          330  +      hash_step(&cx,(const unsigned char*)"R",1);
          331  +      for(i=0; i<nCol; i++){
          332  +        switch( sqlite3_column_type(pStmt,i) ){
          333  +          case SQLITE_NULL: {
          334  +            hash_step(&cx, (const unsigned char*)"N",1);
          335  +            break;
          336  +          }
          337  +          case SQLITE_INTEGER: {
          338  +            sqlite3_uint64 u;
          339  +            int j;
          340  +            unsigned char x[9];
          341  +            sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
          342  +            memcpy(&u, &v, 8);
          343  +            for(j=8; j>=1; j--){
          344  +              x[j] = u & 0xff;
          345  +              u >>= 8;
          346  +            }
          347  +            x[0] = 'I';
          348  +            hash_step(&cx, x, 9);
          349  +            break;
          350  +          }
          351  +          case SQLITE_FLOAT: {
          352  +            sqlite3_uint64 u;
          353  +            int j;
          354  +            unsigned char x[9];
          355  +            double r = sqlite3_column_double(pStmt,i);
          356  +            memcpy(&u, &r, 8);
          357  +            for(j=8; j>=1; j--){
          358  +              x[j] = u & 0xff;
          359  +              u >>= 8;
          360  +            }
          361  +            x[0] = 'F';
          362  +            hash_step(&cx,x,9);
          363  +            break;
          364  +          }
          365  +          case SQLITE_TEXT: {
          366  +            int n2 = sqlite3_column_bytes(pStmt, i);
          367  +            const unsigned char *z2 = sqlite3_column_text(pStmt, i);
          368  +            hash_step_vformat(&cx,"T%d:",n2);
          369  +            hash_step(&cx, z2, n2);
          370  +            break;
          371  +          }
          372  +          case SQLITE_BLOB: {
          373  +            int n2 = sqlite3_column_bytes(pStmt, i);
          374  +            const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
          375  +            hash_step_vformat(&cx,"B%d:",n2);
          376  +            hash_step(&cx, z2, n2);
          377  +            break;
          378  +          }
          379  +        }
          380  +      }
          381  +    }
          382  +    sqlite3_finalize(pStmt);
          383  +  }
          384  +  hash_finish(&cx, zOut);
          385  +  sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
          386  +}
          387  +
          388  +
          389  +#ifdef _WIN32
          390  +__declspec(dllexport)
          391  +#endif
          392  +int sqlite3_sha_init(
          393  +  sqlite3 *db,
          394  +  char **pzErrMsg,
          395  +  const sqlite3_api_routines *pApi
          396  +){
          397  +  int rc = SQLITE_OK;
          398  +  SQLITE_EXTENSION_INIT2(pApi);
          399  +  (void)pzErrMsg;  /* Unused parameter */
          400  +  rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8, 0,
          401  +                               sha1Func, 0, 0);
          402  +  if( rc==SQLITE_OK ){
          403  +    rc = sqlite3_create_function(db, "sha1_query", 1, SQLITE_UTF8, 0,
          404  +                                 sha1QueryFunc, 0, 0);
          405  +  }
          406  +  return rc;
          407  +}

Changes to ext/rtree/rtree.c.

   113    113   ** An rtree virtual-table object.
   114    114   */
   115    115   struct Rtree {
   116    116     sqlite3_vtab base;          /* Base class.  Must be first */
   117    117     sqlite3 *db;                /* Host database connection */
   118    118     int iNodeSize;              /* Size in bytes of each node in the node table */
   119    119     u8 nDim;                    /* Number of dimensions */
          120  +  u8 nDim2;                   /* Twice the number of dimensions */
   120    121     u8 eCoordType;              /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
   121    122     u8 nBytesPerCell;           /* Bytes consumed per cell */
          123  +  u8 inWrTrans;               /* True if inside write transaction */
   122    124     int iDepth;                 /* Current depth of the r-tree structure */
   123    125     char *zDb;                  /* Name of database containing r-tree table */
   124    126     char *zName;                /* Name of r-tree table */ 
   125         -  int nBusy;                  /* Current number of users of this structure */
          127  +  u32 nBusy;                  /* Current number of users of this structure */
   126    128     i64 nRowEst;                /* Estimated number of rows in this table */
          129  +  u32 nCursor;                /* Number of open cursors */
   127    130   
   128    131     /* List of nodes removed during a CondenseTree operation. List is
   129    132     ** linked together via the pointer normally used for hash chains -
   130    133     ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree 
   131    134     ** headed by the node (leaf nodes have RtreeNode.iNode==0).
   132    135     */
   133    136     RtreeNode *pDeleted;
   134    137     int iReinsertHeight;        /* Height of sub-trees Reinsert() has run on */
          138  +
          139  +  /* Blob I/O on xxx_node */
          140  +  sqlite3_blob *pNodeBlob;
   135    141   
   136    142     /* Statements to read/write/delete a record from xxx_node */
   137         -  sqlite3_stmt *pReadNode;
   138    143     sqlite3_stmt *pWriteNode;
   139    144     sqlite3_stmt *pDeleteNode;
   140    145   
   141    146     /* Statements to read/write/delete a record from xxx_rowid */
   142    147     sqlite3_stmt *pReadRowid;
   143    148     sqlite3_stmt *pWriteRowid;
   144    149     sqlite3_stmt *pDeleteRowid;
................................................................................
   359    364   #ifndef MAX
   360    365   # define MAX(x,y) ((x) < (y) ? (y) : (x))
   361    366   #endif
   362    367   #ifndef MIN
   363    368   # define MIN(x,y) ((x) > (y) ? (y) : (x))
   364    369   #endif
   365    370   
          371  +/* What version of GCC is being used.  0 means GCC is not being used */
          372  +#ifndef GCC_VERSION
          373  +#ifdef __GNUC__
          374  +# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
          375  +#else
          376  +# define GCC_VERSION 0
          377  +#endif
          378  +#endif
          379  +
          380  +/* What version of CLANG is being used.  0 means CLANG is not being used */
          381  +#ifndef CLANG_VERSION
          382  +#if defined(__clang__) && !defined(_WIN32)
          383  +# define CLANG_VERSION \
          384  +            (__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__)
          385  +#else
          386  +# define CLANG_VERSION 0
          387  +#endif
          388  +#endif
          389  +
          390  +/* The testcase() macro should already be defined in the amalgamation.  If
          391  +** it is not, make it a no-op.
          392  +*/
          393  +#ifndef SQLITE_AMALGAMATION
          394  +# define testcase(X)
          395  +#endif
          396  +
          397  +/*
          398  +** Macros to determine whether the machine is big or little endian,
          399  +** and whether or not that determination is run-time or compile-time.
          400  +**
          401  +** For best performance, an attempt is made to guess at the byte-order
          402  +** using C-preprocessor macros.  If that is unsuccessful, or if
          403  +** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
          404  +** at run-time.
          405  +*/
          406  +#ifndef SQLITE_BYTEORDER
          407  +#if (defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
          408  +     defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
          409  +     defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
          410  +     defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
          411  +# define SQLITE_BYTEORDER    1234
          412  +#endif
          413  +#if (defined(sparc)    || defined(__ppc__))  \
          414  +    && !defined(SQLITE_RUNTIME_BYTEORDER)
          415  +# define SQLITE_BYTEORDER    4321
          416  +#endif
          417  +# define SQLITE_BYTEORDER    0     /* 0 means "unknown at compile-time" */
          418  +#endif
          419  +
          420  +
          421  +/* What version of MSVC is being used.  0 means MSVC is not being used */
          422  +#ifndef MSVC_VERSION
          423  +#if defined(_MSC_VER)
          424  +# define MSVC_VERSION _MSC_VER
          425  +#else
          426  +# define MSVC_VERSION 0
          427  +#endif
          428  +#endif
          429  +
   366    430   /*
   367    431   ** Functions to deserialize a 16 bit integer, 32 bit real number and
   368    432   ** 64 bit integer. The deserialized value is returned.
   369    433   */
   370    434   static int readInt16(u8 *p){
   371    435     return (p[0]<<8) + p[1];
   372    436   }
   373    437   static void readCoord(u8 *p, RtreeCoord *pCoord){
          438  +  assert( ((((char*)p) - (char*)0)&3)==0 );  /* p is always 4-byte aligned */
          439  +#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
          440  +  pCoord->u = _byteswap_ulong(*(u32*)p);
          441  +#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
          442  +  pCoord->u = __builtin_bswap32(*(u32*)p);
          443  +#elif SQLITE_BYTEORDER==1234
          444  +  pCoord->u = ((pCoord->u>>24)&0xff)|((pCoord->u>>8)&0xff00)|
          445  +              ((pCoord->u&0xff)<<24)|((pCoord->u&0xff00)<<8);
          446  +#elif SQLITE_BYTEORDER==4321
          447  +  pCoord->u = *(u32*)p;
          448  +#else
   374    449     pCoord->u = (
   375    450       (((u32)p[0]) << 24) + 
   376    451       (((u32)p[1]) << 16) + 
   377    452       (((u32)p[2]) <<  8) + 
   378    453       (((u32)p[3]) <<  0)
   379    454     );
          455  +#endif
   380    456   }
   381    457   static i64 readInt64(u8 *p){
          458  +#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
          459  +  u64 x;
          460  +  testcase( ((((char*)p) - (char*)0)&7)!=0 );  /* not always 8-byte aligned */
          461  +  memcpy(&x, p, 8);
          462  +  return (i64)_byteswap_uint64(x);
          463  +#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
          464  +  u64 x;
          465  +  testcase( ((((char*)p) - (char*)0)&7)!=0 );  /* not always 8-byte aligned */
          466  +  memcpy(&x, p, 8);
          467  +  return (i64)__builtin_bswap64(x);
          468  +#elif SQLITE_BYTEORDER==4321
          469  +  i64 x;
          470  +  testcase( ((((char*)p) - (char*)0)&7)!=0 );  /* not always 8-byte aligned */
          471  +  memcpy(&x, p, 8);
          472  +  return x;
          473  +#else
          474  +  testcase( ((((char*)p) - (char*)0)&7)!=0 );  /* not always 8-byte aligned */
   382    475     return (
   383    476       (((i64)p[0]) << 56) + 
   384    477       (((i64)p[1]) << 48) + 
   385    478       (((i64)p[2]) << 40) + 
   386    479       (((i64)p[3]) << 32) + 
   387    480       (((i64)p[4]) << 24) + 
   388    481       (((i64)p[5]) << 16) + 
   389    482       (((i64)p[6]) <<  8) + 
   390    483       (((i64)p[7]) <<  0)
   391    484     );
          485  +#endif
   392    486   }
   393    487   
   394    488   /*
   395    489   ** Functions to serialize a 16 bit integer, 32 bit real number and
   396    490   ** 64 bit integer. The value returned is the number of bytes written
   397    491   ** to the argument buffer (always 2, 4 and 8 respectively).
   398    492   */
................................................................................
   399    493   static int writeInt16(u8 *p, int i){
   400    494     p[0] = (i>> 8)&0xFF;
   401    495     p[1] = (i>> 0)&0xFF;
   402    496     return 2;
   403    497   }
   404    498   static int writeCoord(u8 *p, RtreeCoord *pCoord){
   405    499     u32 i;
          500  +  assert( ((((char*)p) - (char*)0)&3)==0 );  /* p is always 4-byte aligned */
   406    501     assert( sizeof(RtreeCoord)==4 );
   407    502     assert( sizeof(u32)==4 );
          503  +#if SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
          504  +  i = __builtin_bswap32(pCoord->u);
          505  +  memcpy(p, &i, 4);
          506  +#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
          507  +  i = _byteswap_ulong(pCoord->u);
          508  +  memcpy(p, &i, 4);
          509  +#elif SQLITE_BYTEORDER==4321
          510  +  i = pCoord->u;
          511  +  memcpy(p, &i, 4);
          512  +#else
   408    513     i = pCoord->u;
   409    514     p[0] = (i>>24)&0xFF;
   410    515     p[1] = (i>>16)&0xFF;
   411    516     p[2] = (i>> 8)&0xFF;
   412    517     p[3] = (i>> 0)&0xFF;
          518  +#endif
   413    519     return 4;
   414    520   }
   415    521   static int writeInt64(u8 *p, i64 i){
          522  +  testcase( ((((char*)p) - (char*)0)&7)!=0 );  /* Not always 8-byte aligned */
          523  +#if SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
          524  +  i = (i64)__builtin_bswap64((u64)i);
          525  +  memcpy(p, &i, 8);
          526  +#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
          527  +  i = (i64)_byteswap_uint64((u64)i);
          528  +  memcpy(p, &i, 8);
          529  +#elif SQLITE_BYTEORDER==4321
          530  +  memcpy(p, &i, 8);
          531  +#else
   416    532     p[0] = (i>>56)&0xFF;
   417    533     p[1] = (i>>48)&0xFF;
   418    534     p[2] = (i>>40)&0xFF;
   419    535     p[3] = (i>>32)&0xFF;
   420    536     p[4] = (i>>24)&0xFF;
   421    537     p[5] = (i>>16)&0xFF;
   422    538     p[6] = (i>> 8)&0xFF;
   423    539     p[7] = (i>> 0)&0xFF;
          540  +#endif
   424    541     return 8;
   425    542   }
   426    543   
   427    544   /*
   428    545   ** Increment the reference count of node p.
   429    546   */
   430    547   static void nodeReference(RtreeNode *p){
................................................................................
   498    615       pNode->nRef = 1;
   499    616       pNode->pParent = pParent;
   500    617       pNode->isDirty = 1;
   501    618       nodeReference(pParent);
   502    619     }
   503    620     return pNode;
   504    621   }
          622  +
          623  +/*
          624  +** Clear the Rtree.pNodeBlob object
          625  +*/
          626  +static void nodeBlobReset(Rtree *pRtree){
          627  +  if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
          628  +    sqlite3_blob *pBlob = pRtree->pNodeBlob;
          629  +    pRtree->pNodeBlob = 0;
          630  +    sqlite3_blob_close(pBlob);
          631  +  }
          632  +}
   505    633   
   506    634   /*
   507    635   ** Obtain a reference to an r-tree node.
   508    636   */
   509    637   static int nodeAcquire(
   510    638     Rtree *pRtree,             /* R-tree structure */
   511    639     i64 iNode,                 /* Node number to load */
   512    640     RtreeNode *pParent,        /* Either the parent node or NULL */
   513    641     RtreeNode **ppNode         /* OUT: Acquired node */
   514    642   ){
   515         -  int rc;
   516         -  int rc2 = SQLITE_OK;
   517         -  RtreeNode *pNode;
          643  +  int rc = SQLITE_OK;
          644  +  RtreeNode *pNode = 0;
   518    645   
   519    646     /* Check if the requested node is already in the hash table. If so,
   520    647     ** increase its reference count and return it.
   521    648     */
   522    649     if( (pNode = nodeHashLookup(pRtree, iNode)) ){
   523    650       assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
   524    651       if( pParent && !pNode->pParent ){
................................................................................
   526    653         pNode->pParent = pParent;
   527    654       }
   528    655       pNode->nRef++;
   529    656       *ppNode = pNode;
   530    657       return SQLITE_OK;
   531    658     }
   532    659   
   533         -  sqlite3_bind_int64(pRtree->pReadNode, 1, iNode);
   534         -  rc = sqlite3_step(pRtree->pReadNode);
   535         -  if( rc==SQLITE_ROW ){
   536         -    const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
   537         -    if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){
   538         -      pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
   539         -      if( !pNode ){
   540         -        rc2 = SQLITE_NOMEM;
   541         -      }else{
   542         -        pNode->pParent = pParent;
   543         -        pNode->zData = (u8 *)&pNode[1];
   544         -        pNode->nRef = 1;
   545         -        pNode->iNode = iNode;
   546         -        pNode->isDirty = 0;
   547         -        pNode->pNext = 0;
   548         -        memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
   549         -        nodeReference(pParent);
   550         -      }
   551         -    }
   552         -  }
   553         -  rc = sqlite3_reset(pRtree->pReadNode);
   554         -  if( rc==SQLITE_OK ) rc = rc2;
          660  +  if( pRtree->pNodeBlob ){
          661  +    sqlite3_blob *pBlob = pRtree->pNodeBlob;
          662  +    pRtree->pNodeBlob = 0;
          663  +    rc = sqlite3_blob_reopen(pBlob, iNode);
          664  +    pRtree->pNodeBlob = pBlob;
          665  +    if( rc ){
          666  +      nodeBlobReset(pRtree);
          667  +      if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
          668  +    }
          669  +  }
          670  +  if( pRtree->pNodeBlob==0 ){
          671  +    char *zTab = sqlite3_mprintf("%s_node", pRtree->zName);
          672  +    if( zTab==0 ) return SQLITE_NOMEM;
          673  +    rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, zTab, "data", iNode, 0,
          674  +                           &pRtree->pNodeBlob);
          675  +    sqlite3_free(zTab);
          676  +  }
          677  +  if( rc ){
          678  +    nodeBlobReset(pRtree);
          679  +    *ppNode = 0;
          680  +    /* If unable to open an sqlite3_blob on the desired row, that can only
          681  +    ** be because the shadow tables hold erroneous data. */
          682  +    if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
          683  +  }else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
          684  +    pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
          685  +    if( !pNode ){
          686  +      rc = SQLITE_NOMEM;
          687  +    }else{
          688  +      pNode->pParent = pParent;
          689  +      pNode->zData = (u8 *)&pNode[1];
          690  +      pNode->nRef = 1;
          691  +      pNode->iNode = iNode;
          692  +      pNode->isDirty = 0;
          693  +      pNode->pNext = 0;
          694  +      rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
          695  +                             pRtree->iNodeSize, 0);
          696  +      nodeReference(pParent);
          697  +    }
          698  +  }
   555    699   
   556    700     /* If the root node was just loaded, set pRtree->iDepth to the height
   557    701     ** of the r-tree structure. A height of zero means all data is stored on
   558    702     ** the root node. A height of one means the children of the root node
   559    703     ** are the leaves, and so on. If the depth as specified on the root node
   560    704     ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
   561    705     */
................................................................................
   599    743     RtreeNode *pNode,          /* The node into which the cell is to be written */
   600    744     RtreeCell *pCell,          /* The cell to write */
   601    745     int iCell                  /* Index into pNode into which pCell is written */
   602    746   ){
   603    747     int ii;
   604    748     u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
   605    749     p += writeInt64(p, pCell->iRowid);
   606         -  for(ii=0; ii<(pRtree->nDim*2); ii++){
          750  +  for(ii=0; ii<pRtree->nDim2; ii++){
   607    751       p += writeCoord(p, &pCell->aCoord[ii]);
   608    752     }
   609    753     pNode->isDirty = 1;
   610    754   }
   611    755   
   612    756   /*
   613    757   ** Remove the cell with index iCell from node pNode.
................................................................................
   733    877     Rtree *pRtree,               /* The overall R-Tree */
   734    878     RtreeNode *pNode,            /* The node containing the cell to be read */
   735    879     int iCell,                   /* Index of the cell within the node */
   736    880     RtreeCell *pCell             /* OUT: Write the cell contents here */
   737    881   ){
   738    882     u8 *pData;
   739    883     RtreeCoord *pCoord;
   740         -  int ii;
          884  +  int ii = 0;
   741    885     pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
   742    886     pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell);
   743    887     pCoord = pCell->aCoord;
   744         -  for(ii=0; ii<pRtree->nDim*2; ii++){
   745         -    readCoord(&pData[ii*4], &pCoord[ii]);
   746         -  }
          888  +  do{
          889  +    readCoord(pData, &pCoord[ii]);
          890  +    readCoord(pData+4, &pCoord[ii+1]);
          891  +    pData += 8;
          892  +    ii += 2;
          893  +  }while( ii<pRtree->nDim2 );
   747    894   }
   748    895   
   749    896   
   750    897   /* Forward declaration for the function that does the work of
   751    898   ** the virtual table module xCreate() and xConnect() methods.
   752    899   */
   753    900   static int rtreeInit(
................................................................................
   790    937   /*
   791    938   ** Decrement the r-tree reference count. When the reference count reaches
   792    939   ** zero the structure is deleted.
   793    940   */
   794    941   static void rtreeRelease(Rtree *pRtree){
   795    942     pRtree->nBusy--;
   796    943     if( pRtree->nBusy==0 ){
   797         -    sqlite3_finalize(pRtree->pReadNode);
          944  +    pRtree->inWrTrans = 0;
          945  +    pRtree->nCursor = 0;
          946  +    nodeBlobReset(pRtree);
   798    947       sqlite3_finalize(pRtree->pWriteNode);
   799    948       sqlite3_finalize(pRtree->pDeleteNode);
   800    949       sqlite3_finalize(pRtree->pReadRowid);
   801    950       sqlite3_finalize(pRtree->pWriteRowid);
   802    951       sqlite3_finalize(pRtree->pDeleteRowid);
   803    952       sqlite3_finalize(pRtree->pReadParent);
   804    953       sqlite3_finalize(pRtree->pWriteParent);
................................................................................
   828    977       pRtree->zDb, pRtree->zName, 
   829    978       pRtree->zDb, pRtree->zName,
   830    979       pRtree->zDb, pRtree->zName
   831    980     );
   832    981     if( !zCreate ){
   833    982       rc = SQLITE_NOMEM;
   834    983     }else{
          984  +    nodeBlobReset(pRtree);
   835    985       rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);
   836    986       sqlite3_free(zCreate);
   837    987     }
   838    988     if( rc==SQLITE_OK ){
   839    989       rtreeRelease(pRtree);
   840    990     }
   841    991   
................................................................................
   843    993   }
   844    994   
   845    995   /* 
   846    996   ** Rtree virtual table module xOpen method.
   847    997   */
   848    998   static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
   849    999     int rc = SQLITE_NOMEM;
         1000  +  Rtree *pRtree = (Rtree *)pVTab;
   850   1001     RtreeCursor *pCsr;
   851   1002   
   852   1003     pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
   853   1004     if( pCsr ){
   854   1005       memset(pCsr, 0, sizeof(RtreeCursor));
   855   1006       pCsr->base.pVtab = pVTab;
   856   1007       rc = SQLITE_OK;
         1008  +    pRtree->nCursor++;
   857   1009     }
   858   1010     *ppCursor = (sqlite3_vtab_cursor *)pCsr;
   859   1011   
   860   1012     return rc;
   861   1013   }
   862   1014   
   863   1015   
................................................................................
   882   1034   /* 
   883   1035   ** Rtree virtual table module xClose method.
   884   1036   */
   885   1037   static int rtreeClose(sqlite3_vtab_cursor *cur){
   886   1038     Rtree *pRtree = (Rtree *)(cur->pVtab);
   887   1039     int ii;
   888   1040     RtreeCursor *pCsr = (RtreeCursor *)cur;
         1041  +  assert( pRtree->nCursor>0 );
   889   1042     freeCursorConstraints(pCsr);
   890   1043     sqlite3_free(pCsr->aPoint);
   891   1044     for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
   892   1045     sqlite3_free(pCsr);
         1046  +  pRtree->nCursor--;
         1047  +  nodeBlobReset(pRtree);
   893   1048     return SQLITE_OK;
   894   1049   }
   895   1050   
   896   1051   /*
   897   1052   ** Rtree virtual table module xEof method.
   898   1053   **
   899   1054   ** Return non-zero if the cursor does not currently point to a valid 
................................................................................
   908   1063   ** Convert raw bits from the on-disk RTree record into a coordinate value.
   909   1064   ** The on-disk format is big-endian and needs to be converted for little-
   910   1065   ** endian platforms.  The on-disk record stores integer coordinates if
   911   1066   ** eInt is true and it stores 32-bit floating point records if eInt is
   912   1067   ** false.  a[] is the four bytes of the on-disk record to be decoded.
   913   1068   ** Store the results in "r".
   914   1069   **
   915         -** There are three versions of this macro, one each for little-endian and
   916         -** big-endian processors and a third generic implementation.  The endian-
   917         -** specific implementations are much faster and are preferred if the
   918         -** processor endianness is known at compile-time.  The SQLITE_BYTEORDER
   919         -** macro is part of sqliteInt.h and hence the endian-specific
   920         -** implementation will only be used if this module is compiled as part
   921         -** of the amalgamation.
         1070  +** There are five versions of this macro.  The last one is generic.  The
         1071  +** other four are various architectures-specific optimizations.
   922   1072   */
   923         -#if defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==1234
         1073  +#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
         1074  +#define RTREE_DECODE_COORD(eInt, a, r) {                        \
         1075  +    RtreeCoord c;    /* Coordinate decoded */                   \
         1076  +    c.u = _byteswap_ulong(*(u32*)a);                            \
         1077  +    r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
         1078  +}
         1079  +#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
         1080  +#define RTREE_DECODE_COORD(eInt, a, r) {                        \
         1081  +    RtreeCoord c;    /* Coordinate decoded */                   \
         1082  +    c.u = __builtin_bswap32(*(u32*)a);                          \
         1083  +    r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
         1084  +}
         1085  +#elif SQLITE_BYTEORDER==1234
   924   1086   #define RTREE_DECODE_COORD(eInt, a, r) {                        \
   925   1087       RtreeCoord c;    /* Coordinate decoded */                   \
   926   1088       memcpy(&c.u,a,4);                                           \
   927   1089       c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)|                   \
   928   1090             ((c.u&0xff)<<24)|((c.u&0xff00)<<8);                   \
   929   1091       r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
   930   1092   }
   931         -#elif defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==4321
         1093  +#elif SQLITE_BYTEORDER==4321
   932   1094   #define RTREE_DECODE_COORD(eInt, a, r) {                        \
   933   1095       RtreeCoord c;    /* Coordinate decoded */                   \
   934   1096       memcpy(&c.u,a,4);                                           \
   935   1097       r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
   936   1098   }
   937   1099   #else
   938   1100   #define RTREE_DECODE_COORD(eInt, a, r) {                        \
................................................................................
   951   1113     RtreeConstraint *pConstraint,  /* The constraint to test */
   952   1114     int eInt,                      /* True if RTree holding integer coordinates */
   953   1115     u8 *pCellData,                 /* Raw cell content */
   954   1116     RtreeSearchPoint *pSearch,     /* Container of this cell */
   955   1117     sqlite3_rtree_dbl *prScore,    /* OUT: score for the cell */
   956   1118     int *peWithin                  /* OUT: visibility of the cell */
   957   1119   ){
   958         -  int i;                                                /* Loop counter */
   959   1120     sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */
   960   1121     int nCoord = pInfo->nCoord;                           /* No. of coordinates */
   961   1122     int rc;                                             /* Callback return code */
         1123  +  RtreeCoord c;                                       /* Translator union */
   962   1124     sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2];   /* Decoded coordinates */
   963   1125   
   964   1126     assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY );
   965   1127     assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 );
   966   1128   
   967   1129     if( pConstraint->op==RTREE_QUERY && pSearch->iLevel==1 ){
   968   1130       pInfo->iRowid = readInt64(pCellData);
   969   1131     }
   970   1132     pCellData += 8;
   971         -  for(i=0; i<nCoord; i++, pCellData += 4){
   972         -    RTREE_DECODE_COORD(eInt, pCellData, aCoord[i]);
         1133  +#ifndef SQLITE_RTREE_INT_ONLY
         1134  +  if( eInt==0 ){
         1135  +    switch( nCoord ){
         1136  +      case 10:  readCoord(pCellData+36, &c); aCoord[9] = c.f;
         1137  +                readCoord(pCellData+32, &c); aCoord[8] = c.f;
         1138  +      case 8:   readCoord(pCellData+28, &c); aCoord[7] = c.f;
         1139  +                readCoord(pCellData+24, &c); aCoord[6] = c.f;
         1140  +      case 6:   readCoord(pCellData+20, &c); aCoord[5] = c.f;
         1141  +                readCoord(pCellData+16, &c); aCoord[4] = c.f;
         1142  +      case 4:   readCoord(pCellData+12, &c); aCoord[3] = c.f;
         1143  +                readCoord(pCellData+8,  &c); aCoord[2] = c.f;
         1144  +      default:  readCoord(pCellData+4,  &c); aCoord[1] = c.f;
         1145  +                readCoord(pCellData,    &c); aCoord[0] = c.f;
         1146  +    }
         1147  +  }else
         1148  +#endif
         1149  +  {
         1150  +    switch( nCoord ){
         1151  +      case 10:  readCoord(pCellData+36, &c); aCoord[9] = c.i;
         1152  +                readCoord(pCellData+32, &c); aCoord[8] = c.i;
         1153  +      case 8:   readCoord(pCellData+28, &c); aCoord[7] = c.i;
         1154  +                readCoord(pCellData+24, &c); aCoord[6] = c.i;
         1155  +      case 6:   readCoord(pCellData+20, &c); aCoord[5] = c.i;
         1156  +                readCoord(pCellData+16, &c); aCoord[4] = c.i;
         1157  +      case 4:   readCoord(pCellData+12, &c); aCoord[3] = c.i;
         1158  +                readCoord(pCellData+8,  &c); aCoord[2] = c.i;
         1159  +      default:  readCoord(pCellData+4,  &c); aCoord[1] = c.i;
         1160  +                readCoord(pCellData,    &c); aCoord[0] = c.i;
         1161  +    }
   973   1162     }
   974   1163     if( pConstraint->op==RTREE_MATCH ){
         1164  +    int eWithin = 0;
   975   1165       rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo,
   976         -                              nCoord, aCoord, &i);
   977         -    if( i==0 ) *peWithin = NOT_WITHIN;
         1166  +                              nCoord, aCoord, &eWithin);
         1167  +    if( eWithin==0 ) *peWithin = NOT_WITHIN;
   978   1168       *prScore = RTREE_ZERO;
   979   1169     }else{
   980   1170       pInfo->aCoord = aCoord;
   981   1171       pInfo->iLevel = pSearch->iLevel - 1;
   982   1172       pInfo->rScore = pInfo->rParentScore = pSearch->rScore;
   983   1173       pInfo->eWithin = pInfo->eParentWithin = pSearch->eWithin;
   984   1174       rc = pConstraint->u.xQueryFunc(pInfo);
................................................................................
  1006   1196     /* p->iCoord might point to either a lower or upper bound coordinate
  1007   1197     ** in a coordinate pair.  But make pCellData point to the lower bound.
  1008   1198     */
  1009   1199     pCellData += 8 + 4*(p->iCoord&0xfe);
  1010   1200   
  1011   1201     assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
  1012   1202         || p->op==RTREE_GT || p->op==RTREE_EQ );
         1203  +  assert( ((((char*)pCellData) - (char*)0)&3)==0 );  /* 4-byte aligned */
  1013   1204     switch( p->op ){
  1014   1205       case RTREE_LE:
  1015   1206       case RTREE_LT:
  1016   1207       case RTREE_EQ:
  1017   1208         RTREE_DECODE_COORD(eInt, pCellData, val);
  1018   1209         /* val now holds the lower bound of the coordinate pair */
  1019   1210         if( p->u.rValue>=val ) return;
................................................................................
  1046   1237     int *peWithin              /* Adjust downward, as appropriate */
  1047   1238   ){
  1048   1239     RtreeDValue xN;      /* Coordinate value converted to a double */
  1049   1240   
  1050   1241     assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
  1051   1242         || p->op==RTREE_GT || p->op==RTREE_EQ );
  1052   1243     pCellData += 8 + p->iCoord*4;
         1244  +  assert( ((((char*)pCellData) - (char*)0)&3)==0 );  /* 4-byte aligned */
  1053   1245     RTREE_DECODE_COORD(eInt, pCellData, xN);
  1054   1246     switch( p->op ){
  1055   1247       case RTREE_LE: if( xN <= p->u.rValue ) return;  break;
  1056   1248       case RTREE_LT: if( xN <  p->u.rValue ) return;  break;
  1057   1249       case RTREE_GE: if( xN >= p->u.rValue ) return;  break;
  1058   1250       case RTREE_GT: if( xN >  p->u.rValue ) return;  break;
  1059   1251       default:       if( xN == p->u.rValue ) return;  break;
................................................................................
  1362   1554         if( p->iCell>=nCell ){
  1363   1555           RTREE_QUEUE_TRACE(pCur, "POP-S:");
  1364   1556           rtreeSearchPointPop(pCur);
  1365   1557         }
  1366   1558         if( rScore<RTREE_ZERO ) rScore = RTREE_ZERO;
  1367   1559         p = rtreeSearchPointNew(pCur, rScore, x.iLevel);
  1368   1560         if( p==0 ) return SQLITE_NOMEM;
  1369         -      p->eWithin = eWithin;
         1561  +      p->eWithin = (u8)eWithin;
  1370   1562         p->id = x.id;
  1371   1563         p->iCell = x.iCell;
  1372   1564         RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
  1373   1565         break;
  1374   1566       }
  1375   1567       if( p->iCell>=nCell ){
  1376   1568         RTREE_QUEUE_TRACE(pCur, "POP-Se:");
................................................................................
  1550   1742       if( rc==SQLITE_OK && pLeaf!=0 ){
  1551   1743         p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
  1552   1744         assert( p!=0 );  /* Always returns pCsr->sPoint */
  1553   1745         pCsr->aNode[0] = pLeaf;
  1554   1746         p->id = iNode;
  1555   1747         p->eWithin = PARTLY_WITHIN;
  1556   1748         rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
  1557         -      p->iCell = iCell;
         1749  +      p->iCell = (u8)iCell;
  1558   1750         RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
  1559   1751       }else{
  1560   1752         pCsr->atEOF = 1;
  1561   1753       }
  1562   1754     }else{
  1563   1755       /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array 
  1564   1756       ** with the configured constraints. 
................................................................................
  1583   1775               ** can be cast into an RtreeMatchArg object. One created using
  1584   1776               ** an sqlite3_rtree_geometry_callback() SQL user function.
  1585   1777               */
  1586   1778               rc = deserializeGeometry(argv[ii], p);
  1587   1779               if( rc!=SQLITE_OK ){
  1588   1780                 break;
  1589   1781               }
  1590         -            p->pInfo->nCoord = pRtree->nDim*2;
         1782  +            p->pInfo->nCoord = pRtree->nDim2;
  1591   1783               p->pInfo->anQueue = pCsr->anQueue;
  1592   1784               p->pInfo->mxLevel = pRtree->iDepth + 1;
  1593   1785             }else{
  1594   1786   #ifdef SQLITE_RTREE_INT_ONLY
  1595   1787               p->u.rValue = sqlite3_value_int64(argv[ii]);
  1596   1788   #else
  1597   1789               p->u.rValue = sqlite3_value_double(argv[ii]);
................................................................................
  1598   1790   #endif
  1599   1791             }
  1600   1792           }
  1601   1793         }
  1602   1794       }
  1603   1795       if( rc==SQLITE_OK ){
  1604   1796         RtreeSearchPoint *pNew;
  1605         -      pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1);
         1797  +      pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
  1606   1798         if( pNew==0 ) return SQLITE_NOMEM;
  1607   1799         pNew->id = 1;
  1608   1800         pNew->iCell = 0;
  1609   1801         pNew->eWithin = PARTLY_WITHIN;
  1610   1802         assert( pCsr->bPoint==1 );
  1611   1803         pCsr->aNode[0] = pRoot;
  1612   1804         pRoot = 0;
................................................................................
  1726   1918           case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
  1727   1919           default:
  1728   1920             assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
  1729   1921             op = RTREE_MATCH; 
  1730   1922             break;
  1731   1923         }
  1732   1924         zIdxStr[iIdx++] = op;
  1733         -      zIdxStr[iIdx++] = p->iColumn - 1 + '0';
         1925  +      zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
  1734   1926         pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
  1735   1927         pIdxInfo->aConstraintUsage[ii].omit = 1;
  1736   1928       }
  1737   1929     }
  1738   1930   
  1739   1931     pIdxInfo->idxNum = 2;
  1740   1932     pIdxInfo->needToFreeIdxStr = 1;
................................................................................
  1750   1942   }
  1751   1943   
  1752   1944   /*
  1753   1945   ** Return the N-dimensional volumn of the cell stored in *p.
  1754   1946   */
  1755   1947   static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
  1756   1948     RtreeDValue area = (RtreeDValue)1;
  1757         -  int ii;
  1758         -  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
  1759         -    area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])));
         1949  +  assert( pRtree->nDim>=1 && pRtree->nDim<=5 );
         1950  +#ifndef SQLITE_RTREE_INT_ONLY
         1951  +  if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
         1952  +    switch( pRtree->nDim ){
         1953  +      case 5:  area  = p->aCoord[9].f - p->aCoord[8].f;
         1954  +      case 4:  area *= p->aCoord[7].f - p->aCoord[6].f;
         1955  +      case 3:  area *= p->aCoord[5].f - p->aCoord[4].f;
         1956  +      case 2:  area *= p->aCoord[3].f - p->aCoord[2].f;
         1957  +      default: area *= p->aCoord[1].f - p->aCoord[0].f;
         1958  +    }
         1959  +  }else
         1960  +#endif
         1961  +  {
         1962  +    switch( pRtree->nDim ){
         1963  +      case 5:  area  = p->aCoord[9].i - p->aCoord[8].i;
         1964  +      case 4:  area *= p->aCoord[7].i - p->aCoord[6].i;
         1965  +      case 3:  area *= p->aCoord[5].i - p->aCoord[4].i;
         1966  +      case 2:  area *= p->aCoord[3].i - p->aCoord[2].i;
         1967  +      default: area *= p->aCoord[1].i - p->aCoord[0].i;
         1968  +    }
  1760   1969     }
  1761   1970     return area;
  1762   1971   }
  1763   1972   
  1764   1973   /*
  1765   1974   ** Return the margin length of cell p. The margin length is the sum
  1766   1975   ** of the objects size in each dimension.
  1767   1976   */
  1768   1977   static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){
  1769         -  RtreeDValue margin = (RtreeDValue)0;
         1978  +  RtreeDValue margin;
  1770   1979     int ii;
  1771         -  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
         1980  +  margin = DCOORD(p->aCoord[1]) - DCOORD(p->aCoord[0]);
         1981  +  for(ii=2; ii<pRtree->nDim2; ii+=2){
  1772   1982       margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
  1773   1983     }
  1774   1984     return margin;
  1775   1985   }
  1776   1986   
  1777   1987   /*
  1778   1988   ** Store the union of cells p1 and p2 in p1.
  1779   1989   */
  1780   1990   static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
  1781         -  int ii;
         1991  +  int ii = 0;
  1782   1992     if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
  1783         -    for(ii=0; ii<(pRtree->nDim*2); ii+=2){
         1993  +    do{
  1784   1994         p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);
  1785   1995         p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);
  1786         -    }
         1996  +      ii += 2;
         1997  +    }while( ii<pRtree->nDim2 );
  1787   1998     }else{
  1788         -    for(ii=0; ii<(pRtree->nDim*2); ii+=2){
         1999  +    do{
  1789   2000         p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
  1790   2001         p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
  1791         -    }
         2002  +      ii += 2;
         2003  +    }while( ii<pRtree->nDim2 );
  1792   2004     }
  1793   2005   }
  1794   2006   
  1795   2007   /*
  1796   2008   ** Return true if the area covered by p2 is a subset of the area covered
  1797   2009   ** by p1. False otherwise.
  1798   2010   */
  1799   2011   static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
  1800   2012     int ii;
  1801   2013     int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
  1802         -  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
         2014  +  for(ii=0; ii<pRtree->nDim2; ii+=2){
  1803   2015       RtreeCoord *a1 = &p1->aCoord[ii];
  1804   2016       RtreeCoord *a2 = &p2->aCoord[ii];
  1805   2017       if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f)) 
  1806   2018        || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i)) 
  1807   2019       ){
  1808   2020         return 0;
  1809   2021       }
................................................................................
  1830   2042     int nCell
  1831   2043   ){
  1832   2044     int ii;
  1833   2045     RtreeDValue overlap = RTREE_ZERO;
  1834   2046     for(ii=0; ii<nCell; ii++){
  1835   2047       int jj;
  1836   2048       RtreeDValue o = (RtreeDValue)1;
  1837         -    for(jj=0; jj<(pRtree->nDim*2); jj+=2){
         2049  +    for(jj=0; jj<pRtree->nDim2; jj+=2){
  1838   2050         RtreeDValue x1, x2;
  1839   2051         x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
  1840   2052         x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
  1841   2053         if( x2<x1 ){
  1842   2054           o = (RtreeDValue)0;
  1843   2055           break;
  1844   2056         }else{
................................................................................
  2886   3098       **
  2887   3099       ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
  2888   3100       ** with "column" that are interpreted as table constraints.
  2889   3101       ** Example:  CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
  2890   3102       ** This problem was discovered after years of use, so we silently ignore
  2891   3103       ** these kinds of misdeclared tables to avoid breaking any legacy.
  2892   3104       */
  2893         -    assert( nData<=(pRtree->nDim*2 + 3) );
         3105  +    assert( nData<=(pRtree->nDim2 + 3) );
  2894   3106   
  2895   3107   #ifndef SQLITE_RTREE_INT_ONLY
  2896   3108       if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
  2897   3109         for(ii=0; ii<nData-4; ii+=2){
  2898   3110           cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
  2899   3111           cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
  2900   3112           if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
................................................................................
  2975   3187       }
  2976   3188     }
  2977   3189   
  2978   3190   constraint:
  2979   3191     rtreeRelease(pRtree);
  2980   3192     return rc;
  2981   3193   }
         3194  +
         3195  +/*
         3196  +** Called when a transaction starts.
         3197  +*/
         3198  +static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
         3199  +  Rtree *pRtree = (Rtree *)pVtab;
         3200  +  assert( pRtree->inWrTrans==0 );
         3201  +  pRtree->inWrTrans++;
         3202  +  return SQLITE_OK;
         3203  +}
         3204  +
         3205  +/*
         3206  +** Called when a transaction completes (either by COMMIT or ROLLBACK).
         3207  +** The sqlite3_blob object should be released at this point.
         3208  +*/
         3209  +static int rtreeEndTransaction(sqlite3_vtab *pVtab){
         3210  +  Rtree *pRtree = (Rtree *)pVtab;
         3211  +  pRtree->inWrTrans = 0;
         3212  +  nodeBlobReset(pRtree);
         3213  +  return SQLITE_OK;
         3214  +}
  2982   3215   
  2983   3216   /*
  2984   3217   ** The xRename method for rtree module virtual tables.
  2985   3218   */
  2986   3219   static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
  2987   3220     Rtree *pRtree = (Rtree *)pVtab;
  2988   3221     int rc = SQLITE_NOMEM;
................................................................................
  2996   3229     );
  2997   3230     if( zSql ){
  2998   3231       rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0);
  2999   3232       sqlite3_free(zSql);
  3000   3233     }
  3001   3234     return rc;
  3002   3235   }
         3236  +
  3003   3237   
  3004   3238   /*
  3005   3239   ** This function populates the pRtree->nRowEst variable with an estimate
  3006   3240   ** of the number of rows in the virtual table. If possible, this is based
  3007   3241   ** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
  3008   3242   */
  3009   3243   static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
................................................................................
  3056   3290     rtreeClose,                 /* xClose - close a cursor */
  3057   3291     rtreeFilter,                /* xFilter - configure scan constraints */
  3058   3292     rtreeNext,                  /* xNext - advance a cursor */
  3059   3293     rtreeEof,                   /* xEof */
  3060   3294     rtreeColumn,                /* xColumn - read data */
  3061   3295     rtreeRowid,                 /* xRowid - read data */
  3062   3296     rtreeUpdate,                /* xUpdate - write data */
  3063         -  0,                          /* xBegin - begin transaction */
  3064         -  0,                          /* xSync - sync transaction */
  3065         -  0,                          /* xCommit - commit transaction */
  3066         -  0,                          /* xRollback - rollback transaction */
         3297  +  rtreeBeginTransaction,      /* xBegin - begin transaction */
         3298  +  rtreeEndTransaction,        /* xSync - sync transaction */
         3299  +  rtreeEndTransaction,        /* xCommit - commit transaction */
         3300  +  rtreeEndTransaction,        /* xRollback - rollback transaction */
  3067   3301     0,                          /* xFindFunction - function overloading */
  3068   3302     rtreeRename,                /* xRename - rename the table */
  3069   3303     0,                          /* xSavepoint */
  3070   3304     0,                          /* xRelease */
  3071         -  0                           /* xRollbackTo */
         3305  +  0,                          /* xRollbackTo */
  3072   3306   };
  3073   3307   
  3074   3308   static int rtreeSqlInit(
  3075   3309     Rtree *pRtree, 
  3076   3310     sqlite3 *db, 
  3077   3311     const char *zDb, 
  3078   3312     const char *zPrefix, 
  3079   3313     int isCreate
  3080   3314   ){
  3081   3315     int rc = SQLITE_OK;
  3082   3316   
  3083         -  #define N_STATEMENT 9
         3317  +  #define N_STATEMENT 8
  3084   3318     static const char *azSql[N_STATEMENT] = {
  3085         -    /* Read and write the xxx_node table */
  3086         -    "SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1",
         3319  +    /* Write the xxx_node table */
  3087   3320       "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
  3088   3321       "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
  3089   3322   
  3090   3323       /* Read and write the xxx_rowid table */
  3091   3324       "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1",
  3092   3325       "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)",
  3093   3326       "DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1",
................................................................................
  3117   3350       rc = sqlite3_exec(db, zCreate, 0, 0, 0);
  3118   3351       sqlite3_free(zCreate);
  3119   3352       if( rc!=SQLITE_OK ){
  3120   3353         return rc;
  3121   3354       }
  3122   3355     }
  3123   3356   
  3124         -  appStmt[0] = &pRtree->pReadNode;
  3125         -  appStmt[1] = &pRtree->pWriteNode;
  3126         -  appStmt[2] = &pRtree->pDeleteNode;
  3127         -  appStmt[3] = &pRtree->pReadRowid;
  3128         -  appStmt[4] = &pRtree->pWriteRowid;
  3129         -  appStmt[5] = &pRtree->pDeleteRowid;
  3130         -  appStmt[6] = &pRtree->pReadParent;
  3131         -  appStmt[7] = &pRtree->pWriteParent;
  3132         -  appStmt[8] = &pRtree->pDeleteParent;
         3357  +  appStmt[0] = &pRtree->pWriteNode;
         3358  +  appStmt[1] = &pRtree->pDeleteNode;
         3359  +  appStmt[2] = &pRtree->pReadRowid;
         3360  +  appStmt[3] = &pRtree->pWriteRowid;
         3361  +  appStmt[4] = &pRtree->pDeleteRowid;
         3362  +  appStmt[5] = &pRtree->pReadParent;
         3363  +  appStmt[6] = &pRtree->pWriteParent;
         3364  +  appStmt[7] = &pRtree->pDeleteParent;
  3133   3365   
  3134   3366     rc = rtreeQueryStat1(db, pRtree);
  3135   3367     for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
  3136   3368       char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
  3137   3369       if( zSql ){
  3138   3370         rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0); 
  3139   3371       }else{
................................................................................
  3263   3495       return SQLITE_NOMEM;
  3264   3496     }
  3265   3497     memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
  3266   3498     pRtree->nBusy = 1;
  3267   3499     pRtree->base.pModule = &rtreeModule;
  3268   3500     pRtree->zDb = (char *)&pRtree[1];
  3269   3501     pRtree->zName = &pRtree->zDb[nDb+1];
  3270         -  pRtree->nDim = (argc-4)/2;
  3271         -  pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
  3272         -  pRtree->eCoordType = eCoordType;
         3502  +  pRtree->nDim = (u8)((argc-4)/2);
         3503  +  pRtree->nDim2 = pRtree->nDim*2;
         3504  +  pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
         3505  +  pRtree->eCoordType = (u8)eCoordType;
  3273   3506     memcpy(pRtree->zDb, argv[1], nDb);
  3274   3507     memcpy(pRtree->zName, argv[2], nName);
  3275   3508   
  3276   3509     /* Figure out the node size to use. */
  3277   3510     rc = getNodeSize(db, pRtree, isCreate, pzErr);
  3278   3511   
  3279   3512     /* Create/Connect to the underlying relational database schema. If
................................................................................
  3338   3571     RtreeNode node;
  3339   3572     Rtree tree;
  3340   3573     int ii;
  3341   3574   
  3342   3575     UNUSED_PARAMETER(nArg);
  3343   3576     memset(&node, 0, sizeof(RtreeNode));
  3344   3577     memset(&tree, 0, sizeof(Rtree));
  3345         -  tree.nDim = sqlite3_value_int(apArg[0]);
         3578  +  tree.nDim = (u8)sqlite3_value_int(apArg[0]);
         3579  +  tree.nDim2 = tree.nDim*2;
  3346   3580     tree.nBytesPerCell = 8 + 8 * tree.nDim;
  3347   3581     node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
  3348   3582   
  3349   3583     for(ii=0; ii<NCELL(&node); ii++){
  3350   3584       char zCell[512];
  3351   3585       int nCell = 0;
  3352   3586       RtreeCell cell;
  3353   3587       int jj;
  3354   3588   
  3355   3589       nodeGetCell(&tree, &node, ii, &cell);
  3356   3590       sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
  3357   3591       nCell = (int)strlen(zCell);
  3358         -    for(jj=0; jj<tree.nDim*2; jj++){
         3592  +    for(jj=0; jj<tree.nDim2; jj++){
  3359   3593   #ifndef SQLITE_RTREE_INT_ONLY
  3360   3594         sqlite3_snprintf(512-nCell,&zCell[nCell], " %g",
  3361   3595                          (double)cell.aCoord[jj].f);
  3362   3596   #else
  3363   3597         sqlite3_snprintf(512-nCell,&zCell[nCell], " %d",
  3364   3598                          cell.aCoord[jj].i);
  3365   3599   #endif

Changes to ext/rtree/rtreeA.test.

   105    105     1   "SELECT * FROM t1"
   106    106     2   "SELECT * FROM t1 WHERE rowid=5"
   107    107     3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
   108    108     4   "SELECT * FROM t1 WHERE x1<10 AND x2>12"
   109    109   }
   110    110   
   111    111   do_execsql_test  rtreeA-1.2.0 { DROP TABLE t1_node } {}
   112         -do_corruption_tests rtreeA-1.2 -error "SQL logic error or missing database" {
          112  +do_corruption_tests rtreeA-1.2 -error "database disk image is malformed" {
   113    113     1   "SELECT * FROM t1"
   114    114     2   "SELECT * FROM t1 WHERE rowid=5"
   115    115     3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
   116    116     4   "SELECT * FROM t1 WHERE x1<10 AND x2>12"
   117    117   }
   118    118   
   119    119   #-------------------------------------------------------------------------

Changes to ext/session/session1.test.

    16     16   } 
    17     17   source [file join [file dirname [info script]] session_common.tcl]
    18     18   source $testdir/tester.tcl
    19     19   ifcapable !session {finish_test; return}
    20     20   
    21     21   set testprefix session1
    22     22   
    23         -do_execsql_test 1.0 {
    24         -  CREATE TABLE t1(x PRIMARY KEY, y);
           23  +# Run all tests in this file twice. Once with "WITHOUT ROWID", and once
           24  +# with regular rowid tables.
           25  +#
           26  +foreach {tn trailing} {
           27  +  1 ""
           28  +  2 " WITHOUT ROWID "
           29  +} {
           30  +eval [string map [list %WR% $trailing] {
           31  +
           32  +db close
           33  +forcedelete test.db test.db2
           34  +reset_db
           35  +
           36  +do_execsql_test $tn.1.0 {
           37  +  CREATE TABLE t1(x PRIMARY KEY, y) %WR%;
    25     38     INSERT INTO t1 VALUES('abc', 'def');
    26     39   }
    27     40   
    28     41   #-------------------------------------------------------------------------
    29     42   # Test creating, attaching tables to and deleting session objects.
    30     43   #
    31         -do_test 1.1 { sqlite3session S db main } {S}
    32         -do_test 1.2 { S delete } {}
    33         -do_test 1.3 { sqlite3session S db main } {S}
    34         -do_test 1.4 { S attach t1 } {}
    35         -do_test 1.5 { S delete } {}
    36         -do_test 1.6 { sqlite3session S db main } {S}
    37         -do_test 1.7 { S attach t1 ; S attach t2 ; S attach t3 } {}
    38         -do_test 1.8 { S attach t1 ; S attach t2 ; S attach t3 } {}
    39         -do_test 1.9 { S delete } {}
    40         -do_test 1.10 {
           44  +do_test $tn.1.1 { sqlite3session S db main } {S}
           45  +do_test $tn.1.2 { S delete } {}
           46  +do_test $tn.1.3 { sqlite3session S db main } {S}
           47  +do_test $tn.1.4 { S attach t1 } {}
           48  +do_test $tn.1.5 { S delete } {}
           49  +do_test $tn.1.6 { sqlite3session S db main } {S}
           50  +do_test $tn.1.7 { S attach t1 ; S attach t2 ; S attach t3 } {}
           51  +do_test $tn.1.8 { S attach t1 ; S attach t2 ; S attach t3 } {}
           52  +do_test $tn.1.9 { S delete } {}
           53  +do_test $tn.1.10 {
    41     54     sqlite3session S db main
    42     55     S attach t1
    43     56     execsql { INSERT INTO t1 VALUES('ghi', 'jkl') }
    44     57   } {}
    45         -do_test 1.11 { S delete } {}
    46         -do_test 1.12 {
    47         -  sqlite3session S db main
    48         -  S attach t1
    49         -  execsql { INSERT INTO t1 VALUES('mno', 'pqr') }
    50         -  execsql { UPDATE t1 SET x = 111 WHERE rowid = 1 }
    51         -  execsql { DELETE FROM t1 WHERE rowid = 2 }
    52         -} {}
    53         -do_test 1.13 {
    54         -  S changeset
    55         -  S delete
    56         -} {}
           58  +do_test $tn.1.11 { S delete } {}
           59  +if {$tn==1} {
           60  +  do_test $tn.1.12 {
           61  +    sqlite3session S db main
           62  +    S attach t1
           63  +    execsql { INSERT INTO t1 VALUES('mno', 'pqr') }
           64  +    execsql { UPDATE t1 SET x = 111 WHERE rowid = 1 }
           65  +    execsql { DELETE FROM t1 WHERE rowid = 2 }
           66  +  } {}
           67  +  do_test $tn.1.13 {
           68  +    S changeset
           69  +    S delete
           70  +  } {}
           71  +}
    57     72   
    58     73   #-------------------------------------------------------------------------
    59     74   # Simple changeset tests. Also test the sqlite3changeset_invert() 
    60     75   # function.
    61     76   #
    62         -do_test 2.1.1 {
           77  +do_test $tn.2.1.1 {
    63     78     execsql { DELETE FROM t1 }
    64     79     sqlite3session S db main
    65     80     S attach t1
    66     81     execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') }
    67     82     execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') }
    68     83     execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
    69     84   } {}
    70         -do_changeset_test 2.1.2 S {
           85  +do_changeset_test $tn.2.1.2 S {
    71     86     {INSERT t1 0 X. {} {i 1 t Sukhothai}}
    72     87     {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
    73     88     {INSERT t1 0 X. {} {i 3 t Thonburi}}
    74     89   }
    75         -do_changeset_invert_test 2.1.3 S {
           90  +do_changeset_invert_test $tn.2.1.3 S {
    76     91     {DELETE t1 0 X. {i 1 t Sukhothai} {}}
    77     92     {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
    78     93     {DELETE t1 0 X. {i 3 t Thonburi} {}}
    79     94   }
    80         -do_test 2.1.4 { S delete } {}
           95  +do_test $tn.2.1.4 { S delete } {}
    81     96   
    82         -do_test 2.2.1 {
           97  +do_test $tn.2.2.1 {
    83     98     sqlite3session S db main
    84     99     S attach t1
    85    100     execsql { DELETE FROM t1 WHERE 1 }
    86    101   } {}
    87         -do_changeset_test 2.2.2 S {
          102  +do_changeset_test $tn.2.2.2 S {
    88    103     {DELETE t1 0 X. {i 1 t Sukhothai} {}}
    89    104     {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
    90    105     {DELETE t1 0 X. {i 3 t Thonburi} {}}
    91    106   }
    92         -do_changeset_invert_test 2.2.3 S {
          107  +do_changeset_invert_test $tn.2.2.3 S {
    93    108     {INSERT t1 0 X. {} {i 1 t Sukhothai}}
    94    109     {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
    95    110     {INSERT t1 0 X. {} {i 3 t Thonburi}}
    96    111   }
    97         -do_test 2.2.4 { S delete } {}
          112  +do_test $tn.2.2.4 { S delete } {}
    98    113   
    99         -do_test 2.3.1 {
          114  +do_test $tn.2.3.1 {
   100    115     execsql { DELETE FROM t1 }
   101    116     sqlite3session S db main
   102    117     execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') }
   103    118     execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') }
   104    119     execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
   105    120     S attach t1
   106    121     execsql { 
   107    122       UPDATE t1 SET x = 10 WHERE x = 1;
   108    123       UPDATE t1 SET y = 'Surin' WHERE x = 2;
   109    124       UPDATE t1 SET x = 20, y = 'Thapae' WHERE x = 3;
   110    125     }
   111    126   } {}
   112    127   
   113         -do_changeset_test 2.3.2 S {
          128  +do_changeset_test $tn.2.3.2 S {
   114    129     {INSERT t1 0 X. {} {i 10 t Sukhothai}} 
   115    130     {DELETE t1 0 X. {i 1 t Sukhothai} {}} 
   116    131     {UPDATE t1 0 X. {i 2 t Ayutthaya} {{} {} t Surin}} 
   117    132     {DELETE t1 0 X. {i 3 t Thonburi} {}} 
   118    133     {INSERT t1 0 X. {} {i 20 t Thapae}} 
   119    134   }
   120    135   
   121         -do_changeset_invert_test 2.3.3 S {
          136  +do_changeset_invert_test $tn.2.3.3 S {
   122    137     {DELETE t1 0 X. {i 10 t Sukhothai} {}} 
   123    138     {INSERT t1 0 X. {} {i 1 t Sukhothai}} 
   124    139     {UPDATE t1 0 X. {i 2 t Surin} {{} {} t Ayutthaya}} 
   125    140     {INSERT t1 0 X. {} {i 3 t Thonburi}} 
   126    141     {DELETE t1 0 X. {i 20 t Thapae} {}}
   127    142   }
   128         -do_test 2.3.4 { S delete } {}
          143  +do_test $tn.2.3.4 { S delete } {}
   129    144   
   130         -do_test 2.4.1 {
          145  +do_test $tn.2.4.1 {
   131    146     sqlite3session S db main
   132    147     S attach t1
   133    148     execsql { INSERT INTO t1 VALUES(100, 'Bangkok') }
   134    149     execsql { DELETE FROM t1 WHERE x = 100 }
   135    150   } {}
   136         -do_changeset_test 2.4.2 S {}
   137         -do_changeset_invert_test 2.4.3 S {}
   138         -do_test 2.4.4 { S delete } {}
          151  +do_changeset_test $tn.2.4.2 S {}
          152  +do_changeset_invert_test $tn.2.4.3 S {}
          153  +do_test $tn.2.4.4 { S delete } {}
   139    154   
   140    155   #-------------------------------------------------------------------------
   141    156   # Test the application of simple changesets. These tests also test that
   142    157   # the conflict callback is invoked correctly. For these tests, the 
   143    158   # conflict callback always returns OMIT.
   144    159   #
   145    160   db close
................................................................................
   185    200   
   186    201   proc do_db2_test {testname sql {result {}}} {
   187    202     uplevel do_test $testname [list "execsql {$sql} db2"] [list [list {*}$result]]
   188    203   }
   189    204   
   190    205   # Test INSERT changesets.
   191    206   #
   192         -do_test 3.1.0 {
   193         -  execsql { CREATE TABLE t1(a PRIMARY KEY, b NOT NULL) } db2
          207  +do_test $tn.3.1.0 {
          208  +  execsql { CREATE TABLE t1(a PRIMARY KEY, b NOT NULL) %WR% } db2
   194    209     execsql { 
   195         -    CREATE TABLE t1(a PRIMARY KEY, b);
          210  +    CREATE TABLE t1(a PRIMARY KEY, b) %WR%;
   196    211       INSERT INTO t1 VALUES(1, 'one');
   197    212       INSERT INTO t1 VALUES(2, 'two');
   198    213     } db 
   199    214   } {}
   200         -do_db2_test 3.1.1 "INSERT INTO t1 VALUES(6, 'VI')"
   201         -do_conflict_test 3.1.2 -tables t1 -sql {
          215  +do_db2_test $tn.3.1.1 "INSERT INTO t1 VALUES(6, 'VI')"
          216  +do_conflict_test $tn.3.1.2 -tables t1 -sql {
   202    217     INSERT INTO t1 VALUES(3, 'three');
   203    218     INSERT INTO t1 VALUES(4, 'four');
   204    219     INSERT INTO t1 VALUES(5, 'five');
   205    220     INSERT INTO t1 VALUES(6, 'six');
   206    221     INSERT INTO t1 VALUES(7, 'seven');
   207    222     INSERT INTO t1 VALUES(8, NULL);
   208    223   } -conflicts {
   209    224     {INSERT t1 CONFLICT {i 6 t six} {i 6 t VI}}
   210    225     {INSERT t1 CONSTRAINT {i 8 n {}}}
   211    226   }
   212    227   
   213         -do_db2_test 3.1.3 "SELECT * FROM t1" {
   214         -  6 VI 3 three 4 four 5 five 7 seven
          228  +do_db2_test $tn.3.1.3 "SELECT * FROM t1 ORDER BY a" {
          229  +  3 three 4 four 5 five 6 VI 7 seven
   215    230   }
   216         -do_execsql_test 3.1.4 "SELECT * FROM t1" {
          231  +do_execsql_test $tn.3.1.4 "SELECT * FROM t1" {
   217    232     1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 {}
   218    233   }
   219    234   
   220    235   # Test DELETE changesets.
   221    236   #
   222         -do_execsql_test 3.2.1 {
          237  +do_execsql_test $tn.3.2.1 {
   223    238     PRAGMA foreign_keys = on;
   224         -  CREATE TABLE t2(a PRIMARY KEY, b);
          239  +  CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
   225    240     CREATE TABLE t3(c, d REFERENCES t2);
   226    241     INSERT INTO t2 VALUES(1, 'one');
   227    242     INSERT INTO t2 VALUES(2, 'two');
   228    243     INSERT INTO t2 VALUES(3, 'three');
   229    244     INSERT INTO t2 VALUES(4, 'four');
   230    245   }
   231         -do_db2_test 3.2.2 {
          246  +do_db2_test $tn.3.2.2 {
   232    247     PRAGMA foreign_keys = on;
   233         -  CREATE TABLE t2(a PRIMARY KEY, b);
          248  +  CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
   234    249     CREATE TABLE t3(c, d REFERENCES t2);
   235    250     INSERT INTO t2 VALUES(1, 'one');
   236    251     INSERT INTO t2 VALUES(2, 'two');
   237    252     INSERT INTO t2 VALUES(4, 'five');
   238    253     INSERT INTO t3 VALUES('i', 1);
   239    254   }
   240         -do_conflict_test 3.2.3 -tables t2 -sql {
          255  +do_conflict_test $tn.3.2.3 -tables t2 -sql {
   241    256     DELETE FROM t2 WHERE a = 1;
   242    257     DELETE FROM t2 WHERE a = 2;
   243    258     DELETE FROM t2 WHERE a = 3;
   244    259     DELETE FROM t2 WHERE a = 4;
   245    260   } -conflicts {
   246    261     {DELETE t2 NOTFOUND {i 3 t three}}
   247    262     {DELETE t2 DATA {i 4 t four} {i 4 t five}}
   248    263     {FOREIGN_KEY 1}
   249    264   }
   250         -do_execsql_test 3.2.4 "SELECT * FROM t2" {}
   251         -do_db2_test     3.2.5 "SELECT * FROM t2" {4 five}
          265  +do_execsql_test $tn.3.2.4 "SELECT * FROM t2" {}
          266  +do_db2_test $tn.3.2.5 "SELECT * FROM t2" {4 five}
   252    267   
   253    268   # Test UPDATE changesets.
   254    269   #
   255         -do_execsql_test 3.3.1 {
   256         -  CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c));
          270  +do_execsql_test $tn.3.3.1 {
          271  +  CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c))%WR%;
   257    272     INSERT INTO t4 VALUES(1, 2, 3);
   258    273     INSERT INTO t4 VALUES(4, 5, 6);
   259    274     INSERT INTO t4 VALUES(7, 8, 9);
   260    275     INSERT INTO t4 VALUES(10, 11, 12);
   261    276   }
   262         -do_db2_test 3.3.2 {
   263         -  CREATE TABLE t4(a NOT NULL, b, c, PRIMARY KEY(b, c));
          277  +do_db2_test $tn.3.3.2 {
          278  +  CREATE TABLE t4(a NOT NULL, b, c, PRIMARY KEY(b, c))%WR%;
   264    279     INSERT INTO t4 VALUES(0, 2, 3);
   265    280     INSERT INTO t4 VALUES(4, 5, 7);
   266    281     INSERT INTO t4 VALUES(7, 8, 9);
   267    282     INSERT INTO t4 VALUES(10, 11, 12);
   268    283   }
   269         -do_conflict_test 3.3.3 -tables t4 -sql {
          284  +do_conflict_test $tn.3.3.3 -tables t4 -sql {
   270    285     UPDATE t4 SET a = -1 WHERE b = 2;
   271    286     UPDATE t4 SET a = -1 WHERE b = 5;
   272    287     UPDATE t4 SET a = NULL WHERE c = 9;
   273    288     UPDATE t4 SET a = 'x' WHERE b = 11;
   274    289   } -conflicts {
   275    290     {UPDATE t4 DATA {i 1 i 2 i 3} {i -1 {} {} {} {}} {i 0 i 2 i 3}}
   276    291     {UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}}
   277    292     {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}}
   278    293   }
   279         -do_db2_test     3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12}
   280         -do_execsql_test 3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12}
          294  +do_db2_test $tn.3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12}
          295  +do_execsql_test $tn.3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12}
   281    296   
   282    297   #-------------------------------------------------------------------------
   283    298   # This next block of tests verifies that values returned by the conflict
   284    299   # handler are intepreted correctly.
   285    300   #
   286    301   
   287    302   proc test_reset {} {
................................................................................
   293    308   }
   294    309   
   295    310   proc xConflict {args} {
   296    311     lappend ::xConflict $args
   297    312     return $::conflict_return
   298    313   }
   299    314   
   300         -foreach {tn conflict_return after} {
          315  +foreach {tn2 conflict_return after} {
   301    316     1 OMIT      {1 2 value1   4 5 7       10 x x}
   302    317     2 REPLACE   {1 2 value1   4 5 value2  10 8 9}
   303    318   } {
   304    319     test_reset
   305    320   
   306         -  do_test 4.$tn.1 {
          321  +  do_test $tn.4.$tn2.1 {
   307    322       foreach db {db db2} {
   308    323         execsql { 
   309         -        CREATE TABLE t1(a, b, c, PRIMARY KEY(a));
          324  +        CREATE TABLE t1(a, b, c, PRIMARY KEY(a))%WR%;
   310    325           INSERT INTO t1 VALUES(1, 2, 3);
   311    326           INSERT INTO t1 VALUES(4, 5, 6);
   312    327           INSERT INTO t1 VALUES(7, 8, 9);
   313    328         } $db
   314    329       }
   315    330       execsql { 
   316    331         REPLACE INTO t1 VALUES(4, 5, 7);
   317    332         REPLACE INTO t1 VALUES(10, 'x', 'x');
   318    333       } db2
   319    334     } {}
   320    335   
   321         -  do_conflict_test 4.$tn.2 -tables t1 -sql {
          336  +  do_conflict_test $tn.4.$tn2.2 -tables t1 -sql {
   322    337       UPDATE t1 SET c = 'value1' WHERE a = 1;       -- no conflict
   323    338       UPDATE t1 SET c = 'value2' WHERE a = 4;       -- DATA conflict
   324    339       UPDATE t1 SET a = 10 WHERE a = 7;             -- CONFLICT conflict
   325    340     } -conflicts {
   326    341       {INSERT t1 CONFLICT {i 10 i 8 i 9} {i 10 t x t x}}
   327    342       {UPDATE t1 DATA {i 4 {} {} i 6} {{} {} {} {} t value2} {i 4 i 5 i 7}}
   328    343     }
   329    344   
   330         -  do_db2_test 4.$tn.3 "SELECT * FROM t1 ORDER BY a" $after
          345  +  do_db2_test $tn.4.$tn2.3 "SELECT * FROM t1 ORDER BY a" $after
   331    346   }
   332    347   
   333         -foreach {tn conflict_return} {
          348  +foreach {tn2 conflict_return} {
   334    349     1 OMIT
   335    350     2 REPLACE
   336    351   } {
   337    352     test_reset
   338    353   
   339         -  do_test 5.$tn.1 {
          354  +  do_test $tn.5.$tn2.1 {
   340    355       # Create an identical schema in both databases.
   341    356       set schema {
   342         -      CREATE TABLE "'foolish name'"(x, y, z, PRIMARY KEY(x, y));
          357  +      CREATE TABLE "'foolish name'"(x, y, z, PRIMARY KEY(x, y))%WR%;
   343    358       }
   344    359       execsql $schema db
   345    360       execsql $schema db2
   346    361   
   347    362       # Add some rows to [db2]. These rows will cause conflicts later
   348    363       # on when the changeset from [db] is applied to it.
   349    364       execsql { 
................................................................................
   350    365         INSERT INTO "'foolish name'" VALUES('one', 'one', 'ii');
   351    366         INSERT INTO "'foolish name'" VALUES('one', 'two', 'i');
   352    367         INSERT INTO "'foolish name'" VALUES('two', 'two', 'ii');
   353    368       } db2
   354    369   
   355    370     } {}
   356    371   
   357         -  do_conflict_test 5.$tn.2 -tables {{'foolish name'}} -sql {
          372  +  do_conflict_test $tn.5.$tn2.2 -tables {{'foolish name'}} -sql {
   358    373       INSERT INTO "'foolish name'" VALUES('one', 'two', 2);
   359    374     } -conflicts {
   360    375       {INSERT {'foolish name'} CONFLICT {t one t two i 2} {t one t two t i}}
   361    376     }
   362    377   
   363    378     set res(REPLACE) {one one ii one two 2 two two ii}
   364    379     set res(OMIT)    {one one ii one two i two two ii}
   365         -  do_db2_test 5.$tn.3 {
          380  +  do_db2_test $tn.5.$tn2.3 {
   366    381       SELECT * FROM "'foolish name'" ORDER BY x, y
   367    382     } $res($conflict_return)
   368    383   
   369    384   
   370         -  do_test 5.$tn.1 {
          385  +  do_test $tn.5.$tn2.1 {
   371    386       set schema {
   372         -      CREATE TABLE d1("z""z" PRIMARY KEY, y);
          387  +      CREATE TABLE d1("z""z" PRIMARY KEY, y)%WR%;
   373    388         INSERT INTO d1 VALUES(1, 'one');
   374    389         INSERT INTO d1 VALUES(2, 'two');
   375    390       }
   376    391       execsql $schema db
   377    392       execsql $schema db2
   378    393   
   379    394       execsql { 
   380    395         UPDATE d1 SET y = 'TWO' WHERE "z""z" = 2;
   381    396       } db2
   382    397   
   383    398     } {}
   384    399   
   385         -  do_conflict_test 5.$tn.2 -tables d1 -sql {
          400  +  do_conflict_test $tn.5.$tn2.2 -tables d1 -sql {
   386    401       DELETE FROM d1 WHERE "z""z" = 2;
   387    402     } -conflicts {
   388    403       {DELETE d1 DATA {i 2 t two} {i 2 t TWO}}
   389    404     }
   390    405   
   391    406     set res(REPLACE) {1 one}
   392    407     set res(OMIT)    {1 one 2 TWO}
   393         -  do_db2_test 5.$tn.3 "SELECT * FROM d1" $res($conflict_return)
          408  +  do_db2_test $tn.5.$tn2.3 "SELECT * FROM d1" $res($conflict_return)
   394    409   }
   395    410   
   396    411   #-------------------------------------------------------------------------
   397    412   # Test that two tables can be monitored by a single session object.
   398    413   #
   399    414   test_reset
   400    415   set schema {
   401         -  CREATE TABLE t1(a COLLATE nocase PRIMARY KEY, b);
   402         -  CREATE TABLE t2(a, b PRIMARY KEY);
          416  +  CREATE TABLE t1(a COLLATE nocase PRIMARY KEY, b)%WR%;
          417  +  CREATE TABLE t2(a, b PRIMARY KEY)%WR%;
   403    418   }
   404         -do_test 6.0 {
          419  +do_test $tn.6.0 {
   405    420     execsql $schema db
   406    421     execsql $schema db2
   407    422     execsql {
   408    423       INSERT INTO t1 VALUES('a', 'b');
   409    424       INSERT INTO t2 VALUES('a', 'b');
   410    425     } db2
   411    426   } {}
   412    427   
   413    428   set conflict_return ""
   414         -do_conflict_test 6.1 -tables {t1 t2} -sql {
          429  +do_conflict_test $tn.6.1 -tables {t1 t2} -sql {
   415    430     INSERT INTO t1 VALUES('1', '2');
   416    431     INSERT INTO t1 VALUES('A', 'B');
   417    432     INSERT INTO t2 VALUES('A', 'B');
   418    433   } -conflicts {
   419    434     {INSERT t1 CONFLICT {t A t B} {t a t b}}
   420    435   }
   421    436   
   422         -do_db2_test 6.2 "SELECT * FROM t1" {a b 1 2}
   423         -do_db2_test 6.3 "SELECT * FROM t2" {a b A B}
          437  +do_db2_test $tn.6.2 "SELECT * FROM t1 ORDER BY a" {1 2 a b}
          438  +do_db2_test $tn.6.3 "SELECT * FROM t2 ORDER BY a" {A B a b}
   424    439   
   425    440   #-------------------------------------------------------------------------
   426    441   # Test that session objects are not confused by changes to table in
   427    442   # other databases.
   428    443   #
   429    444   catch { db2 close }
   430    445   drop_all_tables
   431    446   forcedelete test.db2
   432         -do_iterator_test 7.1 * {
          447  +do_iterator_test $tn.7.1 * {
   433    448     ATTACH 'test.db2' AS aux;
   434         -  CREATE TABLE main.t1(x PRIMARY KEY, y);
   435         -  CREATE TABLE aux.t1(x PRIMARY KEY, y);
          449  +  CREATE TABLE main.t1(x PRIMARY KEY, y)%WR%;
          450  +  CREATE TABLE aux.t1(x PRIMARY KEY, y)%WR%;
   436    451   
   437    452     INSERT INTO main.t1 VALUES('one', 1);
   438    453     INSERT INTO main.t1 VALUES('two', 2);
   439    454     INSERT INTO aux.t1 VALUES('three', 3);
   440    455     INSERT INTO aux.t1 VALUES('four', 4);
   441    456   } {
   442    457     {INSERT t1 0 X. {} {t two i 2}} 
   443    458     {INSERT t1 0 X. {} {t one i 1}}
   444    459   }
   445    460   
   446    461   #-------------------------------------------------------------------------
   447    462   # Test the sqlite3session_isempty() function.
   448    463   #
   449         -do_test 8.1 {
          464  +do_test $tn.8.1 {
   450    465     execsql {
   451         -    CREATE TABLE t5(x PRIMARY KEY, y);
   452         -    CREATE TABLE t6(x PRIMARY KEY, y);
          466  +    CREATE TABLE t5(x PRIMARY KEY, y)%WR%;
          467  +    CREATE TABLE t6(x PRIMARY KEY, y)%WR%;
   453    468       INSERT INTO t5 VALUES('a', 'b');
   454    469       INSERT INTO t6 VALUES('a', 'b');
   455    470     }
   456    471     sqlite3session S db main
   457    472     S attach *
   458    473   
   459    474     S isempty
   460    475   } {1}
   461         -do_test 8.2 {
          476  +do_test $tn.8.2 {
   462    477     execsql { DELETE FROM t5 }
   463    478     S isempty
   464    479   } {0}
   465         -do_test 8.3 {
          480  +do_test $tn.8.3 {
   466    481     S delete
   467    482     sqlite3session S db main
   468    483     S attach t5
   469    484     execsql { DELETE FROM t5 }
   470    485     S isempty
   471    486   } {1}
   472         -do_test 8.4 { S delete } {}
          487  +do_test $tn.8.4 { S delete } {}
   473    488   
   474         -do_test 8.5 {
          489  +do_test $tn.8.5 {
   475    490     sqlite3session S db main
   476    491     S attach t5
   477    492     S attach t6
   478    493     execsql { INSERT INTO t5 VALUES(1, 2) }
   479    494     S isempty
   480    495   } {0}
   481    496   
   482         -do_test 8.6 {
          497  +do_test $tn.8.6 {
   483    498     S delete
   484    499     sqlite3session S db main
   485    500     S attach t5
   486    501     S attach t6
   487    502     execsql { INSERT INTO t6 VALUES(1, 2) }
   488    503     S isempty
   489    504   } {0}
   490         -do_test 8.7 { S delete } {}
          505  +do_test $tn.8.7 { S delete } {}
   491    506   
   492    507   #-------------------------------------------------------------------------
   493    508   #
   494         -do_execsql_test 9.1 {
   495         -  CREATE TABLE t7(a, b, c, d, e PRIMARY KEY, f, g);
          509  +do_execsql_test $tn.9.1 {
          510  +  CREATE TABLE t7(a, b, c, d, e PRIMARY KEY, f, g)%WR%;
   496    511     INSERT INTO t7 VALUES(1, 1, 1, 1, 1, 1, 1);
   497    512   }
   498         -do_test 9.2 { 
          513  +do_test $tn.9.2 { 
   499    514     sqlite3session S db main 
   500    515     S attach *
   501    516     execsql { UPDATE t7 SET b=2, d=2 }
   502    517   } {}
   503         -do_changeset_test 9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}}
          518  +do_changeset_test $tn.9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}}
   504    519   S delete
   505    520   catch { db2 close }
   506    521    
   507    522   #-------------------------------------------------------------------------
   508    523   # Test a really long table name.
   509    524   #
   510    525   reset_db
   511    526   set tblname [string repeat tblname123 100]
   512         -do_test 10.1.1 {
          527  +do_test $tn.10.1.1 {
   513    528     execsql "
   514         -    CREATE TABLE $tblname (a PRIMARY KEY, b);
          529  +    CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
   515    530       INSERT INTO $tblname VALUES('xyz', 'def');
   516    531     "
   517    532     sqlite3session S db main
   518    533     S attach $tblname
   519    534     execsql " 
   520    535       INSERT INTO $tblname VALUES('uvw', 'abc');
   521    536       DELETE FROM $tblname WHERE a = 'xyz';
   522    537     "
   523    538   } {}
   524    539   breakpoint
   525         -do_changeset_test 10.1.2 S "
          540  +do_changeset_test $tn.10.1.2 S "
   526    541     {INSERT $tblname 0 X. {} {t uvw t abc}}
   527    542     {DELETE $tblname 0 X. {t xyz t def} {}}
   528    543   "
   529         -do_test 10.1.4 { S delete } {}
          544  +do_test $tn.10.1.4 { S delete } {}
   530    545   
   531    546   #---------------------------------------------------------------
   532    547   reset_db
   533         -do_execsql_test 11.1 {
          548  +do_execsql_test $tn.11.1 {
   534    549     CREATE TABLE t1(a, b);
   535    550   }
   536         -do_test 11.2 {
          551  +do_test $tn.11.2 {
   537    552     sqlite3session S db main
   538    553     S attach t1
   539    554     execsql {
   540    555       INSERT INTO t1 VALUES(1, 2);
   541    556     }
   542    557     S changeset
   543    558   } {}
................................................................................
   546    561   
   547    562   
   548    563   #-------------------------------------------------------------------------
   549    564   # Test a really long table name.
   550    565   #
   551    566   reset_db
   552    567   set tblname [string repeat tblname123 100]
   553         -do_test 10.1.1 {
          568  +do_test $tn.10.1.1 {
   554    569     execsql "
   555         -    CREATE TABLE $tblname (a PRIMARY KEY, b);
          570  +    CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
   556    571       INSERT INTO $tblname VALUES('xyz', 'def');
   557    572     "
   558    573     sqlite3session S db main
   559    574     S attach $tblname
   560    575     execsql " 
   561    576       INSERT INTO $tblname VALUES('uvw', 'abc');
   562    577       DELETE FROM $tblname WHERE a = 'xyz';
   563    578     "
   564    579   } {}
   565    580   breakpoint
   566         -do_changeset_test 10.1.2 S "
          581  +do_changeset_test $tn.10.1.2 S "
   567    582     {INSERT $tblname 0 X. {} {t uvw t abc}}
   568    583     {DELETE $tblname 0 X. {t xyz t def} {}}
   569    584   "
   570         -do_test 10.1.4 { S delete } {}
          585  +do_test $tn.10.1.4 { S delete } {}
   571    586   
   572    587   #-------------------------------------------------------------------------
   573    588   # Test the effect of updating a column from 0.0 to 0.0.
   574    589   #
   575    590   reset_db
   576         -do_execsql_test 11.1 {
   577         -  CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL);
          591  +do_execsql_test $tn.11.1 {
          592  +  CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL)%WR%;
   578    593     INSERT INTO t1 VALUES(1, 0.0);
   579    594   }
   580         -do_iterator_test 11.2 * {
          595  +do_iterator_test $tn.11.2 * {
   581    596     UPDATE t1 SET b = 0.0;
   582    597   } {
   583    598   }
          599  +
          600  +reset_db
          601  +do_execsql_test $tn.12.1 {
          602  +  CREATE TABLE t1(r INTEGER PRIMARY KEY, a, b)%WR%;
          603  +  CREATE INDEX i1 ON t1(a);
          604  +  INSERT INTO t1 VALUES(1, 1, 1);
          605  +  INSERT INTO t1 VALUES(2, 1, 2);
          606  +  INSERT INTO t1 VALUES(3, 1, 3);
          607  +}
          608  +
          609  +do_iterator_test $tn.12.2 * {
          610  +  UPDATE t1 SET b='one' WHERE a=1;
          611  +} {
          612  +  {UPDATE t1 0 X.. {i 1 {} {} i 1} {{} {} {} {} t one}}
          613  +  {UPDATE t1 0 X.. {i 2 {} {} i 2} {{} {} {} {} t one}}
          614  +  {UPDATE t1 0 X.. {i 3 {} {} i 3} {{} {} {} {} t one}}
          615  +}
          616  +
          617  +}]
          618  +}
          619  +
   584    620   
   585    621   finish_test

Added ext/session/session_speed_test.c.

            1  +/*
            2  +** 2017 January 31
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +** This file contains the source code for a standalone program used to
           13  +** test the performance of the sessions module. Compile and run:
           14  +**
           15  +**   ./session_speed_test -help
           16  +**
           17  +** for details.
           18  +*/
           19  +
           20  +#include "sqlite3.h"
           21  +#include <stdio.h>
           22  +#include <stdlib.h>
           23  +#include <string.h>
           24  +#include <stddef.h>
           25  +#include <unistd.h>
           26  +
           27  +/*************************************************************************
           28  +** Start of generic command line parser.
           29  +*/
           30  +#define CMDLINE_BARE       0
           31  +#define CMDLINE_INTEGER    1
           32  +#define CMDLINE_STRING     2
           33  +#define CMDLINE_BOOLEAN    3
           34  +
           35  +typedef struct CmdLineOption CmdLineOption;
           36  +struct CmdLineOption {
           37  +  const char *zText;              /* Name of command line option */
           38  +  const char *zHelp;              /* Help text for option */
           39  +  int eType;                      /* One of the CMDLINE_* values */
           40  +  int iOff;                       /* Offset of output variable */
           41  +};
           42  +
           43  +#define CMDLINE_INT32(x,y,z) {x, y, CMDLINE_INTEGER, z}
           44  +#define CMDLINE_BOOL(x,y,z)  {x, y, CMDLINE_BOOLEAN, z}
           45  +#define CMDLINE_TEXT(x,y,z)  {x, y, CMDLINE_STRING, z}
           46  +#define CMDLINE_NONE(x,y,z)  {x, y, CMDLINE_BARE, z}
           47  +
           48  +static void option_requires_argument_error(CmdLineOption *pOpt){
           49  +  fprintf(stderr, "Option requires a%s argument: %s\n", 
           50  +      pOpt->eType==CMDLINE_INTEGER ? "n integer" :
           51  +      pOpt->eType==CMDLINE_STRING ? " string" : " boolean",
           52  +      pOpt->zText
           53  +  );
           54  +  exit(1);
           55  +}
           56  +
           57  +static void ambiguous_option_error(const char *zArg){
           58  +  fprintf(stderr, "Option is ambiguous: %s\n", zArg);
           59  +  exit(1);
           60  +}
           61  +
           62  +static void unknown_option_error(
           63  +  const char *zArg, 
           64  +  CmdLineOption *aOpt,
           65  +  const char *zHelp
           66  +){
           67  +  int i;
           68  +  fprintf(stderr, "Unknown option: %s\n", zArg);
           69  +  fprintf(stderr, "\nOptions are:\n");
           70  +  fprintf(stderr, "  % -30sEcho command line options\n", "-cmdline:verbose");
           71  +  for(i=0; aOpt[i].zText; i++){
           72  +    int eType = aOpt[i].eType;
           73  +    char *zOpt = sqlite3_mprintf("%s %s", aOpt[i].zText,
           74  +        eType==CMDLINE_BARE ? "" :
           75  +        eType==CMDLINE_INTEGER ? "N" :
           76  +        eType==CMDLINE_BOOLEAN ? "BOOLEAN" : "TEXT"
           77  +    );
           78  +    fprintf(stderr, "  % -30s%s\n", zOpt, aOpt[i].zHelp);
           79  +    sqlite3_free(zOpt);
           80  +  }
           81  +  if( zHelp ){
           82  +    fprintf(stderr, "\n%s\n", zHelp);
           83  +  }
           84  +  exit(1);
           85  +}
           86  +
           87  +static int get_integer_option(CmdLineOption *pOpt, const char *zArg){
           88  +  int i = 0;
           89  +  int iRet = 0;
           90  +  int bSign = 1;
           91  +  if( zArg[0]=='-' ){
           92  +    bSign = -1;
           93  +    i = 1;
           94  +  }
           95  +  while( zArg[i] ){
           96  +    if( zArg[i]<'0' || zArg[i]>'9' ) option_requires_argument_error(pOpt);
           97  +    iRet = iRet*10 + (zArg[i] - '0');
           98  +    i++;
           99  +  }
          100  +  return (iRet*bSign);
          101  +}
          102  +
          103  +static int get_boolean_option(CmdLineOption *pOpt, const char *zArg){
          104  +  if( 0==sqlite3_stricmp(zArg, "true") ) return 1;
          105  +  if( 0==sqlite3_stricmp(zArg, "1") ) return 1;
          106  +  if( 0==sqlite3_stricmp(zArg, "0") ) return 0;
          107  +  if( 0==sqlite3_stricmp(zArg, "false") ) return 0;
          108  +  option_requires_argument_error(pOpt);
          109  +  return 0;
          110  +}
          111  +
          112  +static void parse_command_line(
          113  +  int argc, 
          114  +  char **argv, 
          115  +  int iStart,
          116  +  CmdLineOption *aOpt,
          117  +  void *pStruct,
          118  +  const char *zHelp
          119  +){
          120  +  char *pOut = (char*)pStruct;
          121  +  int bVerbose = 0;
          122  +  int iArg;
          123  +
          124  +  for(iArg=iStart; iArg<argc; iArg++){
          125  +    const char *zArg = argv[iArg];
          126  +    int nArg = strlen(zArg);
          127  +    int nMatch = 0;
          128  +    int iOpt;
          129  +
          130  +    for(iOpt=0; aOpt[iOpt].zText; iOpt++){
          131  +      CmdLineOption *pOpt = &aOpt[iOpt];
          132  +      if( 0==sqlite3_strnicmp(pOpt->zText, zArg, nArg) ){
          133  +        if( nMatch ){
          134  +          ambiguous_option_error(zArg);
          135  +        }
          136  +        nMatch++;
          137  +        if( pOpt->eType==CMDLINE_BARE ){
          138  +          *(int*)(&pOut[pOpt->iOff]) = 1;
          139  +        }else{
          140  +          iArg++;
          141  +          if( iArg==argc ){
          142  +            option_requires_argument_error(pOpt);
          143  +          }
          144  +          switch( pOpt->eType ){
          145  +            case CMDLINE_INTEGER:
          146  +              *(int*)(&pOut[pOpt->iOff]) = get_integer_option(pOpt, argv[iArg]);
          147  +              break;
          148  +            case CMDLINE_STRING:
          149  +              *(const char**)(&pOut[pOpt->iOff]) = argv[iArg];
          150  +              break;
          151  +            case CMDLINE_BOOLEAN:
          152  +              *(int*)(&pOut[pOpt->iOff]) = get_boolean_option(pOpt, argv[iArg]);
          153  +              break;
          154  +          }
          155  +        }
          156  +      }
          157  +    }
          158  +
          159  +    if( nMatch==0 && 0==sqlite3_strnicmp("-cmdline:verbose", zArg, nArg) ){
          160  +      bVerbose = 1;
          161  +      nMatch = 1;
          162  +    }
          163  +
          164  +    if( nMatch==0 ){
          165  +      unknown_option_error(zArg, aOpt, zHelp);
          166  +    }
          167  +  }
          168  +
          169  +  if( bVerbose ){
          170  +    int iOpt;
          171  +    fprintf(stdout, "Options are: ");
          172  +    for(iOpt=0; aOpt[iOpt].zText; iOpt++){
          173  +      CmdLineOption *pOpt = &aOpt[iOpt];
          174  +      if( pOpt->eType!=CMDLINE_BARE || *(int*)(&pOut[pOpt->iOff]) ){
          175  +        fprintf(stdout, "%s ", pOpt->zText);
          176  +      }
          177  +      switch( pOpt->eType ){
          178  +        case CMDLINE_INTEGER:
          179  +          fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff]));
          180  +          break;
          181  +        case CMDLINE_BOOLEAN:
          182  +          fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff]));
          183  +          break;
          184  +        case CMDLINE_STRING:
          185  +          fprintf(stdout, "%s ", *(const char**)(&pOut[pOpt->iOff]));
          186  +          break;
          187  +      }
          188  +    }
          189  +    fprintf(stdout, "\n");
          190  +  }
          191  +}
          192  +/* 
          193  +** End of generic command line parser.
          194  +*************************************************************************/
          195  +
          196  +static void abort_due_to_error(int rc){
          197  +  fprintf(stderr, "Error: %d\n");
          198  +  exit(-1);
          199  +}
          200  +
          201  +static void execsql(sqlite3 *db, const char *zSql){
          202  +  int rc = sqlite3_exec(db, zSql, 0, 0, 0);
          203  +  if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          204  +}
          205  +
          206  +static int xConflict(void *pCtx, int eConflict, sqlite3_changeset_iter *p){
          207  +  return SQLITE_CHANGESET_ABORT;
          208  +}
          209  +
          210  +static void run_test(
          211  +  sqlite3 *db, 
          212  +  sqlite3 *db2, 
          213  +  int nRow, 
          214  +  const char *zSql
          215  +){
          216  +  sqlite3_session *pSession = 0;
          217  +  sqlite3_stmt *pStmt = 0;
          218  +  int rc;
          219  +  int i;
          220  +  int nChangeset;
          221  +  void *pChangeset;
          222  +
          223  +  /* Attach a session object to database db */
          224  +  rc = sqlite3session_create(db, "main", &pSession);
          225  +  if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          226  +
          227  +  /* Configure the session to capture changes on all tables */
          228  +  rc = sqlite3session_attach(pSession, 0);
          229  +  if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          230  +
          231  +  /* Prepare the SQL statement */
          232  +  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
          233  +  if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          234  +
          235  +  /* Open a transaction */
          236  +  execsql(db, "BEGIN");
          237  +
          238  +  /* Execute the SQL statement nRow times */
          239  +  for(i=0; i<nRow; i++){
          240  +    sqlite3_bind_int(pStmt, 1, i);
          241  +    sqlite3_step(pStmt);
          242  +    rc = sqlite3_reset(pStmt);
          243  +    if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          244  +  }
          245  +  sqlite3_finalize(pStmt);
          246  +
          247  +  /* Extract a changeset from the sessions object */
          248  +  rc = sqlite3session_changeset(pSession, &nChangeset, &pChangeset);
          249  +  if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          250  +  execsql(db, "COMMIT");
          251  +
          252  +  /* Apply the changeset to the second db */
          253  +  rc = sqlite3changeset_apply(db2, nChangeset, pChangeset, 0, xConflict, 0);
          254  +  if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          255  +
          256  +  /* Cleanup */
          257  +  sqlite3_free(pChangeset);
          258  +  sqlite3session_delete(pSession);
          259  +}
          260  +
          261  +int main(int argc, char **argv){
          262  +  struct Options {
          263  +    int nRow;
          264  +    int bWithoutRowid;
          265  +    int bInteger;
          266  +    int bAll;
          267  +    const char *zDb;
          268  +  };
          269  +  struct Options o = { 2500, 0, 0, 0, "session_speed_test.db" };
          270  +
          271  +  CmdLineOption aOpt[] = {
          272  +    CMDLINE_INT32( "-rows", "number of rows in test",
          273  +      offsetof(struct Options, nRow) ),
          274  +    CMDLINE_BOOL("-without-rowid", "use WITHOUT ROWID tables", 
          275  +      offsetof(struct Options, bWithoutRowid) ),
          276  +    CMDLINE_BOOL("-integer", "use integer data (instead of text/blobs)",
          277  +      offsetof(struct Options, bInteger) ),
          278  +    CMDLINE_NONE("-all", "Run all 4 combos of -without-rowid and -integer",
          279  +      offsetof(struct Options, bAll) ),
          280  +    CMDLINE_TEXT("-database", "prefix for database files to use",
          281  +      offsetof(struct Options, zDb) ),
          282  +    {0, 0, 0, 0}
          283  +  };
          284  +
          285  +  const char *azCreate[] = {
          286  +    "CREATE TABLE t1(a PRIMARY KEY, b, c, d)",
          287  +    "CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID",
          288  +  };
          289  +
          290  +  const char *azInsert[] = {
          291  +    "INSERT INTO t1 VALUES("
          292  +    "printf('%.8d',?), randomblob(50), randomblob(50), randomblob(50))",
          293  +    "INSERT INTO t1 VALUES(?, random(), random(), random())"
          294  +  };
          295  +
          296  +  const char *azUpdate[] = {
          297  +    "UPDATE t1 SET d = randomblob(50) WHERE a = printf('%.8d',?)",
          298  +    "UPDATE t1 SET d = random() WHERE a = ?"
          299  +  };
          300  +
          301  +  const char *azDelete[] = {
          302  +    "DELETE FROM t1 WHERE a = printf('%.8d',?)",
          303  +    "DELETE FROM t1 WHERE a = ?"
          304  +  };
          305  +
          306  +  int rc;
          307  +  sqlite3 *db;
          308  +  sqlite3 *db2;
          309  +  char *zDb2;
          310  +  int bWithoutRowid;
          311  +  int bInteger;
          312  +
          313  +  parse_command_line(argc, argv, 1, aOpt, (void*)&o,
          314  +    "This program creates two new, empty, databases each containing a single\n"
          315  +    "table. It then does the following:\n\n"
          316  +    "  1. Inserts -rows rows into the first database\n"
          317  +    "  2. Updates each row in the first db\n"
          318  +    "  3. Delete each row from the first db\n\n"
          319  +    "The modifications made by each step are captured in a changeset and\n"
          320  +    "applied to the second database.\n"
          321  +  );
          322  +  zDb2 = sqlite3_mprintf("%s2", o.zDb);
          323  +
          324  +  for(bWithoutRowid=0; bWithoutRowid<2; bWithoutRowid++){
          325  +    for(bInteger=0; bInteger<2; bInteger++){
          326  +      if( o.bAll || (o.bWithoutRowid==bWithoutRowid && o.bInteger==bInteger) ){
          327  +        fprintf(stdout, "Testing %s data with %s table\n",
          328  +            bInteger ? "integer" : "blob/text",
          329  +            bWithoutRowid ? "WITHOUT ROWID" : "rowid"
          330  +        );
          331  +
          332  +        /* Open new database handles on two empty databases */
          333  +        unlink(o.zDb);
          334  +        rc = sqlite3_open(o.zDb, &db);
          335  +        if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          336  +        unlink(zDb2);
          337  +        rc = sqlite3_open(zDb2, &db2);
          338  +        if( rc!=SQLITE_OK ) abort_due_to_error(rc);
          339  +
          340  +        /* Create the schema in both databases. */
          341  +        execsql(db, azCreate[o.bWithoutRowid]);
          342  +        execsql(db2, azCreate[o.bWithoutRowid]);
          343  +
          344  +        /* Run the three tests */
          345  +        run_test(db, db2, o.nRow, azInsert[o.bInteger]);
          346  +        run_test(db, db2, o.nRow, azUpdate[o.bInteger]);
          347  +        run_test(db, db2, o.nRow, azDelete[o.bInteger]);
          348  +
          349  +        /* Close the db handles */
          350  +        sqlite3_close(db);
          351  +        sqlite3_close(db2);
          352  +      }
          353  +    }
          354  +  }
          355  +
          356  +
          357  +  return 0;
          358  +}
          359  +
          360  +

Added ext/session/sessionwor.test.

            1  +# 2017 Jan 31
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# The focus of this file is testing the session module. Specifically,
           13  +# testing support for WITHOUT ROWID tables.
           14  +#
           15  +
           16  +if {![info exists testdir]} {
           17  +  set testdir [file join [file dirname [info script]] .. .. test]
           18  +} 
           19  +source [file join [file dirname [info script]] session_common.tcl]
           20  +source $testdir/tester.tcl
           21  +ifcapable !session {finish_test; return}
           22  +
           23  +set testprefix sessionwor
           24  +
           25  +proc test_reset {} {
           26  +  catch { db close }
           27  +  catch { db2 close }
           28  +  forcedelete test.db test.db2
           29  +  sqlite3 db test.db
           30  +  sqlite3 db2 test.db2
           31  +}
           32  +
           33  +
           34  +do_execsql_test 1.0 {
           35  +  CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
           36  +}
           37  +
           38  +do_iterator_test 1.1 t1 {
           39  +  INSERT INTO t1 VALUES('one', 'two');
           40  +} {
           41  +  {INSERT t1 0 X. {} {t one t two}}
           42  +}
           43  +
           44  +do_iterator_test 1.2 t1 {
           45  +  UPDATE t1 SET b='three'
           46  +} {
           47  +  {UPDATE t1 0 X. {t one t two} {{} {} t three}}
           48  +}
           49  +
           50  +do_iterator_test 1.3 t1 {
           51  +  DELETE FROM t1;
           52  +} {
           53  +  {DELETE t1 0 X. {t one t three} {}}
           54  +}
           55  +
           56  +finish_test
           57  +

Changes to src/analyze.c.

   792    792   /*
   793    793   ** Implementation of the stat_get(P,J) SQL function.  This routine is
   794    794   ** used to query statistical information that has been gathered into
   795    795   ** the Stat4Accum object by prior calls to stat_push().  The P parameter
   796    796   ** has type BLOB but it is really just a pointer to the Stat4Accum object.
   797    797   ** The content to returned is determined by the parameter J
   798    798   ** which is one of the STAT_GET_xxxx values defined above.
          799  +**
          800  +** The stat_get(P,J) function is not available to generic SQL.  It is
          801  +** inserted as part of a manually constructed bytecode program.  (See
          802  +** the callStatGet() routine below.)  It is guaranteed that the P
          803  +** parameter will always be a poiner to a Stat4Accum object, never a
          804  +** NULL.
   799    805   **
   800    806   ** If neither STAT3 nor STAT4 are enabled, then J is always
   801    807   ** STAT_GET_STAT1 and is hence omitted and this routine becomes
   802    808   ** a one-parameter function, stat_get(P), that always returns the
   803    809   ** stat1 table entry information.
   804    810   */
   805    811   static void statGet(

Changes to src/btree.c.

  4040   4040   int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
  4041   4041     int rc = SQLITE_OK;
  4042   4042     if( p && p->inTrans==TRANS_WRITE ){
  4043   4043       BtShared *pBt = p->pBt;
  4044   4044       assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
  4045   4045       assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
  4046   4046       sqlite3BtreeEnter(p);
  4047         -    rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
         4047  +    if( op==SAVEPOINT_ROLLBACK ){
         4048  +      rc = saveAllCursors(pBt, 0, 0);
         4049  +    }
         4050  +    if( rc==SQLITE_OK ){
         4051  +      rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
         4052  +    }
  4048   4053       if( rc==SQLITE_OK ){
  4049   4054         if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
  4050   4055           pBt->nPage = 0;
  4051   4056         }
  4052   4057         rc = newDatabase(pBt);
  4053   4058         pBt->nPage = get4byte(28 + pBt->pPage1->aData);
  4054   4059   

Changes to src/delete.c.

   711    711     ** the update-hook is not invoked for rows removed by REPLACE, but the 
   712    712     ** pre-update-hook is.
   713    713     */ 
   714    714     if( pTab->pSelect==0 ){
   715    715       u8 p5 = 0;
   716    716       sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
   717    717       sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
   718         -    sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
          718  +    if( pParse->nested==0 ){
          719  +      sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
          720  +    }
   719    721       if( eMode!=ONEPASS_OFF ){
   720    722         sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE);
   721    723       }
   722    724       if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){
   723    725         sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
   724    726       }
   725    727       if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION;

Changes to src/expr.c.

   963    963       x = (ynVar)(++pParse->nVar);
   964    964     }else{
   965    965       int doAdd = 0;
   966    966       if( z[0]=='?' ){
   967    967         /* Wildcard of the form "?nnn".  Convert "nnn" to an integer and
   968    968         ** use it as the variable number */
   969    969         i64 i;
   970         -      int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
   971         -      x = (ynVar)i;
          970  +      int bOk;
          971  +      if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/
          972  +        i = z[1]-'0';  /* The common case of ?N for a single digit N */
          973  +        bOk = 1;
          974  +      }else{
          975  +        bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
          976  +      }
   972    977         testcase( i==0 );
   973    978         testcase( i==1 );
   974    979         testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
   975    980         testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
   976    981         if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
   977    982           sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
   978    983               db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
   979    984           return;
   980    985         }
          986  +      x = (ynVar)i;
   981    987         if( x>pParse->nVar ){
   982    988           pParse->nVar = (int)x;
   983    989           doAdd = 1;
   984    990         }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){
   985    991           doAdd = 1;
   986    992         }
   987    993       }else{
................................................................................
  1408   1414       struct IdList_item *pNewItem = &pNew->a[i];
  1409   1415       struct IdList_item *pOldItem = &p->a[i];
  1410   1416       pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
  1411   1417       pNewItem->idx = pOldItem->idx;
  1412   1418     }
  1413   1419     return pNew;
  1414   1420   }
  1415         -Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
  1416         -  Select *pNew, *pPrior;
         1421  +Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
         1422  +  Select *pRet = 0;
         1423  +  Select *pNext = 0;
         1424  +  Select **pp = &pRet;
         1425  +  Select *p;
         1426  +
  1417   1427     assert( db!=0 );
  1418         -  if( p==0 ) return 0;
  1419         -  pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
  1420         -  if( pNew==0 ) return 0;
  1421         -  pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
  1422         -  pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
  1423         -  pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
  1424         -  pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
  1425         -  pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
  1426         -  pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
  1427         -  pNew->op = p->op;
  1428         -  pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags);
  1429         -  if( pPrior ) pPrior->pNext = pNew;
  1430         -  pNew->pNext = 0;
  1431         -  pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
  1432         -  pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
  1433         -  pNew->iLimit = 0;
  1434         -  pNew->iOffset = 0;
  1435         -  pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
  1436         -  pNew->addrOpenEphm[0] = -1;
  1437         -  pNew->addrOpenEphm[1] = -1;
  1438         -  pNew->nSelectRow = p->nSelectRow;
  1439         -  pNew->pWith = withDup(db, p->pWith);
  1440         -  sqlite3SelectSetName(pNew, p->zSelName);
  1441         -  return pNew;
         1428  +  for(p=pDup; p; p=p->pPrior){
         1429  +    Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
         1430  +    if( pNew==0 ) break;
         1431  +    pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
         1432  +    pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
         1433  +    pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
         1434  +    pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
         1435  +    pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
         1436  +    pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
         1437  +    pNew->op = p->op;
         1438  +    pNew->pNext = pNext;
         1439  +    pNew->pPrior = 0;
         1440  +    pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
         1441  +    pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
         1442  +    pNew->iLimit = 0;
         1443  +    pNew->iOffset = 0;
         1444  +    pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
         1445  +    pNew->addrOpenEphm[0] = -1;
         1446  +    pNew->addrOpenEphm[1] = -1;
         1447  +    pNew->nSelectRow = p->nSelectRow;
         1448  +    pNew->pWith = withDup(db, p->pWith);
         1449  +    sqlite3SelectSetName(pNew, p->zSelName);
         1450  +    *pp = pNew;
         1451  +    pp = &pNew->pPrior;
         1452  +    pNext = pNew;
         1453  +  }
         1454  +
         1455  +  return pRet;
  1442   1456   }
  1443   1457   #else
  1444   1458   Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
  1445   1459     assert( p==0 );
  1446   1460     return 0;
  1447   1461   }
  1448   1462   #endif

Changes to src/insert.c.

  1726   1726     for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
  1727   1727       if( aRegIdx[i]==0 ) continue;
  1728   1728       bAffinityDone = 1;
  1729   1729       if( pIdx->pPartIdxWhere ){
  1730   1730         sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
  1731   1731         VdbeCoverage(v);
  1732   1732       }
  1733         -    sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
  1734         -                         aRegIdx[i]+1,
  1735         -                         pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
  1736         -    pik_flags = 0;
  1737         -    if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
         1733  +    pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
  1738   1734       if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
  1739   1735         assert( pParse->nested==0 );
  1740   1736         pik_flags |= OPFLAG_NCHANGE;
  1741   1737         pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
         1738  +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
         1739  +      if( update_flags==0 ){
         1740  +        sqlite3VdbeAddOp4(v, OP_InsertInt, 
         1741  +            iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
         1742  +        );
         1743  +        sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
         1744  +      }
         1745  +#endif
  1742   1746       }
         1747  +    sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
         1748  +                         aRegIdx[i]+1,
         1749  +                         pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
  1743   1750       sqlite3VdbeChangeP5(v, pik_flags);
  1744   1751     }
  1745   1752     if( !HasRowid(pTab) ) return;
  1746   1753     regData = regNewData + 1;
  1747   1754     regRec = sqlite3GetTempReg(pParse);
  1748   1755     sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
  1749   1756     sqlite3SetMakeRecordP5(v, pTab);

Changes to src/parse.y.

    61     61   
    62     62   /*
    63     63   ** Indicate that sqlite3ParserFree() will never be called with a null
    64     64   ** pointer.
    65     65   */
    66     66   #define YYPARSEFREENEVERNULL 1
    67     67   
           68  +/*
           69  +** In the amalgamation, the parse.c file generated by lemon and the
           70  +** tokenize.c file are concatenated.  In that case, sqlite3RunParser()
           71  +** has access to the the size of the yyParser object and so the parser
           72  +** engine can be allocated from stack.  In that case, only the
           73  +** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked
           74  +** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be
           75  +** omitted.
           76  +*/
           77  +#ifdef SQLITE_AMALGAMATION
           78  +# define sqlite3Parser_ENGINEALWAYSONSTACK 1
           79  +#endif
           80  +
    68     81   /*
    69     82   ** Alternative datatype for the argument to the malloc() routine passed
    70     83   ** into sqlite3ParserAlloc().  The default is size_t.
    71     84   */
    72     85   #define YYMALLOCARGTYPE  u64
    73     86   
    74     87   /*

Changes to src/pragma.c.

   275    275     return azModeName[eMode];
   276    276   }
   277    277   
   278    278   /*
   279    279   ** Locate a pragma in the aPragmaName[] array.
   280    280   */
   281    281   static const PragmaName *pragmaLocate(const char *zName){
   282         -  int upr, lwr, mid, rc;
          282  +  int upr, lwr, mid = 0, rc;
   283    283     lwr = 0;
   284    284     upr = ArraySize(aPragmaName)-1;
   285    285     while( lwr<=upr ){
   286    286       mid = (lwr+upr)/2;
   287    287       rc = sqlite3_stricmp(zName, aPragmaName[mid].zName);
   288    288       if( rc==0 ) break;
   289    289       if( rc<0 ){

Changes to src/select.c.

  4182   4182         return SQLITE_ERROR;
  4183   4183       }
  4184   4184       assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
  4185   4185   
  4186   4186       pCte->zCteErr = "circular reference: %s";
  4187   4187       pSavedWith = pParse->pWith;
  4188   4188       pParse->pWith = pWith;
  4189         -    sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
         4189  +    if( bMayRecursive ){
         4190  +      Select *pPrior = pSel->pPrior;
         4191  +      assert( pPrior->pWith==0 );
         4192  +      pPrior->pWith = pSel->pWith;
         4193  +      sqlite3WalkSelect(pWalker, pPrior);
         4194  +      pPrior->pWith = 0;
         4195  +    }else{
         4196  +      sqlite3WalkSelect(pWalker, pSel);
         4197  +    }
  4190   4198       pParse->pWith = pWith;
  4191   4199   
  4192   4200       for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
  4193   4201       pEList = pLeft->pEList;
  4194   4202       if( pCte->pCols ){
  4195   4203         if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){
  4196   4204           sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns",
................................................................................
  4226   4234   **
  4227   4235   ** This function is used as the xSelectCallback2() callback by
  4228   4236   ** sqlite3SelectExpand() when walking a SELECT tree to resolve table
  4229   4237   ** names and other FROM clause elements. 
  4230   4238   */
  4231   4239   static void selectPopWith(Walker *pWalker, Select *p){
  4232   4240     Parse *pParse = pWalker->pParse;
  4233         -  With *pWith = findRightmost(p)->pWith;
  4234         -  if( pWith!=0 ){
  4235         -    assert( pParse->pWith==pWith );
  4236         -    pParse->pWith = pWith->pOuter;
         4241  +  if( pParse->pWith && p->pPrior==0 ){
         4242  +    With *pWith = findRightmost(p)->pWith;
         4243  +    if( pWith!=0 ){
         4244  +      assert( pParse->pWith==pWith );
         4245  +      pParse->pWith = pWith->pOuter;
         4246  +    }
  4237   4247     }
  4238   4248   }
  4239   4249   #else
  4240   4250   #define selectPopWith 0
  4241   4251   #endif
  4242   4252   
  4243   4253   /*
................................................................................
  4279   4289       return WRC_Abort;
  4280   4290     }
  4281   4291     if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){
  4282   4292       return WRC_Prune;
  4283   4293     }
  4284   4294     pTabList = p->pSrc;
  4285   4295     pEList = p->pEList;
  4286         -  if( pWalker->xSelectCallback2==selectPopWith ){
  4287         -    sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
         4296  +  if( p->pWith ){
         4297  +    sqlite3WithPush(pParse, p->pWith, 0);
  4288   4298     }
  4289   4299   
  4290   4300     /* Make sure cursor numbers have been assigned to all entries in
  4291   4301     ** the FROM clause of the SELECT statement.
  4292   4302     */
  4293   4303     sqlite3SrcListAssignCursors(pParse, pTabList);
  4294   4304   
................................................................................
  4567   4577     w.xExprCallback = sqlite3ExprWalkNoop;
  4568   4578     w.pParse = pParse;
  4569   4579     if( pParse->hasCompound ){
  4570   4580       w.xSelectCallback = convertCompoundSelectToSubquery;
  4571   4581       sqlite3WalkSelect(&w, pSelect);
  4572   4582     }
  4573   4583     w.xSelectCallback = selectExpander;
  4574         -  if( (pSelect->selFlags & SF_MultiValue)==0 ){
  4575         -    w.xSelectCallback2 = selectPopWith;
  4576         -  }
         4584  +  w.xSelectCallback2 = selectPopWith;
  4577   4585     sqlite3WalkSelect(&w, pSelect);
  4578   4586   }
  4579   4587   
  4580   4588   
  4581   4589   #ifndef SQLITE_OMIT_SUBQUERY
  4582   4590   /*
  4583   4591   ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()

Changes to src/sqlite.h.in.

  5414   5414   ** ^In the case of an update, this is the [rowid] after the update takes place.
  5415   5415   **
  5416   5416   ** ^(The update hook is not invoked when internal system tables are
  5417   5417   ** modified (i.e. sqlite_master and sqlite_sequence).)^
  5418   5418   ** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
  5419   5419   **
  5420   5420   ** ^In the current implementation, the update hook
  5421         -** is not invoked when duplication rows are deleted because of an
         5421  +** is not invoked when conflicting rows are deleted because of an
  5422   5422   ** [ON CONFLICT | ON CONFLICT REPLACE] clause.  ^Nor is the update hook
  5423   5423   ** invoked when rows are deleted using the [truncate optimization].
  5424   5424   ** The exceptions defined in this paragraph might change in a future
  5425   5425   ** release of SQLite.
  5426   5426   **
  5427   5427   ** The update hook implementation must not do anything that will modify
  5428   5428   ** the database connection that invoked the update hook.  Any actions
................................................................................
  6196   6196   **         being opened for read/write access)^.
  6197   6197   ** </ul>
  6198   6198   **
  6199   6199   ** ^Unless it returns SQLITE_MISUSE, this function sets the 
  6200   6200   ** [database connection] error code and message accessible via 
  6201   6201   ** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. 
  6202   6202   **
         6203  +** A BLOB referenced by sqlite3_blob_open() may be read using the
         6204  +** [sqlite3_blob_read()] interface and modified by using
         6205  +** [sqlite3_blob_write()].  The [BLOB handle] can be moved to a
         6206  +** different row of the same table using the [sqlite3_blob_reopen()]
         6207  +** interface.  However, the column, table, or database of a [BLOB handle]
         6208  +** cannot be changed after the [BLOB handle] is opened.
  6203   6209   **
  6204   6210   ** ^(If the row that a BLOB handle points to is modified by an
  6205   6211   ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
  6206   6212   ** then the BLOB handle is marked as "expired".
  6207   6213   ** This is true if any column of the row is changed, even a column
  6208   6214   ** other than the one the BLOB handle is open on.)^
  6209   6215   ** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for
................................................................................
  6219   6225   **
  6220   6226   ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
  6221   6227   ** and the built-in [zeroblob] SQL function may be used to create a 
  6222   6228   ** zero-filled blob to read or write using the incremental-blob interface.
  6223   6229   **
  6224   6230   ** To avoid a resource leak, every open [BLOB handle] should eventually
  6225   6231   ** be released by a call to [sqlite3_blob_close()].
         6232  +**
         6233  +** See also: [sqlite3_blob_close()],
         6234  +** [sqlite3_blob_reopen()], [sqlite3_blob_read()],
         6235  +** [sqlite3_blob_bytes()], [sqlite3_blob_write()].
  6226   6236   */
  6227   6237   int sqlite3_blob_open(
  6228   6238     sqlite3*,
  6229   6239     const char *zDb,
  6230   6240     const char *zTable,
  6231   6241     const char *zColumn,
  6232   6242     sqlite3_int64 iRow,
................................................................................
  6234   6244     sqlite3_blob **ppBlob
  6235   6245   );
  6236   6246   
  6237   6247   /*
  6238   6248   ** CAPI3REF: Move a BLOB Handle to a New Row
  6239   6249   ** METHOD: sqlite3_blob
  6240   6250   **
  6241         -** ^This function is used to move an existing blob handle so that it points
         6251  +** ^This function is used to move an existing [BLOB handle] so that it points
  6242   6252   ** to a different row of the same database table. ^The new row is identified
  6243   6253   ** by the rowid value passed as the second argument. Only the row can be
  6244   6254   ** changed. ^The database, table and column on which the blob handle is open
  6245         -** remain the same. Moving an existing blob handle to a new row can be
         6255  +** remain the same. Moving an existing [BLOB handle] to a new row is
  6246   6256   ** faster than closing the existing handle and opening a new one.
  6247   6257   **
  6248   6258   ** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
  6249   6259   ** it must exist and there must be either a blob or text value stored in
  6250   6260   ** the nominated column.)^ ^If the new row is not present in the table, or if
  6251   6261   ** it does not contain a blob or text value, or if another error occurs, an
  6252   6262   ** SQLite error code is returned and the blob handle is considered aborted.
................................................................................
  8167   8177   ** CAPI3REF: The pre-update hook.
  8168   8178   **
  8169   8179   ** ^These interfaces are only available if SQLite is compiled using the
  8170   8180   ** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
  8171   8181   **
  8172   8182   ** ^The [sqlite3_preupdate_hook()] interface registers a callback function
  8173   8183   ** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
  8174         -** on a [rowid table].
         8184  +** on a database table.
  8175   8185   ** ^At most one preupdate hook may be registered at a time on a single
  8176   8186   ** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
  8177   8187   ** the previous setting.
  8178   8188   ** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()]
  8179   8189   ** with a NULL pointer as the second parameter.
  8180   8190   ** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
  8181   8191   ** the first parameter to callbacks.
  8182   8192   **
  8183         -** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate
  8184         -** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID]
  8185         -** tables.
         8193  +** ^The preupdate hook only fires for changes to real database tables; the
         8194  +** preupdate hook is not invoked for changes to [virtual tables] or to
         8195  +** system tables like sqlite_master or sqlite_stat1.
  8186   8196   **
  8187   8197   ** ^The second parameter to the preupdate callback is a pointer to
  8188   8198   ** the [database connection] that registered the preupdate hook.
  8189   8199   ** ^The third parameter to the preupdate callback is one of the constants
  8190   8200   ** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the
  8191   8201   ** kind of update operation that is about to occur.
  8192   8202   ** ^(The fourth parameter to the preupdate callback is the name of the
  8193   8203   ** database within the database connection that is being modified.  This
  8194   8204   ** will be "main" for the main database or "temp" for TEMP tables or 
  8195   8205   ** the name given after the AS keyword in the [ATTACH] statement for attached
  8196   8206   ** databases.)^
  8197   8207   ** ^The fifth parameter to the preupdate callback is the name of the
  8198   8208   ** table that is being modified.
  8199         -** ^The sixth parameter to the preupdate callback is the initial [rowid] of the
  8200         -** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is
  8201         -** undefined for SQLITE_INSERT changes.
  8202         -** ^The seventh parameter to the preupdate callback is the final [rowid] of
  8203         -** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is
  8204         -** undefined for SQLITE_DELETE changes.
         8209  +**
         8210  +** For an UPDATE or DELETE operation on a [rowid table], the sixth
         8211  +** parameter passed to the preupdate callback is the initial [rowid] of the 
         8212  +** row being modified or deleted. For an INSERT operation on a rowid table,
         8213  +** or any operation on a WITHOUT ROWID table, the value of the sixth 
         8214  +** parameter is undefined. For an INSERT or UPDATE on a rowid table the
         8215  +** seventh parameter is the final rowid value of the row being inserted
         8216  +** or updated. The value of the seventh parameter passed to the callback
         8217  +** function is not defined for operations on WITHOUT ROWID tables, or for
         8218  +** INSERT operations on rowid tables.
  8205   8219   **
  8206   8220   ** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
  8207   8221   ** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
  8208   8222   ** provide additional information about a preupdate event. These routines
  8209   8223   ** may only be called from within a preupdate callback.  Invoking any of
  8210   8224   ** these routines from outside of a preupdate callback or with a
  8211   8225   ** [database connection] pointer that is different from the one supplied

Changes to src/sqliteInt.h.

  2588   2588                                         ** the OR optimization  */
  2589   2589   #define WHERE_GROUPBY          0x0040 /* pOrderBy is really a GROUP BY */
  2590   2590   #define WHERE_DISTINCTBY       0x0080 /* pOrderby is really a DISTINCT clause */
  2591   2591   #define WHERE_WANT_DISTINCT    0x0100 /* All output needs to be distinct */
  2592   2592   #define WHERE_SORTBYGROUP      0x0200 /* Support sqlite3WhereIsSorted() */
  2593   2593   #define WHERE_SEEK_TABLE       0x0400 /* Do not defer seeks on main table */
  2594   2594   #define WHERE_ORDERBY_LIMIT    0x0800 /* ORDERBY+LIMIT on the inner loop */
  2595         -                        /*     0x1000    not currently used */
         2595  +#define WHERE_SEEK_UNIQ_TABLE  0x1000 /* Do not defer seeks if unique */
  2596   2596                           /*     0x2000    not currently used */
  2597   2597   #define WHERE_USE_LIMIT        0x4000 /* Use the LIMIT in cost estimates */
  2598   2598                           /*     0x8000    not currently used */
  2599   2599   
  2600   2600   /* Allowed return values from sqlite3WhereIsDistinct()
  2601   2601   */
  2602   2602   #define WHERE_DISTINCT_NOOP      0  /* DISTINCT keyword not used */
................................................................................
  3053   3053   #define OPFLAG_NCHANGE       0x01    /* OP_Insert: Set to update db->nChange */
  3054   3054                                        /* Also used in P2 (not P5) of OP_Delete */
  3055   3055   #define OPFLAG_EPHEM         0x01    /* OP_Column: Ephemeral output is ok */
  3056   3056   #define OPFLAG_LASTROWID     0x20    /* Set to update db->lastRowid */
  3057   3057   #define OPFLAG_ISUPDATE      0x04    /* This OP_Insert is an sql UPDATE */
  3058   3058   #define OPFLAG_APPEND        0x08    /* This is likely to be an append */
  3059   3059   #define OPFLAG_USESEEKRESULT 0x10    /* Try to avoid a seek in BtreeInsert() */
  3060         -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  3061   3060   #define OPFLAG_ISNOOP        0x40    /* OP_Delete does pre-update-hook only */
  3062         -#endif
  3063   3061   #define OPFLAG_LENGTHARG     0x40    /* OP_Column only used for length() */
  3064   3062   #define OPFLAG_TYPEOFARG     0x80    /* OP_Column only used for typeof() */
  3065   3063   #define OPFLAG_BULKCSR       0x01    /* OP_Open** used to open bulk cursor */
  3066   3064   #define OPFLAG_SEEKEQ        0x02    /* OP_Open** cursor uses EQ seek only */
  3067   3065   #define OPFLAG_FORDELETE     0x08    /* OP_Open should use BTREE_FORDELETE */
  3068   3066   #define OPFLAG_P2ISREG       0x10    /* P2 to OP_Open** is a register number */
  3069   3067   #define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */
................................................................................
  4069   4067   int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
  4070   4068   char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
  4071   4069   #endif
  4072   4070   
  4073   4071   /*
  4074   4072   ** The interface to the LEMON-generated parser
  4075   4073   */
  4076         -void *sqlite3ParserAlloc(void*(*)(u64));
  4077         -void sqlite3ParserFree(void*, void(*)(void*));
         4074  +#ifndef SQLITE_AMALGAMATION
         4075  +  void *sqlite3ParserAlloc(void*(*)(u64));
         4076  +  void sqlite3ParserFree(void*, void(*)(void*));
         4077  +#endif
  4078   4078   void sqlite3Parser(void*, int, Token, Parse*);
  4079   4079   #ifdef YYTRACKMAXSTACKDEPTH
  4080   4080     int sqlite3ParserStackPeak(void*);
  4081   4081   #endif
  4082   4082   
  4083   4083   void sqlite3AutoLoadExtensions(sqlite3*);
  4084   4084   #ifndef SQLITE_OMIT_LOAD_EXTENSION
................................................................................
  4180   4180     FKey *sqlite3FkReferences(Table *);
  4181   4181   #else
  4182   4182     #define sqlite3FkActions(a,b,c,d,e,f)
  4183   4183     #define sqlite3FkCheck(a,b,c,d,e,f)
  4184   4184     #define sqlite3FkDropTable(a,b,c)
  4185   4185     #define sqlite3FkOldmask(a,b)         0
  4186   4186     #define sqlite3FkRequired(a,b,c,d)    0
         4187  +  #define sqlite3FkReferences(a)        0
  4187   4188   #endif
  4188   4189   #ifndef SQLITE_OMIT_FOREIGN_KEY
  4189   4190     void sqlite3FkDelete(sqlite3 *, Table*);
  4190   4191     int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
  4191   4192   #else
  4192   4193     #define sqlite3FkDelete(a,b)
  4193   4194     #define sqlite3FkLocateIndex(a,b,c,d,e)

Changes to src/tokenize.c.

   477    477     int nErr = 0;                   /* Number of errors encountered */
   478    478     int i;                          /* Loop counter */
   479    479     void *pEngine;                  /* The LEMON-generated LALR(1) parser */
   480    480     int tokenType;                  /* type of the next token */
   481    481     int lastTokenParsed = -1;       /* type of the previous token */
   482    482     sqlite3 *db = pParse->db;       /* The database connection */
   483    483     int mxSqlLen;                   /* Max length of an SQL string */
          484  +#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
          485  +  unsigned char zSpace[sizeof(yyParser)];  /* Space for parser engine object */
          486  +#endif
   484    487   
   485    488     assert( zSql!=0 );
   486    489     mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
   487    490     if( db->nVdbeActive==0 ){
   488    491       db->u1.isInterrupted = 0;
   489    492     }
   490    493     pParse->rc = SQLITE_OK;
   491    494     pParse->zTail = zSql;
   492    495     i = 0;
   493    496     assert( pzErrMsg!=0 );
   494    497     /* sqlite3ParserTrace(stdout, "parser: "); */
          498  +#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
          499  +  pEngine = zSpace;
          500  +  sqlite3ParserInit(pEngine);
          501  +#else
   495    502     pEngine = sqlite3ParserAlloc(sqlite3Malloc);
   496    503     if( pEngine==0 ){
   497    504       sqlite3OomFault(db);
   498    505       return SQLITE_NOMEM_BKPT;
   499    506     }
          507  +#endif
   500    508     assert( pParse->pNewTable==0 );
   501    509     assert( pParse->pNewTrigger==0 );
   502    510     assert( pParse->nVar==0 );
   503    511     assert( pParse->pVList==0 );
   504    512     while( 1 ){
   505    513       assert( i>=0 );
   506    514       if( zSql[i]!=0 ){
................................................................................
   544    552   #ifdef YYTRACKMAXSTACKDEPTH
   545    553     sqlite3_mutex_enter(sqlite3MallocMutex());
   546    554     sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
   547    555         sqlite3ParserStackPeak(pEngine)
   548    556     );
   549    557     sqlite3_mutex_leave(sqlite3MallocMutex());
   550    558   #endif /* YYDEBUG */
          559  +#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
          560  +  sqlite3ParserFinalize(pEngine);
          561  +#else
   551    562     sqlite3ParserFree(pEngine, sqlite3_free);
          563  +#endif
   552    564     if( db->mallocFailed ){
   553    565       pParse->rc = SQLITE_NOMEM_BKPT;
   554    566     }
   555    567     if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
   556    568       pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
   557    569     }
   558    570     assert( pzErrMsg!=0 );

Changes to src/update.c.

   388    388     /* Begin the database scan. 
   389    389     **
   390    390     ** Do not consider a single-pass strategy for a multi-row update if
   391    391     ** there are any triggers or foreign keys to process, or rows may
   392    392     ** be deleted as a result of REPLACE conflict handling. Any of these
   393    393     ** things might disturb a cursor being used to scan through the table
   394    394     ** or index, causing a single-pass approach to malfunction.  */
   395         -  flags = WHERE_ONEPASS_DESIRED | WHERE_SEEK_TABLE;
          395  +  flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
   396    396     if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
   397    397       flags |= WHERE_ONEPASS_MULTIROW;
   398    398     }
   399    399     pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur);
   400    400     if( pWInfo==0 ) goto update_cleanup;
   401    401   
   402    402     /* A one-pass strategy that might update more than one row may not

Changes to src/vdbe.c.

   594    594       /* This happens if a malloc() inside a call to sqlite3_column_text() or
   595    595       ** sqlite3_column_text16() failed.  */
   596    596       goto no_mem;
   597    597     }
   598    598     assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY
   599    599               || (p->rc&0xFF)==SQLITE_LOCKED );
   600    600     assert( p->bIsReader || p->readOnly!=0 );
   601         -  p->rc = SQLITE_OK;
   602    601     p->iCurrentTime = 0;
   603    602     assert( p->explain==0 );
   604    603     p->pResultSet = 0;
   605    604     db->busyHandler.nBusy = 0;
   606    605     if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
   607    606     sqlite3VdbeIOTraceSql(p);
   608    607   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
................................................................................
  4381   4380     pData = &aMem[pOp->p2];
  4382   4381     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4383   4382     assert( memIsValid(pData) );
  4384   4383     pC = p->apCsr[pOp->p1];
  4385   4384     assert( pC!=0 );
  4386   4385     assert( pC->eCurType==CURTYPE_BTREE );
  4387   4386     assert( pC->uc.pCursor!=0 );
  4388         -  assert( pC->isTable );
         4387  +  assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
  4389   4388     assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
  4390   4389     REGISTER_TRACE(pOp->p2, pData);
  4391   4390   
  4392   4391     if( pOp->opcode==OP_Insert ){
  4393   4392       pKey = &aMem[pOp->p3];
  4394   4393       assert( pKey->flags & MEM_Int );
  4395   4394       assert( memIsValid(pKey) );
................................................................................
  4397   4396       x.nKey = pKey->u.i;
  4398   4397     }else{
  4399   4398       assert( pOp->opcode==OP_InsertInt );
  4400   4399       x.nKey = pOp->p3;
  4401   4400     }
  4402   4401   
  4403   4402     if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
  4404         -    assert( pC->isTable );
  4405   4403       assert( pC->iDb>=0 );
  4406   4404       zDb = db->aDb[pC->iDb].zDbSName;
  4407   4405       pTab = pOp->p4.pTab;
  4408         -    assert( HasRowid(pTab) );
         4406  +    assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
  4409   4407       op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
  4410   4408     }else{
  4411         -    pTab = 0; /* Not needed.  Silence a comiler warning. */
         4409  +    pTab = 0; /* Not needed.  Silence a compiler warning. */
  4412   4410       zDb = 0;  /* Not needed.  Silence a compiler warning. */
  4413   4411     }
  4414   4412   
  4415   4413   #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  4416   4414     /* Invoke the pre-update hook, if any */
  4417   4415     if( db->xPreUpdateCallback 
  4418   4416      && pOp->p4type==P4_TABLE
  4419   4417      && !(pOp->p5 & OPFLAG_ISUPDATE)
  4420   4418     ){
  4421   4419       sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2);
  4422   4420     }
         4421  +  if( pOp->p5 & OPFLAG_ISNOOP ) break;
  4423   4422   #endif
  4424   4423   
  4425   4424     if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
  4426   4425     if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
  4427   4426     if( pData->flags & MEM_Null ){
  4428   4427       x.pData = 0;
  4429   4428       x.nData = 0;
................................................................................
  4528   4527     }else{
  4529   4528       zDb = 0;   /* Not needed.  Silence a compiler warning. */
  4530   4529       pTab = 0;  /* Not needed.  Silence a compiler warning. */
  4531   4530     }
  4532   4531   
  4533   4532   #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  4534   4533     /* Invoke the pre-update-hook if required. */
  4535         -  if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){
  4536         -    assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) );
         4534  +  if( db->xPreUpdateCallback && pOp->p4.pTab ){
         4535  +    assert( !(opflags & OPFLAG_ISUPDATE) 
         4536  +         || HasRowid(pTab)==0 
         4537  +         || (aMem[pOp->p3].flags & MEM_Int) 
         4538  +    );
  4537   4539       sqlite3VdbePreUpdateHook(p, pC,
  4538   4540           (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, 
  4539   4541           zDb, pTab, pC->movetoTarget,
  4540   4542           pOp->p3
  4541   4543       );
  4542   4544     }
  4543   4545     if( opflags & OPFLAG_ISNOOP ) break;

Changes to src/vdbeInt.h.

   430    430     UnpackedRecord *pUnpacked;      /* Unpacked version of aRecord[] */
   431    431     UnpackedRecord *pNewUnpacked;   /* Unpacked version of new.* record */
   432    432     int iNewReg;                    /* Register for new.* values */
   433    433     i64 iKey1;                      /* First key value passed to hook */
   434    434     i64 iKey2;                      /* Second key value passed to hook */
   435    435     Mem *aNew;                      /* Array of new.* values */
   436    436     Table *pTab;                    /* Schema object being upated */          
          437  +  Index *pPk;                     /* PK index if pTab is WITHOUT ROWID */
   437    438   };
   438    439   
   439    440   /*
   440    441   ** Function prototypes
   441    442   */
   442    443   void sqlite3VdbeError(Vdbe*, const char *, ...);
   443    444   void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);

Changes to src/vdbeapi.c.

  1708   1708   
  1709   1709     /* Test that this call is being made from within an SQLITE_DELETE or
  1710   1710     ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */
  1711   1711     if( !p || p->op==SQLITE_INSERT ){
  1712   1712       rc = SQLITE_MISUSE_BKPT;
  1713   1713       goto preupdate_old_out;
  1714   1714     }
         1715  +  if( p->pPk ){
         1716  +    iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
         1717  +  }
  1715   1718     if( iIdx>=p->pCsr->nField || iIdx<0 ){
  1716   1719       rc = SQLITE_RANGE;
  1717   1720       goto preupdate_old_out;
  1718   1721     }
  1719   1722   
  1720   1723     /* If the old.* record has not yet been loaded into memory, do so now. */
  1721   1724     if( p->pUnpacked==0 ){
................................................................................
  1793   1796     int rc = SQLITE_OK;
  1794   1797     Mem *pMem;
  1795   1798   
  1796   1799     if( !p || p->op==SQLITE_DELETE ){
  1797   1800       rc = SQLITE_MISUSE_BKPT;
  1798   1801       goto preupdate_new_out;
  1799   1802     }
         1803  +  if( p->pPk && p->op!=SQLITE_UPDATE ){
         1804  +    iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
         1805  +  }
  1800   1806     if( iIdx>=p->pCsr->nField || iIdx<0 ){
  1801   1807       rc = SQLITE_RANGE;
  1802   1808       goto preupdate_new_out;
  1803   1809     }
  1804   1810   
  1805   1811     if( p->op==SQLITE_INSERT ){
  1806   1812       /* For an INSERT, memory cell p->iNewReg contains the serialized record

Changes to src/vdbeaux.c.

   660    660     int i;
   661    661     for(i=0; i<p->nOp; i++){
   662    662       assert( p->aOp[i].opcode!=OP_ResultRow );
   663    663     }
   664    664   }
   665    665   #endif
   666    666   
   667         -/*
   668         -** Verify that the VM passed as the only argument does not contain
   669         -** an OP_ResultRow opcode. Fail an assert() if it does. This is used
   670         -** by code in pragma.c to ensure that the implementation of certain
   671         -** pragmas comports with the flags specified in the mkpragmatab.tcl
   672         -** script.
   673         -*/
   674         -#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
   675         -void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
   676         -  int i;
   677         -  for(i=0; i<p->nOp; i++){
   678         -    assert( p->aOp[i].opcode!=OP_ResultRow );
   679         -  }
   680         -}
   681         -#endif
   682         -
   683    667   /*
   684    668   ** This function returns a pointer to the array of opcodes associated with
   685    669   ** the Vdbe passed as the first argument. It is the callers responsibility
   686    670   ** to arrange for the returned array to be eventually freed using the 
   687    671   ** vdbeFreeOpArray() function.
   688    672   **
   689    673   ** Before returning, *pnOp is set to the number of entries in the returned
................................................................................
  4632   4616     i64 iKey2;
  4633   4617     PreUpdate preupdate;
  4634   4618     const char *zTbl = pTab->zName;
  4635   4619     static const u8 fakeSortOrder = 0;
  4636   4620   
  4637   4621     assert( db->pPreUpdate==0 );
  4638   4622     memset(&preupdate, 0, sizeof(PreUpdate));
  4639         -  if( op==SQLITE_UPDATE ){
  4640         -    iKey2 = v->aMem[iReg].u.i;
         4623  +  if( HasRowid(pTab)==0 ){
         4624  +    iKey1 = iKey2 = 0;
         4625  +    preupdate.pPk = sqlite3PrimaryKeyIndex(pTab);
  4641   4626     }else{
  4642         -    iKey2 = iKey1;
         4627  +    if( op==SQLITE_UPDATE ){
         4628  +      iKey2 = v->aMem[iReg].u.i;
         4629  +    }else{
         4630  +      iKey2 = iKey1;
         4631  +    }
  4643   4632     }
  4644   4633   
  4645   4634     assert( pCsr->nField==pTab->nCol 
  4646   4635          || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1)
  4647   4636     );
  4648   4637   
  4649   4638     preupdate.v = v;

Changes to src/vdbeblob.c.

    51     51   ** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will 
    52     52   ** immediately return SQLITE_ABORT.
    53     53   */
    54     54   static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
    55     55     int rc;                         /* Error code */
    56     56     char *zErr = 0;                 /* Error message */
    57     57     Vdbe *v = (Vdbe *)p->pStmt;
    58         -  sqlite3 *db = v->db;
    59     58   
    60     59     /* Set the value of register r[1] in the SQL statement to integer iRow. 
    61     60     ** This is done directly as a performance optimization
    62     61     */
    63     62     v->aMem[1].flags = MEM_Int;
    64     63     v->aMem[1].u.i = iRow;
    65     64   
    66     65     /* If the statement has been run before (and is paused at the OP_ResultRow)
    67     66     ** then back it up to the point where it does the OP_SeekRowid.  This could
    68     67     ** have been down with an extra OP_Goto, but simply setting the program
    69     68     ** counter is faster. */
    70     69     if( v->pc>3 ){
    71     70       v->pc = 3;
    72         -    db->nVdbeExec++;
    73         -    rc = sqlite3VdbeExec((Vdbe*)p->pStmt);
    74         -    db->nVdbeExec--;
           71  +    rc = sqlite3VdbeExec(v);
    75     72     }else{
    76     73       rc = sqlite3_step(p->pStmt);
    77     74     }
    78     75     if( rc==SQLITE_ROW ){
    79     76       VdbeCursor *pC = v->apCsr[0];
    80     77       u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
    81     78       testcase( pC->nHdrParsed==p->iCol );

Changes to src/wherecode.c.

  1587   1587         testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
  1588   1588       }
  1589   1589   
  1590   1590       /* Seek the table cursor, if required */
  1591   1591       if( omitTable ){
  1592   1592         /* pIdx is a covering index.  No need to access the main table. */
  1593   1593       }else if( HasRowid(pIdx->pTable) ){
  1594         -      if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)!=0 ){
         1594  +      if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
         1595  +          (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE) 
         1596  +       && (pWInfo->eOnePass==ONEPASS_SINGLE)
         1597  +      )){
  1595   1598           iRowidReg = ++pParse->nMem;
  1596   1599           sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
  1597   1600           sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
  1598   1601           sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
  1599   1602           VdbeCoverage(v);
  1600   1603         }else{
  1601   1604           codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);

Changes to test/hook.test.

   845    845     DELETE main t4 1 1   3      abc
   846    846     DELETE main t3 1 1   2      abc
   847    847     DELETE main t2 1 1   1      abc
   848    848     DELETE main t1 1 1   0      abc
   849    849   }
   850    850   
   851    851   # No preupdate callbacks for modifying sqlite_master.
   852         -do_preupdate_test 8.1 {
   853         -  CREATE TABLE x1(x, y);
   854         -} {
   855         -}
          852  +do_preupdate_test 8.1 { CREATE TABLE x1(x, y); } { }
          853  +do_preupdate_test 8.2 { ALTER TABLE x1 ADD COLUMN z } { }
          854  +do_preupdate_test 8.3 { ALTER TABLE x1 RENAME TO y1 } { }
          855  +do_preupdate_test 8.4 { CREATE INDEX y1x ON y1(x) } { }
          856  +do_preupdate_test 8.5 { CREATE VIEW v1 AS SELECT * FROM y1 } { }
          857  +do_preupdate_test 8.6 { DROP TABLE y1 } { }
   856    858   
   857    859   #-------------------------------------------------------------------------
   858    860   reset_db
   859    861   db preupdate hook preupdate_hook
   860    862   do_execsql_test 9.0 {
   861    863     CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
   862    864     CREATE TABLE t2(a, b INTEGER PRIMARY KEY);

Added test/hook2.test.

            1  +# 2017 Jan 30
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# The tests in this file focus on the pre-update hook.
           12  +# 
           13  +
           14  +set testdir [file dirname $argv0]
           15  +source $testdir/tester.tcl
           16  +set ::testprefix hook2
           17  +
           18  +ifcapable !preupdate {
           19  +  finish_test
           20  +  return
           21  +}
           22  +
           23  +#-------------------------------------------------------------------------
           24  +proc do_preupdate_test {tn sql x} {
           25  +  set X [list]
           26  +  foreach elem $x {lappend X $elem}
           27  +  uplevel do_test $tn [list "
           28  +    set ::preupdate \[list\]
           29  +    execsql { $sql }
           30  +    set ::preupdate
           31  +  "] [list $X]
           32  +}
           33  +
           34  +proc preupdate_hook {args} {
           35  +  set type [lindex $args 0]
           36  +  eval lappend ::preupdate $args
           37  +  if {$type != "INSERT"} {
           38  +    for {set i 0} {$i < [db preupdate count]} {incr i} {
           39  +      lappend ::preupdate [db preupdate old $i]
           40  +    }
           41  +  }
           42  +  if {$type != "DELETE"} {
           43  +    for {set i 0} {$i < [db preupdate count]} {incr i} {
           44  +      set rc [catch { db preupdate new $i } v]
           45  +      lappend ::preupdate $v
           46  +    }
           47  +  }
           48  +}
           49  +
           50  +#-------------------------------------------------------------------------
           51  +# Simple tests - INSERT, UPDATE and DELETE on a WITHOUT ROWID table.
           52  +#
           53  +db preupdate hook preupdate_hook
           54  +do_execsql_test 1.0 {
           55  +  CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
           56  +}
           57  +do_preupdate_test 1.1 {
           58  +  INSERT INTO t1 VALUES('one', 1);
           59  +} {
           60  +  INSERT main t1 0 0  one 1
           61  +}
           62  +do_preupdate_test 1.2 {
           63  +  UPDATE t1 SET b=2 WHERE a='one';
           64  +} {
           65  +  UPDATE main t1 0 0  one 1 one 2
           66  +}
           67  +do_preupdate_test 1.3 {
           68  +  DELETE FROM t1 WHERE a='one';
           69  +} {
           70  +  DELETE main t1 0 0  one 2
           71  +}
           72  +
           73  +#-------------------------------------------------------------------------
           74  +# Some more complex tests for the pre-update callback on WITHOUT ROWID
           75  +# tables.
           76  +#
           77  +#   2.1.1 - INSERT statement.
           78  +#   2.1.2 - INSERT INTO ... SELECT statement.
           79  +#   2.1.3 - REPLACE INTO ... (PK conflict)
           80  +#   2.1.4 - REPLACE INTO ... (other index conflicts)
           81  +#   2.1.5 - REPLACE INTO ... (both PK and other index conflicts)
           82  +#
           83  +#   2.2.1 - DELETE statement.
           84  +#   2.2.2 - DELETE statement that uses the truncate optimization.
           85  +#
           86  +#   2.3.1 - UPDATE statement.
           87  +#   2.3.2 - UPDATE statement that modifies the PK.
           88  +#   2.3.3 - UPDATE OR REPLACE ... (PK conflict).
           89  +#   2.3.4 - UPDATE OR REPLACE ... (other index conflicts)
           90  +#   2.3.4 - UPDATE OR REPLACE ... (both PK and other index conflicts)
           91  +#
           92  +do_execsql_test 2.0 {
           93  +  CREATE TABLE t2(a DEFAULT 4, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
           94  +  CREATE UNIQUE INDEX t2a ON t2(a);
           95  +}
           96  +
           97  +do_preupdate_test 2.1.1 {
           98  +  INSERT INTO t2(b, c) VALUES(1, 1);
           99  +} {
          100  +  INSERT main t2 0 0  4 1 1
          101  +}
          102  +
          103  +do_execsql_test 2.1.2.0 {
          104  +  CREATE TABLE d1(a DEFAULT 4, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
          105  +  CREATE UNIQUE INDEX d1a ON d1(a);
          106  +  INSERT INTO d1 VALUES(1, 2, 3);
          107  +  INSERT INTO d1 VALUES(11, 12, 13);
          108  +}
          109  +do_preupdate_test 2.1.2.1 {
          110  +  INSERT INTO t2 SELECT * FROM d1;
          111  +} {
          112  +  INSERT main t2 0 0  1 2 3
          113  +  INSERT main t2 0 0  11 12 13
          114  +}
          115  +do_preupdate_test 2.1.2.2 {
          116  +  INSERT INTO t2 SELECT a+20, b+20, c+20 FROM d1;
          117  +} {
          118  +  INSERT main t2 0 0  21 22 23
          119  +  INSERT main t2 0 0  31 32 33
          120  +}
          121  +do_execsql_test 2.1.2.3 {
          122  +  SELECT * FROM t2 ORDER BY b, c;
          123  +} {
          124  +  4 1 1
          125  +  1 2 3
          126  +  11 12 13
          127  +  21 22 23
          128  +  31 32 33
          129  +}
          130  +do_preupdate_test 2.1.3 {
          131  +  REPLACE INTO t2 VALUES(45, 22, 23);
          132  +} {
          133  +  DELETE main t2 0 0 21 22 23
          134  +  INSERT main t2 0 0 45 22 23
          135  +}
          136  +do_preupdate_test 2.1.4 {
          137  +  REPLACE INTO t2 VALUES(11, 100, 100);
          138  +} {
          139  +  DELETE main t2 0 0 11 12 13
          140  +  INSERT main t2 0 0 11 100 100
          141  +}
          142  +do_preupdate_test 2.1.5 {
          143  +  REPLACE INTO t2(c, b) VALUES(33, 32)
          144  +} {
          145  +  DELETE main t2 0 0 4 1 1 
          146  +  DELETE main t2 0 0 31 32 33
          147  +  INSERT main t2 0 0 4 32 33
          148  +}
          149  +
          150  +do_execsql_test 2.2.0 {
          151  +  SELECT * FROM t2 ORDER BY b,c;
          152  +} {
          153  +  1    2   3 
          154  +  45  22  23 
          155  +  4   32  33 
          156  +  11 100 100
          157  +}
          158  +do_preupdate_test 2.2.1 {
          159  +  DELETE FROM t2 WHERE b=22;
          160  +} {
          161  +  DELETE main t2 0 0  45 22 23
          162  +}
          163  +do_preupdate_test 2.2.2 {
          164  +  DELETE FROM t2;
          165  +} {
          166  +  DELETE main t2 0 0 1 2 3 
          167  +  DELETE main t2 0 0 4 32 33 
          168  +  DELETE main t2 0 0 11 100 100
          169  +}
          170  +
          171  +do_execsql_test 2.3.0 {
          172  +  CREATE TABLE t3(x, y PRIMARY KEY, z UNIQUE) WITHOUT ROWID;
          173  +  INSERT INTO t3 VALUES('a', 'b', 'c');
          174  +  INSERT INTO t3 VALUES('d', 'e', 'f');
          175  +
          176  +  INSERT INTO t3 VALUES(1, 1, 1);
          177  +  INSERT INTO t3 VALUES(2, 2, 2);
          178  +  INSERT INTO t3 VALUES(3, 3, 3);
          179  +}
          180  +
          181  +do_preupdate_test 2.3.1 {
          182  +  UPDATE t3 SET x=4 WHERE y IN ('b', 'e', 'x');
          183  +} {
          184  +  UPDATE main t3 0 0  a b c   4 b c
          185  +  UPDATE main t3 0 0  d e f   4 e f
          186  +}
          187  +
          188  +do_preupdate_test 2.3.2 {
          189  +  UPDATE t3 SET y=y||y WHERE z IN('c', 'f');
          190  +} {
          191  +  UPDATE main t3 0 0  4 b c   4 bb c
          192  +  UPDATE main t3 0 0  4 e f   4 ee f
          193  +}
          194  +
          195  +do_preupdate_test 2.3.3 {
          196  +  UPDATE OR REPLACE t3 SET y='bb' WHERE z='f'
          197  +} {
          198  +  DELETE main t3 0 0  4 bb c
          199  +  UPDATE main t3 0 0  4 ee f   4 bb f
          200  +}
          201  +
          202  +do_preupdate_test 2.3.4 {
          203  +  UPDATE OR REPLACE t3 SET z=2 WHERE y=1;
          204  +} {
          205  +  DELETE main t3 0 0  2 2 2
          206  +  UPDATE main t3 0 0  1 1 1  1 1 2
          207  +}
          208  +
          209  +do_preupdate_test 2.3.5 {
          210  +  UPDATE OR REPLACE t3 SET z=2, y='bb' WHERE y=3;
          211  +} {
          212  +  DELETE main t3 0 0  1 1 2
          213  +  DELETE main t3 0 0  4 bb f
          214  +  UPDATE main t3 0 0  3 3 3  3 bb 2
          215  +}
          216  +  
          217  +
          218  +finish_test

Changes to test/kvtest.c.

    63     63   static const char zHelp[] = 
    64     64   "Usage: kvtest COMMAND ARGS...\n"
    65     65   "\n"
    66     66   "   kvtest init DBFILE --count N --size M --pagesize X\n"
    67     67   "\n"
    68     68   "        Generate a new test database file named DBFILE containing N\n"
    69     69   "        BLOBs each of size M bytes.  The page size of the new database\n"
    70         -"        file will be X\n"
           70  +"        file will be X.  Additional options:\n"
           71  +"\n"
           72  +"           --variance V           Randomly vary M by plus or minus V\n"
    71     73   "\n"
    72     74   "   kvtest export DBFILE DIRECTORY\n"
    73     75   "\n"
    74     76   "        Export all the blobs in the kv table of DBFILE into separate\n"
    75     77   "        files in DIRECTORY.\n"
    76     78   "\n"
           79  +"   kvtest stat DBFILE\n"
           80  +"\n"
           81  +"        Display summary information about DBFILE\n"
           82  +"\n"
    77     83   "   kvtest run DBFILE [options]\n"
    78     84   "\n"
    79     85   "        Run a performance test.  DBFILE can be either the name of a\n"
    80     86   "        database or a directory containing sample files.  Options:\n"
    81     87   "\n"
    82     88   "           --asc                  Read blobs in ascending order\n"
    83     89   "           --blob-api             Use the BLOB API\n"
................................................................................
   247    253   ** Do database initialization.
   248    254   */
   249    255   static int initMain(int argc, char **argv){
   250    256     char *zDb;
   251    257     int i, rc;
   252    258     int nCount = 1000;
   253    259     int sz = 10000;
          260  +  int iVariance = 0;
   254    261     int pgsz = 4096;
   255    262     sqlite3 *db;
   256    263     char *zSql;
   257    264     char *zErrMsg = 0;
   258    265   
   259    266     assert( strcmp(argv[1],"init")==0 );
   260    267     assert( argc>=3 );
................................................................................
   270    277         continue;
   271    278       }
   272    279       if( strcmp(z, "-size")==0 ){
   273    280         if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
   274    281         sz = integerValue(argv[++i]);
   275    282         if( sz<1 ) fatalError("the --size must be positive");
   276    283         continue;
          284  +    }
          285  +    if( strcmp(z, "-variance")==0 ){
          286  +      if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
          287  +      iVariance = integerValue(argv[++i]);
          288  +      continue;
   277    289       }
   278    290       if( strcmp(z, "-pagesize")==0 ){
   279    291         if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
   280    292         pgsz = integerValue(argv[++i]);
   281    293         if( pgsz<512 || pgsz>65536 || ((pgsz-1)&pgsz)!=0 ){
   282    294           fatalError("the --pagesize must be power of 2 between 512 and 65536");
   283    295         }
................................................................................
   292    304     zSql = sqlite3_mprintf(
   293    305       "DROP TABLE IF EXISTS kv;\n"
   294    306       "PRAGMA page_size=%d;\n"
   295    307       "VACUUM;\n"
   296    308       "BEGIN;\n"
   297    309       "CREATE TABLE kv(k INTEGER PRIMARY KEY, v BLOB);\n"
   298    310       "WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<%d)"
   299         -    " INSERT INTO kv(k,v) SELECT x, randomblob(%d) FROM c;\n"
          311  +    " INSERT INTO kv(k,v) SELECT x, randomblob(%d+(random()%%(%d))) FROM c;\n"
   300    312       "COMMIT;\n",
   301         -    pgsz, nCount, sz
          313  +    pgsz, nCount, sz, iVariance
   302    314     );
   303    315     rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
   304    316     if( rc ) fatalError("database create failed: %s", zErrMsg);
   305    317     sqlite3_free(zSql);
   306    318     sqlite3_close(db);
   307    319     return 0;
   308    320   }
          321  +
          322  +/*
          323  +** Analyze an existing database file.  Report its content.
          324  +*/
          325  +static int statMain(int argc, char **argv){
          326  +  char *zDb;
          327  +  int i, rc;
          328  +  sqlite3 *db;
          329  +  char *zSql;
          330  +  sqlite3_stmt *pStmt;
          331  +
          332  +  assert( strcmp(argv[1],"stat")==0 );
          333  +  assert( argc>=3 );
          334  +  zDb = argv[2];
          335  +  for(i=3; i<argc; i++){
          336  +    char *z = argv[i];
          337  +    if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
          338  +    if( z[1]=='-' ) z++;
          339  +    fatalError("unknown option: \"%s\"", argv[i]);
          340  +  }
          341  +  rc = sqlite3_open(zDb, &db);
          342  +  if( rc ){
          343  +    fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
          344  +  }
          345  +  zSql = sqlite3_mprintf(
          346  +    "SELECT count(*), min(length(v)), max(length(v)), avg(length(v))"
          347  +    "  FROM kv"
          348  +  );
          349  +  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
          350  +  if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
          351  +  sqlite3_free(zSql);
          352  +  if( sqlite3_step(pStmt)==SQLITE_ROW ){
          353  +    printf("Number of entries:  %8d\n", sqlite3_column_int(pStmt, 0));
          354  +    printf("Average value size: %8d\n", sqlite3_column_int(pStmt, 3));
          355  +    printf("Minimum value size: %8d\n", sqlite3_column_int(pStmt, 1));
          356  +    printf("Maximum value size: %8d\n", sqlite3_column_int(pStmt, 2));
          357  +  }else{
          358  +    printf("No rows\n");
          359  +  }
          360  +  sqlite3_finalize(pStmt);
          361  +  zSql = sqlite3_mprintf("PRAGMA page_size");
          362  +  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
          363  +  if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
          364  +  sqlite3_free(zSql);
          365  +  if( sqlite3_step(pStmt)==SQLITE_ROW ){
          366  +    printf("Page-size:          %8d\n", sqlite3_column_int(pStmt, 0));
          367  +  }
          368  +  sqlite3_finalize(pStmt);
          369  +  zSql = sqlite3_mprintf("PRAGMA page_count");
          370  +  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
          371  +  if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
          372  +  sqlite3_free(zSql);
          373  +  if( sqlite3_step(pStmt)==SQLITE_ROW ){
          374  +    printf("Page-count:         %8d\n", sqlite3_column_int(pStmt, 0));
          375  +  }
          376  +  sqlite3_finalize(pStmt);
          377  +  sqlite3_close(db);
          378  +  return 0;
          379  +}
   309    380   
   310    381   /*
   311    382   ** Implementation of the "writefile(X,Y)" SQL function.  The argument Y
   312    383   ** is written into file X.  The number of bytes written is returned.  Or
   313    384   ** NULL is returned if something goes wrong, such as being unable to open
   314    385   ** file X for writing.
   315    386   */
................................................................................
   796    867       return initMain(argc, argv);
   797    868     }
   798    869     if( strcmp(argv[1],"export")==0 ){
   799    870       return exportMain(argc, argv);
   800    871     }
   801    872     if( strcmp(argv[1],"run")==0 ){
   802    873       return runMain(argc, argv);
          874  +  }
          875  +  if( strcmp(argv[1],"stat")==0 ){
          876  +    return statMain(argc, argv);
   803    877     }
   804    878     showHelp();
   805    879     return 0;
   806    880   }

Changes to test/tabfunc01.test.

   144    144     WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
   145    145       INSERT INTO t600(a,b) SELECT x, printf('(%03d)',x) FROM c;
   146    146     SELECT b FROM t600 WHERE a IN generate_series(2,52,10);
   147    147   } {(002) (012) (022) (032) (042) (052)}
   148    148   
   149    149   
   150    150   do_test tabfunc01-700 {
   151         -  set PTR [intarray_addr 5 7 13 17 23]
          151  +  set PTR1 [intarray_addr 5 7 13 17 23]
   152    152     db eval {
   153         -    SELECT b FROM t600, carray($PTR,5) WHERE a=value;
          153  +    SELECT b FROM t600, carray($PTR1,5) WHERE a=value;
   154    154     }
   155    155   } {(005) (007) (013) (017) (023)}
   156    156   do_test tabfunc01-701 {
   157    157     db eval {
   158         -    SELECT b FROM t600 WHERE a IN carray($PTR,5,'int32');
          158  +    SELECT b FROM t600 WHERE a IN carray($PTR1,5,'int32');
   159    159     }
   160    160   } {(005) (007) (013) (017) (023)}
   161    161   do_test tabfunc01-702 {
   162    162     db eval {
   163         -    SELECT b FROM t600 WHERE a IN carray($PTR,4,'int32');
          163  +    SELECT b FROM t600 WHERE a IN carray($PTR1,4,'int32');
   164    164     }
   165    165   } {(005) (007) (013) (017)}
   166    166   do_catchsql_test tabfunc01-710 {
   167         -  SELECT b FROM t600 WHERE a IN carray($PTR,5,'int33');
          167  +  SELECT b FROM t600 WHERE a IN carray($PTR1,5,'int33');
   168    168   } {1 {unknown datatype: 'int33'}}
   169    169   
   170    170   do_test tabfunc01-720 {
   171         -  set PTR [int64array_addr 5 7 13 17 23]
          171  +  set PTR2 [int64array_addr 5 7 13 17 23]
   172    172     db eval {
   173         -    SELECT b FROM t600, carray($PTR,5,'int64') WHERE a=value;
          173  +    SELECT b FROM t600, carray($PTR2,5,'int64') WHERE a=value;
   174    174     }
   175    175   } {(005) (007) (013) (017) (023)}
   176    176   do_test tabfunc01-721 {
   177    177     db eval {
   178         -    SELECT remember(123,$PTR);
   179         -    SELECT value FROM carray($PTR,5,'int64');
          178  +    SELECT remember(123,$PTR2);
          179  +    SELECT value FROM carray($PTR2,5,'int64');
   180    180     }
   181    181   } {123 123 7 13 17 23}
   182    182   do_test tabfunc01-722 {
   183         -  set PTR2 [expr {$PTR+16}]
          183  +  set PTR3 [expr {$PTR2+16}]
   184    184     db eval {
   185         -    SELECT remember(987,$PTR2);
   186         -    SELECT value FROM carray($PTR,5,'int64');
          185  +    SELECT remember(987,$PTR3);
          186  +    SELECT value FROM carray($PTR2,5,'int64');
   187    187     }
   188    188   } {987 123 7 987 17 23}
   189    189   
   190    190   do_test tabfunc01-730 {
   191         -  set PTR [doublearray_addr 5.0 7.0 13.0 17.0 23.0]
          191  +  set PTR4 [doublearray_addr 5.0 7.0 13.0 17.0 23.0]
   192    192     db eval {
   193         -    SELECT b FROM t600, carray($PTR,5,'double') WHERE a=value;
          193  +    SELECT b FROM t600, carray($PTR4,5,'double') WHERE a=value;
   194    194     }
   195    195   } {(005) (007) (013) (017) (023)}
   196    196   
   197    197   do_test tabfunc01-740 {
   198         -  set PTR [textarray_addr 5 7 13 17 23]
          198  +  set PTR5 [textarray_addr x5 x7 x13 x17 x23]
   199    199     db eval {
   200         -    SELECT b FROM t600, carray($PTR,5,'char*') WHERE a=value;
          200  +    SELECT b FROM t600, carray($PTR5,5,'char*') WHERE a=trim(value,'x');
   201    201     }
   202    202   } {(005) (007) (013) (017) (023)}
   203    203   
          204  +do_test tabfunc01-750 {
          205  +  db eval {
          206  +    SELECT aa.value, bb.value, '|'
          207  +      FROM carray($PTR4,5,'double') AS aa
          208  +      JOIN carray($PTR5,5,'char*') AS bb ON aa.rowid=bb.rowid;
          209  +  }
          210  +} {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |}
   204    211   
          212  +# Free up memory allocations
   205    213   intarray_addr
   206    214   int64array_addr
   207    215   doublearray_addr
   208    216   textarray_addr
   209    217   
   210    218   finish_test

Changes to test/update2.test.

   171    171       3 a 3 3
   172    172       4 a 14 4
   173    173       5 a 15 5
   174    174       6 a 16 6
   175    175       7 a 17 7
   176    176     }
   177    177   }
          178  +
          179  +#-------------------------------------------------------------------------
          180  +#
          181  +do_execsql_test 5.0 {
          182  +  CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
          183  +  CREATE INDEX x1c ON x1(b, c);
          184  +  INSERT INTO x1 VALUES(1, 'a', 1);
          185  +  INSERT INTO x1 VALUES(2, 'a', 2);
          186  +  INSERT INTO x1 VALUES(3, 'a', 3);
          187  +}
          188  +
          189  +do_execsql_test 5.1.1 {
          190  +  UPDATE x1 SET c=c+1 WHERE b='a';
          191  +}
          192  +
          193  +do_execsql_test 5.1.2 {
          194  +  SELECT * FROM x1;
          195  +} {1 a 2 2 a 3 3 a 4}
          196  +
          197  +do_test 5.2 {
          198  +  catch { array unset A }
          199  +  db eval { EXPLAIN UPDATE x1 SET c=c+1 WHERE b='a' } { incr A($opcode) }
          200  +  set A(NotExists)
          201  +} {1}
          202  +
   178    203   
   179    204   finish_test
   180    205   

Added tool/kvtest-speed.sh.

            1  +#!/bin/bash
            2  +#
            3  +# A script for running speed tests using kvtest.
            4  +#
            5  +# The test database must be set up first.  Recommended
            6  +# command-line:
            7  +#
            8  +#    ./kvtest init kvtest.db --count 100K --size 12K --variance 5K
            9  +
           10  +if test "$1" = ""
           11  +then
           12  +  echo "Usage: $0 OUTPUTFILE [OPTIONS]"
           13  +  exit
           14  +fi
           15  +NAME=$1
           16  +shift
           17  +OPTS="-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DIRECT_OVERFLOW_READ -DUSE_PREAD"
           18  +KVARGS="--count 100K --stats"
           19  +gcc -g -Os -I. $OPTS $* kvtest.c sqlite3.c -o kvtest
           20  +
           21  +# First run using SQL
           22  +rm cachegrind.out.[1-9][0-9]*
           23  +valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS 2>&1 | tee summary-kvtest-$NAME.txt
           24  +mv cachegrind.out.[1-9][0-9]* cachegrind.out.sql-$NAME
           25  +cg_anno.tcl cachegrind.out.sql-$NAME >cout-kvtest-sql-$NAME.txt
           26  +
           27  +# Second run using the sqlite3_blob object
           28  +valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS --blob-api 2>&1 | tee -a summary-kvtest-$NAME.txt
           29  +mv cachegrind.out.[1-9][0-9]* cachegrind.out.$NAME
           30  +cg_anno.tcl cachegrind.out.$NAME >cout-kvtest-$NAME.txt
           31  +
           32  +# Diff the sqlite3_blob API analysis for non-trunk runs.
           33  +if test "$NAME" != "trunk"; then
           34  +  fossil test-diff --tk cout-kvtest-trunk.txt cout-kvtest-$NAME.txt &
           35  +fi

Changes to tool/lempar.c.

   312    312   ** putting an appropriate #define in the %include section of the input
   313    313   ** grammar.
   314    314   */
   315    315   #ifndef YYMALLOCARGTYPE
   316    316   # define YYMALLOCARGTYPE size_t
   317    317   #endif
   318    318   
          319  +/* Initialize a new parser that has already been allocated.
          320  +*/
          321  +void ParseInit(void *yypParser){
          322  +  yyParser *pParser = (yyParser*)yypParser;
          323  +#ifdef YYTRACKMAXSTACKDEPTH
          324  +  pParser->yyhwm = 0;
          325  +#endif
          326  +#if YYSTACKDEPTH<=0
          327  +  pParser->yytos = NULL;
          328  +  pParser->yystack = NULL;
          329  +  pParser->yystksz = 0;
          330  +  if( yyGrowStack(pParser) ){
          331  +    pParser->yystack = &pParser->yystk0;
          332  +    pParser->yystksz = 1;
          333  +  }
          334  +#endif
          335  +#ifndef YYNOERRORRECOVERY
          336  +  pParser->yyerrcnt = -1;
          337  +#endif
          338  +  pParser->yytos = pParser->yystack;
          339  +  pParser->yystack[0].stateno = 0;
          340  +  pParser->yystack[0].major = 0;
          341  +}
          342  +
          343  +#ifndef Parse_ENGINEALWAYSONSTACK
   319    344   /* 
   320    345   ** This function allocates a new parser.
   321    346   ** The only argument is a pointer to a function which works like
   322    347   ** malloc.
   323    348   **
   324    349   ** Inputs:
   325    350   ** A pointer to the function used to allocate memory.
................................................................................
   327    352   ** Outputs:
   328    353   ** A pointer to a parser.  This pointer is used in subsequent calls
   329    354   ** to Parse and ParseFree.
   330    355   */
   331    356   void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
   332    357     yyParser *pParser;
   333    358     pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
   334         -  if( pParser ){
   335         -#ifdef YYTRACKMAXSTACKDEPTH
   336         -    pParser->yyhwm = 0;
   337         -#endif
   338         -#if YYSTACKDEPTH<=0
   339         -    pParser->yytos = NULL;
   340         -    pParser->yystack = NULL;
   341         -    pParser->yystksz = 0;
   342         -    if( yyGrowStack(pParser) ){
   343         -      pParser->yystack = &pParser->yystk0;
   344         -      pParser->yystksz = 1;
   345         -    }
   346         -#endif
   347         -#ifndef YYNOERRORRECOVERY
   348         -    pParser->yyerrcnt = -1;
   349         -#endif
   350         -    pParser->yytos = pParser->yystack;
   351         -    pParser->yystack[0].stateno = 0;
   352         -    pParser->yystack[0].major = 0;
   353         -  }
          359  +  if( pParser ) ParseInit(pParser);
   354    360     return pParser;
   355    361   }
          362  +#endif /* Parse_ENGINEALWAYSONSTACK */
          363  +
   356    364   
   357    365   /* The following function deletes the "minor type" or semantic value
   358    366   ** associated with a symbol.  The symbol can be either a terminal
   359    367   ** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
   360    368   ** a pointer to the value to be deleted.  The code used to do the 
   361    369   ** deletions is derived from the %destructor and/or %token_destructor
   362    370   ** directives of the input grammar.
................................................................................
   402    410         yyTracePrompt,
   403    411         yyTokenName[yytos->major]);
   404    412     }
   405    413   #endif
   406    414     yy_destructor(pParser, yytos->major, &yytos->minor);
   407    415   }
   408    416   
          417  +/*
          418  +** Clear all secondary memory allocations from the parser
          419  +*/
          420  +void ParseFinalize(void *p){
          421  +  yyParser *pParser = (yyParser*)p;
          422  +  while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
          423  +#if YYSTACKDEPTH<=0
          424  +  if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
          425  +#endif
          426  +}
          427  +
          428  +#ifndef Parse_ENGINEALWAYSONSTACK
   409    429   /* 
   410    430   ** Deallocate and destroy a parser.  Destructors are called for
   411    431   ** all stack elements before shutting the parser down.
   412    432   **
   413    433   ** If the YYPARSEFREENEVERNULL macro exists (for example because it
   414    434   ** is defined in a %include section of the input grammar) then it is
   415    435   ** assumed that the input pointer is never NULL.
   416    436   */
   417    437   void ParseFree(
   418    438     void *p,                    /* The parser to be deleted */
   419    439     void (*freeProc)(void*)     /* Function used to reclaim memory */
   420    440   ){
   421         -  yyParser *pParser = (yyParser*)p;
   422    441   #ifndef YYPARSEFREENEVERNULL
   423         -  if( pParser==0 ) return;
          442  +  if( p==0 ) return;
   424    443   #endif
   425         -  while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
   426         -#if YYSTACKDEPTH<=0
   427         -  if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
   428         -#endif
   429         -  (*freeProc)((void*)pParser);
          444  +  ParseFinalize(p);
          445  +  (*freeProc)(p);
   430    446   }
          447  +#endif /* Parse_ENGINEALWAYSONSTACK */
   431    448   
   432    449   /*
   433    450   ** Return the peak depth of the stack for a parser.
   434    451   */
   435    452   #ifdef YYTRACKMAXSTACKDEPTH
   436    453   int ParseStackPeak(void *p){
   437    454     yyParser *pParser = (yyParser*)p;

Changes to tool/speed-check.sh.

   138    138   wc sqlite3.c
   139    139   if test $doCachegrind -eq 1; then
   140    140     cg_anno.tcl cachegrind.out.* >cout-$NAME.txt
   141    141   fi
   142    142   if test $doExplain -eq 1; then
   143    143     ./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt
   144    144   fi
          145  +if test "$NAME" != "trunk"; then
          146  +  fossil test-diff --tk cout-trunk.txt cout-$NAME.txt
          147  +fi