From 748b8fda902827d513530846aa6112300eeeaccc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 May 2018 19:22:47 +0000 Subject: [PATCH 001/260] Forward port the geopoly extension functions into the r-tree extension, with the idea of creating a new spatial index based on simply polygons. FossilOrigin-Name: 0593aac88a8c25ddafba4c29a181ee083dfc3dab44335feb6f12fdea6ce7fb27 --- Makefile.in | 6 +- Makefile.msc | 6 +- configure | 44 ++- configure.ac | 10 + ext/rtree/geopoly.c | 853 ++++++++++++++++++++++++++++++++++++++++++++ ext/rtree/rtree.c | 9 + main.mk | 6 +- manifest | 28 +- manifest.uuid | 2 +- tool/mksqlite3c.tcl | 3 +- 10 files changed, 933 insertions(+), 34 deletions(-) create mode 100644 ext/rtree/geopoly.c diff --git a/Makefile.in b/Makefile.in index ac84fe832c..b8bcbd6864 100644 --- a/Makefile.in +++ b/Makefile.in @@ -349,7 +349,8 @@ SRC += \ $(TOP)/ext/icu/icu.c SRC += \ $(TOP)/ext/rtree/rtree.h \ - $(TOP)/ext/rtree/rtree.c + $(TOP)/ext/rtree/rtree.c \ + $(TOP)/ext/rtree/geopoly.c SRC += \ $(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.h @@ -549,7 +550,8 @@ EXTHDR += \ $(TOP)/ext/fts3/fts3_hash.h \ $(TOP)/ext/fts3/fts3_tokenizer.h EXTHDR += \ - $(TOP)/ext/rtree/rtree.h + $(TOP)/ext/rtree/rtree.h \ + $(TOP)/ext/rtree/geopoly.c EXTHDR += \ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ diff --git a/Makefile.msc b/Makefile.msc index 8513996b6a..0c58cb181d 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -338,7 +338,7 @@ SQLITE_TCL_DEP = !IFNDEF OPT_FEATURE_FLAGS !IF $(MINIMAL_AMALGAMATION)==0 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 !ENDIF OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 !ENDIF @@ -1400,6 +1400,7 @@ SRC09 = \ $(TOP)\ext\fts3\fts3_tokenizer.h \ $(TOP)\ext\icu\sqliteicu.h \ $(TOP)\ext\rtree\rtree.h \ + $(TOP)\ext\rtree\geopoly.c \ $(TOP)\ext\rbu\sqlite3rbu.h \ $(TOP)\ext\session\sqlite3session.h @@ -1573,7 +1574,8 @@ EXTHDR = $(EXTHDR) \ $(TOP)\ext\fts3\fts3_hash.h \ $(TOP)\ext\fts3\fts3_tokenizer.h EXTHDR = $(EXTHDR) \ - $(TOP)\ext\rtree\rtree.h + $(TOP)\ext\rtree\rtree.h \ + $(TOP)\ext\rtree\geopoly.c EXTHDR = $(EXTHDR) \ $(TOP)\ext\icu\sqliteicu.h EXTHDR = $(EXTHDR) \ diff --git a/configure b/configure index ea1160120f..c2a232b53c 100755 --- a/configure +++ b/configure @@ -911,6 +911,7 @@ enable_fts4 enable_fts5 enable_json1 enable_update_limit +enable_geopoly enable_rtree enable_session enable_gcov @@ -1563,6 +1564,7 @@ Optional Features: --enable-fts5 Enable the FTS5 extension --enable-json1 Enable the JSON1 extension --enable-update-limit Enable the UPDATE/DELETE LIMIT clause + --enable-geopoly Enable the GEOPOLY extension --enable-rtree Enable the RTREE extension --enable-session Enable the SESSION extension --enable-gcov Enable coverage testing using gcov @@ -3932,13 +3934,13 @@ if ${lt_cv_nm_interface+:} false; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:3935: $ac_compile\"" >&5) + (eval echo "\"\$as_me:3937: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:3938: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:3940: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:3941: output\"" >&5) + (eval echo "\"\$as_me:3943: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -5144,7 +5146,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 5147 "configure"' > conftest.$ac_ext + echo '#line 5149 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6669,11 +6671,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6672: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6674: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6676: \$? = $ac_status" >&5 + echo "$as_me:6678: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7008,11 +7010,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7011: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7013: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7015: \$? = $ac_status" >&5 + echo "$as_me:7017: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7113,11 +7115,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7116: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7118: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7120: \$? = $ac_status" >&5 + echo "$as_me:7122: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -7168,11 +7170,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7171: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7173: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7175: \$? = $ac_status" >&5 + echo "$as_me:7177: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9548,7 +9550,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9551 "configure" +#line 9553 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -9644,7 +9646,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9647 "configure" +#line 9649 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11630,6 +11632,20 @@ if test "${enable_udlimit}" = "yes" ; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT" fi +######### +# See whether we should enable GEOPOLY +# Check whether --enable-geopoly was given. +if test "${enable_geopoly+set}" = set; then : + enableval=$enable_geopoly; enable_geopoly=yes +else + enable_geopoly=no +fi + +if test "${enable_geopoly}" = "yes" ; then + OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY" + enable_rtree=yes +fi + ######### # See whether we should enable RTREE # Check whether --enable-rtree was given. diff --git a/configure.ac b/configure.ac index 7089772d19..f9e347d969 100644 --- a/configure.ac +++ b/configure.ac @@ -660,6 +660,16 @@ if test "${enable_udlimit}" = "yes" ; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT" fi +######### +# See whether we should enable GEOPOLY +AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly], + [Enable the GEOPOLY extension]), + [enable_geopoly=yes],[enable_geopoly=no]) +if test "${enable_geopoly}" = "yes" ; then + OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY" + enable_rtree=yes +fi + ######### # See whether we should enable RTREE AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree], diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c new file mode 100644 index 0000000000..3808871135 --- /dev/null +++ b/ext/rtree/geopoly.c @@ -0,0 +1,853 @@ +/* +** 2018-05-25 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file implements an alternative R-Tree virtual table that +** uses polygons to express the boundaries of 2-dimensional objects. +** +** This file is #include-ed onto the end of "rtree.c" so that it has +** access to all of the R-Tree internals. +*/ +#include + +/* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */ +#ifdef GEOPOLY_ENABLE_DEBUG + static int geo_debug = 0; +# define GEODEBUG(X) if(geo_debug)printf X +#else +# define GEODEBUG(X) +#endif + +#ifndef JSON_NULL /* The following stuff repeats things found in json1 */ +/* +** Versions of isspace(), isalnum() and isdigit() to which it is safe +** to pass signed char values. +*/ +#ifdef sqlite3Isdigit + /* Use the SQLite core versions if this routine is part of the + ** SQLite amalgamation */ +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isxdigit(x) sqlite3Isxdigit(x) +#else + /* Use the standard library for separate compilation */ +#include /* amalgamator: keep */ +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isxdigit(x) isxdigit((unsigned char)(x)) +#endif + +/* +** Growing our own isspace() routine this way is twice as fast as +** the library isspace() function. +*/ +static const char geopolyIsSpace[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x]) +#endif /* JSON NULL - back to original code */ + +/* Compiler and version */ +#ifndef GCC_VERSION +#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) +# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) +#else +# define GCC_VERSION 0 +#endif +#endif +#ifndef MSVC_VERSION +#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) +# define MSVC_VERSION _MSC_VER +#else +# define MSVC_VERSION 0 +#endif +#endif + +/* Datatype for coordinates +*/ +typedef float GeoCoord; + +/* +** Internal representation of a polygon. +** +** The polygon consists of a sequence of vertexes. There is a line +** segment between each pair of vertexes, and one final segment from +** the last vertex back to the first. (This differs from the GeoJSON +** standard in which the final vertex is a repeat of the first.) +** +** The polygon follows the right-hand rule. The area to the right of +** each segment is "outside" and the area to the left is "inside". +** +** The on-disk representation consists of a 4-byte header followed by +** the values. The 4-byte header is: +** +** encoding (1 byte) 0=big-endian, 1=little-endian +** nvertex (3 bytes) Number of vertexes as a big-endian integer +*/ +typedef struct GeoPoly GeoPoly; +struct GeoPoly { + int nVertex; /* Number of vertexes */ + unsigned char hdr[4]; /* Header for on-disk representation */ + GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */ +}; + +/* +** State of a parse of a GeoJSON input. +*/ +typedef struct GeoParse GeoParse; +struct GeoParse { + const unsigned char *z; /* Unparsed input */ + int nVertex; /* Number of vertexes in a[] */ + int nAlloc; /* Space allocated to a[] */ + int nErr; /* Number of errors encountered */ + GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */ +}; + +/* Do a 4-byte byte swap */ +static void geopolySwab32(unsigned char *a){ + unsigned char t = a[0]; + a[0] = a[3]; + a[3] = t; + t = a[1]; + a[1] = a[2]; + a[2] = t; +} + +/* Skip whitespace. Return the next non-whitespace character. */ +static char geopolySkipSpace(GeoParse *p){ + while( p->z[0] && safe_isspace(p->z[0]) ) p->z++; + return p->z[0]; +} + +/* Parse out a number. Write the value into *pVal if pVal!=0. +** return non-zero on success and zero if the next token is not a number. +*/ +static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ + const unsigned char *z = p->z; + char c = geopolySkipSpace(p); + int j; + int seenDP = 0; + int seenE = 0; + assert( '-' < '0' ); + if( c<='0' ){ + j = c=='-'; + if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; + } + j = 1; + for(;; j++){ + c = z[j]; + if( c>='0' && c<='9' ) continue; + if( c=='.' ){ + if( z[j-1]=='-' ) return 0; + if( seenDP ) return 0; + seenDP = 1; + continue; + } + if( c=='e' || c=='E' ){ + if( z[j-1]<'0' ) return 0; + if( seenE ) return -1; + seenDP = seenE = 1; + c = z[j+1]; + if( c=='+' || c=='-' ){ + j++; + c = z[j+1]; + } + if( c<'0' || c>'9' ) return 0; + continue; + } + break; + } + if( z[j-1]<'0' ) return 0; + if( pVal ) *pVal = atof((const char*)p->z); + p->z += j; + return 1; +} + +/* +** If the input is a well-formed JSON array of coordinates, where each +** coordinate is itself a two-value array, then convert the JSON into +** a GeoPoly object and return a pointer to that object. +** +** If any error occurs, return NULL. +*/ +static GeoPoly *geopolyParseJson(const unsigned char *z){ + GeoParse s; + memset(&s, 0, sizeof(s)); + s.z = z; + if( geopolySkipSpace(&s)=='[' ){ + s.z++; + while( geopolySkipSpace(&s)=='[' ){ + int ii = 0; + char c; + s.z++; + if( s.nVertex<=s.nAlloc ){ + GeoCoord *aNew; + s.nAlloc = s.nAlloc*2 + 16; + aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); + if( aNew==0 ){ + s.nErr++; + break; + } + s.a = aNew; + } + while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){ + ii++; + if( ii==2 ) s.nVertex++; + c = geopolySkipSpace(&s); + s.z++; + if( c==',' ) continue; + if( c==']' ) break; + s.nErr++; + goto parse_json_err; + } + if( geopolySkipSpace(&s)==',' ){ + s.z++; + continue; + } + break; + } + if( geopolySkipSpace(&s)==']' && s.nVertex>=4 ){ + int nByte; + GeoPoly *pOut; + int x = (s.nVertex-1)*2; + if( s.a[x]==s.a[0] && s.a[x+1]==s.a[1] ) s.nVertex--; + nByte = sizeof(GeoPoly) * (s.nVertex-1)*2*sizeof(GeoCoord); + pOut = sqlite3_malloc64( nByte ); + x = 1; + if( pOut==0 ) goto parse_json_err; + pOut->nVertex = s.nVertex; + memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord)); + pOut->hdr[0] = *(unsigned char*)&x; + pOut->hdr[1] = (s.nVertex>>16)&0xff; + pOut->hdr[2] = (s.nVertex>>8)&0xff; + pOut->hdr[3] = s.nVertex&0xff; + sqlite3_free(s.a); + return pOut; + }else{ + s.nErr++; + } + } +parse_json_err: + sqlite3_free(s.a); + return 0; +} + +/* +** Given a function parameter, try to interpret it as a polygon, either +** in the binary format or JSON text. Compute a GeoPoly object and +** return a pointer to that object. Or if the input is not a well-formed +** polygon, put an error message in sqlite3_context and return NULL. +*/ +static GeoPoly *geopolyFuncParam(sqlite3_context *pCtx, sqlite3_value *pVal){ + GeoPoly *p = 0; + int nByte; + if( sqlite3_value_type(pVal)==SQLITE_BLOB + && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord)) + ){ + const unsigned char *a = sqlite3_value_blob(pVal); + int nVertex; + nVertex = (a[1]<<16) + (a[2]<<8) + a[3]; + if( (a[0]==0 && a[0]==1) + && (nVertex*2*sizeof(GeoCoord) + 4)==nByte + ){ + p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); + if( p ){ + int x = 1; + p->nVertex = nVertex; + memcpy(p->hdr, a, nByte); + if( a[0] != *(unsigned char*)&x ){ + int ii; + for(ii=0; iia[ii]); + } + p->hdr[0] ^= 1; + } + } + } + }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ + p = geopolyParseJson(sqlite3_value_text(pVal)); + } + if( p==0 ){ + sqlite3_result_error(pCtx, "not a valid polygon", -1); + } + return p; +} + +/* +** Implementation of the geopoly_blob(X) function. +** +** If the input is a well-formed Geopoly BLOB or JSON string +** then return the BLOB representation of the polygon. Otherwise +** return NULL. +*/ +static void geopolyBlobFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyFuncParam(context, argv[0]); + if( p ){ + sqlite3_result_blob(context, p->hdr, + 4+8*p->nVertex, SQLITE_TRANSIENT); + sqlite3_free(p); + } +} + +/* +** SQL function: geopoly_json(X) +** +** Interpret X as a polygon and render it as a JSON array +** of coordinates. Or, if X is not a valid polygon, return NULL. +*/ +static void geopolyJsonFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyFuncParam(context, argv[0]); + if( p ){ + sqlite3 *db = sqlite3_context_db_handle(context); + sqlite3_str *x = sqlite3_str_new(db); + int i; + sqlite3_str_append(x, "[", 1); + for(i=0; inVertex; i++){ + sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]); + } + sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]); + sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); + sqlite3_free(p); + } +} + +/* +** SQL function: geopoly_svg(X, ....) +** +** Interpret X as a polygon and render it as a SVG . +** Additional arguments are added as attributes to the . +*/ +static void geopolySvgFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyFuncParam(context, argv[0]); + if( p ){ + sqlite3 *db = sqlite3_context_db_handle(context); + sqlite3_str *x = sqlite3_str_new(db); + int i; + char cSep = '\''; + sqlite3_str_appendf(x, "a[i*2], p->a[i*2+1]); + cSep = ' '; + } + sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]); + for(i=1; i"); + sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); + sqlite3_free(p); + } +} + +/* +** Implementation of the geopoly_area(X) function. +** +** If the input is a well-formed Geopoly BLOB then return the area +** enclosed by the polygon. If the polygon circulates clockwise instead +** of counterclockwise (as it should) then return the negative of the +** enclosed area. Otherwise return NULL. +*/ +static void geopolyAreaFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyFuncParam(context, argv[0]); + if( p ){ + double rArea = 0.0; + int ii; + for(ii=0; iinVertex-1; ii++){ + rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ + * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ + * 0.5; + } + rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ + * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ + * 0.5; + sqlite3_result_double(context, rArea); + sqlite3_free(p); + } +} + +/* +** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). +** Returns: +** +** +2 x0,y0 is on the line segement +** +** +1 x0,y0 is beneath line segment +** +** 0 x0,y0 is not on or beneath the line segment or the line segment +** is vertical and x0,y0 is not on the line segment +** +** The left-most coordinate min(x1,x2) is not considered to be part of +** the line segment for the purposes of this analysis. +*/ +static int pointBeneathLine( + double x0, double y0, + double x1, double y1, + double x2, double y2 +){ + double y; + if( x0==x1 && y0==y1 ) return 2; + if( x1x2 ) return 0; + }else if( x1>x2 ){ + if( x0<=x2 || x0>x1 ) return 0; + }else{ + /* Vertical line segment */ + if( x0!=x1 ) return 0; + if( y0y1 && y0>y2 ) return 0; + return 2; + } + y = y1 + (y2-y1)*(x0-x1)/(x2-x1); + if( y0==y ) return 2; + if( y0nVertex-1; ii++){ + v = pointBeneathLine(x0,y0,p->a[ii*2],p->a[ii*2+1], + p->a[ii*2+2],p->a[ii*2+3]); + if( v==2 ) break; + cnt += v; + } + if( v!=2 ){ + v = pointBeneathLine(x0,y0,p->a[ii*2],p->a[ii*2+1], + p->a[0],p->a[1]); + } + if( v==2 ){ + sqlite3_result_int(context, 1); + }else if( ((v+cnt)&1)==0 ){ + sqlite3_result_int(context, 0); + }else{ + sqlite3_result_int(context, 2); + } + sqlite3_free(p); + } +} + +/* Objects used by the overlap algorihm. */ +typedef struct GeoEvent GeoEvent; +typedef struct GeoSegment GeoSegment; +typedef struct GeoOverlap GeoOverlap; +struct GeoEvent { + double x; /* X coordinate at which event occurs */ + int eType; /* 0 for ADD, 1 for REMOVE */ + GeoSegment *pSeg; /* The segment to be added or removed */ + GeoEvent *pNext; /* Next event in the sorted list */ +}; +struct GeoSegment { + double C, B; /* y = C*x + B */ + double y; /* Current y value */ + float y0; /* Initial y value */ + unsigned char side; /* 1 for p1, 2 for p2 */ + unsigned int idx; /* Which segment within the side */ + GeoSegment *pNext; /* Next segment in a list sorted by y */ +}; +struct GeoOverlap { + GeoEvent *aEvent; /* Array of all events */ + GeoSegment *aSegment; /* Array of all segments */ + int nEvent; /* Number of events */ + int nSegment; /* Number of segments */ +}; + +/* +** Add a single segment and its associated events. +*/ +static void geopolyAddOneSegment( + GeoOverlap *p, + GeoCoord x0, + GeoCoord y0, + GeoCoord x1, + GeoCoord y1, + unsigned char side, + unsigned int idx +){ + GeoSegment *pSeg; + GeoEvent *pEvent; + if( x0==x1 ) return; /* Ignore vertical segments */ + if( x0>x1 ){ + GeoCoord t = x0; + x0 = x1; + x1 = t; + t = y0; + y0 = y1; + y1 = t; + } + pSeg = p->aSegment + p->nSegment; + p->nSegment++; + pSeg->C = (y1-y0)/(x1-x0); + pSeg->B = y1 - x1*pSeg->C; + pSeg->y0 = y0; + pSeg->side = side; + pSeg->idx = idx; + pEvent = p->aEvent + p->nEvent; + p->nEvent++; + pEvent->x = x0; + pEvent->eType = 0; + pEvent->pSeg = pSeg; + pEvent = p->aEvent + p->nEvent; + p->nEvent++; + pEvent->x = x1; + pEvent->eType = 1; + pEvent->pSeg = pSeg; +} + + + +/* +** Insert all segments and events for polygon pPoly. +*/ +static void geopolyAddSegments( + GeoOverlap *p, /* Add segments to this Overlap object */ + GeoPoly *pPoly, /* Take all segments from this polygon */ + unsigned char side /* The side of pPoly */ +){ + unsigned int i; + GeoCoord *x; + for(i=0; inVertex-1; i++){ + x = pPoly->a + (i*2); + geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i); + } + x = pPoly->a + (i*2); + geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i); +} + +/* +** Merge two lists of sorted events by X coordinate +*/ +static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){ + GeoEvent head, *pLast; + head.pNext = 0; + pLast = &head; + while( pRight && pLeft ){ + if( pRight->x <= pLeft->x ){ + pLast->pNext = pRight; + pLast = pRight; + pRight = pRight->pNext; + }else{ + pLast->pNext = pLeft; + pLast = pLeft; + pLeft = pLeft->pNext; + } + } + pLast->pNext = pRight ? pRight : pLeft; + return head.pNext; +} + +/* +** Sort an array of nEvent event objects into a list. +*/ +static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){ + int mx = 0; + int i, j; + GeoEvent *p; + GeoEvent *a[50]; + for(i=0; ipNext = 0; + for(j=0; j=mx ) mx = j+1; + } + p = 0; + for(i=0; iy - pLeft->y; + if( r==0.0 ) r = pRight->C - pLeft->C; + if( r<0.0 ){ + pLast->pNext = pRight; + pLast = pRight; + pRight = pRight->pNext; + }else{ + pLast->pNext = pLeft; + pLast = pLeft; + pLeft = pLeft->pNext; + } + } + pLast->pNext = pRight ? pRight : pLeft; + return head.pNext; +} + +/* +** Sort a list of GeoSegments in order of increasing Y and in the event of +** a tie, increasing C (slope). +*/ +static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ + int mx = 0; + int i; + GeoSegment *p; + GeoSegment *a[50]; + while( pList ){ + p = pList; + pList = pList->pNext; + p->pNext = 0; + for(i=0; i=mx ) mx = i+1; + } + p = 0; + for(i=0; inVertex + p2->nVertex + 2; + GeoOverlap *p; + int nByte; + GeoEvent *pThisEvent; + double rX; + int rc = 0; + int needSort = 0; + GeoSegment *pActive = 0; + GeoSegment *pSeg; + unsigned char aOverlap[4]; + + nByte = sizeof(GeoEvent)*nVertex*2 + + sizeof(GeoSegment)*nVertex + + sizeof(GeoOverlap); + p = sqlite3_malloc( nByte ); + if( p==0 ) return -1; + p->aEvent = (GeoEvent*)&p[1]; + p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; + p->nEvent = p->nSegment = 0; + geopolyAddSegments(p, p1, 1); + geopolyAddSegments(p, p2, 2); + pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent); + rX = pThisEvent->x==0.0 ? -1.0 : 0.0; + memset(aOverlap, 0, sizeof(aOverlap)); + while( pThisEvent ){ + if( pThisEvent->x!=rX ){ + GeoSegment *pPrev = 0; + int iMask = 0; + GEODEBUG(("Distinct X: %g\n", pThisEvent->x)); + rX = pThisEvent->x; + if( needSort ){ + GEODEBUG(("SORT\n")); + pActive = geopolySortSegmentsByYAndC(pActive); + needSort = 0; + } + for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ + if( pPrev ){ + if( pPrev->y!=pSeg->y ){ + GEODEBUG(("MASK: %d\n", iMask)); + aOverlap[iMask] = 1; + } + } + iMask ^= pSeg->side; + pPrev = pSeg; + } + pPrev = 0; + for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ + double y = pSeg->C*rX + pSeg->B; + GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y)); + pSeg->y = y; + if( pPrev ){ + if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){ + rc = 1; + GEODEBUG(("Crossing: %d.%d and %d.%d\n", + pPrev->side, pPrev->idx, + pSeg->side, pSeg->idx)); + goto geopolyOverlapDone; + }else if( pPrev->y!=pSeg->y ){ + GEODEBUG(("MASK: %d\n", iMask)); + aOverlap[iMask] = 1; + } + } + iMask ^= pSeg->side; + pPrev = pSeg; + } + } + GEODEBUG(("%s %d.%d C=%g B=%g\n", + pThisEvent->eType ? "RM " : "ADD", + pThisEvent->pSeg->side, pThisEvent->pSeg->idx, + pThisEvent->pSeg->C, + pThisEvent->pSeg->B)); + if( pThisEvent->eType==0 ){ + /* Add a segment */ + pSeg = pThisEvent->pSeg; + pSeg->y = pSeg->y0; + pSeg->pNext = pActive; + pActive = pSeg; + needSort = 1; + }else{ + /* Remove a segment */ + if( pActive==pThisEvent->pSeg ){ + pActive = pActive->pNext; + }else{ + for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ + if( pSeg->pNext==pThisEvent->pSeg ){ + pSeg->pNext = pSeg->pNext->pNext; + break; + } + } + } + } + pThisEvent = pThisEvent->pNext; + } + if( aOverlap[3]==0 ){ + rc = 0; + }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){ + rc = 3; + }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){ + rc = 2; + }else if( aOverlap[1]==0 && aOverlap[2]==0 ){ + rc = 4; + }else{ + rc = 1; + } + +geopolyOverlapDone: + sqlite3_free(p); + return rc; +} + +/* +** SQL function: geopoly_overlap(P1,P2) +** +** Determine whether or not P1 and P2 overlap. Return value: +** +** 0 The two polygons are disjoint +** 1 They overlap +** 2 P1 is completely contained within P2 +** 3 P2 is completely contained within P1 +** 4 P1 and P2 are the same polygon +** NULL Either P1 or P2 or both are not valid polygons +*/ +static void geopolyOverlapFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p1 = geopolyFuncParam(context, argv[0]); + GeoPoly *p2 = geopolyFuncParam(context, argv[1]); + if( p1 && p2 ){ + int x = geopolyOverlap(p1, p2); + if( x<0 ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_int(context, x); + } + } + sqlite3_free(p1); + sqlite3_free(p2); +} + +/* +** Enable or disable debugging output +*/ +static void geopolyDebugFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ +#ifdef GEOPOLY_ENABLE_DEBUG + geo_debug = sqlite3_value_int(argv[0]); +#endif +} + +static int sqlite3_geopoly_init(sqlite3 *db){ + int rc = SQLITE_OK; + static const struct { + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + int nArg; + const char *zName; + } aFunc[] = { + { geopolyAreaFunc, 1, "geopoly_area" }, + { geopolyBlobFunc, 1, "geopoly_blob" }, + { geopolyJsonFunc, 1, "geopoly_json" }, + { geopolySvgFunc, -1, "geopoly_svg" }, + { geopolyWithinFunc, 3, "geopoly_within" }, + { geopolyOverlapFunc, 2, "geopoly_overlap" }, + { geopolyDebugFunc, 1, "geopoly_debug" }, + }; + int i; + for(i=0; i Date: Fri, 25 May 2018 20:53:42 +0000 Subject: [PATCH 002/260] Incremental check-in: Progress toward implementing the geopoly vtab. FossilOrigin-Name: 9b7d6f986a19f8fbe26d880dc368870a10df80e06097be34ee3639f78c50be61 --- ext/rtree/geopoly.c | 502 +++++++++++++++++++++++++++++++++++++++++++- manifest | 15 +- manifest.uuid | 2 +- 3 files changed, 508 insertions(+), 11 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 3808871135..f22f762e7c 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -270,7 +270,7 @@ static GeoPoly *geopolyFuncParam(sqlite3_context *pCtx, sqlite3_value *pVal){ const unsigned char *a = sqlite3_value_blob(pVal); int nVertex; nVertex = (a[1]<<16) + (a[2]<<8) + a[3]; - if( (a[0]==0 && a[0]==1) + if( (a[0]==0 || a[0]==1) && (nVertex*2*sizeof(GeoCoord) + 4)==nByte ){ p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); @@ -407,6 +407,79 @@ static void geopolyAreaFunc( } } +/* +** Compute a bound-box on a polygon. Return a new GeoPoly object +** that describes the bounding box. Or, if aCoord is not a NULL pointer +** fill it in with the bounding box instead. +*/ +static GeoPoly *geopolyBBox( + sqlite3_context *context, /* For recording the error */ + sqlite3_value *pPoly, /* The polygon */ + double *aCoord /* Results here */ +){ + GeoPoly *p = geopolyFuncParam(context, pPoly); + GeoPoly *pOut; + if( p ){ + int ii; + float mnX, mxX, mnY, mxY; + mnX = mxX = p->a[0]; + mnY = mxY = p->a[1]; + for(ii=1; iinVertex; ii++){ + double r = p->a[ii*2]; + if( rmxX ) mxX = r; + r = p->a[ii*2+1]; + if( rmxY ) mxY = r; + } + if( aCoord==0 ){ + pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6); + if( pOut==0 ){ + sqlite3_free(p); + sqlite3_result_error_nomem(context); + return 0; + } + pOut->nVertex = 4; + pOut->hdr[1] = 0; + pOut->hdr[2] = 0; + pOut->hdr[3] = 4; + pOut->a[0] = mnX; + pOut->a[1] = mnY; + pOut->a[2] = mxX; + pOut->a[3] = mnY; + pOut->a[4] = mxX; + pOut->a[5] = mxY; + pOut->a[6] = mnX; + pOut->a[7] = mxY; + return pOut; + }else{ + sqlite3_free(p); + aCoord[0] = mnX; + aCoord[1] = mxX; + aCoord[2] = mnY; + aCoord[3] = mxY; + return (GeoPoly*)aCoord; + } + } + return 0; +} + +/* +** Implementation of the geopoly_bbox(X) SQL function. +*/ +static void geopolyBBoxFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyBBox(context, argv[0], 0); + if( p ){ + sqlite3_result_blob(context, p->hdr, + 4+8*p->nVertex, SQLITE_TRANSIENT); + sqlite3_free(p); + } +} + /* ** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). ** Returns: @@ -828,6 +901,429 @@ static void geopolyDebugFunc( #endif } +/* +** This function is the implementation of both the xConnect and xCreate +** methods of the geopoly virtual table. +** +** argv[0] -> module name +** argv[1] -> database name +** argv[2] -> table name +** argv[...] -> column names... +*/ +static int geopolyInit( + sqlite3 *db, /* Database connection */ + void *pAux, /* One of the RTREE_COORD_* constants */ + int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ + sqlite3_vtab **ppVtab, /* OUT: New virtual table */ + char **pzErr, /* OUT: Error message, if any */ + int isCreate /* True for xCreate, false for xConnect */ +){ + int rc = SQLITE_OK; + Rtree *pRtree; + int nDb; /* Length of string argv[1] */ + int nName; /* Length of string argv[2] */ + sqlite3_str *pSql; + char *zSql; + int ii; + char cSep; + + sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); + + /* Allocate the sqlite3_vtab structure */ + nDb = (int)strlen(argv[1]); + nName = (int)strlen(argv[2]); + pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); + if( !pRtree ){ + return SQLITE_NOMEM; + } + memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); + pRtree->nBusy = 1; + pRtree->base.pModule = &rtreeModule; + pRtree->zDb = (char *)&pRtree[1]; + pRtree->zName = &pRtree->zDb[nDb+1]; + pRtree->eCoordType = RTREE_COORD_REAL32; + pRtree->nDim = 2; + pRtree->nDim2 = 4; + memcpy(pRtree->zDb, argv[1], nDb); + memcpy(pRtree->zName, argv[2], nName); + + + /* Create/Connect to the underlying relational database schema. If + ** that is successful, call sqlite3_declare_vtab() to configure + ** the r-tree table schema. + */ + pSql = sqlite3_str_new(db); + sqlite3_str_appendf(pSql, "CREATE TABLE x"); + cSep = '('; + for(ii=3; iinAux++; + sqlite3_str_appendf(pSql, "%c%s", cSep, argv[ii]+1); + cSep = ','; + } + sqlite3_str_appendf(pSql, "%c _poly HIDDEN, _bbox HIDDEN);", cSep); + zSql = sqlite3_str_finish(pSql); + if( !zSql ){ + rc = SQLITE_NOMEM; + }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + } + sqlite3_free(zSql); + if( rc ) goto geopolyInit_fail; + pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; + + /* Figure out the node size to use. */ + rc = getNodeSize(db, pRtree, isCreate, pzErr); + if( rc ) goto geopolyInit_fail; + rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); + if( rc ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + goto geopolyInit_fail; + } + + *ppVtab = (sqlite3_vtab *)pRtree; + return SQLITE_OK; + +geopolyInit_fail: + if( rc==SQLITE_OK ) rc = SQLITE_ERROR; + assert( *ppVtab==0 ); + assert( pRtree->nBusy==1 ); + rtreeRelease(pRtree); + return rc; +} + + +/* +** GEOPOLY virtual table module xCreate method. +*/ +static int geopolyCreate( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1); +} + +/* +** GEOPOLY virtual table module xConnect method. +*/ +static int geopolyConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0); +} + + +/* +** GEOPOLY virtual table module xBestIndex method. There are three +** table scan strategies to choose from (in order from most to +** least desirable): +** +** idxNum idxStr Strategy +** ------------------------------------------------ +** 1 Unused Direct lookup by rowid. +** 2 'Fx' shape query +** 2 '' full-table scan. +** ------------------------------------------------ +** +** If strategy 1 is used, then idxStr is not meaningful. If strategy +** 2 is used, idxStr is either the two-byte string 'Fx' or an empty +** string. +*/ +static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + Rtree *pRtree = (Rtree*)tab; + int rc = SQLITE_OK; + int ii; + int bMatch = 0; /* True if there exists a MATCH constraint */ + i64 nRow; /* Estimated rows returned by this scan */ + + int iIdx = 0; + char zIdxStr[3]; + memset(zIdxStr, 0, sizeof(zIdxStr)); + + /* Check if there exists a MATCH constraint - even an unusable one. If there + ** is, do not consider the lookup-by-rowid plan as using such a plan would + ** require the VDBE to evaluate the MATCH constraint, which is not currently + ** possible. */ + for(ii=0; iinConstraint; ii++){ + if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){ + bMatch = 1; + } + } + + assert( pIdxInfo->idxStr==0 ); + for(ii=0; iinConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ + struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; + + if( bMatch==0 + && p->usable + && p->iColumn<0 + && p->op==SQLITE_INDEX_CONSTRAINT_EQ + ){ + /* We have an equality constraint on the rowid. Use strategy 1. */ + int jj; + for(jj=0; jjaConstraintUsage[jj].argvIndex = 0; + pIdxInfo->aConstraintUsage[jj].omit = 0; + } + pIdxInfo->idxNum = 1; + pIdxInfo->aConstraintUsage[ii].argvIndex = 1; + pIdxInfo->aConstraintUsage[jj].omit = 1; + + /* This strategy involves a two rowid lookups on an B-Tree structures + ** and then a linear search of an R-Tree node. This should be + ** considered almost as quick as a direct rowid lookup (for which + ** sqlite uses an internal cost of 0.0). It is expected to return + ** a single row. + */ + pIdxInfo->estimatedCost = 30.0; + pIdxInfo->estimatedRows = 1; + pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; + return SQLITE_OK; + } + + /* A MATCH operator against the _shape column */ + if( p->usable + && p->iColumn==pRtree->nAux + && p->op==SQLITE_INDEX_CONSTRAINT_MATCH + ){ + zIdxStr[0] = RTREE_MATCH; + zIdxStr[1] = 'x'; + zIdxStr[2] = 0; + pIdxInfo->aConstraintUsage[ii].argvIndex = 0; + pIdxInfo->aConstraintUsage[ii].omit = 1; + } + } + + pIdxInfo->idxNum = 2; + pIdxInfo->needToFreeIdxStr = 1; + if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ + return SQLITE_NOMEM; + } + + nRow = pRtree->nRowEst/100 + 5; + pIdxInfo->estimatedCost = (double)6.0 * (double)nRow; + pIdxInfo->estimatedRows = nRow; + + return rc; +} + + +/* +** GEOPOLY virtual table module xColumn method. +*/ +static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ + Rtree *pRtree = (Rtree *)cur->pVtab; + RtreeCursor *pCsr = (RtreeCursor *)cur; + RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); + int rc = SQLITE_OK; + RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); + + if( rc ) return rc; + if( p==0 ) return SQLITE_OK; + if( i<=pRtree->nAux ){ + if( !pCsr->bAuxValid ){ + if( pCsr->pReadAux==0 ){ + rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, + &pCsr->pReadAux, 0); + if( rc ) return rc; + } + sqlite3_bind_int64(pCsr->pReadAux, 1, + nodeGetRowid(pRtree, pNode, p->iCell)); + rc = sqlite3_step(pCsr->pReadAux); + if( rc==SQLITE_ROW ){ + pCsr->bAuxValid = 1; + }else{ + sqlite3_reset(pCsr->pReadAux); + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + return rc; + } + } + sqlite3_result_value(ctx, + sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1)); + }else{ + /* Must be the _bbox column */ + } + return SQLITE_OK; +} + + +/* +** The xUpdate method for GEOPOLY module virtual tables. +*/ +static int geopolyUpdate( + sqlite3_vtab *pVtab, + int nData, + sqlite3_value **aData, + sqlite_int64 *pRowid +){ + Rtree *pRtree = (Rtree *)pVtab; + int rc = SQLITE_OK; +// RtreeCell cell; /* New cell to insert if nData>1 */ +// int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ +// int iShapeCol; /* Index of the _shape column */ + + if( pRtree->nNodeRef ){ + /* Unable to write to the btree while another cursor is reading from it, + ** since the write might do a rebalance which would disrupt the read + ** cursor. */ + return SQLITE_LOCKED_VTAB; + } + rtreeReference(pRtree); + assert(nData>=1); + +// cell.iRowid = 0; /* Used only to suppress a compiler warning */ +// iShapeCol = pRtree->nAux; + + rc = SQLITE_ERROR; + +#if 0 + + /* Constraint handling. A write operation on an r-tree table may return + ** SQLITE_CONSTRAINT for two reasons: + ** + ** 1. A duplicate rowid value, or + ** 2. The supplied data violates the "x2>=x1" constraint. + ** + ** In the first case, if the conflict-handling mode is REPLACE, then + ** the conflicting row can be removed before proceeding. In the second + ** case, SQLITE_CONSTRAINT must be returned regardless of the + ** conflict-handling mode specified by the user. + */ + if( nData>1 + && (!sqlite3_value_nochange(aData[iShapeCol+2]) + ){ + +#ifndef SQLITE_RTREE_INT_ONLY + if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ + for(ii=0; iicell.aCoord[ii+1].f ){ + rc = rtreeConstraintError(pRtree, ii+1); + goto constraint; + } + } + }else +#endif + { + for(ii=0; iicell.aCoord[ii+1].i ){ + rc = rtreeConstraintError(pRtree, ii+1); + goto constraint; + } + } + } + + /* If a rowid value was supplied, check if it is already present in + ** the table. If so, the constraint has failed. */ + if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){ + cell.iRowid = sqlite3_value_int64(aData[2]); + if( sqlite3_value_type(aData[0])==SQLITE_NULL + || sqlite3_value_int64(aData[0])!=cell.iRowid + ){ + int steprc; + sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); + steprc = sqlite3_step(pRtree->pReadRowid); + rc = sqlite3_reset(pRtree->pReadRowid); + if( SQLITE_ROW==steprc ){ + if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ + rc = rtreeDeleteRowid(pRtree, cell.iRowid); + }else{ + rc = rtreeConstraintError(pRtree, 0); + goto constraint; + } + } + } + bHaveRowid = 1; + } + } + + /* If aData[0] is not an SQL NULL value, it is the rowid of a + ** record to delete from the r-tree table. The following block does + ** just that. + */ + if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){ + rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0])); + } + + /* If the aData[] array contains more than one element, elements + ** (aData[2]..aData[argc-1]) contain a new record to insert into + ** the r-tree structure. + */ + if( rc==SQLITE_OK && nData>1 ){ + /* Insert the new record into the r-tree */ + RtreeNode *pLeaf = 0; + + /* Figure out the rowid of the new row. */ + if( bHaveRowid==0 ){ + rc = newRowid(pRtree, &cell.iRowid); + } + *pRowid = cell.iRowid; + + if( rc==SQLITE_OK ){ + rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); + } + if( rc==SQLITE_OK ){ + int rc2; + pRtree->iReinsertHeight = -1; + rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); + rc2 = nodeRelease(pRtree, pLeaf); + if( rc==SQLITE_OK ){ + rc = rc2; + } + } + if( pRtree->nAux ){ + sqlite3_stmt *pUp = pRtree->pWriteAux; + int jj; + sqlite3_bind_int64(pUp, 1, *pRowid); + for(jj=0; jjnAux; jj++){ + sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); + } + sqlite3_step(pUp); + rc = sqlite3_reset(pUp); + } + } +constraint: +#endif /* 0 */ + + rtreeRelease(pRtree); + return rc; +} + +static sqlite3_module geopolyModule = { + 2, /* iVersion */ + geopolyCreate, /* xCreate - create a table */ + geopolyConnect, /* xConnect - connect to an existing table */ + geopolyBestIndex, /* xBestIndex - Determine search strategy */ + rtreeDisconnect, /* xDisconnect - Disconnect from a table */ + rtreeDestroy, /* xDestroy - Drop a table */ + rtreeOpen, /* xOpen - open a cursor */ + rtreeClose, /* xClose - close a cursor */ + rtreeFilter, /* xFilter - configure scan constraints */ + rtreeNext, /* xNext - advance a cursor */ + rtreeEof, /* xEof */ + geopolyColumn, /* xColumn - read data */ + rtreeRowid, /* xRowid - read data */ + geopolyUpdate, /* xUpdate - write data */ + rtreeBeginTransaction, /* xBegin - begin transaction */ + rtreeEndTransaction, /* xSync - sync transaction */ + rtreeEndTransaction, /* xCommit - commit transaction */ + rtreeEndTransaction, /* xRollback - rollback transaction */ + 0, /* xFindFunction - function overloading */ + rtreeRename, /* xRename - rename the table */ + rtreeSavepoint, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ +}; + static int sqlite3_geopoly_init(sqlite3 *db){ int rc = SQLITE_OK; static const struct { @@ -842,6 +1338,7 @@ static int sqlite3_geopoly_init(sqlite3 *db){ { geopolyWithinFunc, 3, "geopoly_within" }, { geopolyOverlapFunc, 2, "geopoly_overlap" }, { geopolyDebugFunc, 1, "geopoly_debug" }, + { geopolyBBoxFunc, 1, "geopoly_bbox" }, }; int i; for(i=0; i Date: Fri, 25 May 2018 22:39:29 +0000 Subject: [PATCH 003/260] Untested incremental check-in. Basic infrastructure for geopoly in place, except for the MATCH operator. FossilOrigin-Name: b27451910b6880b166d4777e05b14ab2731c3483b5ed0f42c459bbb61c6cd095 --- ext/rtree/geopoly.c | 200 +++++++++++++++++++++----------------------- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 102 insertions(+), 112 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index f22f762e7c..427462b560 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -193,8 +193,9 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ ** ** If any error occurs, return NULL. */ -static GeoPoly *geopolyParseJson(const unsigned char *z){ +static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ GeoParse s; + int rc = SQLITE_OK; memset(&s, 0, sizeof(s)); s.z = z; if( geopolySkipSpace(&s)=='[' ){ @@ -208,6 +209,7 @@ static GeoPoly *geopolyParseJson(const unsigned char *z){ s.nAlloc = s.nAlloc*2 + 16; aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); if( aNew==0 ){ + rc = SQLITE_NOMEM; s.nErr++; break; } @@ -221,6 +223,7 @@ static GeoPoly *geopolyParseJson(const unsigned char *z){ if( c==',' ) continue; if( c==']' ) break; s.nErr++; + rc = SQLITE_ERROR; goto parse_json_err; } if( geopolySkipSpace(&s)==',' ){ @@ -245,12 +248,15 @@ static GeoPoly *geopolyParseJson(const unsigned char *z){ pOut->hdr[2] = (s.nVertex>>8)&0xff; pOut->hdr[3] = s.nVertex&0xff; sqlite3_free(s.a); + if( pRc ) *pRc = SQLITE_OK; return pOut; }else{ s.nErr++; + rc = SQLITE_ERROR; } } parse_json_err: + if( pRc ) *pRc = rc; sqlite3_free(s.a); return 0; } @@ -261,7 +267,11 @@ parse_json_err: ** return a pointer to that object. Or if the input is not a well-formed ** polygon, put an error message in sqlite3_context and return NULL. */ -static GeoPoly *geopolyFuncParam(sqlite3_context *pCtx, sqlite3_value *pVal){ +static GeoPoly *geopolyFuncParam( + sqlite3_context *pCtx, /* Context for error messages */ + sqlite3_value *pVal, /* The value to decode */ + int *pRc /* Write error here */ +){ GeoPoly *p = 0; int nByte; if( sqlite3_value_type(pVal)==SQLITE_BLOB @@ -274,7 +284,10 @@ static GeoPoly *geopolyFuncParam(sqlite3_context *pCtx, sqlite3_value *pVal){ && (nVertex*2*sizeof(GeoCoord) + 4)==nByte ){ p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); - if( p ){ + if( p==0 ){ + if( pRc ) *pRc = SQLITE_NOMEM; + if( pCtx ) sqlite3_result_error_nomem(pCtx); + }else{ int x = 1; p->nVertex = nVertex; memcpy(p->hdr, a, nByte); @@ -287,13 +300,15 @@ static GeoPoly *geopolyFuncParam(sqlite3_context *pCtx, sqlite3_value *pVal){ } } } + if( pRc ) *pRc = SQLITE_OK; + return p; }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ - p = geopolyParseJson(sqlite3_value_text(pVal)); + return geopolyParseJson(sqlite3_value_text(pVal), pRc); + }else{ + *pRc = SQLITE_ERROR; + if( pCtx!=0 ) sqlite3_result_error(pCtx, "not a valid polygon", -1); + return 0; } - if( p==0 ){ - sqlite3_result_error(pCtx, "not a valid polygon", -1); - } - return p; } /* @@ -308,7 +323,7 @@ static void geopolyBlobFunc( int argc, sqlite3_value **argv ){ - GeoPoly *p = geopolyFuncParam(context, argv[0]); + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); if( p ){ sqlite3_result_blob(context, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); @@ -327,7 +342,7 @@ static void geopolyJsonFunc( int argc, sqlite3_value **argv ){ - GeoPoly *p = geopolyFuncParam(context, argv[0]); + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); if( p ){ sqlite3 *db = sqlite3_context_db_handle(context); sqlite3_str *x = sqlite3_str_new(db); @@ -353,7 +368,7 @@ static void geopolySvgFunc( int argc, sqlite3_value **argv ){ - GeoPoly *p = geopolyFuncParam(context, argv[0]); + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); if( p ){ sqlite3 *db = sqlite3_context_db_handle(context); sqlite3_str *x = sqlite3_str_new(db); @@ -390,7 +405,7 @@ static void geopolyAreaFunc( int argc, sqlite3_value **argv ){ - GeoPoly *p = geopolyFuncParam(context, argv[0]); + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); if( p ){ double rArea = 0.0; int ii; @@ -415,10 +430,11 @@ static void geopolyAreaFunc( static GeoPoly *geopolyBBox( sqlite3_context *context, /* For recording the error */ sqlite3_value *pPoly, /* The polygon */ - double *aCoord /* Results here */ + RtreeCoord *aCoord, /* Results here */ + int *pRc /* Error code here */ ){ - GeoPoly *p = geopolyFuncParam(context, pPoly); - GeoPoly *pOut; + GeoPoly *p = geopolyFuncParam(context, pPoly, pRc); + GeoPoly *pOut = 0; if( p ){ int ii; float mnX, mxX, mnY, mxY; @@ -432,11 +448,13 @@ static GeoPoly *geopolyBBox( if( rmxY ) mxY = r; } + if( pRc ) *pRc = SQLITE_OK; if( aCoord==0 ){ pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6); if( pOut==0 ){ sqlite3_free(p); - sqlite3_result_error_nomem(context); + if( context ) sqlite3_result_error_nomem(context); + if( pRc ) *pRc = SQLITE_NOMEM; return 0; } pOut->nVertex = 4; @@ -451,17 +469,15 @@ static GeoPoly *geopolyBBox( pOut->a[5] = mxY; pOut->a[6] = mnX; pOut->a[7] = mxY; - return pOut; }else{ sqlite3_free(p); - aCoord[0] = mnX; - aCoord[1] = mxX; - aCoord[2] = mnY; - aCoord[3] = mxY; - return (GeoPoly*)aCoord; + aCoord[0].f = mnX; + aCoord[1].f = mxX; + aCoord[2].f = mnY; + aCoord[3].f = mxY; } } - return 0; + return pOut; } /* @@ -472,7 +488,7 @@ static void geopolyBBoxFunc( int argc, sqlite3_value **argv ){ - GeoPoly *p = geopolyBBox(context, argv[0], 0); + GeoPoly *p = geopolyBBox(context, argv[0], 0, 0); if( p ){ sqlite3_result_blob(context, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); @@ -530,7 +546,7 @@ static void geopolyWithinFunc( int argc, sqlite3_value **argv ){ - GeoPoly *p = geopolyFuncParam(context, argv[0]); + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); double x0 = sqlite3_value_double(argv[1]); double y0 = sqlite3_value_double(argv[2]); if( p ){ @@ -874,8 +890,8 @@ static void geopolyOverlapFunc( int argc, sqlite3_value **argv ){ - GeoPoly *p1 = geopolyFuncParam(context, argv[0]); - GeoPoly *p2 = geopolyFuncParam(context, argv[1]); + GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); + GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); if( p1 && p2 ){ int x = geopolyOverlap(p1, p2); if( x<0 ){ @@ -955,12 +971,13 @@ static int geopolyInit( pSql = sqlite3_str_new(db); sqlite3_str_appendf(pSql, "CREATE TABLE x"); cSep = '('; + pRtree->nAux = 1; /* Add one for _shape */ for(ii=3; iinAux++; sqlite3_str_appendf(pSql, "%c%s", cSep, argv[ii]+1); cSep = ','; } - sqlite3_str_appendf(pSql, "%c _poly HIDDEN, _bbox HIDDEN);", cSep); + sqlite3_str_appendf(pSql, "%c _shape, _bbox HIDDEN);", cSep); zSql = sqlite3_str_finish(pSql); if( !zSql ){ rc = SQLITE_NOMEM; @@ -1164,9 +1181,13 @@ static int geopolyUpdate( ){ Rtree *pRtree = (Rtree *)pVtab; int rc = SQLITE_OK; -// RtreeCell cell; /* New cell to insert if nData>1 */ -// int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ -// int iShapeCol; /* Index of the _shape column */ + RtreeCell cell; /* New cell to insert if nData>1 */ + int iShapeCol; /* Index of the _shape column */ + i64 oldRowid; /* The old rowid */ + int oldRowidValid; /* True if oldRowid is valid */ + i64 newRowid; /* The new rowid */ + int newRowidValid; /* True if newRowid is valid */ + int coordChange = 0; /* Change in coordinates */ if( pRtree->nNodeRef ){ /* Unable to write to the btree while another cursor is reading from it, @@ -1177,72 +1198,43 @@ static int geopolyUpdate( rtreeReference(pRtree); assert(nData>=1); -// cell.iRowid = 0; /* Used only to suppress a compiler warning */ -// iShapeCol = pRtree->nAux; - + iShapeCol = pRtree->nAux; rc = SQLITE_ERROR; + oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; + oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; + newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL; + newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; + cell.iRowid = newRowid; -#if 0 - - /* Constraint handling. A write operation on an r-tree table may return - ** SQLITE_CONSTRAINT for two reasons: - ** - ** 1. A duplicate rowid value, or - ** 2. The supplied data violates the "x2>=x1" constraint. - ** - ** In the first case, if the conflict-handling mode is REPLACE, then - ** the conflicting row can be removed before proceeding. In the second - ** case, SQLITE_CONSTRAINT must be returned regardless of the - ** conflict-handling mode specified by the user. - */ - if( nData>1 - && (!sqlite3_value_nochange(aData[iShapeCol+2]) + if( nData>1 /* not a DELETE */ + && (!oldRowidValid /* INSERT */ + || !sqlite3_value_nochange(aData[iShapeCol+2]) /* UPDATE _shape */ + || oldRowid!=newRowid) /* Rowid change */ ){ - -#ifndef SQLITE_RTREE_INT_ONLY - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; iicell.aCoord[ii+1].f ){ - rc = rtreeConstraintError(pRtree, ii+1); - goto constraint; - } - } - }else -#endif - { - for(ii=0; iicell.aCoord[ii+1].i ){ - rc = rtreeConstraintError(pRtree, ii+1); - goto constraint; - } + geopolyBBox(0, aData[iShapeCol+2], cell.aCoord, &rc); + if( rc ){ + if( rc==SQLITE_ERROR ){ + pVtab->zErrMsg = + sqlite3_mprintf("_shape does not contain a valid polygon"); } + return rc; } + coordChange = 1; /* If a rowid value was supplied, check if it is already present in ** the table. If so, the constraint has failed. */ - if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){ - cell.iRowid = sqlite3_value_int64(aData[2]); - if( sqlite3_value_type(aData[0])==SQLITE_NULL - || sqlite3_value_int64(aData[0])!=cell.iRowid - ){ - int steprc; - sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); - steprc = sqlite3_step(pRtree->pReadRowid); - rc = sqlite3_reset(pRtree->pReadRowid); - if( SQLITE_ROW==steprc ){ - if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ - rc = rtreeDeleteRowid(pRtree, cell.iRowid); - }else{ - rc = rtreeConstraintError(pRtree, 0); - goto constraint; - } + if( oldRowidValid && oldRowid!=newRowid ){ + int steprc; + sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); + steprc = sqlite3_step(pRtree->pReadRowid); + rc = sqlite3_reset(pRtree->pReadRowid); + if( SQLITE_ROW==steprc ){ + if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ + rc = rtreeDeleteRowid(pRtree, cell.iRowid); + }else{ + rc = rtreeConstraintError(pRtree, 0); } } - bHaveRowid = 1; } } @@ -1250,24 +1242,18 @@ static int geopolyUpdate( ** record to delete from the r-tree table. The following block does ** just that. */ - if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){ - rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0])); + if( rc==SQLITE_OK && (nData==1 || coordChange) ){ + rc = rtreeDeleteRowid(pRtree, oldRowid); } /* If the aData[] array contains more than one element, elements ** (aData[2]..aData[argc-1]) contain a new record to insert into ** the r-tree structure. */ - if( rc==SQLITE_OK && nData>1 ){ + if( rc==SQLITE_OK && nData>1 && coordChange ){ /* Insert the new record into the r-tree */ RtreeNode *pLeaf = 0; - - /* Figure out the rowid of the new row. */ - if( bHaveRowid==0 ){ - rc = newRowid(pRtree, &cell.iRowid); - } *pRowid = cell.iRowid; - if( rc==SQLITE_OK ){ rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); } @@ -1280,19 +1266,23 @@ static int geopolyUpdate( rc = rc2; } } - if( pRtree->nAux ){ - sqlite3_stmt *pUp = pRtree->pWriteAux; - int jj; - sqlite3_bind_int64(pUp, 1, *pRowid); - for(jj=0; jjnAux; jj++){ - sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); - } + } + + /* Change the data */ + if( rc==SQLITE_OK && pRtree->nAux>0 ){ + sqlite3_stmt *pUp = pRtree->pWriteAux; + int jj; + int nChange = 0; + sqlite3_bind_int64(pUp, 1, newRowid); + for(jj=0; jjnAux; jj++){ + if( !sqlite3_value_nochange(aData[jj+2]) ) nChange++; + sqlite3_bind_value(pUp, jj+2, aData[jj+2]); + } + if( nChange ){ sqlite3_step(pUp); rc = sqlite3_reset(pUp); } } -constraint: -#endif /* 0 */ rtreeRelease(pRtree); return rc; diff --git a/manifest b/manifest index 042bcab12b..44b42dc0f8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Incremental\scheck-in:\sProgress\stoward\simplementing\sthe\sgeopoly\svtab. -D 2018-05-25T20:53:42.012 +C Untested\sincremental\scheck-in.\s\sBasic\sinfrastructure\sfor\sgeopoly\sin\splace,\nexcept\sfor\sthe\sMATCH\soperator. +D 2018-05-25T22:39:29.495 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 51407f0e371dcb9e65d368bd4f1a08fc17ef8361ff11aac9356f0f63693b38dd @@ -355,7 +355,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c bf7a5fc70df145e83b60abd3e9828ad036921a9603087f5f108e054d75f12abc +F ext/rtree/geopoly.c e1b192440686ee041f94a510298f5d1d44e24f5c777674c1d00be616c6ac9633 F ext/rtree/rtree.c 2fd3c149c6fc4d3fdf602dc610b34ad9abdf75cca26d0c362f903aa02ea2ef47 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 @@ -1730,7 +1730,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0593aac88a8c25ddafba4c29a181ee083dfc3dab44335feb6f12fdea6ce7fb27 -R 36e4ed5dc1a640520059a271545fd8c3 +P 9b7d6f986a19f8fbe26d880dc368870a10df80e06097be34ee3639f78c50be61 +R ac42d4684558c7281aaaaec9453f13e7 U drh -Z b8c6ea17872c9a8b20afb569a3513051 +Z b54e65d1af2e3764e8c52f03dab6b0ff diff --git a/manifest.uuid b/manifest.uuid index 52355d0aed..78ee84ffb1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9b7d6f986a19f8fbe26d880dc368870a10df80e06097be34ee3639f78c50be61 \ No newline at end of file +b27451910b6880b166d4777e05b14ab2731c3483b5ed0f42c459bbb61c6cd095 \ No newline at end of file From f403e1af0b74300b93395d4feea8e813d43aa749 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 May 2018 12:21:21 +0000 Subject: [PATCH 004/260] Minor correction. FossilOrigin-Name: f20d9a99a477e1d592edb37d741d9d07b015d6772b4c8cf1541ef290d600ca6b --- ext/rtree/geopoly.c | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 427462b560..2effb59f87 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -1109,7 +1109,7 @@ static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ && p->iColumn==pRtree->nAux && p->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - zIdxStr[0] = RTREE_MATCH; + zIdxStr[0] = RTREE_QUERY; zIdxStr[1] = 'x'; zIdxStr[2] = 0; pIdxInfo->aConstraintUsage[ii].argvIndex = 0; diff --git a/manifest b/manifest index 44b42dc0f8..ead659468d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Untested\sincremental\scheck-in.\s\sBasic\sinfrastructure\sfor\sgeopoly\sin\splace,\nexcept\sfor\sthe\sMATCH\soperator. -D 2018-05-25T22:39:29.495 +C Minor\scorrection. +D 2018-05-26T12:21:21.540 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 51407f0e371dcb9e65d368bd4f1a08fc17ef8361ff11aac9356f0f63693b38dd @@ -355,7 +355,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c e1b192440686ee041f94a510298f5d1d44e24f5c777674c1d00be616c6ac9633 +F ext/rtree/geopoly.c 66b0192b554aa344e64aa9e086b8bd8509fa53c82830d698a71f61ac830328cf F ext/rtree/rtree.c 2fd3c149c6fc4d3fdf602dc610b34ad9abdf75cca26d0c362f903aa02ea2ef47 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 @@ -1730,7 +1730,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9b7d6f986a19f8fbe26d880dc368870a10df80e06097be34ee3639f78c50be61 -R ac42d4684558c7281aaaaec9453f13e7 +P b27451910b6880b166d4777e05b14ab2731c3483b5ed0f42c459bbb61c6cd095 +R 0e7fa04f7ff537a47acee804207d1995 U drh -Z b54e65d1af2e3764e8c52f03dab6b0ff +Z e132f6a792319f62f6944c0a7e6e7692 diff --git a/manifest.uuid b/manifest.uuid index 78ee84ffb1..c1b230bdb5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b27451910b6880b166d4777e05b14ab2731c3483b5ed0f42c459bbb61c6cd095 \ No newline at end of file +f20d9a99a477e1d592edb37d741d9d07b015d6772b4c8cf1541ef290d600ca6b \ No newline at end of file From 59155065e07a468e1a74f3a90cc2dc612287a6bf Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 May 2018 18:03:48 +0000 Subject: [PATCH 005/260] Experimental change that allows overloaded functions to be analyzed by the xBestIndex method and used by the xFilter method of a virtual table. FossilOrigin-Name: a353b1d7ee6c5989ba1b98a3990c9a4c2ff39ae66572fd1200606e8ef585e5fa --- manifest | 19 ++++++++++------- manifest.uuid | 2 +- src/expr.c | 2 +- src/sqlite.h.in | 1 + src/whereexpr.c | 57 +++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 1867640d1d..b86958ab3e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Store\sapplication-defined\sfunction\snames\sas\slower-case\sto\savoid\sthe\sneed\nfor\scase\sconversions\sbefore\scalling\sxFindFunction\son\svirtual\stables.\nAvoid\susing\slookaside\sto\sstore\sthe\sdestructors\sfor\sapplication\sdefined\nfunctions,\sas\slookaside\sshould\sbe\sreserved\sfor\stransient\sallocations. -D 2018-05-26T16:00:26.368 +C Experimental\schange\sthat\sallows\soverloaded\sfunctions\sto\sbe\sanalyzed\sby\nthe\sxBestIndex\smethod\sand\sused\sby\sthe\sxFilter\smethod\sof\sa\svirtual\stable. +D 2018-05-26T18:03:48.120 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -446,7 +446,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f -F src/expr.c af4a81a385277510bfc56df87c25d76fc365f98c33bc8797c4a8d84b88e31013 +F src/expr.c 81b3925fb84e226d230eb59d8ef8d680b22a121410934545ba026027d5fe03df F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c e2e3c02621a528a472933fd4733a5da635676f1461be73293f6e9f62f18d4eaa @@ -496,7 +496,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 F src/shell.c.in 51c100206f4b7f86cd9affd80b764825e0edc36ca0190c442e4ca7994611bfe2 -F src/sqlite.h.in db327b5de56909e060da241ff89cc3726eadf98e9eb17386fc831bbce80e0820 +F src/sqlite.h.in 9823d4fee4b4d56d210a2f603c255af3c984c3cacb14a841d35c5bb27707055b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h d2bd297dba08f2390a91c31ff775e0964e9663df5b2910a569fe6f830b8b2beb @@ -581,7 +581,7 @@ F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1 F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53 F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8 -F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a +F src/whereexpr.c a6994e3a616f33e885becc2d6a4377ce5aea92b6e2dff96de3a8dd986ed3113f F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1729,7 +1729,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 27b4fa5dd0defc6ddaf5d8cde6a1e1162b70d99bfdc69c1d2290621a6d23ed91 -R d728fa434c4672bbeedeb70c9aae9549 +P 777189ce88799f93f393fd14fd716111c85bcdcb23690fd561f78ea2bd2ce5da +R 287ad6e657f697576be6591ee557b37e +T *branch * vtab-func-constraint +T *sym-vtab-func-constraint * +T -sym-trunk * U drh -Z 593bd01a2c2330ddb0f8d8891bce9a51 +Z 1dcaa168f6b87a9c36f55e4d22ec80f8 diff --git a/manifest.uuid b/manifest.uuid index 2496e83258..bf9a43fb0d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -777189ce88799f93f393fd14fd716111c85bcdcb23690fd561f78ea2bd2ce5da \ No newline at end of file +a353b1d7ee6c5989ba1b98a3990c9a4c2ff39ae66572fd1200606e8ef585e5fa \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 6aff83a256..a45f38f9c7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3903,7 +3903,7 @@ expr_code_doover: ** "glob(B,A). We want to use the A in "A glob B" to test ** for function overloading. But we use the B term in "glob(B,A)". */ - if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ + if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); }else if( nFarg>0 ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 64e929a89e..979b974699 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6323,6 +6323,7 @@ struct sqlite3_index_info { #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 #define SQLITE_INDEX_CONSTRAINT_IS 72 +#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 /* ** CAPI3REF: Register A Virtual Table Implementation diff --git a/src/whereexpr.c b/src/whereexpr.c index 29750080a1..b177a7d995 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -338,6 +338,7 @@ static int isLikeOrGlob( ** If the expression matches none of the patterns above, return 0. */ static int isAuxiliaryVtabOperator( + sqlite3 *db, /* Parsing context */ Expr *pExpr, /* Test this expression */ unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ Expr **ppLeft, /* Column expression to left of MATCH/op2 */ @@ -361,16 +362,54 @@ static int isAuxiliaryVtabOperator( if( pList==0 || pList->nExpr!=2 ){ return 0; } + + /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a + ** virtual table on their second argument, which is the same as + ** the left-hand side operand in their in-fix form. + ** + ** vtab_column MATCH expression + ** MATCH(expression,vtab_column) + */ pCol = pList->a[1].pExpr; - if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ - return 0; + if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + for(i=0; iu.zToken, aOp[i].zOp)==0 ){ + *peOp2 = aOp[i].eOp2; + *ppRight = pList->a[0].pExpr; + *ppLeft = pCol; + return 1; + } + } } - for(i=0; iu.zToken, aOp[i].zOp)==0 ){ - *peOp2 = aOp[i].eOp2; - *ppRight = pList->a[0].pExpr; - *ppLeft = pCol; - return 1; + + /* We can also match against the first column of overloaded + ** functions where xFindFunction returns a value of at least + ** SQLITE_INDEX_CONSTRAINT_FUNCTION. + ** + ** OVERLOADED(vtab_column,expression) + ** + ** Historically, xFindFunction expected to see lower-case function + ** names. But for this use case, xFindFunction is expected to deal + ** with function names in an arbitrary case. + */ + pCol = pList->a[0].pExpr; + if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + sqlite3_vtab *pVtab; + sqlite3_module *pMod; + void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); + void *pNotUsed; + pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab; + assert( pVtab!=0 ); + assert( pVtab->pModule!=0 ); + pMod = (sqlite3_module *)pVtab->pModule; + if( pMod->xFindFunction!=0 ){ + i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); + if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ + *peOp2 = i; + *ppRight = pList->a[1].pExpr; + *ppLeft = pCol; + return 1; + } } } }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ @@ -1230,7 +1269,7 @@ static void exprAnalyze( */ if( pWC->op==TK_AND ){ Expr *pRight = 0, *pLeft = 0; - int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight); + int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight); while( res-- > 0 ){ int idxNew; WhereTerm *pNewTerm; From 48e4ef56c3dbbd9748f47cddaee7dd1539d8c50c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 28 May 2018 13:23:23 +0000 Subject: [PATCH 006/260] Untested incremental check-in. Add the geopoly_xform() function. Complete basic logic for the geopoly virtual table. FossilOrigin-Name: ed06cc32568a3abaa0535b379e0ee3b04ffb7582dcda6405670620d1fbe8996c --- ext/rtree/geopoly.c | 326 ++++++++++++++++++++++++++++++++------------ manifest | 12 +- manifest.uuid | 2 +- 3 files changed, 243 insertions(+), 97 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 2effb59f87..b5b6282163 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -392,6 +392,51 @@ static void geopolySvgFunc( } } +/* +** SQL Function: geopoly_xform(poly, A, B, C, D, E, F) +** +** Transform and/or translate a polygon as follows: +** +** x1 = A*x0 + B*y0 + E +** y1 = C*x0 + D*y0 + F +** +** For a translation: +** +** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset) +** +** Rotate by R around the point (0,0): +** +** geopoly_xform(poly, cos(R), sin(R), sin(R), cos(R), 0, 0) +*/ +static void geopolyXformFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); + double A = sqlite3_value_double(argv[1]); + double B = sqlite3_value_double(argv[2]); + double C = sqlite3_value_double(argv[3]); + double D = sqlite3_value_double(argv[4]); + double E = sqlite3_value_double(argv[5]); + double F = sqlite3_value_double(argv[7]); + GeoCoord x1, y1, x0, y0; + int ii; + if( p ){ + for(ii=0; iinVertex; ii++){ + x0 = p->a[ii*2]; + y0 = p->a[ii*2+1]; + x1 = A*x0 + B*y0 + E; + y1 = C*x0 + D*y0 + F; + p->a[ii*2] = x1; + p->a[ii*2+1] = y1; + } + sqlite3_result_blob(context, p->hdr, + 4+8*p->nVertex, SQLITE_TRANSIENT); + sqlite3_free(p); + } +} + /* ** Implementation of the geopoly_area(X) function. ** @@ -941,7 +986,6 @@ static int geopolyInit( sqlite3_str *pSql; char *zSql; int ii; - char cSep; sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); @@ -969,15 +1013,13 @@ static int geopolyInit( ** the r-tree table schema. */ pSql = sqlite3_str_new(db); - sqlite3_str_appendf(pSql, "CREATE TABLE x"); - cSep = '('; + sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape"); pRtree->nAux = 1; /* Add one for _shape */ for(ii=3; iinAux++; - sqlite3_str_appendf(pSql, "%c%s", cSep, argv[ii]+1); - cSep = ','; + sqlite3_str_appendf(pSql, ",%s", argv[ii]+1); } - sqlite3_str_appendf(pSql, "%c _shape, _bbox HIDDEN);", cSep); + sqlite3_str_appendf(pSql, ",_bbox HIDDEN);"); zSql = sqlite3_str_finish(pSql); if( !zSql ){ rc = SQLITE_NOMEM; @@ -1036,98 +1078,165 @@ static int geopolyConnect( } +/* +** GEOPOLY virtual table module xFilter method. +** +** Query plans: +** +** 1 rowid lookup +** 2 search for objects overlapping the same bounding box +** that contains polygon argv[0] +** 3 full table scan +*/ +static int geopolyFilter( + sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */ + int idxNum, /* Query plan */ + const char *idxStr, /* Not Used */ + int argc, sqlite3_value **argv /* Parameters to the query plan */ +){ + Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; + RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; + RtreeNode *pRoot = 0; + int rc = SQLITE_OK; + int iCell = 0; + sqlite3_stmt *pStmt; + + rtreeReference(pRtree); + + /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ + freeCursorConstraints(pCsr); + sqlite3_free(pCsr->aPoint); + pStmt = pCsr->pReadAux; + memset(pCsr, 0, sizeof(RtreeCursor)); + pCsr->base.pVtab = (sqlite3_vtab*)pRtree; + pCsr->pReadAux = pStmt; + + pCsr->iStrategy = idxNum; + if( idxNum==1 ){ + /* Special case - lookup by rowid. */ + RtreeNode *pLeaf; /* Leaf on which the required cell resides */ + RtreeSearchPoint *p; /* Search point for the leaf */ + i64 iRowid = sqlite3_value_int64(argv[0]); + i64 iNode = 0; + rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); + if( rc==SQLITE_OK && pLeaf!=0 ){ + p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); + assert( p!=0 ); /* Always returns pCsr->sPoint */ + pCsr->aNode[0] = pLeaf; + p->id = iNode; + p->eWithin = PARTLY_WITHIN; + rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); + p->iCell = (u8)iCell; + RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); + }else{ + pCsr->atEOF = 1; + } + }else{ + /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array + ** with the configured constraints. + */ + rc = nodeAcquire(pRtree, 1, 0, &pRoot); + if( rc==SQLITE_OK && idxNum==2 ){ + RtreeCoord bbox[4]; + RtreeConstraint *p; + assert( argc==1 ); + geopolyBBox(0, argv[0], bbox, &rc); + if( rc ){ + return rc; + } + pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4); + pCsr->nConstraint = 4; + if( p==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); + memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); + p->op = 'B'; + p->iCoord = 'a'; + p->u.rValue = bbox[0].f; + p++; + p->op = 'D'; + p->iCoord = 'b'; + p->u.rValue = bbox[1].f; + p++; + p->op = 'B'; + p->iCoord = 'c'; + p->u.rValue = bbox[2].f; + p++; + p->op = 'D'; + p->iCoord = 'd'; + p->u.rValue = bbox[3].f; + } + } + if( rc==SQLITE_OK ){ + RtreeSearchPoint *pNew; + pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); + if( pNew==0 ) return SQLITE_NOMEM; + pNew->id = 1; + pNew->iCell = 0; + pNew->eWithin = PARTLY_WITHIN; + assert( pCsr->bPoint==1 ); + pCsr->aNode[0] = pRoot; + pRoot = 0; + RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); + rc = rtreeStepToLeaf(pCsr); + } + } + + nodeRelease(pRtree, pRoot); + rtreeRelease(pRtree); + return rc; +} + /* -** GEOPOLY virtual table module xBestIndex method. There are three +** Rtree virtual table module xBestIndex method. There are three ** table scan strategies to choose from (in order from most to ** least desirable): ** ** idxNum idxStr Strategy ** ------------------------------------------------ ** 1 Unused Direct lookup by rowid. -** 2 'Fx' shape query -** 2 '' full-table scan. +** 2 Unused R-tree query +** 3 Unused full-table scan. ** ------------------------------------------------ -** -** If strategy 1 is used, then idxStr is not meaningful. If strategy -** 2 is used, idxStr is either the two-byte string 'Fx' or an empty -** string. */ static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - Rtree *pRtree = (Rtree*)tab; - int rc = SQLITE_OK; int ii; - int bMatch = 0; /* True if there exists a MATCH constraint */ - i64 nRow; /* Estimated rows returned by this scan */ + int iRowidTerm = -1; + int iFuncTerm = -1; - int iIdx = 0; - char zIdxStr[3]; - memset(zIdxStr, 0, sizeof(zIdxStr)); - - /* Check if there exists a MATCH constraint - even an unusable one. If there - ** is, do not consider the lookup-by-rowid plan as using such a plan would - ** require the VDBE to evaluate the MATCH constraint, which is not currently - ** possible. */ for(ii=0; iinConstraint; ii++){ - if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - bMatch = 1; - } - } - - assert( pIdxInfo->idxStr==0 ); - for(ii=0; iinConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; - - if( bMatch==0 - && p->usable - && p->iColumn<0 - && p->op==SQLITE_INDEX_CONSTRAINT_EQ - ){ - /* We have an equality constraint on the rowid. Use strategy 1. */ - int jj; - for(jj=0; jjaConstraintUsage[jj].argvIndex = 0; - pIdxInfo->aConstraintUsage[jj].omit = 0; - } - pIdxInfo->idxNum = 1; - pIdxInfo->aConstraintUsage[ii].argvIndex = 1; - pIdxInfo->aConstraintUsage[jj].omit = 1; - - /* This strategy involves a two rowid lookups on an B-Tree structures - ** and then a linear search of an R-Tree node. This should be - ** considered almost as quick as a direct rowid lookup (for which - ** sqlite uses an internal cost of 0.0). It is expected to return - ** a single row. - */ - pIdxInfo->estimatedCost = 30.0; - pIdxInfo->estimatedRows = 1; - pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; - return SQLITE_OK; + if( !p->usable ) continue; + if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + iRowidTerm = ii; + break; } - - /* A MATCH operator against the _shape column */ - if( p->usable - && p->iColumn==pRtree->nAux - && p->op==SQLITE_INDEX_CONSTRAINT_MATCH - ){ - zIdxStr[0] = RTREE_QUERY; - zIdxStr[1] = 'x'; - zIdxStr[2] = 0; - pIdxInfo->aConstraintUsage[ii].argvIndex = 0; - pIdxInfo->aConstraintUsage[ii].omit = 1; + if( p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION ){ + iFuncTerm = ii; } } - pIdxInfo->idxNum = 2; - pIdxInfo->needToFreeIdxStr = 1; - if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ - return SQLITE_NOMEM; + if( iRowidTerm>=0 ){ + pIdxInfo->idxNum = 1; + pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; + pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; + pIdxInfo->estimatedCost = 30.0; + pIdxInfo->estimatedRows = 1; + pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; + return SQLITE_OK; } - - nRow = pRtree->nRowEst/100 + 5; - pIdxInfo->estimatedCost = (double)6.0 * (double)nRow; - pIdxInfo->estimatedRows = nRow; - - return rc; + if( iFuncTerm>=0 ){ + pIdxInfo->idxNum = 2; + pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; + pIdxInfo->estimatedCost = 300.0; + pIdxInfo->estimatedRows = 10; + return SQLITE_OK; + } + pIdxInfo->idxNum = 3; + pIdxInfo->estimatedCost = 3000000.0; + pIdxInfo->estimatedRows = 100000; + return SQLITE_OK; } @@ -1172,6 +1281,24 @@ static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ /* ** The xUpdate method for GEOPOLY module virtual tables. +** +** For DELETE: +** +** argv[0] = the rowid to be deleted +** +** For INSERT: +** +** argv[0] = SQL NULL +** argv[1] = rowid to insert, or an SQL NULL to select automatically +** argv[2] = _shape column +** argv[3] = first application-defined column.... +** +** For UPDATE: +** +** argv[0] = rowid to modify. Never NULL +** argv[1] = rowid after the change. Never NULL +** argv[2] = new value for _shape +** argv[3] = new value for first application-defined column.... */ static int geopolyUpdate( sqlite3_vtab *pVtab, @@ -1182,7 +1309,6 @@ static int geopolyUpdate( Rtree *pRtree = (Rtree *)pVtab; int rc = SQLITE_OK; RtreeCell cell; /* New cell to insert if nData>1 */ - int iShapeCol; /* Index of the _shape column */ i64 oldRowid; /* The old rowid */ int oldRowidValid; /* True if oldRowid is valid */ i64 newRowid; /* The new rowid */ @@ -1198,7 +1324,6 @@ static int geopolyUpdate( rtreeReference(pRtree); assert(nData>=1); - iShapeCol = pRtree->nAux; rc = SQLITE_ERROR; oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; @@ -1206,12 +1331,12 @@ static int geopolyUpdate( newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; cell.iRowid = newRowid; - if( nData>1 /* not a DELETE */ - && (!oldRowidValid /* INSERT */ - || !sqlite3_value_nochange(aData[iShapeCol+2]) /* UPDATE _shape */ - || oldRowid!=newRowid) /* Rowid change */ + if( nData>1 /* not a DELETE */ + && (!oldRowidValid /* INSERT */ + || !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */ + || oldRowid!=newRowid) /* Rowid change */ ){ - geopolyBBox(0, aData[iShapeCol+2], cell.aCoord, &rc); + geopolyBBox(0, aData[2], cell.aCoord, &rc); if( rc ){ if( rc==SQLITE_ERROR ){ pVtab->zErrMsg = @@ -1223,7 +1348,7 @@ static int geopolyUpdate( /* If a rowid value was supplied, check if it is already present in ** the table. If so, the constraint has failed. */ - if( oldRowidValid && oldRowid!=newRowid ){ + if( newRowidValid ){ int steprc; sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); steprc = sqlite3_step(pRtree->pReadRowid); @@ -1269,7 +1394,7 @@ static int geopolyUpdate( } /* Change the data */ - if( rc==SQLITE_OK && pRtree->nAux>0 ){ + if( rc==SQLITE_OK ){ sqlite3_stmt *pUp = pRtree->pWriteAux; int jj; int nChange = 0; @@ -1288,6 +1413,26 @@ static int geopolyUpdate( return rc; } +/* +** Report that geopoly_overlap() is an overloaded function suitable +** for use in xBestIndex. +*/ +static int geopolyFindFunction( + sqlite3_vtab *pVtab, + int nArg, + const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg +){ + if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){ + *pxFunc = geopolyOverlapFunc; + *ppArg = 0; + return SQLITE_INDEX_CONSTRAINT_FUNCTION; + } + return 0; +} + + static sqlite3_module geopolyModule = { 2, /* iVersion */ geopolyCreate, /* xCreate - create a table */ @@ -1297,7 +1442,7 @@ static sqlite3_module geopolyModule = { rtreeDestroy, /* xDestroy - Drop a table */ rtreeOpen, /* xOpen - open a cursor */ rtreeClose, /* xClose - close a cursor */ - rtreeFilter, /* xFilter - configure scan constraints */ + geopolyFilter, /* xFilter - configure scan constraints */ rtreeNext, /* xNext - advance a cursor */ rtreeEof, /* xEof */ geopolyColumn, /* xColumn - read data */ @@ -1307,7 +1452,7 @@ static sqlite3_module geopolyModule = { rtreeEndTransaction, /* xSync - sync transaction */ rtreeEndTransaction, /* xCommit - commit transaction */ rtreeEndTransaction, /* xRollback - rollback transaction */ - 0, /* xFindFunction - function overloading */ + geopolyFindFunction, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ @@ -1329,6 +1474,7 @@ static int sqlite3_geopoly_init(sqlite3 *db){ { geopolyOverlapFunc, 2, "geopoly_overlap" }, { geopolyDebugFunc, 1, "geopoly_debug" }, { geopolyBBoxFunc, 1, "geopoly_bbox" }, + { geopolyXformFunc, 7, "geopoly_xform" }, }; int i; for(i=0; i Date: Mon, 28 May 2018 23:59:03 +0000 Subject: [PATCH 007/260] The geopoly virtual table seems to be working. But only thinly tested so far. FossilOrigin-Name: 4288f1ad5966701eac4cfe3061e8ce98e34e0d6c112307668729642a06458d5f --- ext/rtree/geopoly.c | 39 +++-- ext/rtree/rtree.c | 4 +- ext/rtree/visual01.txt | 389 +++++++++++++++++++++++++++++++++++++++++ manifest | 15 +- manifest.uuid | 2 +- 5 files changed, 421 insertions(+), 28 deletions(-) create mode 100644 ext/rtree/visual01.txt diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index b5b6282163..9e8de3cfee 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -406,7 +406,7 @@ static void geopolySvgFunc( ** ** Rotate by R around the point (0,0): ** -** geopoly_xform(poly, cos(R), sin(R), sin(R), cos(R), 0, 0) +** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0) */ static void geopolyXformFunc( sqlite3_context *context, @@ -419,7 +419,7 @@ static void geopolyXformFunc( double C = sqlite3_value_double(argv[3]); double D = sqlite3_value_double(argv[4]); double E = sqlite3_value_double(argv[5]); - double F = sqlite3_value_double(argv[7]); + double F = sqlite3_value_double(argv[6]); GeoCoord x1, y1, x0, y0; int ii; if( p ){ @@ -1017,7 +1017,7 @@ static int geopolyInit( pRtree->nAux = 1; /* Add one for _shape */ for(ii=3; iinAux++; - sqlite3_str_appendf(pSql, ",%s", argv[ii]+1); + sqlite3_str_appendf(pSql, ",%s", argv[ii]); } sqlite3_str_appendf(pSql, ",_bbox HIDDEN);"); zSql = sqlite3_str_finish(pSql); @@ -1149,23 +1149,23 @@ static int geopolyFilter( if( p==0 ){ rc = SQLITE_NOMEM; }else{ - memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); + memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4); memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); p->op = 'B'; - p->iCoord = 'a'; - p->u.rValue = bbox[0].f; - p++; - p->op = 'D'; - p->iCoord = 'b'; + p->iCoord = 0; p->u.rValue = bbox[1].f; p++; + p->op = 'D'; + p->iCoord = 1; + p->u.rValue = bbox[0].f; + p++; p->op = 'B'; - p->iCoord = 'c'; - p->u.rValue = bbox[2].f; + p->iCoord = 2; + p->u.rValue = bbox[3].f; p++; p->op = 'D'; - p->iCoord = 'd'; - p->u.rValue = bbox[3].f; + p->iCoord = 3; + p->u.rValue = bbox[2].f; } } if( rc==SQLITE_OK ){ @@ -1228,7 +1228,8 @@ static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ } if( iFuncTerm>=0 ){ pIdxInfo->idxNum = 2; - pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; + pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1; + pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0; pIdxInfo->estimatedCost = 300.0; pIdxInfo->estimatedRows = 10; return SQLITE_OK; @@ -1270,8 +1271,7 @@ static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ return rc; } } - sqlite3_result_value(ctx, - sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1)); + sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); }else{ /* Must be the _bbox column */ } @@ -1367,7 +1367,7 @@ static int geopolyUpdate( ** record to delete from the r-tree table. The following block does ** just that. */ - if( rc==SQLITE_OK && (nData==1 || coordChange) ){ + if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){ rc = rtreeDeleteRowid(pRtree, oldRowid); } @@ -1378,6 +1378,9 @@ static int geopolyUpdate( if( rc==SQLITE_OK && nData>1 && coordChange ){ /* Insert the new record into the r-tree */ RtreeNode *pLeaf = 0; + if( !newRowidValid ){ + rc = rtreeNewRowid(pRtree, &cell.iRowid); + } *pRowid = cell.iRowid; if( rc==SQLITE_OK ){ rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); @@ -1398,7 +1401,7 @@ static int geopolyUpdate( sqlite3_stmt *pUp = pRtree->pWriteAux; int jj; int nChange = 0; - sqlite3_bind_int64(pUp, 1, newRowid); + sqlite3_bind_int64(pUp, 1, cell.iRowid); for(jj=0; jjnAux; jj++){ if( !sqlite3_value_nochange(aData[jj+2]) ) nChange++; sqlite3_bind_value(pUp, jj+2, aData[jj+2]); diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index d817823f96..091c0bc6b4 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -2893,7 +2893,7 @@ static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){ /* ** Select a currently unused rowid for a new r-tree record. */ -static int newRowid(Rtree *pRtree, i64 *piRowid){ +static int rtreeNewRowid(Rtree *pRtree, i64 *piRowid){ int rc; sqlite3_bind_null(pRtree->pWriteRowid, 1); sqlite3_bind_null(pRtree->pWriteRowid, 2); @@ -3180,7 +3180,7 @@ static int rtreeUpdate( /* Figure out the rowid of the new row. */ if( bHaveRowid==0 ){ - rc = newRowid(pRtree, &cell.iRowid); + rc = rtreeNewRowid(pRtree, &cell.iRowid); } *pRowid = cell.iRowid; diff --git a/ext/rtree/visual01.txt b/ext/rtree/visual01.txt new file mode 100644 index 0000000000..bb3e4af5b5 --- /dev/null +++ b/ext/rtree/visual01.txt @@ -0,0 +1,389 @@ +#!sqlite3 +# +# This is a visual test case for the geopoly virtual table. +# +# Run this script in the sqlite3 CLI, and redirect output into an +# HTML file. This display the HTML in a webbrowser. +# + +/* Test data. +** Lots of shapes to be displayed over a 1000x800 canvas. +*/ +CREATE TEMP TABLE basis(name TEXT, jshape TEXT); +INSERT INTO basis(name,jshape) VALUES + ('box-20','[[0,0],[20,0],[20,20],[0,20],[0,0]]'), + ('house-70','[[0,0],[50,0],[50,50],[25,70],[0,50],[0,0]]'), + ('line-40','[[0,0],[40,0],[40,5],[0,5],[0,0]]'), + ('line-80','[[0,0],[80,0],[80,7],[0,7],[0,0]]'), + ('arrow-50','[[0,0],[25,25],[0,50],[15,25],[0,0]]'), + ('triangle-30','[[0,0],[30,0],[15,30],[0,0]]'), + ('angle-30','[[0,0],[30,0],[30,30],[26,30],[26,4],[0,4],[0,0]]'), + ('star-10','[[1,0],[5,2],[9,0],[7,4],[10,8],[7,7],[5,10],[3,7],[0,8],[3,4],[1,0]]'); +CREATE TEMP TABLE xform(A,B,C,D,clr); +INSERT INTO xform(A,B,clr) VALUES + (1,0,'black'), + (0.707,0.707,'blue'), + (0.5,0.866,'red'), + (-0.866,0.5,'green'); +CREATE TEMP TABLE xyoff(id1,id2,xoff,yoff,PRIMARY KEY(id1,id2,xoff,yoff)) + WITHOUT ROWID; +INSERT INTO xyoff VALUES(1,1,811,659); +INSERT INTO xyoff VALUES(1,1,235,550); +INSERT INTO xyoff VALUES(1,1,481,620); +INSERT INTO xyoff VALUES(1,1,106,494); +INSERT INTO xyoff VALUES(1,1,487,106); +INSERT INTO xyoff VALUES(1,1,817,595); +INSERT INTO xyoff VALUES(1,1,240,504); +INSERT INTO xyoff VALUES(1,1,806,457); +INSERT INTO xyoff VALUES(1,1,608,107); +INSERT INTO xyoff VALUES(1,1,768,662); +INSERT INTO xyoff VALUES(1,2,808,528); +INSERT INTO xyoff VALUES(1,2,768,528); +INSERT INTO xyoff VALUES(1,2,771,171); +INSERT INTO xyoff VALUES(1,2,275,671); +INSERT INTO xyoff VALUES(1,2,326,336); +INSERT INTO xyoff VALUES(1,2,690,688); +INSERT INTO xyoff VALUES(1,2,597,239); +INSERT INTO xyoff VALUES(1,2,317,528); +INSERT INTO xyoff VALUES(1,2,366,223); +INSERT INTO xyoff VALUES(1,2,621,154); +INSERT INTO xyoff VALUES(1,3,829,469); +INSERT INTO xyoff VALUES(1,3,794,322); +INSERT INTO xyoff VALUES(1,3,358,387); +INSERT INTO xyoff VALUES(1,3,184,444); +INSERT INTO xyoff VALUES(1,3,729,500); +INSERT INTO xyoff VALUES(1,3,333,523); +INSERT INTO xyoff VALUES(1,3,117,595); +INSERT INTO xyoff VALUES(1,3,496,201); +INSERT INTO xyoff VALUES(1,3,818,601); +INSERT INTO xyoff VALUES(1,3,541,343); +INSERT INTO xyoff VALUES(1,4,603,248); +INSERT INTO xyoff VALUES(1,4,761,649); +INSERT INTO xyoff VALUES(1,4,611,181); +INSERT INTO xyoff VALUES(1,4,607,233); +INSERT INTO xyoff VALUES(1,4,860,206); +INSERT INTO xyoff VALUES(1,4,310,231); +INSERT INTO xyoff VALUES(1,4,727,539); +INSERT INTO xyoff VALUES(1,4,660,661); +INSERT INTO xyoff VALUES(1,4,403,133); +INSERT INTO xyoff VALUES(1,4,619,331); +INSERT INTO xyoff VALUES(2,1,712,578); +INSERT INTO xyoff VALUES(2,1,567,313); +INSERT INTO xyoff VALUES(2,1,231,423); +INSERT INTO xyoff VALUES(2,1,490,175); +INSERT INTO xyoff VALUES(2,1,898,353); +INSERT INTO xyoff VALUES(2,1,589,483); +INSERT INTO xyoff VALUES(2,1,188,462); +INSERT INTO xyoff VALUES(2,1,720,106); +INSERT INTO xyoff VALUES(2,1,793,380); +INSERT INTO xyoff VALUES(2,1,154,396); +INSERT INTO xyoff VALUES(2,2,324,218); +INSERT INTO xyoff VALUES(2,2,120,327); +INSERT INTO xyoff VALUES(2,2,655,133); +INSERT INTO xyoff VALUES(2,2,516,603); +INSERT INTO xyoff VALUES(2,2,529,572); +INSERT INTO xyoff VALUES(2,2,481,212); +INSERT INTO xyoff VALUES(2,2,802,107); +INSERT INTO xyoff VALUES(2,2,234,509); +INSERT INTO xyoff VALUES(2,2,501,269); +INSERT INTO xyoff VALUES(2,2,349,553); +INSERT INTO xyoff VALUES(2,3,495,685); +INSERT INTO xyoff VALUES(2,3,897,372); +INSERT INTO xyoff VALUES(2,3,350,681); +INSERT INTO xyoff VALUES(2,3,832,257); +INSERT INTO xyoff VALUES(2,3,778,149); +INSERT INTO xyoff VALUES(2,3,683,426); +INSERT INTO xyoff VALUES(2,3,693,217); +INSERT INTO xyoff VALUES(2,3,746,317); +INSERT INTO xyoff VALUES(2,3,805,369); +INSERT INTO xyoff VALUES(2,3,336,585); +INSERT INTO xyoff VALUES(2,4,890,255); +INSERT INTO xyoff VALUES(2,4,556,565); +INSERT INTO xyoff VALUES(2,4,865,555); +INSERT INTO xyoff VALUES(2,4,230,293); +INSERT INTO xyoff VALUES(2,4,247,251); +INSERT INTO xyoff VALUES(2,4,730,563); +INSERT INTO xyoff VALUES(2,4,318,282); +INSERT INTO xyoff VALUES(2,4,220,431); +INSERT INTO xyoff VALUES(2,4,828,336); +INSERT INTO xyoff VALUES(2,4,278,525); +INSERT INTO xyoff VALUES(3,1,324,656); +INSERT INTO xyoff VALUES(3,1,625,362); +INSERT INTO xyoff VALUES(3,1,155,570); +INSERT INTO xyoff VALUES(3,1,267,433); +INSERT INTO xyoff VALUES(3,1,599,121); +INSERT INTO xyoff VALUES(3,1,873,498); +INSERT INTO xyoff VALUES(3,1,789,520); +INSERT INTO xyoff VALUES(3,1,656,378); +INSERT INTO xyoff VALUES(3,1,831,601); +INSERT INTO xyoff VALUES(3,1,256,471); +INSERT INTO xyoff VALUES(3,2,332,258); +INSERT INTO xyoff VALUES(3,2,305,463); +INSERT INTO xyoff VALUES(3,2,796,341); +INSERT INTO xyoff VALUES(3,2,830,229); +INSERT INTO xyoff VALUES(3,2,413,271); +INSERT INTO xyoff VALUES(3,2,269,140); +INSERT INTO xyoff VALUES(3,2,628,441); +INSERT INTO xyoff VALUES(3,2,747,643); +INSERT INTO xyoff VALUES(3,2,584,435); +INSERT INTO xyoff VALUES(3,2,784,314); +INSERT INTO xyoff VALUES(3,3,722,233); +INSERT INTO xyoff VALUES(3,3,815,421); +INSERT INTO xyoff VALUES(3,3,401,267); +INSERT INTO xyoff VALUES(3,3,451,650); +INSERT INTO xyoff VALUES(3,3,329,485); +INSERT INTO xyoff VALUES(3,3,878,370); +INSERT INTO xyoff VALUES(3,3,162,616); +INSERT INTO xyoff VALUES(3,3,844,183); +INSERT INTO xyoff VALUES(3,3,161,216); +INSERT INTO xyoff VALUES(3,3,176,676); +INSERT INTO xyoff VALUES(3,4,780,128); +INSERT INTO xyoff VALUES(3,4,566,121); +INSERT INTO xyoff VALUES(3,4,646,120); +INSERT INTO xyoff VALUES(3,4,223,557); +INSERT INTO xyoff VALUES(3,4,251,117); +INSERT INTO xyoff VALUES(3,4,139,209); +INSERT INTO xyoff VALUES(3,4,813,597); +INSERT INTO xyoff VALUES(3,4,454,538); +INSERT INTO xyoff VALUES(3,4,616,198); +INSERT INTO xyoff VALUES(3,4,210,159); +INSERT INTO xyoff VALUES(4,1,208,415); +INSERT INTO xyoff VALUES(4,1,326,665); +INSERT INTO xyoff VALUES(4,1,612,133); +INSERT INTO xyoff VALUES(4,1,537,513); +INSERT INTO xyoff VALUES(4,1,638,438); +INSERT INTO xyoff VALUES(4,1,808,269); +INSERT INTO xyoff VALUES(4,1,552,121); +INSERT INTO xyoff VALUES(4,1,100,189); +INSERT INTO xyoff VALUES(4,1,643,664); +INSERT INTO xyoff VALUES(4,1,726,378); +INSERT INTO xyoff VALUES(4,2,478,409); +INSERT INTO xyoff VALUES(4,2,497,507); +INSERT INTO xyoff VALUES(4,2,233,148); +INSERT INTO xyoff VALUES(4,2,587,237); +INSERT INTO xyoff VALUES(4,2,604,166); +INSERT INTO xyoff VALUES(4,2,165,455); +INSERT INTO xyoff VALUES(4,2,320,258); +INSERT INTO xyoff VALUES(4,2,353,496); +INSERT INTO xyoff VALUES(4,2,347,495); +INSERT INTO xyoff VALUES(4,2,166,622); +INSERT INTO xyoff VALUES(4,3,461,332); +INSERT INTO xyoff VALUES(4,3,685,278); +INSERT INTO xyoff VALUES(4,3,427,594); +INSERT INTO xyoff VALUES(4,3,467,346); +INSERT INTO xyoff VALUES(4,3,125,548); +INSERT INTO xyoff VALUES(4,3,597,680); +INSERT INTO xyoff VALUES(4,3,820,445); +INSERT INTO xyoff VALUES(4,3,144,330); +INSERT INTO xyoff VALUES(4,3,557,434); +INSERT INTO xyoff VALUES(4,3,254,315); +INSERT INTO xyoff VALUES(4,4,157,339); +INSERT INTO xyoff VALUES(4,4,249,220); +INSERT INTO xyoff VALUES(4,4,391,323); +INSERT INTO xyoff VALUES(4,4,589,429); +INSERT INTO xyoff VALUES(4,4,859,592); +INSERT INTO xyoff VALUES(4,4,337,680); +INSERT INTO xyoff VALUES(4,4,410,288); +INSERT INTO xyoff VALUES(4,4,636,596); +INSERT INTO xyoff VALUES(4,4,734,433); +INSERT INTO xyoff VALUES(4,4,559,549); +INSERT INTO xyoff VALUES(5,1,549,607); +INSERT INTO xyoff VALUES(5,1,584,498); +INSERT INTO xyoff VALUES(5,1,699,116); +INSERT INTO xyoff VALUES(5,1,525,524); +INSERT INTO xyoff VALUES(5,1,304,667); +INSERT INTO xyoff VALUES(5,1,302,232); +INSERT INTO xyoff VALUES(5,1,403,149); +INSERT INTO xyoff VALUES(5,1,824,403); +INSERT INTO xyoff VALUES(5,1,697,203); +INSERT INTO xyoff VALUES(5,1,293,689); +INSERT INTO xyoff VALUES(5,2,199,275); +INSERT INTO xyoff VALUES(5,2,395,393); +INSERT INTO xyoff VALUES(5,2,657,642); +INSERT INTO xyoff VALUES(5,2,200,655); +INSERT INTO xyoff VALUES(5,2,882,234); +INSERT INTO xyoff VALUES(5,2,483,565); +INSERT INTO xyoff VALUES(5,2,755,640); +INSERT INTO xyoff VALUES(5,2,810,305); +INSERT INTO xyoff VALUES(5,2,731,655); +INSERT INTO xyoff VALUES(5,2,466,690); +INSERT INTO xyoff VALUES(5,3,563,584); +INSERT INTO xyoff VALUES(5,3,491,117); +INSERT INTO xyoff VALUES(5,3,779,292); +INSERT INTO xyoff VALUES(5,3,375,637); +INSERT INTO xyoff VALUES(5,3,253,553); +INSERT INTO xyoff VALUES(5,3,797,514); +INSERT INTO xyoff VALUES(5,3,229,480); +INSERT INTO xyoff VALUES(5,3,257,194); +INSERT INTO xyoff VALUES(5,3,449,555); +INSERT INTO xyoff VALUES(5,3,849,630); +INSERT INTO xyoff VALUES(5,4,329,286); +INSERT INTO xyoff VALUES(5,4,640,197); +INSERT INTO xyoff VALUES(5,4,104,150); +INSERT INTO xyoff VALUES(5,4,438,272); +INSERT INTO xyoff VALUES(5,4,773,226); +INSERT INTO xyoff VALUES(5,4,441,650); +INSERT INTO xyoff VALUES(5,4,242,340); +INSERT INTO xyoff VALUES(5,4,301,435); +INSERT INTO xyoff VALUES(5,4,171,397); +INSERT INTO xyoff VALUES(5,4,541,619); +INSERT INTO xyoff VALUES(6,1,651,301); +INSERT INTO xyoff VALUES(6,1,637,137); +INSERT INTO xyoff VALUES(6,1,765,643); +INSERT INTO xyoff VALUES(6,1,173,296); +INSERT INTO xyoff VALUES(6,1,263,192); +INSERT INTO xyoff VALUES(6,1,791,302); +INSERT INTO xyoff VALUES(6,1,860,601); +INSERT INTO xyoff VALUES(6,1,780,445); +INSERT INTO xyoff VALUES(6,1,462,214); +INSERT INTO xyoff VALUES(6,1,802,207); +INSERT INTO xyoff VALUES(6,2,811,685); +INSERT INTO xyoff VALUES(6,2,533,531); +INSERT INTO xyoff VALUES(6,2,390,614); +INSERT INTO xyoff VALUES(6,2,260,580); +INSERT INTO xyoff VALUES(6,2,116,377); +INSERT INTO xyoff VALUES(6,2,860,458); +INSERT INTO xyoff VALUES(6,2,438,590); +INSERT INTO xyoff VALUES(6,2,604,562); +INSERT INTO xyoff VALUES(6,2,241,242); +INSERT INTO xyoff VALUES(6,2,667,298); +INSERT INTO xyoff VALUES(6,3,787,698); +INSERT INTO xyoff VALUES(6,3,868,521); +INSERT INTO xyoff VALUES(6,3,412,587); +INSERT INTO xyoff VALUES(6,3,640,131); +INSERT INTO xyoff VALUES(6,3,748,410); +INSERT INTO xyoff VALUES(6,3,257,244); +INSERT INTO xyoff VALUES(6,3,411,195); +INSERT INTO xyoff VALUES(6,3,464,356); +INSERT INTO xyoff VALUES(6,3,157,339); +INSERT INTO xyoff VALUES(6,3,434,505); +INSERT INTO xyoff VALUES(6,4,480,671); +INSERT INTO xyoff VALUES(6,4,519,228); +INSERT INTO xyoff VALUES(6,4,404,513); +INSERT INTO xyoff VALUES(6,4,120,538); +INSERT INTO xyoff VALUES(6,4,403,663); +INSERT INTO xyoff VALUES(6,4,477,677); +INSERT INTO xyoff VALUES(6,4,690,154); +INSERT INTO xyoff VALUES(6,4,606,498); +INSERT INTO xyoff VALUES(6,4,430,665); +INSERT INTO xyoff VALUES(6,4,499,273); +INSERT INTO xyoff VALUES(7,1,118,526); +INSERT INTO xyoff VALUES(7,1,817,522); +INSERT INTO xyoff VALUES(7,1,388,638); +INSERT INTO xyoff VALUES(7,1,181,265); +INSERT INTO xyoff VALUES(7,1,442,332); +INSERT INTO xyoff VALUES(7,1,475,282); +INSERT INTO xyoff VALUES(7,1,722,633); +INSERT INTO xyoff VALUES(7,1,104,394); +INSERT INTO xyoff VALUES(7,1,631,262); +INSERT INTO xyoff VALUES(7,1,372,392); +INSERT INTO xyoff VALUES(7,2,600,413); +INSERT INTO xyoff VALUES(7,2,386,223); +INSERT INTO xyoff VALUES(7,2,839,174); +INSERT INTO xyoff VALUES(7,2,293,410); +INSERT INTO xyoff VALUES(7,2,281,391); +INSERT INTO xyoff VALUES(7,2,859,387); +INSERT INTO xyoff VALUES(7,2,478,347); +INSERT INTO xyoff VALUES(7,2,646,690); +INSERT INTO xyoff VALUES(7,2,713,234); +INSERT INTO xyoff VALUES(7,2,199,588); +INSERT INTO xyoff VALUES(7,3,389,256); +INSERT INTO xyoff VALUES(7,3,349,542); +INSERT INTO xyoff VALUES(7,3,363,345); +INSERT INTO xyoff VALUES(7,3,751,302); +INSERT INTO xyoff VALUES(7,3,423,386); +INSERT INTO xyoff VALUES(7,3,267,444); +INSERT INTO xyoff VALUES(7,3,243,182); +INSERT INTO xyoff VALUES(7,3,453,658); +INSERT INTO xyoff VALUES(7,3,126,345); +INSERT INTO xyoff VALUES(7,3,120,472); +INSERT INTO xyoff VALUES(7,4,359,654); +INSERT INTO xyoff VALUES(7,4,339,516); +INSERT INTO xyoff VALUES(7,4,710,452); +INSERT INTO xyoff VALUES(7,4,810,560); +INSERT INTO xyoff VALUES(7,4,644,692); +INSERT INTO xyoff VALUES(7,4,826,327); +INSERT INTO xyoff VALUES(7,4,465,462); +INSERT INTO xyoff VALUES(7,4,310,456); +INSERT INTO xyoff VALUES(7,4,577,613); +INSERT INTO xyoff VALUES(7,4,502,555); +INSERT INTO xyoff VALUES(8,1,601,620); +INSERT INTO xyoff VALUES(8,1,372,683); +INSERT INTO xyoff VALUES(8,1,758,399); +INSERT INTO xyoff VALUES(8,1,485,552); +INSERT INTO xyoff VALUES(8,1,159,563); +INSERT INTO xyoff VALUES(8,1,536,303); +INSERT INTO xyoff VALUES(8,1,122,263); +INSERT INTO xyoff VALUES(8,1,836,435); +INSERT INTO xyoff VALUES(8,1,544,146); +INSERT INTO xyoff VALUES(8,1,270,277); +INSERT INTO xyoff VALUES(8,2,849,281); +INSERT INTO xyoff VALUES(8,2,563,242); +INSERT INTO xyoff VALUES(8,2,704,463); +INSERT INTO xyoff VALUES(8,2,102,165); +INSERT INTO xyoff VALUES(8,2,797,524); +INSERT INTO xyoff VALUES(8,2,612,426); +INSERT INTO xyoff VALUES(8,2,345,372); +INSERT INTO xyoff VALUES(8,2,820,376); +INSERT INTO xyoff VALUES(8,2,789,156); +INSERT INTO xyoff VALUES(8,2,321,466); +INSERT INTO xyoff VALUES(8,3,150,332); +INSERT INTO xyoff VALUES(8,3,136,152); +INSERT INTO xyoff VALUES(8,3,468,528); +INSERT INTO xyoff VALUES(8,3,409,192); +INSERT INTO xyoff VALUES(8,3,820,216); +INSERT INTO xyoff VALUES(8,3,847,249); +INSERT INTO xyoff VALUES(8,3,801,267); +INSERT INTO xyoff VALUES(8,3,181,670); +INSERT INTO xyoff VALUES(8,3,398,563); +INSERT INTO xyoff VALUES(8,3,439,576); +INSERT INTO xyoff VALUES(8,4,123,309); +INSERT INTO xyoff VALUES(8,4,190,496); +INSERT INTO xyoff VALUES(8,4,571,531); +INSERT INTO xyoff VALUES(8,4,290,255); +INSERT INTO xyoff VALUES(8,4,244,412); +INSERT INTO xyoff VALUES(8,4,264,596); +INSERT INTO xyoff VALUES(8,4,253,420); +INSERT INTO xyoff VALUES(8,4,847,536); +INSERT INTO xyoff VALUES(8,4,120,288); +INSERT INTO xyoff VALUES(8,4,331,639); + +/* Create the geopoly object from test data above */ +CREATE VIRTUAL TABLE geo1 USING geopoly(type,clr); +INSERT INTO geo1(_shape,type,clr) + SELECT geopoly_xform(jshape,A,B,-B,A,xoff,yoff), basis.name, xform.clr + FROM basis, xform, xyoff + WHERE xyoff.id1=basis.rowid AND xyoff.id2=xform.rowid; + + +/* Query polygon */ +CREATE TEMP TABLE querypoly(poly JSON, clr TEXT); +INSERT INTO querypoly(clr, poly) VALUES + ('orange', '[[300,300],[400,350],[500,250],[480,500],[400,480],[300,550],[280,450],[320,400],[280,350],[300,300]]'); + +/* Generate the HTML */ +.print '' +.print '

Everything

' +.print '' +SELECT geopoly_svg(_shape, + printf('style="fill:none;stroke:%s;stroke-width:1"',clr) + ) + FROM geo1; +SELECT geopoly_svg(poly, + printf('style="fill:%s;fill-opacity:0.5;"',clr) + ) + FROM querypoly; +.print '' +.print '

Query

' +.print '' +SELECT geopoly_svg(_shape, + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) + ) + FROM geo1, querypoly + WHERE geopoly_overlap(_shape, poly); +SELECT geopoly_svg(poly, + printf('style="fill:%s;fill-opacity:0.5;"',clr) + ) + FROM querypoly; +.print '' +.print '' diff --git a/manifest b/manifest index 4b67358753..bdb5f15c7b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Untested\sincremental\scheck-in.\s\sAdd\sthe\sgeopoly_xform()\sfunction.\s\sComplete\nbasic\slogic\sfor\sthe\sgeopoly\svirtual\stable. -D 2018-05-28T13:23:23.983 +C The\sgeopoly\svirtual\stable\sseems\sto\sbe\sworking.\s\sBut\sonly\sthinly\stested\sso\sfar. +D 2018-05-28T23:59:03.555 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 51407f0e371dcb9e65d368bd4f1a08fc17ef8361ff11aac9356f0f63693b38dd @@ -355,8 +355,8 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c 8c175a1c1e9c8659533a28c9aabf5ec1315e598b56129707ffe87567fcc475b8 -F ext/rtree/rtree.c 2fd3c149c6fc4d3fdf602dc610b34ad9abdf75cca26d0c362f903aa02ea2ef47 +F ext/rtree/geopoly.c 95626633e615db611c6a61a7cc2c060d7dedea8338a92a4345e4ecce045fe0e8 +F ext/rtree/rtree.c f3c2f1b5eea75b98d4d3dcdec2ebf2a69c036b53f2f3d196e61bf5016298255f F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -382,6 +382,7 @@ F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae926833 F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 +F ext/rtree/visual01.txt ce5473774986a7fde188de9cbfc554f9c0f07109c61a5169019bd0c514776c11 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0 @@ -1730,7 +1731,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2c2a202c14fa8803fb1e4b7356cbc9cd49e65a27e19bf6e3fd0e9dff9d5c67f9 -R f4a9697324257dda7a5826181dabdab6 +P ed06cc32568a3abaa0535b379e0ee3b04ffb7582dcda6405670620d1fbe8996c +R 81c5a462839f4fc8f38c54f9f8566edf U drh -Z 2d47301bf215e61d246a3f2a2f3aad00 +Z 985d2eedc536b0a7cccf298a1cefc057 diff --git a/manifest.uuid b/manifest.uuid index 4ffe498f38..260a10c2c6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed06cc32568a3abaa0535b379e0ee3b04ffb7582dcda6405670620d1fbe8996c \ No newline at end of file +4288f1ad5966701eac4cfe3061e8ce98e34e0d6c112307668729642a06458d5f \ No newline at end of file From b7d376ee13878810122c0fcf0948bd468b527dec Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 May 2018 17:17:22 +0000 Subject: [PATCH 008/260] Fix a problem in the geopoly json parser associated with spaces before a coordinate number. FossilOrigin-Name: 9d8d3af89ab241fd6c68e043e559359c85653aa0e31270b658ff01867ae929c4 --- ext/rtree/geopoly.c | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 9e8de3cfee..5ae2b8f22d 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -146,8 +146,8 @@ static char geopolySkipSpace(GeoParse *p){ ** return non-zero on success and zero if the next token is not a number. */ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ - const unsigned char *z = p->z; char c = geopolySkipSpace(p); + const unsigned char *z = p->z; int j; int seenDP = 0; int seenE = 0; diff --git a/manifest b/manifest index bdb5f15c7b..3d0a40be76 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sgeopoly\svirtual\stable\sseems\sto\sbe\sworking.\s\sBut\sonly\sthinly\stested\sso\sfar. -D 2018-05-28T23:59:03.555 +C Fix\sa\sproblem\sin\sthe\sgeopoly\sjson\sparser\sassociated\swith\sspaces\sbefore\sa\ncoordinate\snumber. +D 2018-05-29T17:17:22.931 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 51407f0e371dcb9e65d368bd4f1a08fc17ef8361ff11aac9356f0f63693b38dd @@ -355,7 +355,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c 95626633e615db611c6a61a7cc2c060d7dedea8338a92a4345e4ecce045fe0e8 +F ext/rtree/geopoly.c 524f336f28d2f2c3c5abf2238c07964e4ddebce441ca79489d08f7f2fae3b27e F ext/rtree/rtree.c f3c2f1b5eea75b98d4d3dcdec2ebf2a69c036b53f2f3d196e61bf5016298255f F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 @@ -1731,7 +1731,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ed06cc32568a3abaa0535b379e0ee3b04ffb7582dcda6405670620d1fbe8996c -R 81c5a462839f4fc8f38c54f9f8566edf +P 4288f1ad5966701eac4cfe3061e8ce98e34e0d6c112307668729642a06458d5f +R 10d3e455a51f13d4bc5211661301b72f U drh -Z 985d2eedc536b0a7cccf298a1cefc057 +Z 37cefd68e4dc10f83a5c791f1094a8b3 diff --git a/manifest.uuid b/manifest.uuid index 260a10c2c6..6580f9fd41 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4288f1ad5966701eac4cfe3061e8ce98e34e0d6c112307668729642a06458d5f \ No newline at end of file +9d8d3af89ab241fd6c68e043e559359c85653aa0e31270b658ff01867ae929c4 \ No newline at end of file From b80bb6ce887506aa44edd89c01575d6bcb3d270a Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 13 Jul 2018 19:52:43 +0000 Subject: [PATCH 009/260] Add the "categories" option to the unicode61 tokenizer in fts5. FossilOrigin-Name: 80d2b9e635e3100f90cffdcffa5b5038da6fbbfccc9f5777c59a4ae760d4cb62 --- ext/fts3/unicode/mkunicode.tcl | 288 ++++++++++++- ext/fts3/unicode/parseunicode.tcl | 36 ++ ext/fts5/fts5Int.h | 4 + ext/fts5/fts5_expr.c | 7 +- ext/fts5/fts5_tokenize.c | 44 +- ext/fts5/fts5_unicode2.c | 660 ++++++++++++++++++++++++------ ext/fts5/test/fts5cat.test | 59 +++ manifest | 24 +- manifest.uuid | 2 +- 9 files changed, 974 insertions(+), 150 deletions(-) create mode 100644 ext/fts5/test/fts5cat.test diff --git a/ext/fts3/unicode/mkunicode.tcl b/ext/fts3/unicode/mkunicode.tcl index de89099122..84b8ddc80b 100644 --- a/ext/fts3/unicode/mkunicode.tcl +++ b/ext/fts3/unicode/mkunicode.tcl @@ -529,6 +529,263 @@ proc print_fold {zFunc} { puts "\}" } +proc code {txt} { + set txt [string trimright $txt] + set txt [string trimleft $txt "\n"] + set n [expr {[string length $txt] - [string length [string trim $txt]]}] + set ret "" + foreach L [split $txt "\n"] { + append ret "[string range $L $n end]\n" + } + return [uplevel "subst -nocommands {$ret}"] +} + +proc intarray {lInt} { + set ret "" + set n [llength $lInt] + for {set i 0} {$i < $n} {incr i 10} { + append ret "\n " + foreach int [lrange $lInt $i [expr $i+9]] { + append ret [format "%-7s" "$int, "] + } + } + append ret "\n " + set ret +} + +proc categories_switch {Cvar first lSecond} { + upvar $Cvar C + set ret "" + append ret "case '$first':\n" + append ret " switch( zCat\[1\] ){\n" + foreach s $lSecond { + append ret " case '$s': aArray\[$C($first$s)\] = 1; break;\n" + } + append ret " case '*': \n" + foreach s $lSecond { + append ret " aArray\[$C($first$s)\] = 1;\n" + } + append ret " break;\n" + append ret " default: return 1;" + append ret " }\n" + append ret " break;\n" +} + +# Argument is a list. Each element of which is itself a list of two elements: +# +# * the codepoint +# * the category +# +# List elements are sorted in order of codepoint. +# +proc print_categories {lMap} { + set categories { + Cc Cf Cn Cs + Ll Lm Lo Lt Lu + Mc Me Mn + Nd Nl No + Pc Pd Pe Pf Pi Po Ps + Sc Sk Sm So + Zl Zp Zs + + LC Co + } + + for {set i 0} {$i < [llength $categories]} {incr i} { + set C([lindex $categories $i]) [expr 1+$i] + } + + set caseC [categories_switch C C {c f n s o}] + set caseL [categories_switch C L {l m o t u C}] + set caseM [categories_switch C M {c e n}] + set caseN [categories_switch C N {d l o}] + set caseP [categories_switch C P {c d e f i o s}] + set caseS [categories_switch C S {c k m o}] + set caseZ [categories_switch C Z {l p s}] + + set nCat [expr [llength [array names C]] + 1] + puts [code { + int sqlite3Fts5UnicodeNCat(void) { + return $nCat; + } + + int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){ + aArray[0] = 1; + switch( zCat[0] ){ + $caseC + $caseL + $caseM + $caseN + $caseP + $caseS + $caseZ + } + return 0; + } + }] + + set nRepeat 0 + set first [lindex $lMap 0 0] + set class [lindex $lMap 0 1] + set prev -1 + + set CASE(0) "Lu" + set CASE(1) "Ll" + + foreach m $lMap { + foreach {codepoint cl} $m {} + set codepoint [expr "0x$codepoint"] + if {$codepoint>=(1<<20)} continue + + set bNew 0 + if {$codepoint!=($prev+1)} { + set bNew 1 + } elseif { + $cl==$class || ($class=="LC" && $cl==$CASE([expr $nRepeat & 0x01])) + } { + incr nRepeat + } elseif {$class=="Lu" && $nRepeat==1 && $cl=="Ll"} { + set class LC + incr nRepeat + } else { + set bNew 1 + } + if {$bNew} { + lappend lEntries [list $first $class $nRepeat] + set nRepeat 1 + set first $codepoint + set class $cl + } + set prev $codepoint + } + if {$nRepeat>0} { + lappend lEntries [list $first $class $nRepeat] + } + + set aBlock [list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + set aMap [list] + foreach e $lEntries { + foreach {cp class nRepeat} $e {} + set block [expr ($cp>>16)] + if {$block>0 && [lindex $aBlock $block]==0} { + for {set i 1} {$i<=$block} {incr i} { + if {[lindex $aBlock $i]==0} { + lset aBlock $i [llength $aMap] + } + } + } + lappend aMap [expr {$cp & 0xFFFF}] + lappend aData [expr {($nRepeat << 5) + $C($class)}] + } + for {set i 1} {$i<[llength $aBlock]} {incr i} { + if {[lindex $aBlock $i]==0} { + lset aBlock $i [llength $aMap] + } + } + + set aBlockArray [intarray $aBlock] + set aMapArray [intarray $aMap] + set aDataArray [intarray $aData] + puts [code { + static u16 aFts5UnicodeBlock[] = {$aBlockArray}; + static u16 aFts5UnicodeMap[] = {$aMapArray}; + static u16 aFts5UnicodeData[] = {$aDataArray}; + + int sqlite3Fts5UnicodeCategory(int iCode) { + int iRes = -1; + int iHi; + int iLo; + int ret; + u16 iKey; + + if( iCode>=(1<<20) ){ + return 0; + } + iLo = aFts5UnicodeBlock[(iCode>>16)]; + iHi = aFts5UnicodeBlock[1+(iCode>>16)]; + iKey = (iCode & 0xFFFF); + while( iHi>iLo ){ + int iTest = (iHi + iLo) / 2; + assert( iTest>=iLo && iTest=aFts5UnicodeMap[iTest] ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest; + } + } + + if( iRes<0 ) return 0; + if( iKey>=(aFts5UnicodeMap[iRes]+(aFts5UnicodeData[iRes]>>5)) ) return 0; + ret = aFts5UnicodeData[iRes] & 0x1F; + if( ret!=$C(LC) ) return ret; + return ((iKey - aFts5UnicodeMap[iRes]) & 0x01) ? $C(Ll) : $C(Lu); + } + + void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){ + int i = 0; + int iTbl = 0; + while( i<128 ){ + int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ]; + int n = (aFts5UnicodeData[iTbl] >> 5) + i; + for(; i<128 && i" puts "" puts "int main(int argc, char **argv)\{" - puts " int r1, r2;" + puts " int r1, r2, r3;" puts " int code;" + puts " r3 = 0;" puts " r1 = isalnum_test(&code);" puts " if( r1 ) printf(\"isalnum(): Problem with code %d\\n\",code);" puts " else printf(\"isalnum(): test passed\\n\");" puts " r2 = fold_test(&code);" puts " if( r2 ) printf(\"fold(): Problem with code %d\\n\",code);" puts " else printf(\"fold(): test passed\\n\");" - puts " return (r1 || r2);" + if {$::generate_fts5_code} { + puts " r3 = categories_test(&code);" + puts " if( r3 ) printf(\"categories(): Problem with code %d\\n\",code);" + puts " else printf(\"categories(): test passed\\n\");" + } + puts " return (r1 || r2 || r3);" puts "\}" } @@ -651,10 +914,18 @@ for {set i 0} {$i < [llength $argv]-2} {incr i} { print_fileheader +if {$::generate_test_code} { + puts "typedef unsigned short int u16;" + puts "typedef unsigned char u8;" + puts "#include " +} + # Print the isalnum() function to stdout. # set lRange [an_load_separator_ranges] -print_isalnum ${function_prefix}UnicodeIsalnum $lRange +if {$generate_fts5_code==0} { + print_isalnum ${function_prefix}UnicodeIsalnum $lRange +} # Leave a gap between the two generated C functions. # @@ -677,12 +948,21 @@ puts "" # print_fold ${function_prefix}UnicodeFold +if {$generate_fts5_code} { + puts "" + puts "" + print_categories [cc_load_unicodedata_text ${unicodedata.txt}] +} + # Print the test routines and main() function to stdout, if -test # was specified. # if {$::generate_test_code} { - print_test_isalnum ${function_prefix}UnicodeIsalnum $lRange + if {$generate_fts5_code==0} { + print_test_isalnum ${function_prefix}UnicodeIsalnum $lRange + } print_fold_test ${function_prefix}UnicodeFold $mappings + print_test_categories [cc_load_unicodedata_text ${unicodedata.txt}] print_test_main } diff --git a/ext/fts3/unicode/parseunicode.tcl b/ext/fts3/unicode/parseunicode.tcl index 0cb2c83a18..966d7bdd3a 100644 --- a/ext/fts3/unicode/parseunicode.tcl +++ b/ext/fts3/unicode/parseunicode.tcl @@ -143,4 +143,40 @@ proc tl_load_casefolding_txt {zName} { } } +proc cc_load_unicodedata_text {zName} { + set fd [open $zName] + set lField { + code + character_name + general_category + canonical_combining_classes + bidirectional_category + character_decomposition_mapping + decimal_digit_value + digit_value + numeric_value + mirrored + unicode_1_name + iso10646_comment_field + uppercase_mapping + lowercase_mapping + titlecase_mapping + } + set lRet [list] + + while { ![eof $fd] } { + set line [gets $fd] + if {$line == ""} continue + + set fields [split $line ";"] + if {[llength $fields] != [llength $lField]} { error "parse error: $line" } + foreach $lField $fields {} + + lappend lRet [list $code $general_category] + } + + close $fd + set lRet +} + diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index c87583676b..d667f3747c 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -787,6 +787,10 @@ int sqlite3Fts5VocabInit(Fts5Global*, sqlite3*); int sqlite3Fts5UnicodeIsalnum(int c); int sqlite3Fts5UnicodeIsdiacritic(int c); int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); + +int sqlite3Fts5UnicodeCatParse(const char*, u8*); +int sqlite3Fts5UnicodeCategory(int iCode); +void sqlite3Fts5UnicodeAscii(u8*, u8*); /* ** End of interface to code in fts5_unicode2.c. **************************************************************************/ diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index c21d69d9ee..a09fe7def8 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -2541,14 +2541,19 @@ static void fts5ExprIsAlnum( sqlite3_value **apVal /* Function arguments */ ){ int iCode; + u8 aArr[32]; if( nArg!=1 ){ sqlite3_result_error(pCtx, "wrong number of arguments to function fts5_isalnum", -1 ); return; } + memset(aArr, 0, sizeof(aArr)); + sqlite3Fts5UnicodeCatParse("L*", aArr); + sqlite3Fts5UnicodeCatParse("N*", aArr); + sqlite3Fts5UnicodeCatParse("Co", aArr); iCode = sqlite3_value_int(apVal[0]); - sqlite3_result_int(pCtx, sqlite3Fts5UnicodeIsalnum(iCode)); + sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]); } static void fts5ExprFold( diff --git a/ext/fts5/fts5_tokenize.c b/ext/fts5/fts5_tokenize.c index b72a0c24ab..af2bc222f2 100644 --- a/ext/fts5/fts5_tokenize.c +++ b/ext/fts5/fts5_tokenize.c @@ -237,6 +237,8 @@ struct Unicode61Tokenizer { int bRemoveDiacritic; /* True if remove_diacritics=1 is set */ int nException; int *aiException; + + unsigned char aCategory[32]; /* True for token char categories */ }; static int fts5UnicodeAddExceptions( @@ -261,7 +263,7 @@ static int fts5UnicodeAddExceptions( if( iCode<128 ){ p->aTokenChar[iCode] = (unsigned char)bTokenChars; }else{ - bToken = sqlite3Fts5UnicodeIsalnum(iCode); + bToken = p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]; assert( (bToken==0 || bToken==1) ); assert( (bTokenChars==0 || bTokenChars==1) ); if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){ @@ -322,6 +324,21 @@ static void fts5UnicodeDelete(Fts5Tokenizer *pTok){ return; } +static int unicodeSetCategories(Unicode61Tokenizer *p, const char *zCat){ + const char *z = zCat; + + while( *z ){ + while( *z==' ' || *z=='\t' ) z++; + if( *z && sqlite3Fts5UnicodeCatParse(z, p->aCategory) ){ + return SQLITE_ERROR; + } + while( *z!=' ' && *z!='\t' && *z!='\0' ) z++; + } + + sqlite3Fts5UnicodeAscii(p->aCategory, p->aTokenChar); + return SQLITE_OK; +} + /* ** Create a "unicode61" tokenizer. */ @@ -340,15 +357,28 @@ static int fts5UnicodeCreate( }else{ p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); if( p ){ + const char *zCat = "L* N* Co"; int i; memset(p, 0, sizeof(Unicode61Tokenizer)); - memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar)); + p->bRemoveDiacritic = 1; p->nFold = 64; p->aFold = sqlite3_malloc(p->nFold * sizeof(char)); if( p->aFold==0 ){ rc = SQLITE_NOMEM; } + + /* Search for a "categories" argument */ + for(i=0; rc==SQLITE_OK && iaCategory[sqlite3Fts5UnicodeCategory(iCode)] + ^ fts5UnicodeIsException(p, iCode) + ); } static int fts5UnicodeTokenize( diff --git a/ext/fts5/fts5_unicode2.c b/ext/fts5/fts5_unicode2.c index 1ef56f6156..e0c5fa07f3 100644 --- a/ext/fts5/fts5_unicode2.c +++ b/ext/fts5/fts5_unicode2.c @@ -18,135 +18,6 @@ #include -/* -** Return true if the argument corresponds to a unicode codepoint -** classified as either a letter or a number. Otherwise false. -** -** The results are undefined if the value passed to this function -** is less than zero. -*/ -int sqlite3Fts5UnicodeIsalnum(int c){ - /* Each unsigned integer in the following array corresponds to a contiguous - ** range of unicode codepoints that are not either letters or numbers (i.e. - ** codepoints for which this function should return 0). - ** - ** The most significant 22 bits in each 32-bit value contain the first - ** codepoint in the range. The least significant 10 bits are used to store - ** the size of the range (always at least 1). In other words, the value - ** ((C<<22) + N) represents a range of N codepoints starting with codepoint - ** C. It is not possible to represent a range larger than 1023 codepoints - ** using this format. - */ - static const unsigned int aEntry[] = { - 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, - 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, - 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, - 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, - 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, - 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, - 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, - 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, - 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, - 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, - 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, - 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, - 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, - 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, - 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, - 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, - 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, - 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, - 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, - 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, - 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, - 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, - 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, - 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, - 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, - 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, - 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, - 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, - 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, - 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, - 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, - 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, - 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, - 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, - 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, - 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, - 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, - 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, - 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, - 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, - 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, - 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, - 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, - 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, - 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, - 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, - 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, - 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, - 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, - 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, - 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, - 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, - 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, - 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, - 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, - 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, - 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, - 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, - 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, - 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, - 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, - 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, - 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013, - 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, - 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, - 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01, - 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403, - 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, - 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003, - 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003, - 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E, - 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046, - 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, - 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, - 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, - 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C, - 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002, - 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025, - 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6, - 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46, - 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060, - 0x380400F0, - }; - static const unsigned int aAscii[4] = { - 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, - }; - - if( (unsigned int)c<128 ){ - return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); - }else if( (unsigned int)c<(1<<22) ){ - unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; - int iRes = 0; - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; - int iLo = 0; - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( key >= aEntry[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( aEntry[0]=aEntry[iRes] ); - return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); - } - return 1; -} /* @@ -358,3 +229,534 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){ return ret; } + + +int sqlite3Fts5UnicodeNCat(void) { + return 32; +} + +int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){ + aArray[0] = 1; + switch( zCat[0] ){ + case 'C': + switch( zCat[1] ){ + case 'c': aArray[1] = 1; break; + case 'f': aArray[2] = 1; break; + case 'n': aArray[3] = 1; break; + case 's': aArray[4] = 1; break; + case 'o': aArray[31] = 1; break; + case '*': + aArray[1] = 1; + aArray[2] = 1; + aArray[3] = 1; + aArray[4] = 1; + aArray[31] = 1; + break; + default: return 1; } + break; + + case 'L': + switch( zCat[1] ){ + case 'l': aArray[5] = 1; break; + case 'm': aArray[6] = 1; break; + case 'o': aArray[7] = 1; break; + case 't': aArray[8] = 1; break; + case 'u': aArray[9] = 1; break; + case 'C': aArray[30] = 1; break; + case '*': + aArray[5] = 1; + aArray[6] = 1; + aArray[7] = 1; + aArray[8] = 1; + aArray[9] = 1; + aArray[30] = 1; + break; + default: return 1; } + break; + + case 'M': + switch( zCat[1] ){ + case 'c': aArray[10] = 1; break; + case 'e': aArray[11] = 1; break; + case 'n': aArray[12] = 1; break; + case '*': + aArray[10] = 1; + aArray[11] = 1; + aArray[12] = 1; + break; + default: return 1; } + break; + + case 'N': + switch( zCat[1] ){ + case 'd': aArray[13] = 1; break; + case 'l': aArray[14] = 1; break; + case 'o': aArray[15] = 1; break; + case '*': + aArray[13] = 1; + aArray[14] = 1; + aArray[15] = 1; + break; + default: return 1; } + break; + + case 'P': + switch( zCat[1] ){ + case 'c': aArray[16] = 1; break; + case 'd': aArray[17] = 1; break; + case 'e': aArray[18] = 1; break; + case 'f': aArray[19] = 1; break; + case 'i': aArray[20] = 1; break; + case 'o': aArray[21] = 1; break; + case 's': aArray[22] = 1; break; + case '*': + aArray[16] = 1; + aArray[17] = 1; + aArray[18] = 1; + aArray[19] = 1; + aArray[20] = 1; + aArray[21] = 1; + aArray[22] = 1; + break; + default: return 1; } + break; + + case 'S': + switch( zCat[1] ){ + case 'c': aArray[23] = 1; break; + case 'k': aArray[24] = 1; break; + case 'm': aArray[25] = 1; break; + case 'o': aArray[26] = 1; break; + case '*': + aArray[23] = 1; + aArray[24] = 1; + aArray[25] = 1; + aArray[26] = 1; + break; + default: return 1; } + break; + + case 'Z': + switch( zCat[1] ){ + case 'l': aArray[27] = 1; break; + case 'p': aArray[28] = 1; break; + case 's': aArray[29] = 1; break; + case '*': + aArray[27] = 1; + aArray[28] = 1; + aArray[29] = 1; + break; + default: return 1; } + break; + + } + return 0; +} + +static u16 aFts5UnicodeBlock[] = { + 0, 1471, 1753, 1760, 1760, 1760, 1760, 1760, 1760, 1760, + 1760, 1760, 1760, 1760, 1760, 1763, 1765, + }; +static u16 aFts5UnicodeMap[] = { + 0, 32, 33, 36, 37, 40, 41, 42, 43, 44, + 45, 46, 48, 58, 60, 63, 65, 91, 92, 93, + 94, 95, 96, 97, 123, 124, 125, 126, 127, 160, + 161, 162, 166, 167, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 180, 181, 182, 184, 185, + 186, 187, 188, 191, 192, 215, 216, 223, 247, 248, + 256, 312, 313, 329, 330, 377, 383, 385, 387, 388, + 391, 394, 396, 398, 402, 403, 405, 406, 409, 412, + 414, 415, 417, 418, 423, 427, 428, 431, 434, 436, + 437, 440, 442, 443, 444, 446, 448, 452, 453, 454, + 455, 456, 457, 458, 459, 460, 461, 477, 478, 496, + 497, 498, 499, 500, 503, 505, 506, 564, 570, 572, + 573, 575, 577, 580, 583, 584, 592, 660, 661, 688, + 706, 710, 722, 736, 741, 748, 749, 750, 751, 768, + 880, 884, 885, 886, 890, 891, 894, 900, 902, 903, + 904, 908, 910, 912, 913, 931, 940, 975, 977, 978, + 981, 984, 1008, 1012, 1014, 1015, 1018, 1020, 1021, 1072, + 1120, 1154, 1155, 1160, 1162, 1217, 1231, 1232, 1329, 1369, + 1370, 1377, 1417, 1418, 1423, 1425, 1470, 1471, 1472, 1473, + 1475, 1476, 1478, 1479, 1488, 1520, 1523, 1536, 1542, 1545, + 1547, 1548, 1550, 1552, 1563, 1566, 1568, 1600, 1601, 1611, + 1632, 1642, 1646, 1648, 1649, 1748, 1749, 1750, 1757, 1758, + 1759, 1765, 1767, 1769, 1770, 1774, 1776, 1786, 1789, 1791, + 1792, 1807, 1808, 1809, 1810, 1840, 1869, 1958, 1969, 1984, + 1994, 2027, 2036, 2038, 2039, 2042, 2048, 2070, 2074, 2075, + 2084, 2085, 2088, 2089, 2096, 2112, 2137, 2142, 2208, 2210, + 2276, 2304, 2307, 2308, 2362, 2363, 2364, 2365, 2366, 2369, + 2377, 2381, 2382, 2384, 2385, 2392, 2402, 2404, 2406, 2416, + 2417, 2418, 2425, 2433, 2434, 2437, 2447, 2451, 2474, 2482, + 2486, 2492, 2493, 2494, 2497, 2503, 2507, 2509, 2510, 2519, + 2524, 2527, 2530, 2534, 2544, 2546, 2548, 2554, 2555, 2561, + 2563, 2565, 2575, 2579, 2602, 2610, 2613, 2616, 2620, 2622, + 2625, 2631, 2635, 2641, 2649, 2654, 2662, 2672, 2674, 2677, + 2689, 2691, 2693, 2703, 2707, 2730, 2738, 2741, 2748, 2749, + 2750, 2753, 2759, 2761, 2763, 2765, 2768, 2784, 2786, 2790, + 2800, 2801, 2817, 2818, 2821, 2831, 2835, 2858, 2866, 2869, + 2876, 2877, 2878, 2879, 2880, 2881, 2887, 2891, 2893, 2902, + 2903, 2908, 2911, 2914, 2918, 2928, 2929, 2930, 2946, 2947, + 2949, 2958, 2962, 2969, 2972, 2974, 2979, 2984, 2990, 3006, + 3008, 3009, 3014, 3018, 3021, 3024, 3031, 3046, 3056, 3059, + 3065, 3066, 3073, 3077, 3086, 3090, 3114, 3125, 3133, 3134, + 3137, 3142, 3146, 3157, 3160, 3168, 3170, 3174, 3192, 3199, + 3202, 3205, 3214, 3218, 3242, 3253, 3260, 3261, 3262, 3263, + 3264, 3270, 3271, 3274, 3276, 3285, 3294, 3296, 3298, 3302, + 3313, 3330, 3333, 3342, 3346, 3389, 3390, 3393, 3398, 3402, + 3405, 3406, 3415, 3424, 3426, 3430, 3440, 3449, 3450, 3458, + 3461, 3482, 3507, 3517, 3520, 3530, 3535, 3538, 3542, 3544, + 3570, 3572, 3585, 3633, 3634, 3636, 3647, 3648, 3654, 3655, + 3663, 3664, 3674, 3713, 3716, 3719, 3722, 3725, 3732, 3737, + 3745, 3749, 3751, 3754, 3757, 3761, 3762, 3764, 3771, 3773, + 3776, 3782, 3784, 3792, 3804, 3840, 3841, 3844, 3859, 3860, + 3861, 3864, 3866, 3872, 3882, 3892, 3893, 3894, 3895, 3896, + 3897, 3898, 3899, 3900, 3901, 3902, 3904, 3913, 3953, 3967, + 3968, 3973, 3974, 3976, 3981, 3993, 4030, 4038, 4039, 4046, + 4048, 4053, 4057, 4096, 4139, 4141, 4145, 4146, 4152, 4153, + 4155, 4157, 4159, 4160, 4170, 4176, 4182, 4184, 4186, 4190, + 4193, 4194, 4197, 4199, 4206, 4209, 4213, 4226, 4227, 4229, + 4231, 4237, 4238, 4239, 4240, 4250, 4253, 4254, 4256, 4295, + 4301, 4304, 4347, 4348, 4349, 4682, 4688, 4696, 4698, 4704, + 4746, 4752, 4786, 4792, 4800, 4802, 4808, 4824, 4882, 4888, + 4957, 4960, 4969, 4992, 5008, 5024, 5120, 5121, 5741, 5743, + 5760, 5761, 5787, 5788, 5792, 5867, 5870, 5888, 5902, 5906, + 5920, 5938, 5941, 5952, 5970, 5984, 5998, 6002, 6016, 6068, + 6070, 6071, 6078, 6086, 6087, 6089, 6100, 6103, 6104, 6107, + 6108, 6109, 6112, 6128, 6144, 6150, 6151, 6155, 6158, 6160, + 6176, 6211, 6212, 6272, 6313, 6314, 6320, 6400, 6432, 6435, + 6439, 6441, 6448, 6450, 6451, 6457, 6464, 6468, 6470, 6480, + 6512, 6528, 6576, 6593, 6600, 6608, 6618, 6622, 6656, 6679, + 6681, 6686, 6688, 6741, 6742, 6743, 6744, 6752, 6753, 6754, + 6755, 6757, 6765, 6771, 6783, 6784, 6800, 6816, 6823, 6824, + 6912, 6916, 6917, 6964, 6965, 6966, 6971, 6972, 6973, 6978, + 6979, 6981, 6992, 7002, 7009, 7019, 7028, 7040, 7042, 7043, + 7073, 7074, 7078, 7080, 7082, 7083, 7084, 7086, 7088, 7098, + 7142, 7143, 7144, 7146, 7149, 7150, 7151, 7154, 7164, 7168, + 7204, 7212, 7220, 7222, 7227, 7232, 7245, 7248, 7258, 7288, + 7294, 7360, 7376, 7379, 7380, 7393, 7394, 7401, 7405, 7406, + 7410, 7412, 7413, 7424, 7468, 7531, 7544, 7545, 7579, 7616, + 7676, 7680, 7830, 7838, 7936, 7944, 7952, 7960, 7968, 7976, + 7984, 7992, 8000, 8008, 8016, 8025, 8027, 8029, 8031, 8033, + 8040, 8048, 8064, 8072, 8080, 8088, 8096, 8104, 8112, 8118, + 8120, 8124, 8125, 8126, 8127, 8130, 8134, 8136, 8140, 8141, + 8144, 8150, 8152, 8157, 8160, 8168, 8173, 8178, 8182, 8184, + 8188, 8189, 8192, 8203, 8208, 8214, 8216, 8217, 8218, 8219, + 8221, 8222, 8223, 8224, 8232, 8233, 8234, 8239, 8240, 8249, + 8250, 8251, 8255, 8257, 8260, 8261, 8262, 8263, 8274, 8275, + 8276, 8277, 8287, 8288, 8298, 8304, 8305, 8308, 8314, 8317, + 8318, 8319, 8320, 8330, 8333, 8334, 8336, 8352, 8400, 8413, + 8417, 8418, 8421, 8448, 8450, 8451, 8455, 8456, 8458, 8459, + 8462, 8464, 8467, 8468, 8469, 8470, 8472, 8473, 8478, 8484, + 8485, 8486, 8487, 8488, 8489, 8490, 8494, 8495, 8496, 8500, + 8501, 8505, 8506, 8508, 8510, 8512, 8517, 8519, 8522, 8523, + 8524, 8526, 8527, 8528, 8544, 8579, 8581, 8585, 8592, 8597, + 8602, 8604, 8608, 8609, 8611, 8612, 8614, 8615, 8622, 8623, + 8654, 8656, 8658, 8659, 8660, 8661, 8692, 8960, 8968, 8972, + 8992, 8994, 9001, 9002, 9003, 9084, 9085, 9115, 9140, 9180, + 9186, 9216, 9280, 9312, 9372, 9450, 9472, 9655, 9656, 9665, + 9666, 9720, 9728, 9839, 9840, 9985, 10088, 10089, 10090, 10091, + 10092, 10093, 10094, 10095, 10096, 10097, 10098, 10099, 10100, 10101, + 10102, 10132, 10176, 10181, 10182, 10183, 10214, 10215, 10216, 10217, + 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10240, 10496, 10627, + 10628, 10629, 10630, 10631, 10632, 10633, 10634, 10635, 10636, 10637, + 10638, 10639, 10640, 10641, 10642, 10643, 10644, 10645, 10646, 10647, + 10648, 10649, 10712, 10713, 10714, 10715, 10716, 10748, 10749, 10750, + 11008, 11056, 11077, 11079, 11088, 11264, 11312, 11360, 11363, 11365, + 11367, 11374, 11377, 11378, 11380, 11381, 11383, 11388, 11390, 11393, + 11394, 11492, 11493, 11499, 11503, 11506, 11513, 11517, 11518, 11520, + 11559, 11565, 11568, 11631, 11632, 11647, 11648, 11680, 11688, 11696, + 11704, 11712, 11720, 11728, 11736, 11744, 11776, 11778, 11779, 11780, + 11781, 11782, 11785, 11786, 11787, 11788, 11789, 11790, 11799, 11800, + 11802, 11803, 11804, 11805, 11806, 11808, 11809, 11810, 11811, 11812, + 11813, 11814, 11815, 11816, 11817, 11818, 11823, 11824, 11834, 11904, + 11931, 12032, 12272, 12288, 12289, 12292, 12293, 12294, 12295, 12296, + 12297, 12298, 12299, 12300, 12301, 12302, 12303, 12304, 12305, 12306, + 12308, 12309, 12310, 12311, 12312, 12313, 12314, 12315, 12316, 12317, + 12318, 12320, 12321, 12330, 12334, 12336, 12337, 12342, 12344, 12347, + 12348, 12349, 12350, 12353, 12441, 12443, 12445, 12447, 12448, 12449, + 12539, 12540, 12543, 12549, 12593, 12688, 12690, 12694, 12704, 12736, + 12784, 12800, 12832, 12842, 12872, 12880, 12881, 12896, 12928, 12938, + 12977, 12992, 13056, 13312, 19893, 19904, 19968, 40908, 40960, 40981, + 40982, 42128, 42192, 42232, 42238, 42240, 42508, 42509, 42512, 42528, + 42538, 42560, 42606, 42607, 42608, 42611, 42612, 42622, 42623, 42624, + 42655, 42656, 42726, 42736, 42738, 42752, 42775, 42784, 42786, 42800, + 42802, 42864, 42865, 42873, 42878, 42888, 42889, 42891, 42896, 42912, + 43000, 43002, 43003, 43010, 43011, 43014, 43015, 43019, 43020, 43043, + 43045, 43047, 43048, 43056, 43062, 43064, 43065, 43072, 43124, 43136, + 43138, 43188, 43204, 43214, 43216, 43232, 43250, 43256, 43259, 43264, + 43274, 43302, 43310, 43312, 43335, 43346, 43359, 43360, 43392, 43395, + 43396, 43443, 43444, 43446, 43450, 43452, 43453, 43457, 43471, 43472, + 43486, 43520, 43561, 43567, 43569, 43571, 43573, 43584, 43587, 43588, + 43596, 43597, 43600, 43612, 43616, 43632, 43633, 43639, 43642, 43643, + 43648, 43696, 43697, 43698, 43701, 43703, 43705, 43710, 43712, 43713, + 43714, 43739, 43741, 43742, 43744, 43755, 43756, 43758, 43760, 43762, + 43763, 43765, 43766, 43777, 43785, 43793, 43808, 43816, 43968, 44003, + 44005, 44006, 44008, 44009, 44011, 44012, 44013, 44016, 44032, 55203, + 55216, 55243, 55296, 56191, 56319, 57343, 57344, 63743, 63744, 64112, + 64256, 64275, 64285, 64286, 64287, 64297, 64298, 64312, 64318, 64320, + 64323, 64326, 64434, 64467, 64830, 64831, 64848, 64914, 65008, 65020, + 65021, 65024, 65040, 65047, 65048, 65049, 65056, 65072, 65073, 65075, + 65077, 65078, 65079, 65080, 65081, 65082, 65083, 65084, 65085, 65086, + 65087, 65088, 65089, 65090, 65091, 65092, 65093, 65095, 65096, 65097, + 65101, 65104, 65108, 65112, 65113, 65114, 65115, 65116, 65117, 65118, + 65119, 65122, 65123, 65124, 65128, 65129, 65130, 65136, 65142, 65279, + 65281, 65284, 65285, 65288, 65289, 65290, 65291, 65292, 65293, 65294, + 65296, 65306, 65308, 65311, 65313, 65339, 65340, 65341, 65342, 65343, + 65344, 65345, 65371, 65372, 65373, 65374, 65375, 65376, 65377, 65378, + 65379, 65380, 65382, 65392, 65393, 65438, 65440, 65474, 65482, 65490, + 65498, 65504, 65506, 65507, 65508, 65509, 65512, 65513, 65517, 65529, + 65532, 0, 13, 40, 60, 63, 80, 128, 256, 263, + 311, 320, 373, 377, 394, 400, 464, 509, 640, 672, + 768, 800, 816, 833, 834, 842, 896, 927, 928, 968, + 976, 977, 1024, 1064, 1104, 1184, 2048, 2056, 2058, 2103, + 2108, 2111, 2135, 2136, 2304, 2326, 2335, 2336, 2367, 2432, + 2494, 2560, 2561, 2565, 2572, 2576, 2581, 2585, 2616, 2623, + 2624, 2640, 2656, 2685, 2687, 2816, 2873, 2880, 2904, 2912, + 2936, 3072, 3680, 4096, 4097, 4098, 4099, 4152, 4167, 4178, + 4198, 4224, 4226, 4227, 4272, 4275, 4279, 4281, 4283, 4285, + 4286, 4304, 4336, 4352, 4355, 4391, 4396, 4397, 4406, 4416, + 4480, 4482, 4483, 4531, 4534, 4543, 4545, 4549, 4560, 5760, + 5803, 5804, 5805, 5806, 5808, 5814, 5815, 5824, 8192, 9216, + 9328, 12288, 26624, 28416, 28496, 28497, 28559, 28563, 45056, 53248, + 53504, 53545, 53605, 53607, 53610, 53613, 53619, 53627, 53635, 53637, + 53644, 53674, 53678, 53760, 53826, 53829, 54016, 54112, 54272, 54298, + 54324, 54350, 54358, 54376, 54402, 54428, 54430, 54434, 54437, 54441, + 54446, 54454, 54459, 54461, 54469, 54480, 54506, 54532, 54535, 54541, + 54550, 54558, 54584, 54587, 54592, 54598, 54602, 54610, 54636, 54662, + 54688, 54714, 54740, 54766, 54792, 54818, 54844, 54870, 54896, 54922, + 54952, 54977, 54978, 55003, 55004, 55010, 55035, 55036, 55061, 55062, + 55068, 55093, 55094, 55119, 55120, 55126, 55151, 55152, 55177, 55178, + 55184, 55209, 55210, 55235, 55236, 55242, 55246, 60928, 60933, 60961, + 60964, 60967, 60969, 60980, 60985, 60987, 60994, 60999, 61001, 61003, + 61005, 61009, 61012, 61015, 61017, 61019, 61021, 61023, 61025, 61028, + 61031, 61036, 61044, 61049, 61054, 61056, 61067, 61089, 61093, 61099, + 61168, 61440, 61488, 61600, 61617, 61633, 61649, 61696, 61712, 61744, + 61808, 61926, 61968, 62016, 62032, 62208, 62256, 62263, 62336, 62368, + 62406, 62432, 62464, 62528, 62530, 62713, 62720, 62784, 62800, 62971, + 63045, 63104, 63232, 0, 42710, 42752, 46900, 46912, 47133, 63488, + 1, 32, 256, 0, 65533, + }; +static u16 aFts5UnicodeData[] = { + 1025, 61, 117, 55, 117, 54, 50, 53, 57, 53, + 49, 85, 333, 85, 121, 85, 841, 54, 53, 50, + 56, 48, 56, 837, 54, 57, 50, 57, 1057, 61, + 53, 151, 58, 53, 56, 58, 39, 52, 57, 34, + 58, 56, 58, 57, 79, 56, 37, 85, 56, 47, + 39, 51, 111, 53, 745, 57, 233, 773, 57, 261, + 1822, 37, 542, 37, 1534, 222, 69, 73, 37, 126, + 126, 73, 69, 137, 37, 73, 37, 105, 101, 73, + 37, 73, 37, 190, 158, 37, 126, 126, 73, 37, + 126, 94, 37, 39, 94, 69, 135, 41, 40, 37, + 41, 40, 37, 41, 40, 37, 542, 37, 606, 37, + 41, 40, 37, 126, 73, 37, 1886, 197, 73, 37, + 73, 69, 126, 105, 37, 286, 2181, 39, 869, 582, + 152, 390, 472, 166, 248, 38, 56, 38, 568, 3596, + 158, 38, 56, 94, 38, 101, 53, 88, 41, 53, + 105, 41, 73, 37, 553, 297, 1125, 94, 37, 105, + 101, 798, 133, 94, 57, 126, 94, 37, 1641, 1541, + 1118, 58, 172, 75, 1790, 478, 37, 2846, 1225, 38, + 213, 1253, 53, 49, 55, 1452, 49, 44, 53, 76, + 53, 76, 53, 44, 871, 103, 85, 162, 121, 85, + 55, 85, 90, 364, 53, 85, 1031, 38, 327, 684, + 333, 149, 71, 44, 3175, 53, 39, 236, 34, 58, + 204, 70, 76, 58, 140, 71, 333, 103, 90, 39, + 469, 34, 39, 44, 967, 876, 2855, 364, 39, 333, + 1063, 300, 70, 58, 117, 38, 711, 140, 38, 300, + 38, 108, 38, 172, 501, 807, 108, 53, 39, 359, + 876, 108, 42, 1735, 44, 42, 44, 39, 106, 268, + 138, 44, 74, 39, 236, 327, 76, 85, 333, 53, + 38, 199, 231, 44, 74, 263, 71, 711, 231, 39, + 135, 44, 39, 106, 140, 74, 74, 44, 39, 42, + 71, 103, 76, 333, 71, 87, 207, 58, 55, 76, + 42, 199, 71, 711, 231, 71, 71, 71, 44, 106, + 76, 76, 108, 44, 135, 39, 333, 76, 103, 44, + 76, 42, 295, 103, 711, 231, 71, 167, 44, 39, + 106, 172, 76, 42, 74, 44, 39, 71, 76, 333, + 53, 55, 44, 74, 263, 71, 711, 231, 71, 167, + 44, 39, 42, 44, 42, 140, 74, 74, 44, 44, + 42, 71, 103, 76, 333, 58, 39, 207, 44, 39, + 199, 103, 135, 71, 39, 71, 71, 103, 391, 74, + 44, 74, 106, 106, 44, 39, 42, 333, 111, 218, + 55, 58, 106, 263, 103, 743, 327, 167, 39, 108, + 138, 108, 140, 76, 71, 71, 76, 333, 239, 58, + 74, 263, 103, 743, 327, 167, 44, 39, 42, 44, + 170, 44, 74, 74, 76, 74, 39, 71, 76, 333, + 71, 74, 263, 103, 1319, 39, 106, 140, 106, 106, + 44, 39, 42, 71, 76, 333, 207, 58, 199, 74, + 583, 775, 295, 39, 231, 44, 106, 108, 44, 266, + 74, 53, 1543, 44, 71, 236, 55, 199, 38, 268, + 53, 333, 85, 71, 39, 71, 39, 39, 135, 231, + 103, 39, 39, 71, 135, 44, 71, 204, 76, 39, + 167, 38, 204, 333, 135, 39, 122, 501, 58, 53, + 122, 76, 218, 333, 335, 58, 44, 58, 44, 58, + 44, 54, 50, 54, 50, 74, 263, 1159, 460, 42, + 172, 53, 76, 167, 364, 1164, 282, 44, 218, 90, + 181, 154, 85, 1383, 74, 140, 42, 204, 42, 76, + 74, 76, 39, 333, 213, 199, 74, 76, 135, 108, + 39, 106, 71, 234, 103, 140, 423, 44, 74, 76, + 202, 44, 39, 42, 333, 106, 44, 90, 1225, 41, + 41, 1383, 53, 38, 10631, 135, 231, 39, 135, 1319, + 135, 1063, 135, 231, 39, 135, 487, 1831, 135, 2151, + 108, 309, 655, 519, 346, 2727, 49, 19847, 85, 551, + 61, 839, 54, 50, 2407, 117, 110, 423, 135, 108, + 583, 108, 85, 583, 76, 423, 103, 76, 1671, 76, + 42, 236, 266, 44, 74, 364, 117, 38, 117, 55, + 39, 44, 333, 335, 213, 49, 149, 108, 61, 333, + 1127, 38, 1671, 1319, 44, 39, 2247, 935, 108, 138, + 76, 106, 74, 44, 202, 108, 58, 85, 333, 967, + 167, 1415, 554, 231, 74, 333, 47, 1114, 743, 76, + 106, 85, 1703, 42, 44, 42, 236, 44, 42, 44, + 74, 268, 202, 332, 44, 333, 333, 245, 38, 213, + 140, 42, 1511, 44, 42, 172, 42, 44, 170, 44, + 74, 231, 333, 245, 346, 300, 314, 76, 42, 967, + 42, 140, 74, 76, 42, 44, 74, 71, 333, 1415, + 44, 42, 76, 106, 44, 42, 108, 74, 149, 1159, + 266, 268, 74, 76, 181, 333, 103, 333, 967, 198, + 85, 277, 108, 53, 428, 42, 236, 135, 44, 135, + 74, 44, 71, 1413, 2022, 421, 38, 1093, 1190, 1260, + 140, 4830, 261, 3166, 261, 265, 197, 201, 261, 265, + 261, 265, 197, 201, 261, 41, 41, 41, 94, 229, + 265, 453, 261, 264, 261, 264, 261, 264, 165, 69, + 137, 40, 56, 37, 120, 101, 69, 137, 40, 120, + 133, 69, 137, 120, 261, 169, 120, 101, 69, 137, + 40, 88, 381, 162, 209, 85, 52, 51, 54, 84, + 51, 54, 52, 277, 59, 60, 162, 61, 309, 52, + 51, 149, 80, 117, 57, 54, 50, 373, 57, 53, + 48, 341, 61, 162, 194, 47, 38, 207, 121, 54, + 50, 38, 335, 121, 54, 50, 422, 855, 428, 139, + 44, 107, 396, 90, 41, 154, 41, 90, 37, 105, + 69, 105, 37, 58, 41, 90, 57, 169, 218, 41, + 58, 41, 58, 41, 58, 137, 58, 37, 137, 37, + 135, 37, 90, 69, 73, 185, 94, 101, 58, 57, + 90, 37, 58, 527, 1134, 94, 142, 47, 185, 186, + 89, 154, 57, 90, 57, 90, 57, 250, 57, 1018, + 89, 90, 57, 58, 57, 1018, 8601, 282, 153, 666, + 89, 250, 54, 50, 2618, 57, 986, 825, 1306, 217, + 602, 1274, 378, 1935, 2522, 719, 5882, 57, 314, 57, + 1754, 281, 3578, 57, 4634, 3322, 54, 50, 54, 50, + 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, + 975, 1434, 185, 54, 50, 1017, 54, 50, 54, 50, + 54, 50, 54, 50, 54, 50, 537, 8218, 4217, 54, + 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, + 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, + 50, 2041, 54, 50, 54, 50, 1049, 54, 50, 8281, + 1562, 697, 90, 217, 346, 1513, 1509, 126, 73, 69, + 254, 105, 37, 94, 37, 94, 165, 70, 105, 37, + 3166, 37, 218, 158, 108, 94, 149, 47, 85, 1221, + 37, 37, 1799, 38, 53, 44, 743, 231, 231, 231, + 231, 231, 231, 231, 231, 1036, 85, 52, 51, 52, + 51, 117, 52, 51, 53, 52, 51, 309, 49, 85, + 49, 53, 52, 51, 85, 52, 51, 54, 50, 54, + 50, 54, 50, 54, 50, 181, 38, 341, 81, 858, + 2874, 6874, 410, 61, 117, 58, 38, 39, 46, 54, + 50, 54, 50, 54, 50, 54, 50, 54, 50, 90, + 54, 50, 54, 50, 54, 50, 54, 50, 49, 54, + 82, 58, 302, 140, 74, 49, 166, 90, 110, 38, + 39, 53, 90, 2759, 76, 88, 70, 39, 49, 2887, + 53, 102, 39, 1319, 3015, 90, 143, 346, 871, 1178, + 519, 1018, 335, 986, 271, 58, 495, 1050, 335, 1274, + 495, 2042, 8218, 39, 39, 2074, 39, 39, 679, 38, + 36583, 1786, 1287, 198, 85, 8583, 38, 117, 519, 333, + 71, 1502, 39, 44, 107, 53, 332, 53, 38, 798, + 44, 2247, 334, 76, 213, 760, 294, 88, 478, 69, + 2014, 38, 261, 190, 350, 38, 88, 158, 158, 382, + 70, 37, 231, 44, 103, 44, 135, 44, 743, 74, + 76, 42, 154, 207, 90, 55, 58, 1671, 149, 74, + 1607, 522, 44, 85, 333, 588, 199, 117, 39, 333, + 903, 268, 85, 743, 364, 74, 53, 935, 108, 42, + 1511, 44, 74, 140, 74, 44, 138, 437, 38, 333, + 85, 1319, 204, 74, 76, 74, 76, 103, 44, 263, + 44, 42, 333, 149, 519, 38, 199, 122, 39, 42, + 1543, 44, 39, 108, 71, 76, 167, 76, 39, 44, + 39, 71, 38, 85, 359, 42, 76, 74, 85, 39, + 70, 42, 44, 199, 199, 199, 231, 231, 1127, 74, + 44, 74, 44, 74, 53, 42, 44, 333, 39, 39, + 743, 1575, 36, 68, 68, 36, 63, 63, 11719, 3399, + 229, 165, 39, 44, 327, 57, 423, 167, 39, 71, + 71, 3463, 536, 11623, 54, 50, 2055, 1735, 391, 55, + 58, 524, 245, 54, 50, 53, 236, 53, 81, 80, + 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, + 54, 50, 54, 50, 54, 50, 85, 54, 50, 149, + 112, 117, 149, 49, 54, 50, 54, 50, 54, 50, + 117, 57, 49, 121, 53, 55, 85, 167, 4327, 34, + 117, 55, 117, 54, 50, 53, 57, 53, 49, 85, + 333, 85, 121, 85, 841, 54, 53, 50, 56, 48, + 56, 837, 54, 57, 50, 57, 54, 50, 53, 54, + 50, 85, 327, 38, 1447, 70, 999, 199, 199, 199, + 103, 87, 57, 56, 58, 87, 58, 153, 90, 98, + 90, 391, 839, 615, 71, 487, 455, 3943, 117, 1455, + 314, 1710, 143, 570, 47, 410, 1466, 44, 935, 1575, + 999, 143, 551, 46, 263, 46, 967, 53, 1159, 263, + 53, 174, 1289, 1285, 2503, 333, 199, 39, 1415, 71, + 39, 743, 53, 271, 711, 207, 53, 839, 53, 1799, + 71, 39, 108, 76, 140, 135, 103, 871, 108, 44, + 271, 309, 935, 79, 53, 1735, 245, 711, 271, 615, + 271, 2343, 1007, 42, 44, 42, 1703, 492, 245, 655, + 333, 76, 42, 1447, 106, 140, 74, 76, 85, 34, + 149, 807, 333, 108, 1159, 172, 42, 268, 333, 149, + 76, 42, 1543, 106, 300, 74, 135, 149, 333, 1383, + 44, 42, 44, 74, 204, 42, 44, 333, 28135, 3182, + 149, 34279, 18215, 2215, 39, 1482, 140, 422, 71, 7898, + 1274, 1946, 74, 108, 122, 202, 258, 268, 90, 236, + 986, 140, 1562, 2138, 108, 58, 2810, 591, 841, 837, + 841, 229, 581, 841, 837, 41, 73, 41, 73, 137, + 265, 133, 37, 229, 357, 841, 837, 73, 137, 265, + 233, 837, 73, 137, 169, 41, 233, 837, 841, 837, + 841, 837, 841, 837, 841, 837, 841, 837, 841, 901, + 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, + 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, + 809, 57, 805, 57, 197, 94, 1613, 135, 871, 71, + 39, 39, 327, 135, 39, 39, 39, 39, 39, 39, + 103, 71, 39, 39, 39, 39, 39, 39, 71, 39, + 135, 231, 135, 135, 39, 327, 551, 103, 167, 551, + 89, 1434, 3226, 506, 474, 506, 506, 367, 1018, 1946, + 1402, 954, 1402, 314, 90, 1082, 218, 2266, 666, 1210, + 186, 570, 2042, 58, 5850, 154, 2010, 154, 794, 2266, + 378, 2266, 3738, 39, 39, 39, 39, 39, 39, 17351, + 34, 3074, 7692, 63, 63, + }; + +int sqlite3Fts5UnicodeCategory(int iCode) { + int iRes = -1; + int iHi; + int iLo; + int ret; + u16 iKey; + + if( iCode>=(1<<20) ){ + return 0; + } + iLo = aFts5UnicodeBlock[(iCode>>16)]; + iHi = aFts5UnicodeBlock[1+(iCode>>16)]; + iKey = (iCode & 0xFFFF); + while( iHi>iLo ){ + int iTest = (iHi + iLo) / 2; + assert( iTest>=iLo && iTest=aFts5UnicodeMap[iTest] ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest; + } + } + + if( iRes<0 ) return 0; + if( iKey>=(aFts5UnicodeMap[iRes]+(aFts5UnicodeData[iRes]>>5)) ) return 0; + ret = aFts5UnicodeData[iRes] & 0x1F; + if( ret!=30 ) return ret; + return ((iKey - aFts5UnicodeMap[iRes]) & 0x01) ? 5 : 9; +} + +void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){ + int i = 0; + int iTbl = 0; + while( i<128 ){ + int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ]; + int n = (aFts5UnicodeData[iTbl] >> 5) + i; + for(; i<128 && i Date: Fri, 13 Jul 2018 20:28:54 +0000 Subject: [PATCH 010/260] Remove an unused function declaration from fts5. FossilOrigin-Name: 148d9b61471a874a16a9ec9c9603da03cadb3a40662fb550af51cb36212426b1 --- ext/fts5/fts5Int.h | 1 - ext/fts5/fts5_unicode2.c | 2 ++ manifest | 15 +++++++-------- manifest.uuid | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index d667f3747c..a460a7af34 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -784,7 +784,6 @@ int sqlite3Fts5VocabInit(Fts5Global*, sqlite3*); /************************************************************************** ** Interface to automatically generated code in fts5_unicode2.c. */ -int sqlite3Fts5UnicodeIsalnum(int c); int sqlite3Fts5UnicodeIsdiacritic(int c); int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); diff --git a/ext/fts5/fts5_unicode2.c b/ext/fts5/fts5_unicode2.c index e0c5fa07f3..ad2dd89bb0 100644 --- a/ext/fts5/fts5_unicode2.c +++ b/ext/fts5/fts5_unicode2.c @@ -231,9 +231,11 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){ } +#if 0 int sqlite3Fts5UnicodeNCat(void) { return 32; } +#endif int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){ aArray[0] = 1; diff --git a/manifest b/manifest index c56b0d6dcc..3434a91fcf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"categories"\soption\sto\sthe\sunicode61\stokenizer\sin\sfts5. -D 2018-07-13T19:52:43.227 +C Remove\san\sunused\sfunction\sdeclaration\sfrom\sfts5. +D 2018-07-13T20:28:54.141 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -108,7 +108,7 @@ F ext/fts3/unicode/mkunicode.tcl 0069320b64db6ee269c5e95f1f150d070fbf0a863fc7b35 F ext/fts3/unicode/parseunicode.tcl 024ae0bdd96309d7b8fc479148191e9b3001dc74017a3f65f9a27de3b3ff968b F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7 -F ext/fts5/fts5Int.h 6354c8f830487a48b7a0872c9eb33b4258a57f9e3c315df9da95c896d70a732b +F ext/fts5/fts5Int.h 39f12034b598df4e0f59bbe6cf03af03a905a534b04f182d155641a04e1eb797 F ext/fts5/fts5_aux.c ca666a3bbe07c5a3bbe9fffaea19c935a1efaf337333e28bad7bdd1971ffd093 F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 @@ -121,7 +121,7 @@ F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282 F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6 F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26 F ext/fts5/fts5_tokenize.c ebd13d034f3dc7c841e1c32c364a4fca5cc2e05a0b91682a93fa1e6defcd4292 -F ext/fts5/fts5_unicode2.c bcf4afd86a00be1608deac305b914ca101161e43feed026818fcdde19e9b30e2 +F ext/fts5/fts5_unicode2.c f074475acb251e9deb2fd4c72b2fe175f596ff25cf330fb044f869cf742da644 F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c 1cd79854cb21543e66507b25b0578bc1b20aa6a1349b7feceb8e8fed0e7a77a6 F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05 @@ -1747,8 +1747,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 650a3fe03d61068e06f3097878a777ca8ed713a769444cdb3f8be7d1e19a0b83 -R dca8016ca1ceb389549f1bc1385b49e3 -T +closed 8e59dc7807d15d4fca6ee7b6a624447748eb24afb48f902fca27c2d550d84f1c +P 80d2b9e635e3100f90cffdcffa5b5038da6fbbfccc9f5777c59a4ae760d4cb62 +R 81cc2fe2a6c094c9b67be82b05d8bc76 U dan -Z 28a0d1fcc85b29bafa0cd6ceb5a53164 +Z 27c2f249d1d32a1646d5c8126ba109c2 diff --git a/manifest.uuid b/manifest.uuid index 97be00cc68..d7389e66a7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -80d2b9e635e3100f90cffdcffa5b5038da6fbbfccc9f5777c59a4ae760d4cb62 \ No newline at end of file +148d9b61471a874a16a9ec9c9603da03cadb3a40662fb550af51cb36212426b1 \ No newline at end of file From 140a59874b2545917d2ce7434466ae7fc3ee0280 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 14 Jul 2018 20:25:13 +0000 Subject: [PATCH 011/260] If an SQLITE_IOERR error is encountered as part of an atomic commit on an F2FS file-system, retry the commit in legacy journal mode. FossilOrigin-Name: 1c41250f67ac5de423b0426ef2ab8fe3303278a270225920033933ca9609592a --- manifest | 18 +++++---- manifest.uuid | 2 +- src/pager.c | 42 +++++++++++++-------- src/test_vfs.c | 34 +++++++++++++++-- test/atomic2.test | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 164 insertions(+), 27 deletions(-) create mode 100644 test/atomic2.test diff --git a/manifest b/manifest index 3434a91fcf..da41e2346f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\sfunction\sdeclaration\sfrom\sfts5. -D 2018-07-13T20:28:54.141 +C If\san\sSQLITE_IOERR\serror\sis\sencountered\sas\spart\sof\san\satomic\scommit\son\san\sF2FS\nfile-system,\sretry\sthe\scommit\sin\slegacy\sjournal\smode. +D 2018-07-14T20:25:13.305 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -483,7 +483,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f +F src/pager.c 26959078356a658e152de9faf0cd870a36d881e92666c1b80a75938e30a29964 F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 F src/parse.y 3bd43415ea974b9921b0ff2c0bd3e9100f6e501ede0b6d3b90cca2ab6af25485 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd @@ -552,7 +552,7 @@ F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939 F src/test_tclsh.c 06317648b0d85a85fd823f7973b55535c59a3156c1ef59394fe511f932cfa78d F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858 -F src/test_vfs.c f0186261a24de2671d080bcd8050732f0cb64f6e +F src/test_vfs.c 112f1f9271c33c211812e0e681830a84262dac065da58579ff49f9cefec97d4f F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1 F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215 @@ -621,6 +621,7 @@ F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0 F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061 +F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce F test/attach3.test c59d92791070c59272e00183b7353eeb94915976 @@ -1747,7 +1748,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 80d2b9e635e3100f90cffdcffa5b5038da6fbbfccc9f5777c59a4ae760d4cb62 -R 81cc2fe2a6c094c9b67be82b05d8bc76 +P 148d9b61471a874a16a9ec9c9603da03cadb3a40662fb550af51cb36212426b1 +R 49a0ed84c0ce130af574e6c49ed456cc +T *branch * exp-retry-atomic-commit +T *sym-exp-retry-atomic-commit * +T -sym-trunk * U dan -Z 27c2f249d1d32a1646d5c8126ba109c2 +Z b2768f20163b2f8528694b9d7a295551 diff --git a/manifest.uuid b/manifest.uuid index d7389e66a7..265f42856a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -148d9b61471a874a16a9ec9c9603da03cadb3a40662fb550af51cb36212426b1 \ No newline at end of file +1c41250f67ac5de423b0426ef2ab8fe3303278a270225920033933ca9609592a \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index a5e1edf782..7c69271831 100644 --- a/src/pager.c +++ b/src/pager.c @@ -6382,9 +6382,10 @@ int sqlite3PagerCommitPhaseOne( ** backup in progress needs to be restarted. */ sqlite3BackupRestart(pPager->pBackup); }else{ + PgHdr *pList; if( pagerUseWal(pPager) ){ - PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); PgHdr *pPageOne = 0; + pList = sqlite3PcacheDirtyList(pPager->pPCache); if( pList==0 ){ /* Must have at least one page for the WAL commit flag. ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ @@ -6407,7 +6408,7 @@ int sqlite3PagerCommitPhaseOne( */ sqlite3_file *fd = pPager->fd; #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ + int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC) && !pPager->noSync && sqlite3JournalIsInMemory(pPager->jfd); @@ -6464,15 +6465,16 @@ int sqlite3PagerCommitPhaseOne( } } } -#else +#else /* SQLITE_ENABLE_ATOMIC_WRITE */ #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE if( zMaster ){ rc = sqlite3JournalCreate(pPager->jfd); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + assert( bBatch==0 ); } #endif rc = pager_incr_changecounter(pPager, 0); -#endif +#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */ if( rc!=SQLITE_OK ) goto commit_phase_one_exit; /* Write the master journal name into the journal file. If a master @@ -6496,24 +6498,34 @@ int sqlite3PagerCommitPhaseOne( rc = syncJournal(pPager, 0); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + pList = sqlite3PcacheDirtyList(pPager->pPCache); if( bBatch ){ - /* The pager is now in DBMOD state. But regardless of what happens - ** next, attempting to play the journal back into the database would - ** be unsafe. Close it now to make sure that does not happen. */ - sqlite3OsClose(pPager->jfd); rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - } - rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); - if( bBatch ){ if( rc==SQLITE_OK ){ - rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); + rc = pager_write_pagelist(pPager, pList); + if( rc==SQLITE_OK ){ + rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); + } + if( rc!=SQLITE_OK ){ + sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); + } } - if( rc!=SQLITE_OK ){ - sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); + + if( (rc&0xFF)==SQLITE_IOERR && rc!=SQLITE_IOERR_NOMEM ){ + rc = sqlite3JournalCreate(pPager->jfd); + if( rc!=SQLITE_OK ){ + sqlite3OsClose(pPager->jfd); + } + bBatch = 0; + }else{ + sqlite3OsClose(pPager->jfd); } } + if( bBatch==0 && rc==SQLITE_OK ){ + rc = pager_write_pagelist(pPager, pList); + } + if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_IOERR_BLOCKED ); goto commit_phase_one_exit; diff --git a/src/test_vfs.c b/src/test_vfs.c index fb987a6163..4a98ac214c 100644 --- a/src/test_vfs.c +++ b/src/test_vfs.c @@ -133,8 +133,9 @@ struct Testvfs { #define TESTVFS_UNLOCK_MASK 0x00020000 #define TESTVFS_LOCK_MASK 0x00040000 #define TESTVFS_CKLOCK_MASK 0x00080000 +#define TESTVFS_FCNTL_MASK 0x00100000 -#define TESTVFS_ALL_MASK 0x000FFFFF +#define TESTVFS_ALL_MASK 0x001FFFFF #define TESTVFS_MAX_PAGES 1024 @@ -517,7 +518,8 @@ static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ ** File control method. For custom operations on an tvfs-file. */ static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ - TestvfsFd *p = tvfsGetFd(pFile); + TestvfsFd *pFd = tvfsGetFd(pFile); + Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( op==SQLITE_FCNTL_PRAGMA ){ char **argv = (char**)pArg; if( sqlite3_stricmp(argv[1],"error")==0 ){ @@ -535,11 +537,34 @@ static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ return rc; } if( sqlite3_stricmp(argv[1], "filename")==0 ){ - argv[0] = sqlite3_mprintf("%s", p->zFilename); + argv[0] = sqlite3_mprintf("%s", pFd->zFilename); return SQLITE_OK; } } - return sqlite3OsFileControl(p->pReal, op, pArg); + if( p->pScript && (p->mask&TESTVFS_FCNTL_MASK) ){ + struct Fcntl { + int iFnctl; + const char *zFnctl; + } aF[] = { + { SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, "BEGIN_ATOMIC_WRITE" }, + { SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, "COMMIT_ATOMIC_WRITE" }, + }; + int i; + for(i=0; izFilename, -1), + Tcl_NewStringObj(aF[i].zFnctl, -1), + 0, 0 + ); + tvfsResultCode(p, &rc); + if( rc ) return rc; + } + } + return sqlite3OsFileControl(pFd->pReal, op, pArg); } /* @@ -1160,6 +1185,7 @@ static int SQLITE_TCLAPI testvfs_obj_cmd( { "xUnlock", TESTVFS_UNLOCK_MASK }, { "xLock", TESTVFS_LOCK_MASK }, { "xCheckReservedLock", TESTVFS_CKLOCK_MASK }, + { "xFileControl", TESTVFS_FCNTL_MASK }, }; Tcl_Obj **apElem = 0; int nElem = 0; diff --git a/test/atomic2.test b/test/atomic2.test new file mode 100644 index 0000000000..5b786586bf --- /dev/null +++ b/test/atomic2.test @@ -0,0 +1,95 @@ +# 2018-07-15 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is testing that if an IO error is encountered +# as part of an atomic F2FS commit, an attempt is made to commit the +# transaction using a legacy journal commit. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +set ::testprefix atomic2 + +db close +if {[atomic_batch_write test.db]==0} { + puts "No f2fs atomic-batch-write support. Skipping tests..." + finish_test + return +} + +reset_db + +do_execsql_test 1.0 { + CREATE TABLE t1(x, y); + CREATE INDEX i1x ON t1(x); + CREATE INDEX i2x ON t1(y); + + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 ) + INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s; +} + +set setup [list \ + -injectstart at_injectstart \ + -injectstop at_injectstop \ +] + +set ::at_fail 0 +set ::at_nfail 0 + +proc at_injectstart {iFail} { + set ::at_fail $iFail + set ::at_nfail 0 +} +proc at_injectstop {} { + set ::at_fail 0 + return $::at_nfail +} + +proc at_vfs_callback {method file z args} { + if {$::at_fail>0} { + incr ::at_fail -1 + if {$::at_fail==0} { + incr ::at_nfail + return SQLITE_IOERR + } elseif {$method=="xFileControl" && $z=="COMMIT_ATOMIC_WRITE"} { + set ::at_fail 0 + } + } + return SQLITE_OK +} + +testvfs tvfs -default 1 +tvfs script at_vfs_callback +tvfs filter {xFileControl xWrite} + +faultsim_save_and_close + +do_one_faultsim_test 2.0 {*}$setup -prep { + faultsim_restore_and_reopen +} -body { + execsql { + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 ) + INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s; + } +} -test { + faultsim_test_result {0 {}} + + set res [execsql {SELECT count(*) FROM t1; PRAGMA integrity_check}] + if {$res!="200 ok"} { + error "expected {200 ok}, got $res" + } +} + +db close +tvfs delete + +finish_test From 7f32dc94a3397818ceff488483387b7d63add877 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 16 Jul 2018 11:32:59 +0000 Subject: [PATCH 012/260] Minor simplification to sqlite3RollbackAll(). FossilOrigin-Name: 432fdc221550b3cca4140b1ae411da22201f689c30c72c5472dfdbc79bec9d90 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/main.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 3434a91fcf..92e8676358 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\sfunction\sdeclaration\sfrom\sfts5. -D 2018-07-13T20:28:54.141 +C Minor\ssimplification\sto\ssqlite3RollbackAll(). +D 2018-07-16T11:32:59.740 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -460,7 +460,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 8613af9c5ba1503bc68f4e9432c6c024e0fdafdc791575c50f380f73ec91189f F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b -F src/main.c fa70bde00ebe7865cfa3fe1e2de87a003d575c1ec4598ff0a1f414ecb1404928 +F src/main.c a67aa346d68608a449aca06a975056c4a5b6c193290e09539efaeb3664ed3707 F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -1747,7 +1747,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 80d2b9e635e3100f90cffdcffa5b5038da6fbbfccc9f5777c59a4ae760d4cb62 -R 81cc2fe2a6c094c9b67be82b05d8bc76 -U dan -Z 27c2f249d1d32a1646d5c8126ba109c2 +P 148d9b61471a874a16a9ec9c9603da03cadb3a40662fb550af51cb36212426b1 +R 9731515b749f0bceaf8a9239bf3b3da0 +U drh +Z 7d83889f4fd55f54443283ec8ab17e29 diff --git a/manifest.uuid b/manifest.uuid index d7389e66a7..4a268b88a2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -148d9b61471a874a16a9ec9c9603da03cadb3a40662fb550af51cb36212426b1 \ No newline at end of file +432fdc221550b3cca4140b1ae411da22201f689c30c72c5472dfdbc79bec9d90 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 0ce5040cad..e0b1c23ad2 100644 --- a/src/main.c +++ b/src/main.c @@ -1291,7 +1291,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); - if( (db->mDbFlags&DBFLAG_SchemaChange)!=0 && db->init.busy==0 ){ + if( schemaChange ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); } From e79522633ab063eb3897e81b20d0e7b47e7f76d1 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 16 Jul 2018 20:44:00 +0000 Subject: [PATCH 013/260] Add new file doc/F2FS.txt, containing notes on the way SQLite uses the F2FS atomic commit feature. FossilOrigin-Name: 59efb1bfaba12742379aae45c8c796ca539f089af9e553a3a55d6899a9c583c8 --- doc/F2FS.txt | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ manifest | 14 ++++----- manifest.uuid | 2 +- 3 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 doc/F2FS.txt diff --git a/doc/F2FS.txt b/doc/F2FS.txt new file mode 100644 index 0000000000..47ad2297f4 --- /dev/null +++ b/doc/F2FS.txt @@ -0,0 +1,87 @@ + +SQLite's OS layer contains the following definitions used in F2FS related +calls: + +#define F2FS_IOCTL_MAGIC 0xf5 +#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) +#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) +#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3) +#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) +#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32) +#define F2FS_FEATURE_ATOMIC_WRITE 0x0004 + +After opening a database file on Linux (including Android), SQLite determines +whether or not a file supports F2FS atomic commits as follows: + + u32 flags = 0; + rc = ioctl(fd, F2FS_IOC_GET_FEATURES, &flags); + if( rc==0 && (flags & F2FS_FEATURE_ATOMIC_WRITE) ){ + /* File supports F2FS atomic commits */ + }else{ + /* File does NOT support F2FS atomic commits */ + } + +where "fd" is the file-descriptor open on the database file. + +Usually, when writing to a database file that supports atomic commits, SQLite +accumulates the entire transaction in heap memory, deferring all writes to the +db file until the transaction is committed. + +When it is time to commit a transaction on a file that supports atomic +commits, SQLite does: + + /* Take an F_WRLCK lock on the database file. This prevents any other + ** SQLite clients from reading or writing the file until the lock + ** is released. */ + rc = fcntl(fd, F_SETLK, ...); + if( rc!=0 ) goto failed; + + rc = ioctl(fd, F2FS_IOC_START_ATOMIC_WRITE); + if( rc!=0 ) goto fallback_to_legacy_journal_commit; + + foreach (dirty page){ + rc = write(fd, ...dirty page...); + if( rc!=0 ){ + ioctl(fd, F2FS_IOC_ABORT_VOLATILE_WRITE); + goto fallback_to_legacy_journal_commit; + } + } + + rc = ioctl(fd, F2FS_IOC_COMMIT_ATOMIC_WRITE); + if( rc!=0 ){ + ioctl(fd, F2FS_IOC_ABORT_VOLATILE_WRITE); + goto fallback_to_legacy_journal_commit; + } + + /* If we get there, the transaction has been successfully + ** committed to persistent storage. The following call + ** relinquishes the F_WRLCK lock. */ + fcntl(fd, F_SETLK, ...); + +Assumptions: + +1. After either of the F2FS_IOC_ABORT_VOLATILE_WRITE calls return, + the database file is in the state that it was in before + F2FS_IOC_START_ATOMIC_WRITE was invoked. Even if the ioctl() + fails - we're ignoring the return code. + + This is true regardless of the type of error that occurred in + ioctl() or write(). + +2. If the system fails before the F2FS_IOC_COMMIT_ATOMIC_WRITE is + completed, then following a reboot the database file is in the + state that it was in before F2FS_IOC_START_ATOMIC_WRITE was invoked. + Or, if the write was commited right before the system failed, in a + state indicating that all write() calls were successfully committed + to persistent storage before the failure occurred. + +3. If the process crashes before the F2FS_IOC_COMMIT_ATOMIC_WRITE is + completed then the file is automatically restored to the state that + it was in before F2FS_IOC_START_ATOMIC_WRITE was called. This occurs + before the posix advisory lock is automatically dropped - there is + no chance that another client will be able to read the file in a + half-committed state before the rollback operation occurs. + + + + diff --git a/manifest b/manifest index da41e2346f..c6b0b5c82a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\san\sSQLITE_IOERR\serror\sis\sencountered\sas\spart\sof\san\satomic\scommit\son\san\sF2FS\nfile-system,\sretry\sthe\scommit\sin\slegacy\sjournal\smode. -D 2018-07-14T20:25:13.305 +C Add\snew\sfile\sdoc/F2FS.txt,\scontaining\snotes\son\sthe\sway\sSQLite\suses\sthe\sF2FS\satomic\scommit\sfeature. +D 2018-07-16T20:44:00.735 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -36,6 +36,7 @@ F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 F configure a46cba271ae08d635a1f331384c04563bdd37adb3d63cbdcffb1d91babfb64f5 x F configure.ac 18c93e8bbeec8254832c4ea90eb06e7187fd150ef098baed02467eeb374afb17 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad +F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a @@ -1748,10 +1749,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 148d9b61471a874a16a9ec9c9603da03cadb3a40662fb550af51cb36212426b1 -R 49a0ed84c0ce130af574e6c49ed456cc -T *branch * exp-retry-atomic-commit -T *sym-exp-retry-atomic-commit * -T -sym-trunk * +P 1c41250f67ac5de423b0426ef2ab8fe3303278a270225920033933ca9609592a +R 2220ce8debd68fb6b704ee2986103f77 U dan -Z b2768f20163b2f8528694b9d7a295551 +Z 3478246bf34685cf426f48a9a3e3b106 diff --git a/manifest.uuid b/manifest.uuid index 265f42856a..9f8867a454 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c41250f67ac5de423b0426ef2ab8fe3303278a270225920033933ca9609592a \ No newline at end of file +59efb1bfaba12742379aae45c8c796ca539f089af9e553a3a55d6899a9c583c8 \ No newline at end of file From 4522c3e8d138ab3c2e4a5bfa91bb8b05464f7673 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 17 Jul 2018 13:55:08 +0000 Subject: [PATCH 014/260] Fix for builds without SQLITE_ENABLE_BATCH_ATOMIC_WRITE. FossilOrigin-Name: b10ec14ef7edcc5d7b0ad298c8230d1eca5508e8cf673fbbc97a0928b76c92fb --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index c6b0b5c82a..6e1a90bd6c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\sfile\sdoc/F2FS.txt,\scontaining\snotes\son\sthe\sway\sSQLite\suses\sthe\sF2FS\satomic\scommit\sfeature. -D 2018-07-16T20:44:00.735 +C Fix\sfor\sbuilds\swithout\sSQLITE_ENABLE_BATCH_ATOMIC_WRITE. +D 2018-07-17T13:55:08.594 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -484,7 +484,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 26959078356a658e152de9faf0cd870a36d881e92666c1b80a75938e30a29964 +F src/pager.c 84996f4ff32bd4c556254241106c531473c75880df6fa8e698b921a5ec2bf89a F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 F src/parse.y 3bd43415ea974b9921b0ff2c0bd3e9100f6e501ede0b6d3b90cca2ab6af25485 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd @@ -1749,7 +1749,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1c41250f67ac5de423b0426ef2ab8fe3303278a270225920033933ca9609592a -R 2220ce8debd68fb6b704ee2986103f77 +P 59efb1bfaba12742379aae45c8c796ca539f089af9e553a3a55d6899a9c583c8 +R f80f88392522b1bdb8d9dd2500fd726f U dan -Z 3478246bf34685cf426f48a9a3e3b106 +Z a92c63bc8962be8f1fcb4cef36d7f989 diff --git a/manifest.uuid b/manifest.uuid index 9f8867a454..91f656d5df 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -59efb1bfaba12742379aae45c8c796ca539f089af9e553a3a55d6899a9c583c8 \ No newline at end of file +b10ec14ef7edcc5d7b0ad298c8230d1eca5508e8cf673fbbc97a0928b76c92fb \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 7c69271831..bd511227af 100644 --- a/src/pager.c +++ b/src/pager.c @@ -6499,6 +6499,7 @@ int sqlite3PagerCommitPhaseOne( if( rc!=SQLITE_OK ) goto commit_phase_one_exit; pList = sqlite3PcacheDirtyList(pPager->pPCache); +#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE if( bBatch ){ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); if( rc==SQLITE_OK ){ @@ -6521,6 +6522,7 @@ int sqlite3PagerCommitPhaseOne( sqlite3OsClose(pPager->jfd); } } +#endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ if( bBatch==0 && rc==SQLITE_OK ){ rc = pager_write_pagelist(pPager, pList); From 378a2da91eaf4552abdede3904bcf62516538046 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 18 Jul 2018 17:37:51 +0000 Subject: [PATCH 015/260] Fix a harmless compiler warning in the pager. Enhance the docs for sqlite3_changes() and sqlite3_total_changes() to refer to the data_version pragma. FossilOrigin-Name: 4c70ea5b0e2a512c6a46ac1f14397720e8c8556875701e78c30b19f850c24f55 --- manifest | 17 ++++++++--------- manifest.uuid | 2 +- src/pager.c | 4 ++-- src/sqlite.h.in | 22 ++++++++++++++++------ 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index 3238f82679..150614f638 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\san\sSQLITE_IOERR\serror\sis\sencountered\sas\spart\sof\san\satomic\scommit\son\san\sF2FS\sfile-system,\sretry\sthe\scommit\sin\slegacy\sjournal\smode. -D 2018-07-17T14:01:55.153 +C Fix\sa\sharmless\scompiler\swarning\sin\sthe\spager.\s\sEnhance\sthe\sdocs\sfor\nsqlite3_changes()\sand\ssqlite3_total_changes()\sto\srefer\sto\sthe\sdata_version\npragma. +D 2018-07-18T17:37:51.142 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -484,7 +484,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 84996f4ff32bd4c556254241106c531473c75880df6fa8e698b921a5ec2bf89a +F src/pager.c c4269e3481aa3cc5325a52b2d2663bf80f0c6eb0b0adfef7691cd6b113619eb9 F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 F src/parse.y 3bd43415ea974b9921b0ff2c0bd3e9100f6e501ede0b6d3b90cca2ab6af25485 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd @@ -499,7 +499,7 @@ F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 2e9661d4424f43ccf595c4a7b4acdf32db523c0f6b31cbd62e6e5a2f43118981 F src/shell.c.in f1c79c537117ee61317a5ed85cdbcb854998cd690eb34ab803779358a2ace780 -F src/sqlite.h.in 36f0b3f88241863530f4b7e57e673e19311dd609ec4edad83b23291928cdf853 +F src/sqlite.h.in 679a25353c90ccd83b16207888704d09bc0e5d5bd6fc1828e7ac653336ee4575 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h c2ceebe60d1d2e11674b90c8b55fdffd91386ce8d7ae38613fbcc61659b8fcac @@ -1749,8 +1749,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 432fdc221550b3cca4140b1ae411da22201f689c30c72c5472dfdbc79bec9d90 b10ec14ef7edcc5d7b0ad298c8230d1eca5508e8cf673fbbc97a0928b76c92fb -R 87d1309d70d437ae68a1599993e70cbb -T +closed b10ec14ef7edcc5d7b0ad298c8230d1eca5508e8cf673fbbc97a0928b76c92fb -U dan -Z f77b0e3b42ed0976545721536fc22e40 +P 2e0357c2ed30927921cd17129e348a18a6f3fd086d1fc0a42756036b321a084d +R 471d432eb2ed159696aafa5a0bf72e5a +U drh +Z 5df8cf4ea35c08c158f5d1145417612b diff --git a/manifest.uuid b/manifest.uuid index 167d45e9b0..f477a0b101 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e0357c2ed30927921cd17129e348a18a6f3fd086d1fc0a42756036b321a084d \ No newline at end of file +4c70ea5b0e2a512c6a46ac1f14397720e8c8556875701e78c30b19f850c24f55 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index bd511227af..65591632ab 100644 --- a/src/pager.c +++ b/src/pager.c @@ -6406,14 +6406,14 @@ int sqlite3PagerCommitPhaseOne( ** should be used. No rollback journal is created if batch-atomic-write ** is enabled. */ - sqlite3_file *fd = pPager->fd; #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + sqlite3_file *fd = pPager->fd; int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC) && !pPager->noSync && sqlite3JournalIsInMemory(pPager->jfd); #else -# define bBatch 0 +# define bBatch 0 #endif #ifdef SQLITE_ENABLE_ATOMIC_WRITE diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 6070934e39..22c5339bdc 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2276,12 +2276,17 @@ void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); ** program, the value returned reflects the number of rows modified by the ** previous INSERT, UPDATE or DELETE statement within the same trigger. ** -** See also the [sqlite3_total_changes()] interface, the -** [count_changes pragma], and the [changes() SQL function]. -** ** If a separate thread makes changes on the same database connection ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. +** +** See also: +**
    +**
  • the [sqlite3_total_changes()] interface +**
  • the [count_changes pragma] +**
  • the [changes() SQL function] +**
  • the [data_version pragma] +**
*/ int sqlite3_changes(sqlite3*); @@ -2300,12 +2305,17 @@ int sqlite3_changes(sqlite3*); ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers ** are not counted. ** -** See also the [sqlite3_changes()] interface, the -** [count_changes pragma], and the [total_changes() SQL function]. -** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. +** +** See also: +**
    +**
  • the [sqlite3_changes()] interface +**
  • the [count_changes pragma] +**
  • the [changes() SQL function] +**
  • the [data_version pragma] +**
*/ int sqlite3_total_changes(sqlite3*); From ea99a31c59d5b5ec711d54ef4e4a4f1eae6710a4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 18 Jul 2018 19:09:07 +0000 Subject: [PATCH 016/260] Add the SQLITE_FCNTL_DATA_VERSION file control FossilOrigin-Name: a5087c5c87ad65f92e3bc96bbc84afb43faf10ab6b9ed3ba16304b5c60ad069f --- manifest | 21 +++++----- manifest.uuid | 2 +- src/main.c | 3 ++ src/pager.c | 1 - src/shell.c.in | 3 ++ src/sqlite.h.in | 42 ++++++++++++++++++-- src/test1.c | 39 +++++++++++++++++++ test/dataversion1.test | 87 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 test/dataversion1.test diff --git a/manifest b/manifest index 150614f638..31443dc45a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\scompiler\swarning\sin\sthe\spager.\s\sEnhance\sthe\sdocs\sfor\nsqlite3_changes()\sand\ssqlite3_total_changes()\sto\srefer\sto\sthe\sdata_version\npragma. -D 2018-07-18T17:37:51.142 +C Add\sthe\sSQLITE_FCNTL_DATA_VERSION\sfile\scontrol +D 2018-07-18T19:09:07.674 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -461,7 +461,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 8613af9c5ba1503bc68f4e9432c6c024e0fdafdc791575c50f380f73ec91189f F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b -F src/main.c a67aa346d68608a449aca06a975056c4a5b6c193290e09539efaeb3664ed3707 +F src/main.c 9c8ef68bd3779d493d632946b3a65156b2e636ad2c7a1b7cd1450e87dc0c6a7d F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -484,7 +484,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c c4269e3481aa3cc5325a52b2d2663bf80f0c6eb0b0adfef7691cd6b113619eb9 +F src/pager.c 29c48653efacf4f3a0b0e193515b789a1e9eee7d232816704cef95216906baa3 F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 F src/parse.y 3bd43415ea974b9921b0ff2c0bd3e9100f6e501ede0b6d3b90cca2ab6af25485 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd @@ -498,8 +498,8 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 2e9661d4424f43ccf595c4a7b4acdf32db523c0f6b31cbd62e6e5a2f43118981 -F src/shell.c.in f1c79c537117ee61317a5ed85cdbcb854998cd690eb34ab803779358a2ace780 -F src/sqlite.h.in 679a25353c90ccd83b16207888704d09bc0e5d5bd6fc1828e7ac653336ee4575 +F src/shell.c.in 239aee5570703fcbf9e6bec176a3ba7704bf327515f9f0dbd2498f00746e82b6 +F src/sqlite.h.in 6203acde410e38d96ffb24e9b6349f87eb80914ba5676466ac5d8478b6b8f144 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h c2ceebe60d1d2e11674b90c8b55fdffd91386ce8d7ae38613fbcc61659b8fcac @@ -507,7 +507,7 @@ F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce -F src/test1.c ca6bdbbffcf8322de014570741c0d627e81d441b9e6464cc349538bd899ef2ca +F src/test1.c 335740ddc632c0b54765b6fd373da7f76a397adde3ded3592390dd1e5fb0dd55 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 @@ -749,6 +749,7 @@ F test/csv01.test 6e1445b3207d574cff22fc41a8e549dfcf2466ee90546ada97d22a90fa89eb F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3 F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856 F test/cursorhint2.test 0078ae1ded4afcf5eb80d06e3a72b6e1c3f1a646aab26eeb583b0a9ec6f0d56e +F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8 F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373 F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10 F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e @@ -1749,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2e0357c2ed30927921cd17129e348a18a6f3fd086d1fc0a42756036b321a084d -R 471d432eb2ed159696aafa5a0bf72e5a +P 4c70ea5b0e2a512c6a46ac1f14397720e8c8556875701e78c30b19f850c24f55 +R 77c9c3d812b42dbbcdaf40ac46fb4612 U drh -Z 5df8cf4ea35c08c158f5d1145417612b +Z 68e40ab59c72a085fa81a9bdc778d1c6 diff --git a/manifest.uuid b/manifest.uuid index f477a0b101..0d7d2629fa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c70ea5b0e2a512c6a46ac1f14397720e8c8556875701e78c30b19f850c24f55 \ No newline at end of file +a5087c5c87ad65f92e3bc96bbc84afb43faf10ab6b9ed3ba16304b5c60ad069f \ No newline at end of file diff --git a/src/main.c b/src/main.c index e0b1c23ad2..9c10cab6ae 100644 --- a/src/main.c +++ b/src/main.c @@ -3711,6 +3711,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; + }else if( op==SQLITE_FCNTL_DATA_VERSION ){ + *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager); + rc = SQLITE_OK; }else{ rc = sqlite3OsFileControl(fd, op, pArg); } diff --git a/src/pager.c b/src/pager.c index 65591632ab..4794c5f73f 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1764,7 +1764,6 @@ static void pager_reset(Pager *pPager){ ** Return the pPager->iDataVersion value */ u32 sqlite3PagerDataVersion(Pager *pPager){ - assert( pPager->eState>PAGER_OPEN ); return pPager->iDataVersion; } diff --git a/src/shell.c.in b/src/shell.c.in index 66c0c5b67e..ab1ec6af71 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4354,6 +4354,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ "SELECT total(length(sql)) FROM %s" }, }; int i; + unsigned iDataVersion; char *zSchemaTab; char *zDb = nArg>=2 ? azArg[1] : "main"; sqlite3_stmt *pStmt = 0; @@ -4406,6 +4407,8 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val); } sqlite3_free(zSchemaTab); + sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion); + utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion); return 0; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 22c5339bdc..4e37136058 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1073,6 +1073,25 @@ struct sqlite3_io_methods { ** a file lock using the xLock or xShmLock methods of the VFS to wait ** for up to M milliseconds before failing, where M is the single ** unsigned integer parameter. +** +**
  • [[SQLITE_FCNTL_DATA_VERSION]] +** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to +** a database file. The argument is a pointer to a 32-bit unsigned integer. +** The "data version" for the pager is written into the pointer. The +** "data version" changes whenever any change occurs to the corresponding +** database file, either through SQL statements on the same database +** connection, or through transactions committed by separate database +** connections possibly in other processes. The [sqlite3_total_changes()] +** interface can be used to find if any database on the connection has changed, +** but that interface response to changes on TEMP as well as MAIN and does +** not provide a mechanism to detect changes to MAIN only. Also, the +** [sqlite3_total_changes()] interface response to internal changes only and +** omits changes made by other database connections. The +** [PRAGMA data_version] command provide a mechanism to detect changes to +** a single attached database that occur due to other database connections, +** but omits changes implemented by the database connection for which it is +** called. This file control is the only mechanism to detect changes that +** happen either internally or externally on a single database. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1108,6 +1127,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 #define SQLITE_FCNTL_LOCK_TIMEOUT 34 +#define SQLITE_FCNTL_DATA_VERSION 35 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -2304,6 +2324,13 @@ int sqlite3_changes(sqlite3*); ** count, but those made as part of REPLACE constraint resolution are ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers ** are not counted. +** +** This the [sqlite3_total_changes(D)] interface only reports the number +** of rows that changed due to SQL statement run against database +** connection D. Any changes by other database connections are ignored. +** To detect changes against a database file from other database +** connections use the [PRAGMA data_version] command or the +** [SQLITE_FCNTL_DATA_VERSION] [file control]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value @@ -2315,6 +2342,7 @@ int sqlite3_changes(sqlite3*); **
  • the [count_changes pragma] **
  • the [changes() SQL function] **
  • the [data_version pragma] +**
  • the [SQLITE_FCNTL_DATA_VERSION] [file control] ** */ int sqlite3_total_changes(sqlite3*); @@ -7087,6 +7115,7 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files ** METHOD: sqlite3 +** KEYWORDS: {file control} ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated @@ -7101,11 +7130,18 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** the xFileControl method. ^The return value of the xFileControl ** method becomes the return value of this routine. ** +** A few opcodes for [sqlite3_file_control()] are handled directly +** by the SQLite core and never invoke the +** sqlite3_io_methods.xFileControl method. ** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes ** a pointer to the underlying [sqlite3_file] object to be written into -** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER] -** case is a short-circuit path which does not actually invoke the -** underlying sqlite3_io_methods.xFileControl method. +** the space pointed to by the 4th parameter. The +** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns +** the [sqlite3_file] object associated with the journal file instead of +** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns +** a pointer to the underlying [sqlite3_vfs] object for the file. +** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter +** from the pager. ** ** ^If the second parameter (zDbName) does not match the name of any ** open database file, then SQLITE_ERROR is returned. ^This error diff --git a/src/test1.c b/src/test1.c index 127650537d..9ffc2e2a82 100644 --- a/src/test1.c +++ b/src/test1.c @@ -5684,6 +5684,44 @@ static int SQLITE_TCLAPI file_control_lasterrno_test( return TCL_OK; } +/* +** tclcmd: file_control_data_version DB DBNAME +** +** This TCL command runs the sqlite3_file_control with the +** SQLITE_FCNTL_DATA_VERSION opcode, returning the result. +*/ +static int SQLITE_TCLAPI file_control_data_version( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + unsigned int iVers; /* data version */ + char *zDb; /* Db name ("main", "temp" etc.) */ + sqlite3 *db; /* Database handle */ + int rc; /* file_control() return code */ + char zBuf[100]; + + if( objc!=3 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB [DBNAME]"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ + return TCL_ERROR; + } + zDb = objc==3 ? Tcl_GetString(objv[2]) : NULL; + + rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_DATA_VERSION, (void *)&iVers); + if( rc ){ + Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); + return TCL_ERROR; + }else{ + sqlite3_snprintf(sizeof(zBuf),zBuf,"%u",iVers); + Tcl_SetResult(interp, (char *)zBuf, TCL_VOLATILE); + return TCL_OK; + } +} + /* ** tclcmd: file_control_chunksize_test DB DBNAME SIZE ** @@ -7700,6 +7738,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, { "file_control_chunksize_test", file_control_chunksize_test, 0 }, { "file_control_sizehint_test", file_control_sizehint_test, 0 }, + { "file_control_data_version", file_control_data_version, 0 }, #if SQLITE_OS_WIN { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, { "file_control_win32_get_handle", file_control_win32_get_handle, 0 }, diff --git a/test/dataversion1.test b/test/dataversion1.test new file mode 100644 index 0000000000..55f7aada0c --- /dev/null +++ b/test/dataversion1.test @@ -0,0 +1,87 @@ +# 2018-07-18 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test case for SQLITE_FCNTL_DATA_VERSION +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Construct a database and get its initial data version +sqlite3 db test.db +do_test dataversion1-100 { + db eval { + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES(99); + SELECT * FROM t1; + } +} {99} +set dv1 [file_control_data_version db main] + +# The data version does not change by ATTACH or by changes to +# other schemas within the same connection. +# +do_test dataversion1-101 { + db eval { + ATTACH ':memory:' AS aux1; + CREATE TABLE aux1.t2(y); + CREATE TEMP TABLE t3(z); + } + file_control_data_version db main +} $dv1 + +# The data version does change when SQL modifies the table +do_test dataversion1-110 { + db eval { + UPDATE t1 SET x=x+1; + } + set dv2 [file_control_data_version db] + expr {$::dv1==$dv2} +} {0} + +# But the data version is constant if there are changes to other +# schemas +set dv1 [file_control_data_version db main] +do_test dataversion1-120 { + db eval { + UPDATE t2 SET y=y+1; + } + file_control_data_version db +} $dv1 + +# Changes to the database via another connection are not detected +# until there is a read transaction. +# +sqlite3 db2 test.db +do_test dataversion1-130 { + db2 eval { + SELECT * FROM t1 + } +} {100} +do_test dataversion1-131 { + file_control_data_version db +} $dv1 +do_test dataversion1-132 { + db2 eval { + UPDATE t1 SET x=x+1; + } + set dv2 [file_control_data_version db] + expr {$::dv1==$dv2} +} {1} +do_test dataversion1-133 { + db eval {SELECT * FROM t1} + set dv2 [file_control_data_version db] + expr {$::dv1==$dv2} +} {0} + + + +finish_test From ea933f07b0a59d45ae1f53eae6126c198e234518 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 19 Jul 2018 11:44:02 +0000 Subject: [PATCH 017/260] Experimental fix for resetting databases that have been deemed read-only due to a corrupt "read-version" header field. FossilOrigin-Name: e2394002d02754bb45d56e805df9bc5a2ef0d14e5d94262c1f8ab7643bc27c8f --- manifest | 19 +++++++++++-------- manifest.uuid | 2 +- src/btree.c | 6 ++++++ test/resetdb.test | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 31443dc45a..7ba93031ab 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_FCNTL_DATA_VERSION\sfile\scontrol -D 2018-07-18T19:09:07.674 +C Experimental\sfix\sfor\sresetting\sdatabases\sthat\shave\sbeen\sdeemed\sread-only\sdue\nto\sa\scorrupt\s"read-version"\sheader\sfield. +D 2018-07-19T11:44:02.889 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -438,7 +438,7 @@ F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c d9dcccd604aa8b128a20b195001570a46c354525d7abe165b1256ba1ffc307d1 +F src/btree.c 4b91880ab0f6595c52f13b17f3ef269062073341c254311b3c38925db5b89b9a F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c d8f6ac1e9e484eb3f3921a8336d3dc6c87273d9db8729702162ef045997a1463 @@ -1181,7 +1181,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/releasetest.tcl 769892f81050b3f59c66f274d478d855159b474ea27019dec82f1215c0b91ef7 x -F test/resetdb.test c70ac9b8ceef3ccb094e22df19d5e7c283b1fb2f729c544c5c211aa58057f4aa +F test/resetdb.test b7df373608a56b1fc7a9ed942e8d91fa3ad25b87b63bdb36c88811ad1d0a9c90 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6 @@ -1750,7 +1750,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4c70ea5b0e2a512c6a46ac1f14397720e8c8556875701e78c30b19f850c24f55 -R 77c9c3d812b42dbbcdaf40ac46fb4612 -U drh -Z 68e40ab59c72a085fa81a9bdc778d1c6 +P a5087c5c87ad65f92e3bc96bbc84afb43faf10ab6b9ed3ba16304b5c60ad069f +R cc038e87dc659a807799369c4759d0af +T *branch * exp-dbreset-fix +T *sym-exp-dbreset-fix * +T -sym-trunk * +U dan +Z c2723926c6d15ad4b82159593e2d431c diff --git a/manifest.uuid b/manifest.uuid index 0d7d2629fa..4d55cea609 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a5087c5c87ad65f92e3bc96bbc84afb43faf10ab6b9ed3ba16304b5c60ad069f \ No newline at end of file +e2394002d02754bb45d56e805df9bc5a2ef0d14e5d94262c1f8ab7643bc27c8f \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 553817e0f8..269967ec9a 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3316,6 +3316,12 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ } assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); + if( (p->db->flags & SQLITE_ResetDatabase) + && sqlite3PagerIsreadonly(pBt->pPager)==0 + ){ + pBt->btsFlags &= ~BTS_READ_ONLY; + } + /* Write transactions are not possible on a read-only database */ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ rc = SQLITE_READONLY; diff --git a/test/resetdb.test b/test/resetdb.test index 55a7ef00d9..ae84764986 100644 --- a/test/resetdb.test +++ b/test/resetdb.test @@ -207,5 +207,39 @@ do_execsql_test -db db2 630 { SELECT * FROM sqlite_master } {} +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 700 { + PRAGMA page_size=512; + CREATE TABLE t1(a,b,c); + CREATE INDEX t1a ON t1(a); + CREATE INDEX t1bc ON t1(b,c); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10) + INSERT INTO t1(a,b,c) SELECT x, randomblob(100),randomblob(100) FROM c; + PRAGMA page_count; + PRAGMA integrity_check; +} {19 ok} + +do_execsql_test 710 { + UPDATE sqlite_dbpage SET data= + X'53514C69746520666F726D61742033000200030100402020000000000000001300000000000000000000000300000004000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000D00000003017C0001D801AC017C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E03061715110145696E6465787431626374310443524541544520494E4445582074316263204F4E20743128622C63292A0206171311013F696E64657874316174310343524541544520494E44455820743161204F4E20743128612926010617111101397461626C657431743102435245415445205441424C4520743128612C622C6329' WHERE pgno=1; +} + +do_execsql_test 720 { + PRAGMA integrity_check; +} {ok} + +do_test 730 { + sqlite3_db_config db RESET_DB 1 + db eval VACUUM + sqlite3_db_config db RESET_DB 0 +} {0} + +do_execsql_test 740 { + PRAGMA page_count; + PRAGMA integrity_check; +} {1 ok} + finish_test From b0b0230082499d74998b70ccd6782f9e4a160a25 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 19 Jul 2018 15:27:35 +0000 Subject: [PATCH 018/260] Avoid a branch in the commit logic that is unreachable when compiled without SQLITE_ENABLE_BATCH_ATOMIC_WRITE. FossilOrigin-Name: 271b8980c3bcd0403a40aec26681ec111be1d88d2d5d35199a85a10f09ad6920 --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/pager.c | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 9e4893de63..c389802f23 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sthe\sVACUUM\sfollowing\sSQLITE_DBCONFIG_RESET_DATABASE\sto\sproceed\seven\nif\sthe\swrite-version\sin\sthe\sheader\sindicates\sthat\sthe\sdatabase\sfile\sis\snot\nwritable. -D 2018-07-19T14:40:41.861 +C Avoid\sa\sbranch\sin\sthe\scommit\slogic\sthat\sis\sunreachable\swhen\scompiled\nwithout\sSQLITE_ENABLE_BATCH_ATOMIC_WRITE. +D 2018-07-19T15:27:35.652 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -484,7 +484,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 29c48653efacf4f3a0b0e193515b789a1e9eee7d232816704cef95216906baa3 +F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 F src/parse.y 3bd43415ea974b9921b0ff2c0bd3e9100f6e501ede0b6d3b90cca2ab6af25485 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd @@ -1750,8 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a5087c5c87ad65f92e3bc96bbc84afb43faf10ab6b9ed3ba16304b5c60ad069f e2394002d02754bb45d56e805df9bc5a2ef0d14e5d94262c1f8ab7643bc27c8f -R cc038e87dc659a807799369c4759d0af -T +closed e2394002d02754bb45d56e805df9bc5a2ef0d14e5d94262c1f8ab7643bc27c8f +P 3dca8b9d5ab1f35f17fc527d8f2a20b6bac989d1406c883d5b4d6719953ef6b4 +R 9d87f8b3543e4885b3df693f32810d50 U drh -Z ef1b233b53118b1e787b272f555289dd +Z 8ce51e79b3fa48485d8d0335e63cb9ef diff --git a/manifest.uuid b/manifest.uuid index c1c9abfdbb..16f747d62e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3dca8b9d5ab1f35f17fc527d8f2a20b6bac989d1406c883d5b4d6719953ef6b4 \ No newline at end of file +271b8980c3bcd0403a40aec26681ec111be1d88d2d5d35199a85a10f09ad6920 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 4794c5f73f..9fafa17cb0 100644 --- a/src/pager.c +++ b/src/pager.c @@ -6515,6 +6515,7 @@ int sqlite3PagerCommitPhaseOne( rc = sqlite3JournalCreate(pPager->jfd); if( rc!=SQLITE_OK ){ sqlite3OsClose(pPager->jfd); + goto commit_phase_one_exit; } bBatch = 0; }else{ @@ -6523,10 +6524,9 @@ int sqlite3PagerCommitPhaseOne( } #endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ - if( bBatch==0 && rc==SQLITE_OK ){ + if( bBatch==0 ){ rc = pager_write_pagelist(pPager, pList); } - if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_IOERR_BLOCKED ); goto commit_phase_one_exit; From 91d5866eb6fad7341805ec1004b7b842c505a330 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 20 Jul 2018 13:39:28 +0000 Subject: [PATCH 019/260] Enhanced detection of problems on the freelist and on overflow list in PRAGMA integrity_check. FossilOrigin-Name: 11e58f5b37d99848978007d834d187c262d904eb9d58924742e028d7cb324e64 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btree.c | 24 ++++++++++-------------- test/corrupt2.test | 4 ++-- test/corrupt3.test | 12 ++++++++---- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/manifest b/manifest index c389802f23..0eb200455e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sa\sbranch\sin\sthe\scommit\slogic\sthat\sis\sunreachable\swhen\scompiled\nwithout\sSQLITE_ENABLE_BATCH_ATOMIC_WRITE. -D 2018-07-19T15:27:35.652 +C Enhanced\sdetection\sof\sproblems\son\sthe\sfreelist\sand\son\soverflow\slist\sin\nPRAGMA\sintegrity_check. +D 2018-07-20T13:39:28.100 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -438,7 +438,7 @@ F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 4b91880ab0f6595c52f13b17f3ef269062073341c254311b3c38925db5b89b9a +F src/btree.c 76395ea8cb88e7075af1ba6465b1d2751b92cbaa0bcbc8618b6e1787c61c10d9 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c d8f6ac1e9e484eb3f3921a8336d3dc6c87273d9db8729702162ef045997a1463 @@ -711,8 +711,8 @@ F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9 F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97 -F test/corrupt2.test b6281ceadd6114d55e89b25e01c617af930dda71567f6a0996a719c385ac142e -F test/corrupt3.test e676f478fe602915d721472811f6f410b75ddc7e +F test/corrupt2.test fdfdffab9bc37d6d173f56ffb82472206f11dd4a68caad9360ac4db2eddb34c8 +F test/corrupt3.test f95d7bf78109e0b84eb285a787ce91a3fd6a2dd7d0cb55882abff3bdc081a57e F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107 F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568 @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3dca8b9d5ab1f35f17fc527d8f2a20b6bac989d1406c883d5b4d6719953ef6b4 -R 9d87f8b3543e4885b3df693f32810d50 +P 271b8980c3bcd0403a40aec26681ec111be1d88d2d5d35199a85a10f09ad6920 +R 12f9a839a98e388a878641cfa671f691 U drh -Z 8ce51e79b3fa48485d8d0335e63cb9ef +Z 9f541998dc72c18645337f8a0e2a985a diff --git a/manifest.uuid b/manifest.uuid index 16f747d62e..6617ca082a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -271b8980c3bcd0403a40aec26681ec111be1d88d2d5d35199a85a10f09ad6920 \ No newline at end of file +11e58f5b37d99848978007d834d187c262d904eb9d58924742e028d7cb324e64 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 269967ec9a..45ff2bfe8f 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9337,8 +9337,7 @@ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ - if( iPage==0 ) return 1; - if( iPage>pCheck->nPage ){ + if( iPage>pCheck->nPage || iPage==0 ){ checkAppendMsg(pCheck, "invalid page number %d", iPage); return 1; } @@ -9393,17 +9392,12 @@ static void checkList( ){ int i; int expected = N; - int iFirst = iPage; - while( N-- > 0 && pCheck->mxErr ){ + int nErrAtStart = pCheck->nErr; + while( iPage!=0 && pCheck->mxErr ){ DbPage *pOvflPage; unsigned char *pOvflData; - if( iPage<1 ){ - checkAppendMsg(pCheck, - "%d of %d pages missing from overflow list starting at %d", - N+1, expected, iFirst); - break; - } if( checkRef(pCheck, iPage) ) break; + N--; if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ checkAppendMsg(pCheck, "failed to get page %d", iPage); break; @@ -9447,10 +9441,12 @@ static void checkList( #endif iPage = get4byte(pOvflData); sqlite3PagerUnref(pOvflPage); - - if( isFreeList && N<(iPage!=0) ){ - checkAppendMsg(pCheck, "free-page count in header is too small"); - } + } + if( N && nErrAtStart==pCheck->nErr ){ + checkAppendMsg(pCheck, + "%s is %d but should be %d", + isFreeList ? "size" : "overflow list length", + expected-N, expected); } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ diff --git a/test/corrupt2.test b/test/corrupt2.test index 4b58da1cc1..9512d0f242 100644 --- a/test/corrupt2.test +++ b/test/corrupt2.test @@ -591,7 +591,7 @@ do_test 14.2 { do_execsql_test 14.3 { PRAGMA integrity_check; } {{*** in database main *** -Main freelist: free-page count in header is too small}} +Main freelist: size is 3 but should be 2}} # Use 2 of the free pages on the free-list. # @@ -603,7 +603,7 @@ do_execsql_test 14.4 { do_execsql_test 14.5 { PRAGMA integrity_check; } {{*** in database main *** -Page 3 is never used}} +Main freelist: size is 1 but should be 0}} finish_test diff --git a/test/corrupt3.test b/test/corrupt3.test index 85139420b8..3c911dadb6 100644 --- a/test/corrupt3.test +++ b/test/corrupt3.test @@ -67,8 +67,7 @@ do_test corrupt3-1.5 { integrity_check corrupt3-1.6 # Make the overflow chain loop back on itself. See if the -# corruption is detected. (Actually, the last pointer in -# an overflow chain is ignored, so this is not an error.) +# corruption is detected. # do_test corrupt3-1.7 { db close @@ -78,7 +77,12 @@ do_test corrupt3-1.7 { SELECT x FROM t1 } } [list 0 $bigstring] -integrity_check corrupt3-1.8 +do_test corrupt3-1.8 { + catchsql { + PRAGMA integrity_check + } +} {0 {{*** in database main *** +On tree page 2 cell 0: 2nd reference to page 3}}} # Change the pointer for the first page of the overflow # change to be a non-existant page. @@ -111,7 +115,7 @@ do_test corrupt3-1.12 { PRAGMA integrity_check } } {0 {{*** in database main *** -On tree page 2 cell 0: 1 of 1 pages missing from overflow list starting at 0 +On tree page 2 cell 0: overflow list length is 0 but should be 1 Page 3 is never used}}} finish_test From 040d77aa715cf24697e48e47a20b2302e3e48d27 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 20 Jul 2018 15:44:09 +0000 Subject: [PATCH 020/260] New checked in PRAGMA integrity_check to validate the autovacuum settings in the header. FossilOrigin-Name: a4663f09c91d1381a831f61a2b8e8a113eb6083932c4aea2ad0c011ece1418c5 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 0eb200455e..7867f7d9f5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhanced\sdetection\sof\sproblems\son\sthe\sfreelist\sand\son\soverflow\slist\sin\nPRAGMA\sintegrity_check. -D 2018-07-20T13:39:28.100 +C New\schecked\sin\sPRAGMA\sintegrity_check\sto\svalidate\sthe\sautovacuum\ssettings\nin\sthe\sheader. +D 2018-07-20T15:44:09.800 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -438,7 +438,7 @@ F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 76395ea8cb88e7075af1ba6465b1d2751b92cbaa0bcbc8618b6e1787c61c10d9 +F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c d8f6ac1e9e484eb3f3921a8336d3dc6c87273d9db8729702162ef045997a1463 @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 271b8980c3bcd0403a40aec26681ec111be1d88d2d5d35199a85a10f09ad6920 -R 12f9a839a98e388a878641cfa671f691 +P 11e58f5b37d99848978007d834d187c262d904eb9d58924742e028d7cb324e64 +R c0acde69723fe0b5e3fbc25297e0d544 U drh -Z 9f541998dc72c18645337f8a0e2a985a +Z 0f08918d98de0383295ceae1a107394a diff --git a/manifest.uuid b/manifest.uuid index 6617ca082a..4205d45f50 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -11e58f5b37d99848978007d834d187c262d904eb9d58924742e028d7cb324e64 \ No newline at end of file +a4663f09c91d1381a831f61a2b8e8a113eb6083932c4aea2ad0c011ece1418c5 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 45ff2bfe8f..2fb5285474 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9840,6 +9840,24 @@ char *sqlite3BtreeIntegrityCheck( /* Check all the tables. */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + int mx = 0; + int mxInHdr; + for(i=0; (int)ipPage1->aData[52]); + if( mx!=mxInHdr ){ + checkAppendMsg(&sCheck, + "max rootpage (%d) disagrees with header (%d)", + mx, mxInHdr + ); + } + }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){ + checkAppendMsg(&sCheck, + "incremental_vacuum enabled with a max rootpage of zero" + ); + } +#endif testcase( pBt->db->flags & SQLITE_CellSizeCk ); pBt->db->flags &= ~SQLITE_CellSizeCk; for(i=0; (int)i Date: Fri, 20 Jul 2018 19:24:02 +0000 Subject: [PATCH 021/260] Change the SQLITE_Stat34 bit of the optimization test-control so that it prevents STAT4 data from being used but allows it to be loaded into the Index objects. This permits STAT4 to be turned on and off on a per-statement basis. FossilOrigin-Name: 489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/analyze.c | 2 +- src/where.c | 5 ++++- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 7867f7d9f5..0d921a529a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\schecked\sin\sPRAGMA\sintegrity_check\sto\svalidate\sthe\sautovacuum\ssettings\nin\sthe\sheader. -D 2018-07-20T15:44:09.800 +C Change\sthe\sSQLITE_Stat34\sbit\sof\sthe\soptimization\stest-control\sso\sthat\sit\nprevents\sSTAT4\sdata\sfrom\sbeing\sused\sbut\sallows\sit\sto\sbe\sloaded\sinto\sthe\nIndex\sobjects.\s\sThis\spermits\sSTAT4\sto\sbe\sturned\son\sand\soff\son\sa\sper-statement\nbasis. +D 2018-07-20T19:24:02.431 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -432,7 +432,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 6beb476095a4cfeb95ebedb2e5e17894d1687b24fddd5b8761a4de120e0392c6 -F src/analyze.c 91b5e7c0f4a08dbb1f7a24b24e7ab49be8b0a2fd1906a35add62a855d1c0ceb9 +F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab @@ -582,7 +582,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d44a0811afd2155b1157c38b33141d4ac028fda6232485bed664015bb05819ca F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4 -F src/where.c cd6710e24d3d5c29d6890df93865c22d896453907eb83988c505a3098e90179f +F src/where.c 2d313b446758317b60626763d0e1285e04b04c061ce94945dcfffad9525badc1 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 F src/wherecode.c fe23a55294b4c94bf658d2a6eb7996170dd563bf33af4c3e5d71aff3483e4b08 F src/whereexpr.c 571618c67a3eb5ce0f1158c2792c1aee9b4a4a264392fc4fb1b35467f80abf9a @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 11e58f5b37d99848978007d834d187c262d904eb9d58924742e028d7cb324e64 -R c0acde69723fe0b5e3fbc25297e0d544 +P a4663f09c91d1381a831f61a2b8e8a113eb6083932c4aea2ad0c011ece1418c5 +R 92bbbb13f79b62d8c050503e495d0c69 U drh -Z 0f08918d98de0383295ceae1a107394a +Z 3d92f0bafb408ca7e67c911625997c83 diff --git a/manifest.uuid b/manifest.uuid index 4205d45f50..b1f58c2ec2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a4663f09c91d1381a831f61a2b8e8a113eb6083932c4aea2ad0c011ece1418c5 \ No newline at end of file +489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 37b1eec0c7..5075b57867 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1914,7 +1914,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ /* Load the statistics from the sqlite_stat4 table. */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ + if( rc==SQLITE_OK ){ db->lookaside.bDisable++; rc = loadStat4(db, sInfo.zDatabase); db->lookaside.bDisable--; diff --git a/src/where.c b/src/where.c index aa7567fa83..d4f88a27af 100644 --- a/src/where.c +++ b/src/where.c @@ -1436,7 +1436,9 @@ static int whereRangeScanEst( Index *p = pLoop->u.btree.pIndex; int nEq = pLoop->u.btree.nEq; - if( p->nSample>0 && nEqnSampleCol ){ + if( p->nSample>0 && nEqnSampleCol + && OptimizationEnabled(pParse->db, SQLITE_Stat34) + ){ if( nEq==pBuilder->nRecValid ){ UnpackedRecord *pRec = pBuilder->pRec; tRowcnt a[2]; @@ -2584,6 +2586,7 @@ static int whereLoopAddBtreeIndex( && pProbe->nSample && pNew->u.btree.nEq<=pProbe->nSampleCol && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) + && OptimizationEnabled(db, SQLITE_Stat34) ){ Expr *pExpr = pTerm->pExpr; if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ From 0fc2da3f7982129bc1dbe3b04d8e003c12384221 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 20 Jul 2018 20:56:22 +0000 Subject: [PATCH 022/260] When dropping a view, skip trying to delete from 'sqlite_stat*'. FossilOrigin-Name: 2f5be3a2ddf469bd1b37b9e357545ce872b90c479a07094de2101d0a43ad70a4 --- manifest | 19 +++++++++++-------- manifest.uuid | 2 +- src/build.c | 6 ++++-- test/view.test | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 0d921a529a..1f8cc3f219 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sSQLITE_Stat34\sbit\sof\sthe\soptimization\stest-control\sso\sthat\sit\nprevents\sSTAT4\sdata\sfrom\sbeing\sused\sbut\sallows\sit\sto\sbe\sloaded\sinto\sthe\nIndex\sobjects.\s\sThis\spermits\sSTAT4\sto\sbe\sturned\son\sand\soff\son\sa\sper-statement\nbasis. -D 2018-07-20T19:24:02.431 +C When\sdropping\sa\sview,\sskip\strying\sto\sdelete\sfrom\s'sqlite_stat*'. +D 2018-07-20T20:56:22.700 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -441,7 +441,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 -F src/build.c d8f6ac1e9e484eb3f3921a8336d3dc6c87273d9db8729702162ef045997a1463 +F src/build.c 80cd1c21e0c4fc92c6d57bdd4343e81557a0bfde7d883e00937f50e7733d78a6 F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48 @@ -1540,7 +1540,7 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2 F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab +F test/view.test 42b97dcd3d7c2f5f9439e41b0983e0c6a5718d8b874e9d5e82d3cd25a50ffcf7 F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e @@ -1750,7 +1750,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a4663f09c91d1381a831f61a2b8e8a113eb6083932c4aea2ad0c011ece1418c5 -R 92bbbb13f79b62d8c050503e495d0c69 -U drh -Z 3d92f0bafb408ca7e67c911625997c83 +P 489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a +R 3f6b04b00398c1c2ef246fa87ef97b67 +T *branch * dropViewNoStat +T *sym-dropViewNoStat * +T -sym-trunk * +U mistachkin +Z 38c445a25934f5d7f055153013691fd1 diff --git a/manifest.uuid b/manifest.uuid index b1f58c2ec2..70bc9a3656 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a \ No newline at end of file +2f5be3a2ddf469bd1b37b9e357545ce872b90c479a07094de2101d0a43ad70a4 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 6b761da02a..ba43e76a58 100644 --- a/src/build.c +++ b/src/build.c @@ -2662,8 +2662,10 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ v = sqlite3GetVdbe(pParse); if( v ){ sqlite3BeginWriteOperation(pParse, 1, iDb); - sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); - sqlite3FkDropTable(pParse, pName, pTab); + if( !isView ){ + sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); + sqlite3FkDropTable(pParse, pName, pTab); + } sqlite3CodeDropTable(pParse, pTab, iDb, isView); } diff --git a/test/view.test b/test/view.test index 694b3c6abd..857d077345 100644 --- a/test/view.test +++ b/test/view.test @@ -674,5 +674,27 @@ do_test view-22.2 { lsort [array names x] } {{} * :1 :2} +do_test view-25.1 { + db eval { + CREATE TABLE t25 (x); + INSERT INTO t25 (x) VALUES (1); + ANALYZE; + } + proc authLogDelete {code arg1 arg2 arg3 arg4 args} { + if {$code=="SQLITE_DELETE" && [string match sqlite_stat* $arg1]} { + lappend ::log [list $code $arg1 $arg2 $arg3 $arg4 $args] + } + return SQLITE_OK + } + set log "" + db authorizer ::authLogDelete + db eval {DROP VIEW x1;} + set log +} {} +do_test view-25.2 { + set log "" + db eval {DROP TABLE t25;} + set log +} {{SQLITE_DELETE sqlite_stat1 {} main {} {}}} finish_test From 9676e611b647dc0d871aa3b5632e228c7d9e4679 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 21 Jul 2018 23:15:55 +0000 Subject: [PATCH 023/260] In 'resetdb.test', close a database prior to trying to delete it. FossilOrigin-Name: 45137053a511b976f5447b0668e3f3a636785d242f44b110a1107898e847e95e --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/resetdb.test | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 0d921a529a..494fd0c96f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sSQLITE_Stat34\sbit\sof\sthe\soptimization\stest-control\sso\sthat\sit\nprevents\sSTAT4\sdata\sfrom\sbeing\sused\sbut\sallows\sit\sto\sbe\sloaded\sinto\sthe\nIndex\sobjects.\s\sThis\spermits\sSTAT4\sto\sbe\sturned\son\sand\soff\son\sa\sper-statement\nbasis. -D 2018-07-20T19:24:02.431 +C In\s'resetdb.test',\sclose\sa\sdatabase\sprior\sto\strying\sto\sdelete\sit. +D 2018-07-21T23:15:55.399 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -1181,7 +1181,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/releasetest.tcl 769892f81050b3f59c66f274d478d855159b474ea27019dec82f1215c0b91ef7 x -F test/resetdb.test b7df373608a56b1fc7a9ed942e8d91fa3ad25b87b63bdb36c88811ad1d0a9c90 +F test/resetdb.test d8750cc9d241fc01810d9d333e7b84a2716e8e97170fa796818c86f0ddf83ad9 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6 @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a4663f09c91d1381a831f61a2b8e8a113eb6083932c4aea2ad0c011ece1418c5 -R 92bbbb13f79b62d8c050503e495d0c69 -U drh -Z 3d92f0bafb408ca7e67c911625997c83 +P 489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a +R e84942c529b96d262f5ac6a49ad06eb8 +U mistachkin +Z ec1ae19a2021f5d3e44f3773bdfba892 diff --git a/manifest.uuid b/manifest.uuid index b1f58c2ec2..f1c854d416 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a \ No newline at end of file +45137053a511b976f5447b0668e3f3a636785d242f44b110a1107898e847e95e \ No newline at end of file diff --git a/test/resetdb.test b/test/resetdb.test index ae84764986..5b419d3ae6 100644 --- a/test/resetdb.test +++ b/test/resetdb.test @@ -208,6 +208,7 @@ do_execsql_test -db db2 630 { } {} #------------------------------------------------------------------------- +db2 close reset_db do_execsql_test 700 { From 9a047bb8818bdb844f81ce3ae56af171f97a0811 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 22 Jul 2018 00:45:11 +0000 Subject: [PATCH 024/260] Remove an unused branch in the FK logic. FossilOrigin-Name: 523ff77925f1da361cf31e3fc82bcb1708ed356a2391430ab14ef620c9bf2327 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/fkey.c | 3 ++- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 1f8cc3f219..a41f2dd458 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sdropping\sa\sview,\sskip\strying\sto\sdelete\sfrom\s'sqlite_stat*'. -D 2018-07-20T20:56:22.700 +C Remove\san\sunused\sbranch\sin\sthe\sFK\slogic. +D 2018-07-22T00:45:11.915 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -451,7 +451,7 @@ F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f F src/expr.c bb148f4c45b6e53b5b58a912974253547e8862685cb001fbdfaef0ab24812e6f F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee +F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128 F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a @@ -1750,10 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a -R 3f6b04b00398c1c2ef246fa87ef97b67 -T *branch * dropViewNoStat -T *sym-dropViewNoStat * -T -sym-trunk * -U mistachkin -Z 38c445a25934f5d7f055153013691fd1 +P 2f5be3a2ddf469bd1b37b9e357545ce872b90c479a07094de2101d0a43ad70a4 +R e0000bc54eae37361f9929961ff6e6b2 +U drh +Z 18bbbe031e5d9c4a1f1bd3bf41814fc9 diff --git a/manifest.uuid b/manifest.uuid index 70bc9a3656..9826c9df40 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2f5be3a2ddf469bd1b37b9e357545ce872b90c479a07094de2101d0a43ad70a4 \ No newline at end of file +523ff77925f1da361cf31e3fc82bcb1708ed356a2391430ab14ef620c9bf2327 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 256b19db8a..0f5248fea2 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -710,11 +710,12 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ */ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ sqlite3 *db = pParse->db; - if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){ + if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){ int iSkip = 0; Vdbe *v = sqlite3GetVdbe(pParse); assert( v ); /* VDBE has already been allocated */ + assert( pTab->pSelect==0 ); /* Not a view */ if( sqlite3FkReferences(pTab)==0 ){ /* Search for a deferred foreign key constraint for which this table ** is the child table. If one cannot be found, return without From 1e8487db29c940d07e2826a0663d72047a0104ea Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 22 Jul 2018 06:25:35 +0000 Subject: [PATCH 025/260] In the Win32 VFS, when truncating a file, unmap it first. FossilOrigin-Name: 21510a66dce4d0843ccfe20f092a01f5a52563ef244a94f1d5d2563305cab925 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/os_win.c | 24 ++++++++++++++++++------ src/shell.c.in | 20 ++++++++++++++++++++ src/tclsqlite.c | 21 ++++++++++++++++----- test/mmap1.test | 42 ++++++++++++++++++++++++++++++++++++++++++ test/permutations.test | 2 +- 7 files changed, 108 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 494fd0c96f..fe9fbc9ebb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\s'resetdb.test',\sclose\sa\sdatabase\sprior\sto\strying\sto\sdelete\sit. -D 2018-07-21T23:15:55.399 +C In\sthe\sWin32\sVFS,\swhen\struncating\sa\sfile,\sunmap\sit\sfirst. +D 2018-07-22T06:25:35.628 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -482,7 +482,7 @@ F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 -F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354 +F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 @@ -498,7 +498,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 2e9661d4424f43ccf595c4a7b4acdf32db523c0f6b31cbd62e6e5a2f43118981 -F src/shell.c.in 239aee5570703fcbf9e6bec176a3ba7704bf327515f9f0dbd2498f00746e82b6 +F src/shell.c.in f6ebd05c461805a7c708333cd645e74e0a93560d2118f5adb73a75d8c9cf6b01 F src/sqlite.h.in 6203acde410e38d96ffb24e9b6349f87eb80914ba5676466ac5d8478b6b8f144 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 @@ -506,7 +506,7 @@ F src/sqliteInt.h c2ceebe60d1d2e11674b90c8b55fdffd91386ce8d7ae38613fbcc61659b8fc F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce +F src/tclsqlite.c e0bf71a6d24b8c23393c000abffab05979bbca2a72d0b0f79260e2cf1527fda5 F src/test1.c 335740ddc632c0b54765b6fd373da7f76a397adde3ded3592390dd1e5fb0dd55 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 @@ -1100,7 +1100,7 @@ F test/misc7.test 349855706310f0de6b91645d199f6874f518627fd057743fa4e3689b60d06e F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7 F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795 -F test/mmap1.test d2cfc1635171c434dcff0ece2f1c8e0a658807ce +F test/mmap1.test 9f812fe1461b229020be9b8e4d0898b083a516b33db70892929129b9a35f45e8 F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022 F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93 @@ -1154,7 +1154,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 5c2167e03dc55ff697e11bb3abf10c66ba452e4afb2dbd85a2b144048355300e +F test/permutations.test 728b0f6080da0bc3248b7e7c8c472d9ac9ad7ff01d51712ed3671ef66d66e0f2 F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30 F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 489f3caf5dcc8cace20a0da58ceb32fdea5770ba570fa3c9f712cd35e726846a -R e84942c529b96d262f5ac6a49ad06eb8 +P 45137053a511b976f5447b0668e3f3a636785d242f44b110a1107898e847e95e +R 4d371b6c751e8a4167cbe1e1406e13ab U mistachkin -Z ec1ae19a2021f5d3e44f3773bdfba892 +Z ad8056df2b1c5e2a584433b5604fada6 diff --git a/manifest.uuid b/manifest.uuid index f1c854d416..815d5e8868 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45137053a511b976f5447b0668e3f3a636785d242f44b110a1107898e847e95e \ No newline at end of file +21510a66dce4d0843ccfe20f092a01f5a52563ef244a94f1d5d2563305cab925 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 3eb2f3c612..2a4b613ff8 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -2904,6 +2904,9 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ winFile *pFile = (winFile*)id; /* File handle object */ int rc = SQLITE_OK; /* Return code for this function */ DWORD lastErrno; +#if SQLITE_MAX_MMAP_SIZE>0 + sqlite3_int64 oldMmapSize; +#endif assert( pFile ); SimulateIOError(return SQLITE_IOERR_TRUNCATE); @@ -2919,6 +2922,15 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; } +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFile->pMapRegion ){ + oldMmapSize = pFile->mmapSize; + }else{ + oldMmapSize = 0; + } + winUnmapfile(pFile); +#endif + /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ if( winSeekFile(pFile, nByte) ){ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, @@ -2931,12 +2943,12 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ } #if SQLITE_MAX_MMAP_SIZE>0 - /* If the file was truncated to a size smaller than the currently - ** mapped region, reduce the effective mapping size as well. SQLite will - ** use read() and write() to access data beyond this point from now on. - */ - if( pFile->pMapRegion && nBytemmapSize ){ - pFile->mmapSize = nByte; + if( rc==SQLITE_OK && oldMmapSize>0 ){ + if( oldMmapSize>nByte ){ + winMapfile(pFile, -1); + }else{ + winMapfile(pFile, oldMmapSize); + } } #endif diff --git a/src/shell.c.in b/src/shell.c.in index ab1ec6af71..59ea6aac0d 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -79,12 +79,15 @@ typedef unsigned char u8; #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) # include # include +# define GETPID getpid # if defined(__MINGW32__) # define DIRENT dirent # ifndef S_ISLNK # define S_ISLNK(mode) (0) # endif # endif +#else +# define GETPID (int)GetCurrentProcessId #endif #include #include @@ -8348,6 +8351,23 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ stdin_is_interactive = isatty(0); stdout_is_console = isatty(1); +#if !defined(_WIN32_WCE) + if( getenv("SQLITE_DEBUG_BREAK") ){ + if( isatty(0) && isatty(2) ){ + fprintf(stderr, + "attach debugger to process %d and press any key to continue.\n", + GETPID()); + fgetc(stdin); + }else{ +#if defined(_WIN32) || defined(WIN32) + DebugBreak(); +#elif defined(SIGTRAP) + raise(SIGTRAP); +#endif + } + } +#endif + #if USE_SYSTEM_SQLITE+0!=1 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", diff --git a/src/tclsqlite.c b/src/tclsqlite.c index e5984ec804..d0b4634d45 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -60,6 +60,7 @@ /* Used to get the current process ID */ #if !defined(_WIN32) +# include # include # define GETPID getpid #elif !defined(_WIN32_WCE) @@ -69,6 +70,8 @@ # endif # include # endif +# include +# define isatty(h) _isatty(h) # define GETPID (int)GetCurrentProcessId #endif @@ -3733,11 +3736,19 @@ int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){ #endif #if !defined(_WIN32_WCE) - if( getenv("BREAK") ){ - fprintf(stderr, - "attach debugger to process %d and press any key to continue.\n", - GETPID()); - fgetc(stdin); + if( getenv("SQLITE_DEBUG_BREAK") ){ + if( isatty(0) && isatty(2) ){ + fprintf(stderr, + "attach debugger to process %d and press any key to continue.\n", + GETPID()); + fgetc(stdin); + }else{ +#if defined(_WIN32) || defined(WIN32) + DebugBreak(); +#elif defined(SIGTRAP) + raise(SIGTRAP); +#endif + } } #endif diff --git a/test/mmap1.test b/test/mmap1.test index c7c72c0ab2..d88de1784d 100644 --- a/test/mmap1.test +++ b/test/mmap1.test @@ -276,5 +276,47 @@ do_test 5.5 { sqlite3_finalize $::STMT } SQLITE_OK +# +# The "6.*" tests are designed to test the interaction of mmap with file +# truncation (e.g. on Win32) via the VACUUM command. +# +forcedelete test2.db +sqlite3 db2 test2.db +do_test 6.0 { + db2 eval { + PRAGMA page_size = 4096; + } +} {} +do_test 6.1 { + db2 eval { + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES(randomblob(1000000)); + } +} {} +do_test 6.2 { + db2 eval { + PRAGMA mmap_size = 1048576; + } +} {1048576} +do_test 6.3 { + expr {[file size test2.db] > 1000000} +} {1} +do_test 6.4 { + db2 eval { + DELETE FROM t1; + } +} {} +do_test 6.5 { + expr {[file size test2.db] > 1000000} +} {1} +do_test 6.6 { + db2 eval { + VACUUM; + } +} {} +do_test 6.7 { + expr {[file size test2.db] < 1000000} +} {1} +db2 close finish_test diff --git a/test/permutations.test b/test/permutations.test index 475ad10a65..b7ee91e810 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -105,7 +105,7 @@ set alltests [test_set $alltests -exclude { all.test async.test quick.test veryquick.test memleak.test permutations.test soak.test fts3.test mallocAll.test rtree.test full.test extraquick.test - session.test + session.test rbu.test }] set allquicktests [test_set $alltests -exclude { From 5db9a2b364a43c72a0d262dc6c63483d6b96ee66 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 22 Jul 2018 20:24:38 +0000 Subject: [PATCH 026/260] Fix harmless compiler warning. FossilOrigin-Name: ead4762dfcd284127e60483e14f88aa4f4f034c2e1efb68a150359ba8f307776 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_window.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index fe9fbc9ebb..1df979a971 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sWin32\sVFS,\swhen\struncating\sa\sfile,\sunmap\sit\sfirst. -D 2018-07-22T06:25:35.628 +C Fix\sharmless\scompiler\swarning. +D 2018-07-22T20:24:38.583 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -557,7 +557,7 @@ F src/test_vfs.c 112f1f9271c33c211812e0e681830a84262dac065da58579ff49f9cefec97d4 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1 F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215 -F src/test_window.c 0d19b33e7a262d3b55e85bc0fb84a70f503686cbd769939176162fe866ce7f9e +F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 01e96d1b639c3eb0b9ef90616e766d453935c554f1f7aa86b6db937b79554b97 @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 45137053a511b976f5447b0668e3f3a636785d242f44b110a1107898e847e95e -R 4d371b6c751e8a4167cbe1e1406e13ab +P 21510a66dce4d0843ccfe20f092a01f5a52563ef244a94f1d5d2563305cab925 +R 8ba74e2b6733eeef2af1d3e7be2b3e82 U mistachkin -Z ad8056df2b1c5e2a584433b5604fada6 +Z e0a5249e4c04275baa17e7720a945ccf diff --git a/manifest.uuid b/manifest.uuid index 815d5e8868..4bdfaddafd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -21510a66dce4d0843ccfe20f092a01f5a52563ef244a94f1d5d2563305cab925 \ No newline at end of file +ead4762dfcd284127e60483e14f88aa4f4f034c2e1efb68a150359ba8f307776 \ No newline at end of file diff --git a/src/test_window.c b/src/test_window.c index 1b43c27175..48ab022116 100644 --- a/src/test_window.c +++ b/src/test_window.c @@ -151,7 +151,7 @@ static int SQLITE_TCLAPI test_create_window( if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zName = Tcl_GetString(objv[2]); - pNew = ckalloc(sizeof(TestWindow)); + pNew = (TestWindow*)ckalloc(sizeof(TestWindow)); memset(pNew, 0, sizeof(TestWindow)); pNew->xStep = Tcl_DuplicateObj(objv[3]); pNew->xFinal = Tcl_DuplicateObj(objv[4]); From 8417863fe1691e2234f5476dc83f32e898e7e24b Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 22 Jul 2018 21:08:35 +0000 Subject: [PATCH 027/260] Another minor revision to the 'fulltestonly' set of tests. FossilOrigin-Name: 61f8e2a4c6c146ffba498c8bb40f2b5627fdc14020057eab63b7e900bf88a9ed --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/all.test | 1 + test/permutations.test | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 1df979a971..b3def9f9da 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarning. -D 2018-07-22T20:24:38.583 +C Another\sminor\srevision\sto\sthe\s'fulltestonly'\sset\sof\stests. +D 2018-07-22T21:08:35.561 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -593,7 +593,7 @@ F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 -F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783 +F test/all.test ae17c4412639e16bd797c7617864a16c2badc0035c808ae8246f145e38f8e2f9 F test/alter.test b820ab9dcf85f8e3a65bc8326accb2f0c7be64ef F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3 @@ -1154,7 +1154,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 728b0f6080da0bc3248b7e7c8c472d9ac9ad7ff01d51712ed3671ef66d66e0f2 +F test/permutations.test 5e67065f0d8395d4c43cb41fbce22fd3c9793cb855629e9090abfd41e8d6d858 F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30 F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 21510a66dce4d0843ccfe20f092a01f5a52563ef244a94f1d5d2563305cab925 -R 8ba74e2b6733eeef2af1d3e7be2b3e82 +P ead4762dfcd284127e60483e14f88aa4f4f034c2e1efb68a150359ba8f307776 +R 8ae422253c6d9f82752a102d54b5d17e U mistachkin -Z e0a5249e4c04275baa17e7720a945ccf +Z 633e5c02e757c867c16f916aa50f510f diff --git a/manifest.uuid b/manifest.uuid index 4bdfaddafd..2f1bf1ac02 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ead4762dfcd284127e60483e14f88aa4f4f034c2e1efb68a150359ba8f307776 \ No newline at end of file +61f8e2a4c6c146ffba498c8bb40f2b5627fdc14020057eab63b7e900bf88a9ed \ No newline at end of file diff --git a/test/all.test b/test/all.test index f6e722f2df..f8aac2cd75 100644 --- a/test/all.test +++ b/test/all.test @@ -16,6 +16,7 @@ source $testdir/permutations.test run_test_suite full +run_test_suite rbu run_test_suite no_optimization run_test_suite memsubsys1 run_test_suite memsubsys2 diff --git a/test/permutations.test b/test/permutations.test index b7ee91e810..380dc8ea00 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -122,7 +122,7 @@ set allquicktests [test_set $alltests -exclude { vtab_err.test walslow.test walcrash.test walcrash3.test walthread.test rtree3.test indexfault.test securedel2.test sort3.test sort4.test fts4growth.test fts4growth2.test - bigsort.test rbu.test walprotocol.test mmap4.test fuzzer2.test + bigsort.test walprotocol.test mmap4.test fuzzer2.test walcrash2.test e_fkey.test backup.test fts4merge.test fts4merge2.test fts4merge4.test fts4check.test From 709c822f5e2be7773ac10d31c2e3a304d3af1483 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sun, 22 Jul 2018 21:23:19 +0000 Subject: [PATCH 028/260] Fix more harmless compiler warnings seen with MSVC. FossilOrigin-Name: edab5666f8470b37e6031dfd80e615b1aab95d1d85ccbe4ece1a813f8b3d4d95 --- ext/fts5/fts5_unicode2.c | 2 +- ext/rbu/rbu.c | 12 ++++++------ manifest | 16 ++++++++-------- manifest.uuid | 2 +- tool/lempar.c | 8 ++++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ext/fts5/fts5_unicode2.c b/ext/fts5/fts5_unicode2.c index ad2dd89bb0..8c48aaa49b 100644 --- a/ext/fts5/fts5_unicode2.c +++ b/ext/fts5/fts5_unicode2.c @@ -756,7 +756,7 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){ int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ]; int n = (aFts5UnicodeData[iTbl] >> 5) + i; for(; i<128 && iyytos->stateno ); - yyact = yy_find_shift_action(yymajor,yyact); + yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); if( yyact >= YY_MIN_REDUCE ){ yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, yyminor ParseCTX_PARAM); }else if( yyact <= YY_MAX_SHIFTREDUCE ){ - yy_shift(yypParser,yyact,yymajor,yyminor); + yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif From 78ccff100e3e3369bf4e5ff8369b16aed45775c9 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 23 Jul 2018 10:57:53 +0000 Subject: [PATCH 029/260] Fix the macros used to generate the output of "PRAGMA compile_options" so that they handle valid values for the SQLITE_DEFAULT_LOOKASIDE macro (which contain a "," character). FossilOrigin-Name: 1cc72845f92198f2f6c1d34957921cd8f5bc82eaccab9f844006993f0b8d7a96 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/ctime.c | 8 +++++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 97ce169a1d..2f6e6b2c83 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\smore\sharmless\scompiler\swarnings\sseen\swith\sMSVC. -D 2018-07-22T21:23:19.364 +C Fix\sthe\smacros\sused\sto\sgenerate\sthe\soutput\sof\s"PRAGMA\scompile_options"\sso\sthat\nthey\shandle\svalid\svalues\sfor\sthe\sSQLITE_DEFAULT_LOOKASIDE\smacro\s(which\ncontain\sa\s","\scharacter). +D 2018-07-23T10:57:53.983 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -444,7 +444,7 @@ F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd9 F src/build.c d8f6ac1e9e484eb3f3921a8336d3dc6c87273d9db8729702162ef045997a1463 F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48 +F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 61f8e2a4c6c146ffba498c8bb40f2b5627fdc14020057eab63b7e900bf88a9ed -R 862d4b20f2f5a0218839c7d34462c954 -U mistachkin -Z c89b915c22f0a4aa95abfee0ec86429f +P edab5666f8470b37e6031dfd80e615b1aab95d1d85ccbe4ece1a813f8b3d4d95 +R ab08c735d580e80bb905333523d50aa1 +U dan +Z ed7583eb4e8fa40c5de2beb0e331302c diff --git a/manifest.uuid b/manifest.uuid index dfa7ac9677..cdaa00c77a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -edab5666f8470b37e6031dfd80e615b1aab95d1d85ccbe4ece1a813f8b3d4d95 \ No newline at end of file +1cc72845f92198f2f6c1d34957921cd8f5bc82eaccab9f844006993f0b8d7a96 \ No newline at end of file diff --git a/src/ctime.c b/src/ctime.c index da79f3a350..f408a3b5f0 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -30,6 +30,12 @@ #define CTIMEOPT_VAL_(opt) #opt #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) +/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This +** option requires a separate macro because legal values contain a single +** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */ +#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2 +#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt) + /* ** An array of names of all compile-time options. This array should ** be sorted A-Z. @@ -113,7 +119,7 @@ static const char * const sqlite3azCompileOpt[] = { "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif #ifdef SQLITE_DEFAULT_LOOKASIDE - "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE), + "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE), #endif #if SQLITE_DEFAULT_MEMSTATUS "DEFAULT_MEMSTATUS", From eca5d3a30c513944152c14be5be078958d2f9d44 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 23 Jul 2018 18:32:42 +0000 Subject: [PATCH 030/260] Attempt to improve the documentation for snapshots. No changes to code. FossilOrigin-Name: 46dd076af5880e6e9a7de974758b26bc43d0dc074f8143234038fa9cdcc726ee --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 49 +++++++++++++++++++++++++------------------------ 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/manifest b/manifest index 2f6e6b2c83..ad1bc01e17 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\smacros\sused\sto\sgenerate\sthe\soutput\sof\s"PRAGMA\scompile_options"\sso\sthat\nthey\shandle\svalid\svalues\sfor\sthe\sSQLITE_DEFAULT_LOOKASIDE\smacro\s(which\ncontain\sa\s","\scharacter). -D 2018-07-23T10:57:53.983 +C Attempt\sto\simprove\sthe\sdocumentation\sfor\ssnapshots.\s\sNo\schanges\sto\scode. +D 2018-07-23T18:32:42.936 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -499,7 +499,7 @@ F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 2e9661d4424f43ccf595c4a7b4acdf32db523c0f6b31cbd62e6e5a2f43118981 F src/shell.c.in f6ebd05c461805a7c708333cd645e74e0a93560d2118f5adb73a75d8c9cf6b01 -F src/sqlite.h.in 6203acde410e38d96ffb24e9b6349f87eb80914ba5676466ac5d8478b6b8f144 +F src/sqlite.h.in 37615597574060538595ea0b8ceee2bdcdc5a8757455a703733847654d5957d0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h c2ceebe60d1d2e11674b90c8b55fdffd91386ce8d7ae38613fbcc61659b8fcac @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P edab5666f8470b37e6031dfd80e615b1aab95d1d85ccbe4ece1a813f8b3d4d95 -R ab08c735d580e80bb905333523d50aa1 -U dan -Z ed7583eb4e8fa40c5de2beb0e331302c +P 1cc72845f92198f2f6c1d34957921cd8f5bc82eaccab9f844006993f0b8d7a96 +R 16a67761ea0f9460199dbe384d3dc3c5 +U drh +Z 8f0ee2824f9a0341e2a813799c934102 diff --git a/manifest.uuid b/manifest.uuid index cdaa00c77a..d3a6b0fe80 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1cc72845f92198f2f6c1d34957921cd8f5bc82eaccab9f844006993f0b8d7a96 \ No newline at end of file +46dd076af5880e6e9a7de974758b26bc43d0dc074f8143234038fa9cdcc726ee \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 4e37136058..dc9246812b 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -887,7 +887,8 @@ struct sqlite3_io_methods { **
  • [[SQLITE_FCNTL_PERSIST_WAL]] ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the ** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary -** write ahead log and shared memory files used for transaction control +** write ahead log ([WAL file]) and shared memory +** files used for transaction control ** are automatically deleted when the latest connection to the database ** closes. Setting persistent WAL mode causes those files to persist after ** close. Persisting the files is useful when other processes that do not @@ -8960,7 +8961,6 @@ int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot ** KEYWORDS: {snapshot} {sqlite3_snapshot} -** EXPERIMENTAL ** ** An instance of the snapshot object records the state of a [WAL mode] ** database for some specific point in history. @@ -8977,11 +8977,6 @@ int sqlite3_system_errno(sqlite3*); ** version of the database file so that it is possible to later open a new read ** transaction that sees that historical version of the database rather than ** the most recent version. -** -** The constructor for this object is [sqlite3_snapshot_get()]. The -** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer -** to an historical snapshot (if possible). The destructor for -** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ typedef struct sqlite3_snapshot { unsigned char hidden[48]; @@ -8989,7 +8984,7 @@ typedef struct sqlite3_snapshot { /* ** CAPI3REF: Record A Database Snapshot -** EXPERIMENTAL +** CONSTRUCTOR: sqlite3_snapshot ** ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a ** new [sqlite3_snapshot] object that records the current state of @@ -9028,7 +9023,7 @@ typedef struct sqlite3_snapshot { ** to avoid a memory leak. ** ** The [sqlite3_snapshot_get()] interface is only available when the -** SQLITE_ENABLE_SNAPSHOT compile-time option is used. +** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, @@ -9038,7 +9033,7 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( /* ** CAPI3REF: Start a read transaction on an historical snapshot -** EXPERIMENTAL +** METHOD: sqlite3_snapshot ** ** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a ** read transaction for schema S of @@ -9066,7 +9061,7 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( ** database connection in order to make it ready to use snapshots.) ** ** The [sqlite3_snapshot_open()] interface is only available when the -** SQLITE_ENABLE_SNAPSHOT compile-time option is used. +** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, @@ -9076,20 +9071,20 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( /* ** CAPI3REF: Destroy a snapshot -** EXPERIMENTAL +** DESTRUCTOR: sqlite3_snapshot ** ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. ** The application must eventually free every [sqlite3_snapshot] object ** using this routine to avoid a memory leak. ** ** The [sqlite3_snapshot_free()] interface is only available when the -** SQLITE_ENABLE_SNAPSHOT compile-time option is used. +** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. -** EXPERIMENTAL +** METHOD: sqlite3_snapshot ** ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages ** of two valid snapshot handles. @@ -9108,6 +9103,9 @@ SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); ** Otherwise, this API returns a negative value if P1 refers to an older ** snapshot than P2, zero if the two handles refer to the same database ** snapshot, and a positive value if P1 is a newer snapshot than P2. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_SNAPSHOT] option. */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, @@ -9116,23 +9114,26 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( /* ** CAPI3REF: Recover snapshots from a wal file -** EXPERIMENTAL +** METHOD: sqlite3_snapshot ** -** If all connections disconnect from a database file but do not perform -** a checkpoint, the existing wal file is opened along with the database -** file the next time the database is opened. At this point it is only -** possible to successfully call sqlite3_snapshot_open() to open the most -** recent snapshot of the database (the one at the head of the wal file), -** even though the wal file may contain other valid snapshots for which -** clients have sqlite3_snapshot handles. +** If a [WAL file] remains on disk after all database connections close +** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] +** or because the last process to have the database opened exited without +** calling [sqlite3_close()]) and a new connection is subsequently opened +** on that database and [WAL file], the [sqlite3_snapshot_open()] interface +** will only be able to open the last transaction added to the WAL file +** even though the WAL file contains other valid transactions. ** -** This function attempts to scan the wal file associated with database zDb +** This function attempts to scan the WAL file associated with database zDb ** of database handle db and make all valid snapshots available to ** sqlite3_snapshot_open(). It is an error if there is already a read -** transaction open on the database, or if the database is not a wal mode +** transaction open on the database, or if the database is not a WAL mode ** database. ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_SNAPSHOT] option. */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); From 1489785be5cafe108bbed3dc6760ce0d03871c89 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 23 Jul 2018 18:53:49 +0000 Subject: [PATCH 031/260] Fix typo of 'SQLITE_OMIT_WINDOWFUNC'. FossilOrigin-Name: 8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/treeview.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index ad1bc01e17..6af55b184c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Attempt\sto\simprove\sthe\sdocumentation\sfor\ssnapshots.\s\sNo\schanges\sto\scode. -D 2018-07-23T18:32:42.936 +C Fix\stypo\sof\s'SQLITE_OMIT_WINDOWFUNC'. +D 2018-07-23T18:53:49.829 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -561,7 +561,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 01e96d1b639c3eb0b9ef90616e766d453935c554f1f7aa86b6db937b79554b97 -F src/treeview.c 462346b82a892316a62291791c77e3dd5f1927745fe4a44b846ab4fd16eb28c3 +F src/treeview.c 26c5674083674377b0f41737647802e93ac31f1da89c9b9648501d8a34a44698 F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 F src/update.c 7b7c768dc415a8d2eb9fd2cea8b524cb29cf354f319700e22f94f262d3f507cb F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88 @@ -1750,7 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1cc72845f92198f2f6c1d34957921cd8f5bc82eaccab9f844006993f0b8d7a96 -R 16a67761ea0f9460199dbe384d3dc3c5 -U drh -Z 8f0ee2824f9a0341e2a813799c934102 +P 46dd076af5880e6e9a7de974758b26bc43d0dc074f8143234038fa9cdcc726ee +R 386d9db3da1c3cf3e08fdb519ac6201a +U mistachkin +Z 0f7169e4827257e93fc7e2c2fe7438e0 diff --git a/manifest.uuid b/manifest.uuid index d3a6b0fe80..800ba6509c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -46dd076af5880e6e9a7de974758b26bc43d0dc074f8143234038fa9cdcc726ee \ No newline at end of file +8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc \ No newline at end of file diff --git a/src/treeview.c b/src/treeview.c index d98ad8ffe1..7605fa2cb3 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -508,7 +508,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ if( pFarg ){ sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); } -#ifndef SQLITe_OMIT_WINDOWFUNC +#ifndef SQLITE_OMIT_WINDOWFUNC if( pWin ){ sqlite3TreeViewWindow(pView, pWin, 0); } From da6dc2404a062a02ff5e0c7ab8ba59a5dfe40965 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 23 Jul 2018 21:10:37 +0000 Subject: [PATCH 032/260] First attempt at reducing mutex contention in the unix VFS by providing a separate mutex for each unixInodeInfo object. FossilOrigin-Name: f69afaf00a659cd768a863c5f4a1d527f01187e037240da0ada527cb52c5afe8 --- manifest | 17 ++++++++++------- manifest.uuid | 2 +- src/os_unix.c | 51 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index 6af55b184c..572f99e747 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo\sof\s'SQLITE_OMIT_WINDOWFUNC'. -D 2018-07-23T18:53:49.829 +C First\sattempt\sat\sreducing\smutex\scontention\sin\sthe\sunix\sVFS\sby\sproviding\na\sseparate\smutex\sfor\seach\sunixInodeInfo\sobject. +D 2018-07-23T21:10:37.802 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -481,7 +481,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 +F src/os_unix.c c275a32d1112973457908bee494ae0444468c0b96c07057913ade6d69781dab3 F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 @@ -1750,7 +1750,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 46dd076af5880e6e9a7de974758b26bc43d0dc074f8143234038fa9cdcc726ee -R 386d9db3da1c3cf3e08fdb519ac6201a -U mistachkin -Z 0f7169e4827257e93fc7e2c2fe7438e0 +P 8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc +R acece63ae9d3f4b29a8a0d5614555a1e +T *branch * separate-lock-mutex +T *sym-separate-lock-mutex * +T -sym-trunk * +U drh +Z c02c3e5d8cc1425b437d3294ad5c5e34 diff --git a/manifest.uuid b/manifest.uuid index 800ba6509c..de8e1e71e2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc \ No newline at end of file +f69afaf00a659cd768a863c5f4a1d527f01187e037240da0ada527cb52c5afe8 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 0dd461da0a..48067f4cc3 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1108,15 +1108,29 @@ struct unixFileId { ** A single inode can have multiple file descriptors, so each unixFile ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of unixFile pointing to it. +** +** Mutex rules: +** +** (1) The pLockMutex mutex must be held in order to read or write +** any of the locking fields: +** nShared, nLock, eFileLock, or bProcessLock +** +** (2) When nRef>0, then the following fields are unchanging and can +** be read (but not written) without holding any mutex: +** fileId, pLockMutex +** +** (3) With the exceptions above, all the fields may only be read +** or written while holding the global unixBigLock mutex. */ struct unixInodeInfo { struct unixFileId fileId; /* The lookup key */ - int nShared; /* Number of SHARED locks held */ - unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ - unsigned char bProcessLock; /* An exclusive process lock is held */ + sqlite3_mutex *pLockMutex; /* Hold this mutex for... */ + int nShared; /* Number of SHARED locks held */ + int nLock; /* Number of outstanding file locks */ + unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ + unsigned char bProcessLock; /* An exclusive process lock is held */ int nRef; /* Number of pointers to this structure */ unixShmNode *pShmNode; /* Shared memory associated with this inode */ - int nLock; /* Number of outstanding file locks */ UnixUnusedFd *pUnused; /* Unused file descriptors to close */ unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ unixInodeInfo *pPrev; /* .... doubly linked */ @@ -1273,6 +1287,7 @@ static void releaseInodeInfo(unixFile *pFile){ assert( pInode->pNext->pPrev==pInode ); pInode->pNext->pPrev = pInode->pPrev; } + sqlite3_mutex_free(pInode->pLockMutex); sqlite3_free(pInode); } } @@ -1358,6 +1373,7 @@ static int findInodeInfo( } memset(pInode, 0, sizeof(*pInode)); memcpy(&pInode->fileId, &fileId, sizeof(fileId)); + pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); pInode->nRef = 1; pInode->pNext = inodeList; pInode->pPrev = 0; @@ -1436,7 +1452,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ assert( pFile ); assert( pFile->eFileLock<=SHARED_LOCK ); - unixEnterMutex(); /* Because pFile->pInode is shared across threads */ + sqlite3_mutex_enter(pFile->pInode->pLockMutex); /* Check if a thread in this process holds such a lock */ if( pFile->pInode->eFileLock>SHARED_LOCK ){ @@ -1461,7 +1477,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ } #endif - unixLeaveMutex(); + sqlite3_mutex_leave(pFile->pInode->pLockMutex); OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); *pResOut = reserved; @@ -1527,8 +1543,8 @@ static int osSetPosixAdvisoryLock( static int unixFileLock(unixFile *pFile, struct flock *pLock){ int rc; unixInodeInfo *pInode = pFile->pInode; - assert( unixMutexHeld() ); assert( pInode!=0 ); + assert( sqlite3_mutex_held(pInode->pLockMutex) ); if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){ if( pInode->bProcessLock==0 ){ struct flock lock; @@ -1647,8 +1663,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){ /* This mutex is needed because pFile->pInode is shared across threads */ - unixEnterMutex(); pInode = pFile->pInode; + sqlite3_mutex_enter(pInode->pLockMutex); /* If some thread using this PID has a lock via a different unixFile* ** handle that precludes the requested lock, return BUSY. @@ -1791,7 +1807,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ } end_lock: - unixLeaveMutex(); + sqlite3_mutex_leave(pInode->pLockMutex); OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), rc==SQLITE_OK ? "ok" : "failed")); return rc; @@ -1839,8 +1855,8 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ if( pFile->eFileLock<=eFileLock ){ return SQLITE_OK; } - unixEnterMutex(); pInode = pFile->pInode; + sqlite3_mutex_enter(pInode->pLockMutex); assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); @@ -1972,7 +1988,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ } end_unlock: - unixLeaveMutex(); + sqlite3_mutex_leave(pInode->pLockMutex); if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; return rc; } @@ -2771,8 +2787,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){ *pResOut = 1; return SQLITE_OK; } - unixEnterMutex(); /* Because pFile->pInode is shared across threads */ - + sqlite3_mutex_enter(pFile->pInode->pLockMutex); /* Check if a thread in this process holds such a lock */ if( pFile->pInode->eFileLock>SHARED_LOCK ){ reserved = 1; @@ -2796,7 +2811,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){ } } - unixLeaveMutex(); + sqlite3_mutex_leave(pFile->pInode->pLockMutex); OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved)); *pResOut = reserved; @@ -2859,8 +2874,8 @@ static int afpLock(sqlite3_file *id, int eFileLock){ /* This mutex is needed because pFile->pInode is shared across threads */ - unixEnterMutex(); pInode = pFile->pInode; + sqlite3_mutex_enter(pInode->pLockMutex); /* If some thread using this PID has a lock via a different unixFile* ** handle that precludes the requested lock, return BUSY. @@ -2996,7 +3011,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ } afp_end_lock: - unixLeaveMutex(); + sqlite3_mutex_leave(pInode->pLockMutex); OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), rc==SQLITE_OK ? "ok" : "failed")); return rc; @@ -3028,8 +3043,8 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { if( pFile->eFileLock<=eFileLock ){ return SQLITE_OK; } - unixEnterMutex(); pInode = pFile->pInode; + sqlite3_mutex_enter(pInode->pLockMutex); assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); @@ -3104,7 +3119,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { } } - unixLeaveMutex(); + sqlite3_mutex_leave(pInode->pLockMutex); if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; return rc; } From 6886d6dbc4bc2f912303db31dd513c64ba8dd214 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 23 Jul 2018 22:55:10 +0000 Subject: [PATCH 033/260] Return an SQLITE_NOMEM error if the locking mutex fails to allocate. FossilOrigin-Name: 1c94834879be0601ac40ef3c4fb1b140f7737e89af7808f2f1db4ceb3daae19f --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/os_unix.c | 8 +++++++- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 572f99e747..89a7752c5f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C First\sattempt\sat\sreducing\smutex\scontention\sin\sthe\sunix\sVFS\sby\sproviding\na\sseparate\smutex\sfor\seach\sunixInodeInfo\sobject. -D 2018-07-23T21:10:37.802 +C Return\san\sSQLITE_NOMEM\serror\sif\sthe\slocking\smutex\sfails\sto\sallocate. +D 2018-07-23T22:55:10.825 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -481,7 +481,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c c275a32d1112973457908bee494ae0444468c0b96c07057913ade6d69781dab3 +F src/os_unix.c d9cf5ae0c79f31019d8325e8736c83914aeed64d8327a8d91a62b6439b748948 F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 @@ -1750,10 +1750,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc -R acece63ae9d3f4b29a8a0d5614555a1e -T *branch * separate-lock-mutex -T *sym-separate-lock-mutex * -T -sym-trunk * +P f69afaf00a659cd768a863c5f4a1d527f01187e037240da0ada527cb52c5afe8 +R 545987b031198ddb83ad8081fc620520 U drh -Z c02c3e5d8cc1425b437d3294ad5c5e34 +Z 436188ee6c79b5ad3607625e6db74233 diff --git a/manifest.uuid b/manifest.uuid index de8e1e71e2..273911bebb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f69afaf00a659cd768a863c5f4a1d527f01187e037240da0ada527cb52c5afe8 \ No newline at end of file +1c94834879be0601ac40ef3c4fb1b140f7737e89af7808f2f1db4ceb3daae19f \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 48067f4cc3..aacca93d14 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1373,7 +1373,13 @@ static int findInodeInfo( } memset(pInode, 0, sizeof(*pInode)); memcpy(&pInode->fileId, &fileId, sizeof(fileId)); - pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( sqlite3GlobalConfig.bCoreMutex ){ + pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pInode->pLockMutex==0 ){ + sqlite3_free(pInode); + return SQLITE_NOMEM_BKPT; + } + } pInode->nRef = 1; pInode->pNext = inodeList; pInode->pPrev = 0; From 5a193dd8e609c2cd6827fbb3d9cc4ff7c66e0c25 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 24 Jul 2018 13:57:44 +0000 Subject: [PATCH 034/260] Add missing SQLITE_OMIT_WINDOWFUNC check to the json1 extension. FossilOrigin-Name: fe19f8239dc474db0854a0a8ce5189ac4195c736b496f475a59a185e0879b40c --- ext/misc/json1.c | 2 ++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index c7e0aab2d1..f1b633d2c6 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -2459,12 +2459,14 @@ int sqlite3Json1Init(sqlite3 *db){ (void*)&aFunc[i].flag, aFunc[i].xFunc, 0, 0); } +#ifndef SQLITE_OMIT_WINDOWFUNC for(i=0; i Date: Tue, 24 Jul 2018 22:02:12 +0000 Subject: [PATCH 035/260] Do not abort running queries due to a CREATE INDEX statement. Allow them to run to completion before being reprepared. Fix for ticket [c694113e50321afdf9]. FossilOrigin-Name: 2bd593332da0aade467e7a4ee89e966aa6302f37540a2c5e23671f98a6cb599c --- manifest | 29 +++++++++++++++-------------- manifest.uuid | 2 +- src/auth.c | 2 +- src/build.c | 2 +- src/main.c | 8 ++++---- src/sqliteInt.h | 2 +- src/vdbe.c | 19 +++++++++++++------ src/vdbeInt.h | 4 ++-- src/vdbeaux.c | 12 ++++++++++-- src/vtab.c | 2 +- test/tkt-c694113d5.test | 36 ++++++++++++++++++++++++++++++++++++ 11 files changed, 85 insertions(+), 33 deletions(-) create mode 100644 test/tkt-c694113d5.test diff --git a/manifest b/manifest index 6c75bec677..9ab6fc62d2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smissing\sSQLITE_OMIT_WINDOWFUNC\scheck\sto\sthe\sjson1\sextension. -D 2018-07-24T13:57:44.003 +C Do\snot\sabort\srunning\squeries\sdue\sto\sa\sCREATE\sINDEX\sstatement.\s\sAllow\sthem\nto\srun\sto\scompletion\sbefore\sbeing\sreprepared.\s\sFix\sfor\sticket\n[c694113e50321afdf9]. +D 2018-07-24T22:02:12.832 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -434,14 +434,14 @@ F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 6beb476095a4cfeb95ebedb2e5e17894d1687b24fddd5b8761a4de120e0392c6 F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a -F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8 +F src/auth.c 8272da9ff761bf84f0357298ccc6e5924e3f7fac143c6587f06aa72b202445a2 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 -F src/build.c d8f6ac1e9e484eb3f3921a8336d3dc6c87273d9db8729702162ef045997a1463 +F src/build.c ae6edcd6e14a3dcaf9e1f63910cd4d99555338508d7a60e4660147f8a77c023b F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387 @@ -461,7 +461,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 8613af9c5ba1503bc68f4e9432c6c024e0fdafdc791575c50f380f73ec91189f F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b -F src/main.c 9c8ef68bd3779d493d632946b3a65156b2e636ad2c7a1b7cd1450e87dc0c6a7d +F src/main.c 73a3db1c9788de97a826ac794bf98a8a811c7594e93bef4f0c085b3f9ddeb76d F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -502,7 +502,7 @@ F src/shell.c.in f6ebd05c461805a7c708333cd645e74e0a93560d2118f5adb73a75d8c9cf6b0 F src/sqlite.h.in 37615597574060538595ea0b8ceee2bdcdc5a8757455a703733847654d5957d0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 -F src/sqliteInt.h c2ceebe60d1d2e11674b90c8b55fdffd91386ce8d7ae38613fbcc61659b8fcac +F src/sqliteInt.h 427471586351daefbc81155384a702b2173801051fe345bc25a09558b919db77 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -568,16 +568,16 @@ F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 -F src/vdbe.c 9933ec035072c72fc26c5439f6c8a1eef902ce9132916d5a05e8733b0266eb67 +F src/vdbe.c f5e6c0eab497c34f695a9b40800bbc09cd9488cabbd434048f3cbb3e85aaec38 F src/vdbe.h d93abdc8bc9295e0a256e582c19f548c545dc498319d108bbc9dd29de31c48a2 -F src/vdbeInt.h 6b5cbd338dc9aaad343fb11b455e47463b0474d9f79710f50e647158941146e0 +F src/vdbeInt.h 2a45270d7f44870ca5452f48cdf3c56387019ae03331c008d670a7d0a3e1ba3f F src/vdbeapi.c af4a3de00d1851bcbc55b85dfbe52849aa2b1e17b4a5a1f3d9c257df7af361ff -F src/vdbeaux.c c2d65c763b0811afe409e02e9d0d1f300c6e97892474fc94eec3da71955cd418 +F src/vdbeaux.c 1265a36260c36eb55afb40d744ffc1a3f11252d5712274c6218efb087204a7e5 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbemem.c a699a1d7ccc3f94cdff69ddf35d5f7540dbf52ca44cf040eda3c87520e67858c F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392 -F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b +F src/vtab.c 678992ac8ec677a3f9b08126aaf891441083805e3b42574e3654d44538381c14 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d44a0811afd2155b1157c38b33141d4ac028fda6232485bed664015bb05819ca F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a @@ -1387,6 +1387,7 @@ F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877 F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898 F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447 +F test/tkt-c694113d5.test 82c461924ada5c14866c47e85535b0b0923ba16a2e907e370061a5ca77f65d77 F test/tkt-cbd054fa6b.test 06ccd57af3c0c7895d0f7dc844f13c51f8258885 F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09 @@ -1750,7 +1751,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc -R 04e27003b3e25ff2b1b306cb41502a3f -U mistachkin -Z fd864996daa329dbed22fdd8a051a565 +P fe19f8239dc474db0854a0a8ce5189ac4195c736b496f475a59a185e0879b40c +R 83c4c1a5e9b7c188b0be756d9d206b1e +U drh +Z 595aea1a22de944630d679d3a06354dc diff --git a/manifest.uuid b/manifest.uuid index 36be2d7c44..43557f4be8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fe19f8239dc474db0854a0a8ce5189ac4195c736b496f475a59a185e0879b40c \ No newline at end of file +2bd593332da0aade467e7a4ee89e966aa6302f37540a2c5e23671f98a6cb599c \ No newline at end of file diff --git a/src/auth.c b/src/auth.c index 03e4cf9f54..a708d0c247 100644 --- a/src/auth.c +++ b/src/auth.c @@ -78,7 +78,7 @@ int sqlite3_set_authorizer( sqlite3_mutex_enter(db->mutex); db->xAuth = (sqlite3_xauth)xAuth; db->pAuthArg = pArg; - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } diff --git a/src/build.c b/src/build.c index 6b761da02a..af899d278d 100644 --- a/src/build.c +++ b/src/build.c @@ -3468,7 +3468,7 @@ void sqlite3CreateIndex( sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); - sqlite3VdbeAddOp0(v, OP_Expire); + sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); } sqlite3VdbeJumpHere(v, pIndex->tnum); diff --git a/src/main.c b/src/main.c index 9c10cab6ae..07f6688810 100644 --- a/src/main.c +++ b/src/main.c @@ -849,7 +849,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ db->flags &= ~aFlagOp[i].mask; } if( oldFlags!=db->flags ){ - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); } if( pRes ){ *pRes = (db->flags & aFlagOp[i].mask)!=0; @@ -1292,7 +1292,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ sqlite3EndBenignMalloc(); if( schemaChange ){ - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); sqlite3ResetAllSchemasOfConnection(db); } sqlite3BtreeLeaveAll(db); @@ -1747,7 +1747,7 @@ int sqlite3CreateFunc( assert( !db->mallocFailed ); return SQLITE_BUSY; }else{ - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); } } @@ -2522,7 +2522,7 @@ static int createCollation( "unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); /* If collation sequence pColl was created directly by a call to ** sqlite3_create_collation, and not generated by synthCollSeq(), diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f84cd780ff..2c52dfec5c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4223,7 +4223,7 @@ void sqlite3AlterFunctions(void); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); int sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...); -void sqlite3ExpirePreparedStatements(sqlite3*); +void sqlite3ExpirePreparedStatements(sqlite3*, int); int sqlite3CodeSubselect(Parse*, Expr *, int, int); void sqlite3SelectPrep(Parse*, Select*, NameContext*); void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); diff --git a/src/vdbe.c b/src/vdbe.c index f9c7eba91a..39b307980d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3102,7 +3102,7 @@ case OP_Savepoint: { } } if( isSchemaChange ){ - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); sqlite3ResetAllSchemasOfConnection(db); db->mDbFlags |= DBFLAG_SchemaChange; } @@ -3391,7 +3391,7 @@ case OP_SetCookie: { if( pOp->p1==1 ){ /* Invalidate all prepared statements whenever the TEMP database ** schema is changed. Ticket #1644 */ - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); p->expired = 0; } if( rc ) goto abort_due_to_error; @@ -3509,7 +3509,7 @@ case OP_OpenWrite: assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx || p->readOnly==0 ); - if( p->expired ){ + if( p->expired==1 ){ rc = SQLITE_ABORT_ROLLBACK; goto abort_due_to_error; } @@ -6690,7 +6690,7 @@ case OP_IncrVacuum: { /* jump */ } #endif -/* Opcode: Expire P1 * * * * +/* Opcode: Expire P1 P2 * * * ** ** Cause precompiled statements to expire. When an expired statement ** is executed using sqlite3_step() it will either automatically @@ -6699,12 +6699,19 @@ case OP_IncrVacuum: { /* jump */ ** ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, ** then only the currently executing statement is expired. +** +** If P2 is 0, then SQL statements are expired immediately. If P2 is 1, +** then running SQL statements are allowed to continue to run to completion. +** The P2==1 case occurs when a CREATE INDEX or similar schema change happens +** that might help the statement run faster but which does not affect the +** correctness of operation. */ case OP_Expire: { + assert( pOp->p2==0 || pOp->p2==1 ); if( !pOp->p1 ){ - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, pOp->p2); }else{ - p->expired = 1; + p->expired = pOp->p2+1; } break; } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index d6c566027a..e291825e31 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -390,9 +390,9 @@ struct Vdbe { u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ - bft expired:1; /* True if the VM needs to be recompiled */ - bft doingRerun:1; /* True if rerunning after an auto-reprepare */ + bft expired:2; /* 1: recompile VM immediately 2: when convenient */ bft explain:2; /* True if EXPLAIN present on SQL command */ + bft doingRerun:1; /* True if rerunning after an auto-reprepare */ bft changeCntOn:1; /* True to update the change-counter */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d6efead321..4550c7cf7f 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -4659,11 +4659,19 @@ void sqlite3VdbeCountChanges(Vdbe *v){ ** programs obsolete. Removing user-defined functions or collating ** sequences, or changing an authorization function are the types of ** things that make prepared statements obsolete. +** +** If iCode is 1, then expiration is advisory. The statement should +** be reprepared before being restarted, but if it is already running +** it is allowed to run to completion. +** +** Internally, this function just sets the Vdbe.expired flag on all +** prepared statements. The flag is set to 1 for an immediate expiration +** and set to 2 for an advisory expiration. */ -void sqlite3ExpirePreparedStatements(sqlite3 *db){ +void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){ Vdbe *p; for(p = db->pVdbe; p; p=p->pNext){ - p->expired = 1; + p->expired = iCode+1; } } diff --git a/src/vtab.c b/src/vtab.c index 7894bbc8b8..c9ce83890c 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -262,7 +262,7 @@ void sqlite3VtabUnlockList(sqlite3 *db){ assert( sqlite3_mutex_held(db->mutex) ); if( p ){ - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); do { VTable *pNext = p->pNext; sqlite3VtabUnlock(p); diff --git a/test/tkt-c694113d5.test b/test/tkt-c694113d5.test new file mode 100644 index 0000000000..bac91fc900 --- /dev/null +++ b/test/tkt-c694113d5.test @@ -0,0 +1,36 @@ +# 2018-07-24 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. Specifically, +# it tests that ticket [c694113e50321afdf952e2d1235b08ba663f8399]: +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_test tkt-c694113d5.100 { + sqlite3 db :memory: + db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY); + CREATE TABLE t2(d INTEGER PRIMARY KEY,e,f); + INSERT INTO t1(a) VALUES(1),(2),(3),(4); + } + set answer {} + db eval {SELECT a FROM t1 WHERE NOT EXISTS(SELECT 1 FROM t2 WHERE d=a)} { + if {$a==3} { + lappend answer "CREATE INDEX" + db eval {CREATE INDEX t2e ON t2(e);} + } + lappend answer "a=$a" + } + set answer +} {a=1 a=2 {CREATE INDEX} a=3 a=4} + +finish_test From caf0a2540ce3f9e621b0cec8ee8027b017114f05 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 25 Jul 2018 07:29:20 +0000 Subject: [PATCH 036/260] Fix a typo in the documentation for sqlite3_snapshot_get(). FossilOrigin-Name: cd9713c9a88cd30887c67f477abbbf8ef90299051a0b9bb52a04cf4132987c9c --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 9ab6fc62d2..5f60cd81d3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sabort\srunning\squeries\sdue\sto\sa\sCREATE\sINDEX\sstatement.\s\sAllow\sthem\nto\srun\sto\scompletion\sbefore\sbeing\sreprepared.\s\sFix\sfor\sticket\n[c694113e50321afdf9]. -D 2018-07-24T22:02:12.832 +C Fix\sa\stypo\sin\sthe\sdocumentation\sfor\ssqlite3_snapshot_get(). +D 2018-07-25T07:29:20.225 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -499,7 +499,7 @@ F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 2e9661d4424f43ccf595c4a7b4acdf32db523c0f6b31cbd62e6e5a2f43118981 F src/shell.c.in f6ebd05c461805a7c708333cd645e74e0a93560d2118f5adb73a75d8c9cf6b01 -F src/sqlite.h.in 37615597574060538595ea0b8ceee2bdcdc5a8757455a703733847654d5957d0 +F src/sqlite.h.in c6451bb876adced3aba5b1682c6317d215c5eceaba21a6ce979e71a0b8d0bf95 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h 427471586351daefbc81155384a702b2173801051fe345bc25a09558b919db77 @@ -1751,7 +1751,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fe19f8239dc474db0854a0a8ce5189ac4195c736b496f475a59a185e0879b40c -R 83c4c1a5e9b7c188b0be756d9d206b1e -U drh -Z 595aea1a22de944630d679d3a06354dc +P 2bd593332da0aade467e7a4ee89e966aa6302f37540a2c5e23671f98a6cb599c +R ec4b7ae75f333dd2e05c5e6caef8a051 +U dan +Z c5f5094bf24e926b943d16fe8beeac07 diff --git a/manifest.uuid b/manifest.uuid index 43557f4be8..94dd68b8c6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2bd593332da0aade467e7a4ee89e966aa6302f37540a2c5e23671f98a6cb599c \ No newline at end of file +cd9713c9a88cd30887c67f477abbbf8ef90299051a0b9bb52a04cf4132987c9c \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index dc9246812b..bdecac5d10 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -9000,7 +9000,7 @@ typedef struct sqlite3_snapshot { ** in this case. ** ** */ #define SQLITE_FCNTL_LOCKSTATE 1 From 16b870d8040290f84bbd99061b5cdc746ebca117 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 12 Sep 2018 15:51:56 +0000 Subject: [PATCH 199/260] Restrict the scope of internal-use functions in alter.c. FossilOrigin-Name: 4396914f8e1a847d86c22fb0b91e7431cf19aa260cbec520af3564248d6897ad --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/alter.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 9aa1c3e5a4..e7f12d03e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\sdocumentation\sfor\sSQLITE_FCNTL_DATA_VERSION.\nNo\schanges\sto\scode. -D 2018-09-12T14:28:45.796 +C Restrict\sthe\sscope\sof\sinternal-use\sfunctions\sin\salter.c. +D 2018-09-12T15:51:56.382 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -435,7 +435,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c b04e36e22fea9db48974cbbc66bcf0a34f4a42a97a351f47d993d490bb167861 +F src/alter.c 3800f24c922dfcab2e7a05b49123e2f9c903c26fccea71a5f9ac765e91949355 F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114 @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 572de7e4e33562c72cd90790b267ba389370f21ddcaebc4db609fd76ae9b7ada -R e455f3eaa906d427b1a5b3d685d9a895 +P 27837624336d2883f721310bd4dceedb77085d1008af5e12557f634936d48b8c +R 8c74c0be917d870f4ce6d5afdcc4480b U drh -Z 05885c65ec17fd37d679fda087c37874 +Z f845bcddfc6ed1eb1eebbad288573085 diff --git a/manifest.uuid b/manifest.uuid index 5f026d9c8c..4fc4f09744 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -27837624336d2883f721310bd4dceedb77085d1008af5e12557f634936d48b8c \ No newline at end of file +4396914f8e1a847d86c22fb0b91e7431cf19aa260cbec520af3564248d6897ad \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index ff3845290b..c33dfdfb85 100644 --- a/src/alter.c +++ b/src/alter.c @@ -43,7 +43,7 @@ static int isSystemTable(Parse *pParse, const char *zName){ ** statement to ensure that the operation has not rendered any schema ** objects unusable. */ -void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ +static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ sqlite3NestedParse(pParse, "SELECT 1 " "FROM \"%w\".%s " @@ -70,7 +70,7 @@ void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ ** Generate code to reload the schema for database iDb. And, if iDb!=1, for ** the temp database as well. */ -void renameReloadSchema(Parse *pParse, int iDb){ +static void renameReloadSchema(Parse *pParse, int iDb){ Vdbe *v = pParse->pVdbe; if( v ){ sqlite3ChangeCookie(pParse, iDb); @@ -650,7 +650,7 @@ struct RenameCtx { ** Technically, as x no longer points into a valid object or to the byte ** following a valid object, it may not be used in comparison operations. */ -void renameTokenCheckAll(Parse *pParse, void *pPtr){ +static void renameTokenCheckAll(Parse *pParse, void *pPtr){ if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){ RenameToken *p; u8 i = 0; From a86acc213226b5c575dfbed70723eb957ac2a450 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 12 Sep 2018 20:32:19 +0000 Subject: [PATCH 200/260] Fix an assert() in os_unix.c that is not true when using RBU. FossilOrigin-Name: 028ed8618af012b51104a06cc155b45d98bc4ff833d4431b9c38fd6851a74e82 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_unix.c | 4 +++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e7f12d03e6..5c904d4cc9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Restrict\sthe\sscope\sof\sinternal-use\sfunctions\sin\salter.c. -D 2018-09-12T15:51:56.382 +C Fix\san\sassert()\sin\sos_unix.c\sthat\sis\snot\strue\swhen\susing\sRBU. +D 2018-09-12T20:32:19.959 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -485,7 +485,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c 03a5cd0e254dfecd86e800e442a35636c755ececb9e33863a978d9ab23120938 +F src/os_unix.c d8e37bc3af9b15a52c3fecd366c95416251aa8d89481dd56170bad538b421721 F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 27837624336d2883f721310bd4dceedb77085d1008af5e12557f634936d48b8c -R 8c74c0be917d870f4ce6d5afdcc4480b -U drh -Z f845bcddfc6ed1eb1eebbad288573085 +P 4396914f8e1a847d86c22fb0b91e7431cf19aa260cbec520af3564248d6897ad +R 04270aabbf5aa7a25158dc0e14607b5c +U dan +Z 006b0a748ebdda21ed6dd1a66ca8163c diff --git a/manifest.uuid b/manifest.uuid index 4fc4f09744..b8b3f62d8f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4396914f8e1a847d86c22fb0b91e7431cf19aa260cbec520af3564248d6897ad \ No newline at end of file +028ed8618af012b51104a06cc155b45d98bc4ff833d4431b9c38fd6851a74e82 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index a15592ef37..f4c0570cc3 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4879,7 +4879,9 @@ static void unixShmBarrier( ){ UNUSED_PARAMETER(fd); sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ - assert( unixFileMutexNotheld((unixFile*)fd) ); + assert( fd->pMethods->xLock==nolockLock + || unixFileMutexNotheld((unixFile*)fd) + ); unixEnterMutex(); /* Also mutex, for redundancy */ unixLeaveMutex(); } From 396a103612298c5dd52b26f513631f8301a19fad Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 13 Sep 2018 13:17:14 +0000 Subject: [PATCH 201/260] Fix a requirement mark on a test script. No changes to code. FossilOrigin-Name: 628d5c0aa057c05c7cf84c330a51b8a44720c97250eadf0e5e8c750b7a2969c3 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/e_createtable.test | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 5c904d4cc9..77810b7b0c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sin\sos_unix.c\sthat\sis\snot\strue\swhen\susing\sRBU. -D 2018-09-12T20:32:19.959 +C Fix\sa\srequirement\smark\son\sa\stest\sscript.\s\sNo\schanges\sto\scode. +D 2018-09-13T13:17:14.135 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -785,7 +785,7 @@ F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145 F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14 F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 -F test/e_createtable.test e1c4512b9e15fe7bedbbfc0c6daac8a4af65f32dc3c48310b0135b5735857b26 +F test/e_createtable.test 1c602347e73ab80b11b9fa083f47155861aaafcff8054aac9e0b76d0df33b0a7 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5 @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4396914f8e1a847d86c22fb0b91e7431cf19aa260cbec520af3564248d6897ad -R 04270aabbf5aa7a25158dc0e14607b5c -U dan -Z 006b0a748ebdda21ed6dd1a66ca8163c +P 028ed8618af012b51104a06cc155b45d98bc4ff833d4431b9c38fd6851a74e82 +R 0f1bd7f3d2cd804864fd41a3f49e7a96 +U drh +Z 46ea13a8e199c56a06cef89eced0ea11 diff --git a/manifest.uuid b/manifest.uuid index b8b3f62d8f..773d9c11f1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -028ed8618af012b51104a06cc155b45d98bc4ff833d4431b9c38fd6851a74e82 \ No newline at end of file +628d5c0aa057c05c7cf84c330a51b8a44720c97250eadf0e5e8c750b7a2969c3 \ No newline at end of file diff --git a/test/e_createtable.test b/test/e_createtable.test index 65cb7f2935..7f6cf48ce9 100644 --- a/test/e_createtable.test +++ b/test/e_createtable.test @@ -883,8 +883,8 @@ do_execsql_test e_createtable-3.3.1 { ); } {} -# EVIDENCE-OF: R-18415-27776 For the purposes of the DEFAULT clause, an -# expression is considered constant if it does contains no sub-queries, +# EVIDENCE-OF: R-33440-07331 For the purposes of the DEFAULT clause, an +# expression is considered constant if it contains no sub-queries, # column or table references, bound parameters, or string literals # enclosed in double-quotes instead of single-quotes. # From af524a6343e82d577dc34f443bfa090caca69c71 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 13 Sep 2018 17:07:12 +0000 Subject: [PATCH 202/260] Make sure the %z optimization for printf() is not invoked if there has been a prior error (SQLITE_NOMEM or SQLITE_TOOBIG) associated with the same printf() call. FossilOrigin-Name: a2304a3474b0ca35eee0af64286ce2f7cb24d181323e128d5f04f7fe6e1c0980 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/printf.c | 7 ++++++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 77810b7b0c..9ae6851590 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\srequirement\smark\son\sa\stest\sscript.\s\sNo\schanges\sto\scode. -D 2018-09-13T13:17:14.135 +C Make\ssure\sthe\s%z\soptimization\sfor\sprintf()\sis\snot\sinvoked\sif\sthere\shas\sbeen\na\sprior\serror\s(SQLITE_NOMEM\sor\sSQLITE_TOOBIG)\sassociated\swith\sthe\ssame\nprintf()\scall. +D 2018-09-13T17:07:12.853 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -497,7 +497,7 @@ F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c 79abc65c08d2754048efee3ba99fe91863dfeab0ba699a4439fa5053ec87cf36 F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 -F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365 +F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 028ed8618af012b51104a06cc155b45d98bc4ff833d4431b9c38fd6851a74e82 -R 0f1bd7f3d2cd804864fd41a3f49e7a96 +P 628d5c0aa057c05c7cf84c330a51b8a44720c97250eadf0e5e8c750b7a2969c3 +R 9ca2cce3607aac6321c4dd78c66175b1 U drh -Z 46ea13a8e199c56a06cef89eced0ea11 +Z 594b11f9bfe9f2af28e3c404580a1217 diff --git a/manifest.uuid b/manifest.uuid index 773d9c11f1..644926dd86 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -628d5c0aa057c05c7cf84c330a51b8a44720c97250eadf0e5e8c750b7a2969c3 \ No newline at end of file +a2304a3474b0ca35eee0af64286ce2f7cb24d181323e128d5f04f7fe6e1c0980 \ No newline at end of file diff --git a/src/printf.c b/src/printf.c index 71296ac907..7bce83f3e2 100644 --- a/src/printf.c +++ b/src/printf.c @@ -686,7 +686,12 @@ void sqlite3_str_vappendf( if( bufpt==0 ){ bufpt = ""; }else if( xtype==etDYNSTRING ){ - if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){ + if( pAccum->nChar==0 + && pAccum->mxAlloc + && width==0 + && precision<0 + && pAccum->accError==0 + ){ /* Special optimization for sqlite3_mprintf("%z..."): ** Extend an existing memory allocation rather than creating ** a new one. */ From f86ff13206e5bd875d80fc0168099ac937f9464a Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 13 Sep 2018 17:11:51 +0000 Subject: [PATCH 203/260] Update releasetest.tcl to run "make test" as part of the "Fast-One" configuration. FossilOrigin-Name: d5ebfe1c75d336dac374d9cfa257e45e77ab51f9c2f24d1af615cbbe9dd83d9b --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/releasetest.tcl | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 9ae6851590..e71161eb8c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\s%z\soptimization\sfor\sprintf()\sis\snot\sinvoked\sif\sthere\shas\sbeen\na\sprior\serror\s(SQLITE_NOMEM\sor\sSQLITE_TOOBIG)\sassociated\swith\sthe\ssame\nprintf()\scall. -D 2018-09-13T17:07:12.853 +C Update\sreleasetest.tcl\sto\srun\s"make\stest"\sas\spart\sof\sthe\s"Fast-One"\nconfiguration. +D 2018-09-13T17:11:51.873 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -1191,7 +1191,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl 769892f81050b3f59c66f274d478d855159b474ea27019dec82f1215c0b91ef7 x +F test/releasetest.tcl 7e90ec5d2854d80e2574f70df834ef9cae705d21fe43a19dc217a3ce33a3798c x F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 628d5c0aa057c05c7cf84c330a51b8a44720c97250eadf0e5e8c750b7a2969c3 -R 9ca2cce3607aac6321c4dd78c66175b1 -U drh -Z 594b11f9bfe9f2af28e3c404580a1217 +P a2304a3474b0ca35eee0af64286ce2f7cb24d181323e128d5f04f7fe6e1c0980 +R c36dfea444f63a820bb98b56bfc7ace7 +U dan +Z 126a894e1401fe957650ba021c0b1dc8 diff --git a/manifest.uuid b/manifest.uuid index 644926dd86..ec77426478 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a2304a3474b0ca35eee0af64286ce2f7cb24d181323e128d5f04f7fe6e1c0980 \ No newline at end of file +d5ebfe1c75d336dac374d9cfa257e45e77ab51f9c2f24d1af615cbbe9dd83d9b \ No newline at end of file diff --git a/test/releasetest.tcl b/test/releasetest.tcl index 65f6dadad9..cbd4f9cad3 100755 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -268,7 +268,7 @@ array set ::Configs [strip_comments { array set ::Platforms [strip_comments { Linux-x86_64 { "Check-Symbols" checksymbols - "Fast-One" fuzztest + "Fast-One" "fuzztest test" "Debug-One" "mptest test" "Have-Not" test "Secure-Delete" test From 9fd842546739c504fffc9b45b62e41bc77317156 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 14 Sep 2018 17:42:47 +0000 Subject: [PATCH 204/260] Fix minor typos in comments that get carried over into documentation. No changes to code. FossilOrigin-Name: 7921dd91a1745aa79ea157b91b22c380e9331800050861ee6ca1f0efa0a97628 --- ext/fts5/fts5.h | 4 ++-- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqlite.h.in | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ext/fts5/fts5.h b/ext/fts5/fts5.h index a45c145d38..037da64d42 100644 --- a/ext/fts5/fts5.h +++ b/ext/fts5/fts5.h @@ -444,7 +444,7 @@ struct Fts5ExtensionApi { ** This way, even if the tokenizer does not provide synonyms ** when tokenizing query text (it should not - to do would be ** inefficient), it doesn't matter if the user queries for -** 'first + place' or '1st + place', as there are entires in the +** 'first + place' or '1st + place', as there are entries in the ** FTS index corresponding to both forms of the first token. ** ** @@ -472,7 +472,7 @@ struct Fts5ExtensionApi { ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the -** token "first" is subsituted for "1st" by the tokenizer, then the query: +** token "first" is substituted for "1st" by the tokenizer, then the query: ** ** ** ... MATCH '1s*' diff --git a/manifest b/manifest index e71161eb8c..9b621346b4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sreleasetest.tcl\sto\srun\s"make\stest"\sas\spart\sof\sthe\s"Fast-One"\nconfiguration. -D 2018-09-13T17:11:51.873 +C Fix\sminor\stypos\sin\scomments\sthat\sget\scarried\sover\sinto\sdocumentation.\nNo\schanges\sto\scode. +D 2018-09-14T17:42:47.736 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -108,7 +108,7 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7 F ext/fts3/unicode/mkunicode.tcl 0069320b64db6ee269c5e95f1f150d070fbf0a863fc7b3549d7e52bd068fb118 F ext/fts3/unicode/parseunicode.tcl 024ae0bdd96309d7b8fc479148191e9b3001dc74017a3f65f9a27de3b3ff968b F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 -F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7 +F ext/fts5/fts5.h 5edc74ca603d71284d475886e6e91b5c5cf2e8e93e9ba3a36ba2f2440ee97948 F ext/fts5/fts5Int.h 39f12034b598df4e0f59bbe6cf03af03a905a534b04f182d155641a04e1eb797 F ext/fts5/fts5_aux.c ca666a3bbe07c5a3bbe9fffaea19c935a1efaf337333e28bad7bdd1971ffd093 F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff @@ -503,7 +503,7 @@ F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f -F src/sqlite.h.in 5a61ffbc0ade918025951a7abc9640fd870e5afd8e730b48751298d2404de888 +F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 F src/sqliteInt.h ce34da1aacca2cd4b63803db697f682af95c02d1e1750f240438b0d96a59bdb8 @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a2304a3474b0ca35eee0af64286ce2f7cb24d181323e128d5f04f7fe6e1c0980 -R c36dfea444f63a820bb98b56bfc7ace7 -U dan -Z 126a894e1401fe957650ba021c0b1dc8 +P d5ebfe1c75d336dac374d9cfa257e45e77ab51f9c2f24d1af615cbbe9dd83d9b +R cd1dec78fa9aef334fc060d76165a055 +U drh +Z ac91d22849e2e00aa7d80ffd22f4486b diff --git a/manifest.uuid b/manifest.uuid index ec77426478..26e8edb3a4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5ebfe1c75d336dac374d9cfa257e45e77ab51f9c2f24d1af615cbbe9dd83d9b \ No newline at end of file +7921dd91a1745aa79ea157b91b22c380e9331800050861ee6ca1f0efa0a97628 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 97ba319664..2d090e3ec7 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -4732,7 +4732,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt); ** ** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ** and xInverse) passed to sqlite3_create_window_function are pointers to -** C-lanugage callbacks that implement the new function. xStep and xFinal +** C-language callbacks that implement the new function. xStep and xFinal ** must both be non-NULL. xValue and xInverse may either both be NULL, in ** which case a regular aggregate function is created, or must both be ** non-NULL, in which case the new function may be used as either an aggregate @@ -9258,7 +9258,7 @@ int sqlite3_deserialize( ** in the P argument is held in memory obtained from [sqlite3_malloc64()] ** and that SQLite should take ownership of this memory and automatically ** free it when it has finished using it. Without this flag, the caller -** is resposible for freeing any dynamically allocated memory. +** is responsible for freeing any dynamically allocated memory. ** ** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to ** grow the size of the database using calls to [sqlite3_realloc64()]. This From f7d3b7a56cd6ebb85ba999913acb335de83b53ec Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 15 Sep 2018 04:01:47 +0000 Subject: [PATCH 205/260] Version 3.25.0 FossilOrigin-Name: b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760 --- manifest | 11 +++++++---- manifest.uuid | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/manifest b/manifest index 9b621346b4..46d27e5e27 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sminor\stypos\sin\scomments\sthat\sget\scarried\sover\sinto\sdocumentation.\nNo\schanges\sto\scode. -D 2018-09-14T17:42:47.736 +C Version\s3.25.0 +D 2018-09-15T04:01:47.208 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -1765,7 +1765,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d5ebfe1c75d336dac374d9cfa257e45e77ab51f9c2f24d1af615cbbe9dd83d9b +P 7921dd91a1745aa79ea157b91b22c380e9331800050861ee6ca1f0efa0a97628 R cd1dec78fa9aef334fc060d76165a055 +T +bgcolor * #d0c0ff +T +sym-release * +T +sym-version-3.25.0 * U drh -Z ac91d22849e2e00aa7d80ffd22f4486b +Z 7af864335c95fcb0688b7f5b8af875de diff --git a/manifest.uuid b/manifest.uuid index 26e8edb3a4..b71e552f9e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7921dd91a1745aa79ea157b91b22c380e9331800050861ee6ca1f0efa0a97628 \ No newline at end of file +b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760 \ No newline at end of file From e9816d82a79ec748f4280fabf7ba30717d0c43a3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 15 Sep 2018 21:38:48 +0000 Subject: [PATCH 206/260] Optimization: when doing an UPDATE on a table with indexes on an expression, do not update the expression indexes if they do not refer to any of the columns of the table being updated. FossilOrigin-Name: a71b101635ed28a4c99734dabb20bd65ef1018c1d63ac143b7321cdb0fafa5d7 --- manifest | 21 +++++++++------------ manifest.uuid | 2 +- src/insert.c | 34 +++++++++++++++++++++++++--------- src/sqliteInt.h | 1 + src/update.c | 31 ++++++++++++++++++++++++++++--- test/indexexpr2.test | 38 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 102 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index 46d27e5e27..04f1f435c4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.25.0 -D 2018-09-15T04:01:47.208 +C Optimization:\swhen\sdoing\san\sUPDATE\son\sa\stable\swith\sindexes\son\san\sexpression,\ndo\snot\supdate\sthe\sexpression\sindexes\sif\sthey\sdo\snot\srefer\sto\sany\sof\sthe\ncolumns\sof\sthe\stable\sbeing\supdated. +D 2018-09-15T21:38:48.076 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -462,7 +462,7 @@ F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c c723716f0de7aa0a679300f7d3541c89645f4a9882161cecdb3093fc07f8cc4b +F src/insert.c 0a214201afec77880a31a59c33d86b473a160fc5cc31981eab2041ae03d8bf2f F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 30b140d0e5031924c56f802760506c0a235ced0dff9f3d95119aa86df12856e2 F src/main.c 1f54ee71990bfbf4cdc2dc79bdc33e7c4f54eef6922447b4c910f9b5885a4478 @@ -506,7 +506,7 @@ F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1 F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 -F src/sqliteInt.h ce34da1aacca2cd4b63803db697f682af95c02d1e1750f240438b0d96a59bdb8 +F src/sqliteInt.h 83ee9b55db521b70294b2858872e69b96d0a4810d8221796def3e99cca5ee663 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -567,7 +567,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd -F src/update.c 345ce35eb1332eb4829857aa8b1f65a614b07dae91d0346c0dc2baacafbcc51b +F src/update.c deb215e3532be46e1e2b6aa38ed9e3eb96e42ebc4cbe7a498cd365788220a432 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 @@ -1007,7 +1007,7 @@ F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e -F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216 +F test/indexexpr2.test 05f490de32b07bce041947cb63475eb04cbd5af2ea2979ca6b9a694cde176efd F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a @@ -1765,10 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7921dd91a1745aa79ea157b91b22c380e9331800050861ee6ca1f0efa0a97628 -R cd1dec78fa9aef334fc060d76165a055 -T +bgcolor * #d0c0ff -T +sym-release * -T +sym-version-3.25.0 * +P b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760 +R 3dbbbb152576c732493eb0793eda163f U drh -Z 7af864335c95fcb0688b7f5b8af875de +Z 14fba317833d2195e2283bec86cb6487 diff --git a/manifest.uuid b/manifest.uuid index b71e552f9e..dbfdf2d5da 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760 \ No newline at end of file +a71b101635ed28a4c99734dabb20bd65ef1018c1d63ac143b7321cdb0fafa5d7 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 12a6bb805e..d110ab7634 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1126,14 +1126,15 @@ insert_cleanup: #endif /* -** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() +** Meanings of bits in of pWalker->eCode for +** sqlite3ExprReferencesUpdatedColumn() */ #define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ #define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ -/* This is the Walker callback from checkConstraintUnchanged(). Set -** bit 0x01 of pWalker->eCode if -** pWalker->eCode to 0 if this expression node references any of the +/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). +* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this +** expression node references any of the ** columns that are being modifed by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ @@ -1155,12 +1156,21 @@ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ ** only columns that are modified by the UPDATE are those for which ** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. ** -** Return true if CHECK constraint pExpr does not use any of the +** Return true if CHECK constraint pExpr uses any of the ** changing columns (or the rowid if it is changing). In other words, -** return true if this CHECK constraint can be skipped when validating +** return true if this CHECK constraint must be validated for ** the new row in the UPDATE statement. +** +** 2018-09-15: pExpr might also be an expression for an index-on-expressions. +** The operation of this routine is the same - return true if an only if +** the expression uses one or more of columns identified by the second and +** third arguments. */ -static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ +int sqlite3ExprReferencesUpdatedColumn( + Expr *pExpr, /* The expression to be checked */ + int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */ + int chngRowid /* True if UPDATE changes the rowid */ +){ Walker w; memset(&w, 0, sizeof(w)); w.eCode = 0; @@ -1175,7 +1185,7 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ testcase( w.eCode==CKCNSTRNT_COLUMN ); testcase( w.eCode==CKCNSTRNT_ROWID ); testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); - return !w.eCode; + return w.eCode!=0; } /* @@ -1381,7 +1391,13 @@ void sqlite3GenerateConstraintChecks( for(i=0; inExpr; i++){ int allOk; Expr *pExpr = pCheck->a[i].pExpr; - if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; + if( aiChng + && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng) + ){ + /* The check constraints do not reference any of the columns being + ** updated so there is no point it verifying the check constraint */ + continue; + } allOk = sqlite3VdbeMakeLabel(v); sqlite3VdbeVerifyAbortable(v, onError); sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 79d41e8a03..74438b5abc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4002,6 +4002,7 @@ void sqlite3GenerateRowDelete( void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); void sqlite3ResolvePartIdxLabel(Parse*,int); +int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*,int*,Upsert*); #ifdef SQLITE_ENABLE_NULL_TRIM diff --git a/src/update.c b/src/update.c index 94e169fd01..c9ec95bb65 100644 --- a/src/update.c +++ b/src/update.c @@ -79,6 +79,29 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ #endif } +/* +** Check to see if column iCol of index pIdx references any of the +** columns defined by aXRef and chngRowid. Return true if it does +** and false if not. +** +** The iCol-th column of pIdx will be an expression. +** +** aXRef[j] will be non-negative if column j of the original table is +** being updated. chngRowid will be true if the rowid of the table is +** being updated. +*/ +static int indexExprRefsUpdatedColumn( + Index *pIdx, /* The index containing the expression to analyze */ + int iCol, /* Which column of the index is the expression */ + int *aXRef, /* aXRef[j]>=0 if column j is being updated */ + int chngRowid /* true if the rowid is being updated */ +){ + assert( pIdx->aColExpr!=0 ); + assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); + return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, + aXRef,chngRowid); +} + /* ** Process an UPDATE statement. ** @@ -302,8 +325,6 @@ void sqlite3Update( /* There is one entry in the aRegIdx[] array for each index on the table ** being updated. Fill in aRegIdx[] with a register number that will hold ** the key for accessing each index. - ** - ** FIXME: Be smarter about omitting indexes that use expressions. */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; @@ -314,7 +335,11 @@ void sqlite3Update( reg = 0; for(i=0; inKeyCol; i++){ i16 iIdxCol = pIdx->aiColumn[i]; - if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ + if( (iIdxCol>=0 && aXRef[iIdxCol]>=0) + || iIdxCol==XN_ROWID + || (iIdxCol==XN_EXPR + && indexExprRefsUpdatedColumn(pIdx,i,aXRef,chngRowid)) + ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; if( (onError==OE_Replace) diff --git a/test/indexexpr2.test b/test/indexexpr2.test index aed887a848..856992201e 100644 --- a/test/indexexpr2.test +++ b/test/indexexpr2.test @@ -159,5 +159,43 @@ do_execsql_test 3.4.6 { SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE binary; } {.ABC1 1 .ABC3 3 .abc2 2 .abc4 4} +# 2014-09-15: Verify that UPDATEs of columns not referenced by a +# index on expression do not modify the index. +# +unset -nocomplain cnt +set cnt 0 +proc refcnt {x} { + global cnt + incr cnt + return $x +} +db close +sqlite3 db :memory: +db function refcnt -deterministic refcnt +do_test 4.100 { + db eval { + CREATE TABLE t1(a,b,c,d,e,f); + CREATE INDEX t1abc ON t1(refcnt(a+b+c)); + } + set ::cnt +} {0} +do_test 4.110 { + db eval {INSERT INTO t1 VALUES(1,2,3,4,5,6);} + set ::cnt + # The refcnt() function is invoked once to compute the index value +} {1} +do_test 4.120 { + set ::cnt 0 + db eval {UPDATE t1 SET b=b+1;} + set ::cnt + # The refcnt() function is invoked twice, once to remove the old index + # entry and a second time to insert the new one. +} {2} +do_test 4.130 { + set ::cnt 0 + db eval {UPDATE t1 SET d=d+1;} + set ::cnt + # Refcnt() should not be invoked because that index does not change. +} {0} finish_test From 6a9afa918bdb05f727e8464fa3267c8114043660 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 15 Sep 2018 21:43:14 +0000 Subject: [PATCH 207/260] Increase the version number to 3.26.0 as we start the next development cycle. FossilOrigin-Name: 885f0f8252aae776a86c64bcc7da582f0ed58f2caae8ebff810a83ca339da820 --- VERSION | 2 +- configure | 18 +++++++++--------- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/VERSION b/VERSION index 0914443131..419ede3b9c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.25.0 +3.26.0 diff --git a/configure b/configure index 0d58c4a7d6..51653aa599 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.25.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.26.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -726,8 +726,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.25.0' -PACKAGE_STRING='sqlite 3.25.0' +PACKAGE_VERSION='3.26.0' +PACKAGE_STRING='sqlite 3.26.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1466,7 +1466,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.25.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1531,7 +1531,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.25.0:";; + short | recursive ) echo "Configuration of sqlite 3.26.0:";; esac cat <<\_ACEOF @@ -1657,7 +1657,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.25.0 +sqlite configure 3.26.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2076,7 +2076,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.25.0, which was +It was created by sqlite $as_me 3.26.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12232,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.25.0, which was +This file was extended by sqlite $as_me 3.26.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12298,7 +12298,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.25.0 +sqlite config.status 3.26.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/manifest b/manifest index 04f1f435c4..440891880d 100644 --- a/manifest +++ b/manifest @@ -1,12 +1,12 @@ -C Optimization:\swhen\sdoing\san\sUPDATE\son\sa\stable\swith\sindexes\son\san\sexpression,\ndo\snot\supdate\sthe\sexpression\sindexes\sif\sthey\sdo\snot\srefer\sto\sany\sof\sthe\ncolumns\sof\sthe\stable\sbeing\supdated. -D 2018-09-15T21:38:48.076 +C Increase\sthe\sversion\snumber\sto\s3.26.0\sas\swe\sstart\sthe\snext\sdevelopment\scycle. +D 2018-09-15T21:43:14.220 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a889c6981a222d639f8a548adcfb3183ac07871e27452ace4d810735750f216a F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee -F VERSION d3e3afdec1165a5e593dcdfffd8e0f33a2b0186067eb51a073ef6c4aec34923d +F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -33,7 +33,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure e80ab4e1f5c63a6979971712d35142ad69ef40da6ee4e4df3456be1a77439124 x +F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760 -R 3dbbbb152576c732493eb0793eda163f +P a71b101635ed28a4c99734dabb20bd65ef1018c1d63ac143b7321cdb0fafa5d7 +R f789e4a5b00a14bd183ffb1db488fa1d U drh -Z 14fba317833d2195e2283bec86cb6487 +Z 95fb510f742b1570e7d262774a3b689f diff --git a/manifest.uuid b/manifest.uuid index dbfdf2d5da..f6f159f71e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a71b101635ed28a4c99734dabb20bd65ef1018c1d63ac143b7321cdb0fafa5d7 \ No newline at end of file +885f0f8252aae776a86c64bcc7da582f0ed58f2caae8ebff810a83ca339da820 \ No newline at end of file From 2b7cdf6f6bef59774c16ee648b3945946a4d1ba6 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 16 Sep 2018 15:01:25 +0000 Subject: [PATCH 208/260] Improved presentation on the new code that prevents unnecessary writes to expressions on indexes during an UPDATE when the expression does not reference any of the columns that are changing. FossilOrigin-Name: c9f045295c4577752b0847ff2027b44661e6cb15bb08b942ccb3a0ef396f3dec --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/update.c | 21 ++++++++++----------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index 440891880d..8eb0bd6afc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.26.0\sas\swe\sstart\sthe\snext\sdevelopment\scycle. -D 2018-09-15T21:43:14.220 +C Improved\spresentation\son\sthe\snew\scode\sthat\sprevents\sunnecessary\swrites\sto\nexpressions\son\sindexes\sduring\san\sUPDATE\swhen\sthe\sexpression\sdoes\snot\sreference\nany\sof\sthe\scolumns\sthat\sare\schanging. +D 2018-09-16T15:01:25.994 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -567,7 +567,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd -F src/update.c deb215e3532be46e1e2b6aa38ed9e3eb96e42ebc4cbe7a498cd365788220a432 +F src/update.c 74feccd67570dcb731b6b6ee9960710a5e8a59c8403f2fa88f5eb82dbb8e36fa F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 @@ -1765,7 +1765,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a71b101635ed28a4c99734dabb20bd65ef1018c1d63ac143b7321cdb0fafa5d7 -R f789e4a5b00a14bd183ffb1db488fa1d +P 885f0f8252aae776a86c64bcc7da582f0ed58f2caae8ebff810a83ca339da820 +R 1d15143421504697e5d8ab90a5ba9295 U drh -Z 95fb510f742b1570e7d262774a3b689f +Z 8e73db792f1c5d12613e11c54c1867c6 diff --git a/manifest.uuid b/manifest.uuid index f6f159f71e..ee1b06ef03 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -885f0f8252aae776a86c64bcc7da582f0ed58f2caae8ebff810a83ca339da820 \ No newline at end of file +c9f045295c4577752b0847ff2027b44661e6cb15bb08b942ccb3a0ef396f3dec \ No newline at end of file diff --git a/src/update.c b/src/update.c index c9ec95bb65..2e14f161e0 100644 --- a/src/update.c +++ b/src/update.c @@ -84,18 +84,22 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ ** columns defined by aXRef and chngRowid. Return true if it does ** and false if not. ** -** The iCol-th column of pIdx will be an expression. -** ** aXRef[j] will be non-negative if column j of the original table is ** being updated. chngRowid will be true if the rowid of the table is ** being updated. */ -static int indexExprRefsUpdatedColumn( - Index *pIdx, /* The index containing the expression to analyze */ - int iCol, /* Which column of the index is the expression */ +static int indexColumnIsBeingUpdated( + Index *pIdx, /* The index to check */ + int iCol, /* Which column of the index to check */ int *aXRef, /* aXRef[j]>=0 if column j is being updated */ int chngRowid /* true if the rowid is being updated */ ){ + i16 iIdxCol = pIdx->aiColumn[iCol]; + if( iIdxCol>=0 ){ + return aXRef[iIdxCol]>=0; + } + if( iIdxCol==XN_ROWID ) return 1; + assert( iIdxCol==XN_EXPR ); assert( pIdx->aColExpr!=0 ); assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, @@ -334,12 +338,7 @@ void sqlite3Update( }else{ reg = 0; for(i=0; inKeyCol; i++){ - i16 iIdxCol = pIdx->aiColumn[i]; - if( (iIdxCol>=0 && aXRef[iIdxCol]>=0) - || iIdxCol==XN_ROWID - || (iIdxCol==XN_EXPR - && indexExprRefsUpdatedColumn(pIdx,i,aXRef,chngRowid)) - ){ + if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; if( (onError==OE_Replace) From 9b84f03556eea1c5d70d57c20e606796553cd494 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 16 Sep 2018 16:18:01 +0000 Subject: [PATCH 209/260] Add the new "explain" virtual table in ext/misc. Use this virtual table for additional test cases for the optimization that avoids updating indexes on expressions when none of the columns changed by the UPDATE are in the expression. FossilOrigin-Name: 2404304cc15eaeee2744cf3c8f9cac0a544631c4f1060c5a17a78b43ca86edf0 --- Makefile.in | 1 + Makefile.msc | 1 + ext/misc/explain.c | 308 +++++++++++++++++++++++++++++++++++++++++++ main.mk | 1 + manifest | 21 +-- manifest.uuid | 2 +- src/test1.c | 2 + test/indexexpr2.test | 32 +++++ 8 files changed, 357 insertions(+), 11 deletions(-) create mode 100644 ext/misc/explain.c diff --git a/Makefile.in b/Makefile.in index f84dcc25ee..96e2eb11f8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -437,6 +437,7 @@ TESTSRC += \ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/csv.c \ $(TOP)/ext/misc/eval.c \ + $(TOP)/ext/misc/explain.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/fts5/fts5_tcl.c \ diff --git a/Makefile.msc b/Makefile.msc index 4c6cdfba1d..b9fab7c408 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1515,6 +1515,7 @@ TESTEXT = \ $(TOP)\ext\misc\closure.c \ $(TOP)\ext\misc\csv.c \ $(TOP)\ext\misc\eval.c \ + $(TOP)\ext\misc\explain.c \ $(TOP)\ext\misc\fileio.c \ $(TOP)\ext\misc\fuzzer.c \ $(TOP)\ext\fts5\fts5_tcl.c \ diff --git a/ext/misc/explain.c b/ext/misc/explain.c new file mode 100644 index 0000000000..c2c8c07a5c --- /dev/null +++ b/ext/misc/explain.c @@ -0,0 +1,308 @@ +/* +** 2018-09-16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file demonstrates an eponymous virtual table that returns the +** EXPLAIN output from an SQL statement. +** +** Usage example: +** +** .load ./explain +** SELECT p2 FROM explain('SELECT * FROM sqlite_master') +** WHERE opcode='OpenRead'; +*/ +#if !defined(SQLITEINT_H) +#include "sqlite3ext.h" +#endif +SQLITE_EXTENSION_INIT1 +#include +#include + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* explain_vtab is a subclass of sqlite3_vtab which will +** serve as the underlying representation of a explain virtual table +*/ +typedef struct explain_vtab explain_vtab; +struct explain_vtab { + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this explain vtab */ +}; + +/* explain_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result from an EXPLAIN operation. +*/ +typedef struct explain_cursor explain_cursor; +struct explain_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this cursor */ + char *zSql; /* Value for the EXPLN_COLUMN_SQL column */ + sqlite3_stmt *pExplain; /* Statement being explained */ + int rc; /* Result of last sqlite3_step() on pExplain */ +}; + +/* +** The explainConnect() method is invoked to create a new +** explain_vtab that describes the explain virtual table. +** +** Think of this routine as the constructor for explain_vtab objects. +** +** All this routine needs to do is: +** +** (1) Allocate the explain_vtab object and initialize all fields. +** +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the +** result set of queries against explain will look like. +*/ +static int explainConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + explain_vtab *pNew; + int rc; + +/* Column numbers */ +#define EXPLN_COLUMN_ADDR 0 /* Instruction address */ +#define EXPLN_COLUMN_OPCODE 1 /* Opcode */ +#define EXPLN_COLUMN_P1 2 /* Operand 1 */ +#define EXPLN_COLUMN_P2 3 /* Operand 2 */ +#define EXPLN_COLUMN_P3 4 /* Operand 3 */ +#define EXPLN_COLUMN_P4 5 /* Operand 4 */ +#define EXPLN_COLUMN_P5 6 /* Operand 5 */ +#define EXPLN_COLUMN_COMMENT 7 /* Comment */ +#define EXPLN_COLUMN_SQL 8 /* SQL that is being explained */ + + + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(addr,opcode,p1,p2,p3,p4,p5,comment,sql HIDDEN)"); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); + *ppVtab = (sqlite3_vtab*)pNew; + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + pNew->db = db; + } + return rc; +} + +/* +** This method is the destructor for explain_cursor objects. +*/ +static int explainDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** Constructor for a new explain_cursor object. +*/ +static int explainOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + explain_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + pCur->db = ((explain_vtab*)p)->db; + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Destructor for a explain_cursor. +*/ +static int explainClose(sqlite3_vtab_cursor *cur){ + explain_cursor *pCur = (explain_cursor*)cur; + sqlite3_finalize(pCur->pExplain); + sqlite3_free(pCur->zSql); + sqlite3_free(pCur); + return SQLITE_OK; +} + + +/* +** Advance a explain_cursor to its next row of output. +*/ +static int explainNext(sqlite3_vtab_cursor *cur){ + explain_cursor *pCur = (explain_cursor*)cur; + pCur->rc = sqlite3_step(pCur->pExplain); + if( pCur->rc!=SQLITE_DONE && pCur->rc!=SQLITE_ROW ) return pCur->rc; + return SQLITE_OK; +} + +/* +** Return values of columns for the row at which the explain_cursor +** is currently pointing. +*/ +static int explainColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + explain_cursor *pCur = (explain_cursor*)cur; + if( i==EXPLN_COLUMN_SQL ){ + sqlite3_result_text(ctx, pCur->zSql, -1, SQLITE_TRANSIENT); + }else{ + sqlite3_result_value(ctx, sqlite3_column_value(pCur->pExplain, i)); + } + return SQLITE_OK; +} + +/* +** Return the rowid for the current row. In this implementation, the +** rowid is the same as the output value. +*/ +static int explainRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + explain_cursor *pCur = (explain_cursor*)cur; + *pRowid = sqlite3_column_int64(pCur->pExplain, 0); + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int explainEof(sqlite3_vtab_cursor *cur){ + explain_cursor *pCur = (explain_cursor*)cur; + return pCur->rc!=SQLITE_ROW; +} + +/* +** This method is called to "rewind" the explain_cursor object back +** to the first row of output. This method is always called at least +** once prior to any call to explainColumn() or explainRowid() or +** explainEof(). +** +** The argv[0] is the SQL statement that is to be explained. +*/ +static int explainFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + explain_cursor *pCur = (explain_cursor *)pVtabCursor; + char *zSql = 0; + int rc; + sqlite3_finalize(pCur->pExplain); + pCur->pExplain = 0; + if( sqlite3_value_type(argv[0])!=SQLITE_TEXT ){ + pCur->rc = SQLITE_DONE; + return SQLITE_OK; + } + sqlite3_free(pCur->zSql); + pCur->zSql = sqlite3_mprintf("%s", sqlite3_value_text(argv[0])); + if( pCur->zSql ){ + zSql = sqlite3_mprintf("EXPLAIN %s", pCur->zSql); + } + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0); + } + if( rc ){ + sqlite3_finalize(pCur->pExplain); + pCur->pExplain = 0; + sqlite3_free(pCur->zSql); + pCur->zSql = 0; + }else{ + pCur->rc = sqlite3_step(pCur->pExplain); + rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc; + } + return rc; +} + +/* +** SQLite will invoke this method one or more times while planning a query +** that uses the explain virtual table. This routine needs to create +** a query plan for each invocation and compute an estimated cost for that +** plan. +*/ +static int explainBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; + + pIdxInfo->estimatedCost = (double)1000000; + pIdxInfo->estimatedRows = 500; + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; + if( p->usable + && p->iColumn==EXPLN_COLUMN_SQL + && p->op==SQLITE_INDEX_CONSTRAINT_EQ + ){ + pIdxInfo->estimatedCost = 10.0; + pIdxInfo->idxNum = 1; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + break; + } + } + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the +** explain virtual table. +*/ +static sqlite3_module explainModule = { + 0, /* iVersion */ + 0, /* xCreate */ + explainConnect, /* xConnect */ + explainBestIndex, /* xBestIndex */ + explainDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + explainOpen, /* xOpen - open a cursor */ + explainClose, /* xClose - close a cursor */ + explainFilter, /* xFilter - configure scan constraints */ + explainNext, /* xNext - advance a cursor */ + explainEof, /* xEof - check for end of scan */ + explainColumn, /* xColumn - read data */ + explainRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +int sqlite3ExplainVtabInit(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "explain", &explainModule, 0); +#endif + return rc; +} + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_explain_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3ExplainVtabInit(db); +#endif + return rc; +} diff --git a/main.mk b/main.mk index f32624dfd3..1df68076c1 100644 --- a/main.mk +++ b/main.mk @@ -361,6 +361,7 @@ TESTSRC += \ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/csv.c \ $(TOP)/ext/misc/eval.c \ + $(TOP)/ext/misc/explain.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/misc/ieee754.c \ diff --git a/manifest b/manifest index 8eb0bd6afc..015c3618f7 100644 --- a/manifest +++ b/manifest @@ -1,10 +1,10 @@ -C Improved\spresentation\son\sthe\snew\scode\sthat\sprevents\sunnecessary\swrites\sto\nexpressions\son\sindexes\sduring\san\sUPDATE\swhen\sthe\sexpression\sdoes\snot\sreference\nany\sof\sthe\scolumns\sthat\sare\schanging. -D 2018-09-16T15:01:25.994 +C Add\sthe\snew\s"explain"\svirtual\stable\sin\sext/misc.\s\sUse\sthis\svirtual\stable\nfor\sadditional\stest\scases\sfor\sthe\soptimization\sthat\savoids\supdating\sindexes\non\sexpressions\swhen\snone\sof\sthe\scolumns\schanged\sby\sthe\sUPDATE\sare\sin\sthe\nexpression. +D 2018-09-16T16:18:01.470 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea -F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 +F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc a889c6981a222d639f8a548adcfb3183ac07871e27452ace4d810735750f216a +F Makefile.msc b946f8806a5d401a299453f61de80dfd1a9df14fa4902b299e6465e3c3134872 F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -281,6 +281,7 @@ F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f0 F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657 F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3 +F ext/misc/explain.c 657b95855157379b406af602ed0e1cf5d136c0947cdd207fa5470797c8a1ce18 F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f83069fd F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c @@ -423,7 +424,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 1db6df4bff24ed6684917e3fe311ce28f5924d6417c698fe4326f7cadf02df31 +F main.mk ff82d38126f8f0668b7990e0f1f3dcd74fa2d477c19b2e3feaaba586051e9b48 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -511,7 +512,7 @@ F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c e0bf71a6d24b8c23393c000abffab05979bbca2a72d0b0f79260e2cf1527fda5 -F src/test1.c 31c491ccb536bd9916a084e732ffe783b3c8973f2586d5a56aed0e3a9701dfff +F src/test1.c 9bb042e4afedc570f78638993fc9cc1760d897d3b27dd72c20618044b2a8fa5e F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 @@ -1007,7 +1008,7 @@ F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e -F test/indexexpr2.test 05f490de32b07bce041947cb63475eb04cbd5af2ea2979ca6b9a694cde176efd +F test/indexexpr2.test d8f56b6cf4e5663486129bc18c6bde4cef9f8876942b001bfdd692a2b1a42668 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a @@ -1765,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 885f0f8252aae776a86c64bcc7da582f0ed58f2caae8ebff810a83ca339da820 -R 1d15143421504697e5d8ab90a5ba9295 +P c9f045295c4577752b0847ff2027b44661e6cb15bb08b942ccb3a0ef396f3dec +R 58a4dfba8e02bbbb06c952d22469b1fa U drh -Z 8e73db792f1c5d12613e11c54c1867c6 +Z ae02262bf6d409f9ac69a0871114af64 diff --git a/manifest.uuid b/manifest.uuid index ee1b06ef03..1c4ba86291 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9f045295c4577752b0847ff2027b44661e6cb15bb08b942ccb3a0ef396f3dec \ No newline at end of file +2404304cc15eaeee2744cf3c8f9cac0a544631c4f1060c5a17a78b43ca86edf0 \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index 7f301714bd..d2c997bdfe 100644 --- a/src/test1.c +++ b/src/test1.c @@ -7038,6 +7038,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd( extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*); + extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); @@ -7062,6 +7063,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd( { "closure", sqlite3_closure_init }, { "csv", sqlite3_csv_init }, { "eval", sqlite3_eval_init }, + { "explain", sqlite3_explain_init }, { "fileio", sqlite3_fileio_init }, { "fuzzer", sqlite3_fuzzer_init }, { "ieee754", sqlite3_ieee_init }, diff --git a/test/indexexpr2.test b/test/indexexpr2.test index 856992201e..3fa3faf87a 100644 --- a/test/indexexpr2.test +++ b/test/indexexpr2.test @@ -198,4 +198,36 @@ do_test 4.130 { # Refcnt() should not be invoked because that index does not change. } {0} +# Additional test cases to show that UPDATE does not modify indexes that +# do not involve unchanged columns. +# +load_static_extension db explain +do_execsql_test 4.200 { + CREATE TABLE t2(a,b,c,d,e,f); + INSERT INTO t2 VALUES(2,3,4,5,6,7); + CREATE INDEX t2abc ON t2(a+b+c); + CREATE INDEX t2cd ON t2(c*d); + CREATE INDEX t2def ON t2(d,e+25*f); + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET b=b+1') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; +} {t2 t2abc} +do_execsql_test 4.210 { + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET c=c+1') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; +} {t2 t2abc t2cd} +do_execsql_test 4.220 { + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; +} {t2 t2abc t2cd t2def} + + finish_test From 6557a07ca8a7b8aad6ebf0c5c6102a5f86c1ba82 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 16 Sep 2018 16:34:31 +0000 Subject: [PATCH 210/260] Fix a memory leak in the explain extension. FossilOrigin-Name: d0c92b047a5355726aea87f38038e5bda3adf6137492919be94bd29bb847eddb --- ext/misc/explain.c | 1 + manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ext/misc/explain.c b/ext/misc/explain.c index c2c8c07a5c..b228440f58 100644 --- a/ext/misc/explain.c +++ b/ext/misc/explain.c @@ -208,6 +208,7 @@ static int explainFilter( rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0); + sqlite3_free(zSql); } if( rc ){ sqlite3_finalize(pCur->pExplain); diff --git a/manifest b/manifest index 015c3618f7..49d43aeba6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\snew\s"explain"\svirtual\stable\sin\sext/misc.\s\sUse\sthis\svirtual\stable\nfor\sadditional\stest\scases\sfor\sthe\soptimization\sthat\savoids\supdating\sindexes\non\sexpressions\swhen\snone\sof\sthe\scolumns\schanged\sby\sthe\sUPDATE\sare\sin\sthe\nexpression. -D 2018-09-16T16:18:01.470 +C Fix\sa\smemory\sleak\sin\sthe\sexplain\sextension. +D 2018-09-16T16:34:31.947 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -281,7 +281,7 @@ F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f0 F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657 F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3 -F ext/misc/explain.c 657b95855157379b406af602ed0e1cf5d136c0947cdd207fa5470797c8a1ce18 +F ext/misc/explain.c 5851a1a4a1bba6e078da4103fcafc84aa54adfd8edbba419f5cf1eba9f000d50 F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f83069fd F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c9f045295c4577752b0847ff2027b44661e6cb15bb08b942ccb3a0ef396f3dec -R 58a4dfba8e02bbbb06c952d22469b1fa +P 2404304cc15eaeee2744cf3c8f9cac0a544631c4f1060c5a17a78b43ca86edf0 +R adb45010554cac59e3a349d9c44c8ea1 U drh -Z ae02262bf6d409f9ac69a0871114af64 +Z d3428e60bf87865d7969feaa7735e32f diff --git a/manifest.uuid b/manifest.uuid index 1c4ba86291..5c03e13318 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2404304cc15eaeee2744cf3c8f9cac0a544631c4f1060c5a17a78b43ca86edf0 \ No newline at end of file +d0c92b047a5355726aea87f38038e5bda3adf6137492919be94bd29bb847eddb \ No newline at end of file From 86f349265074e8801f405cdc4677ff838e8614ba Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 16 Sep 2018 18:23:48 +0000 Subject: [PATCH 211/260] Remove an unreachable branch from the index-on-expression optimization. FossilOrigin-Name: 2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/update.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 49d43aeba6..7dda1dfbb7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\smemory\sleak\sin\sthe\sexplain\sextension. -D 2018-09-16T16:34:31.947 +C Remove\san\sunreachable\sbranch\sfrom\sthe\sindex-on-expression\soptimization. +D 2018-09-16T18:23:48.660 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -568,7 +568,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd -F src/update.c 74feccd67570dcb731b6b6ee9960710a5e8a59c8403f2fa88f5eb82dbb8e36fa +F src/update.c 52d926be53e011050b0ed1d6d1a09d268ffb864ce875bf3a8ce4cd1b1b8b616e F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2404304cc15eaeee2744cf3c8f9cac0a544631c4f1060c5a17a78b43ca86edf0 -R adb45010554cac59e3a349d9c44c8ea1 +P d0c92b047a5355726aea87f38038e5bda3adf6137492919be94bd29bb847eddb +R 15742f49a8284f0d50788336ea1ceec8 U drh -Z d3428e60bf87865d7969feaa7735e32f +Z 742041dc2da982886153478b782feb91 diff --git a/manifest.uuid b/manifest.uuid index 5c03e13318..3ce9051c72 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d0c92b047a5355726aea87f38038e5bda3adf6137492919be94bd29bb847eddb \ No newline at end of file +2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee \ No newline at end of file diff --git a/src/update.c b/src/update.c index 2e14f161e0..9e76c445ea 100644 --- a/src/update.c +++ b/src/update.c @@ -95,10 +95,10 @@ static int indexColumnIsBeingUpdated( int chngRowid /* true if the rowid is being updated */ ){ i16 iIdxCol = pIdx->aiColumn[iCol]; + assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */ if( iIdxCol>=0 ){ return aXRef[iIdxCol]>=0; } - if( iIdxCol==XN_ROWID ) return 1; assert( iIdxCol==XN_EXPR ); assert( pIdx->aColExpr!=0 ); assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); From 95f78d98b968781e4b08b9f6063793aa33193890 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 16 Sep 2018 23:27:37 +0000 Subject: [PATCH 212/260] First proposed fix for the ALTER TABLE problem described by ticket [b41031ea2b5372378cb3d2d] FossilOrigin-Name: 05a9d129254e01a5f6b5e4033c105190eae386575a94b020ef3e0cbd30bbf056 --- manifest | 17 ++++++++++------- manifest.uuid | 2 +- src/resolve.c | 4 +++- test/alter.test | 20 +++++++++++++++++++- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 7dda1dfbb7..03f188a18e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunreachable\sbranch\sfrom\sthe\sindex-on-expression\soptimization. -D 2018-09-16T18:23:48.660 +C First\sproposed\sfix\sfor\sthe\sALTER\sTABLE\sproblem\sdescribed\sby\sticket\n[b41031ea2b5372378cb3d2d] +D 2018-09-16T23:27:37.486 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -500,7 +500,7 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b +F src/resolve.c c1bc3a26460721d2cba0797f59879fd53bd6c841afa00b8b31642c0dfd1fdf3c F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f @@ -599,7 +599,7 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13 -F test/alter.test cf28c2f35253d3395cf16334fb9dde1d8c4b035cb7c89204353ee1f47feaec1b +F test/alter.test 99e72759d48d6531ac2a9f346b4a9b5fe8f89c67a0fa5e916a3990d3b1fe9d09 F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3 F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433 @@ -1766,7 +1766,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d0c92b047a5355726aea87f38038e5bda3adf6137492919be94bd29bb847eddb -R 15742f49a8284f0d50788336ea1ceec8 +P 2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee +R fe632daa0f368e2d5f1d4be59c87d7ab +T *branch * tkt-b41031ea +T *sym-tkt-b41031ea * +T -sym-trunk * U drh -Z 742041dc2da982886153478b782feb91 +Z 491184a3fb91134029b6eaff416a99f5 diff --git a/manifest.uuid b/manifest.uuid index 3ce9051c72..4858388b5f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee \ No newline at end of file +05a9d129254e01a5f6b5e4033c105190eae386575a94b020ef3e0cbd30bbf056 \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index 9fb4d4c63f..017b026de3 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -240,7 +240,9 @@ static int lookupName( for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); - assert( pTab->nCol>0 ); + if( pTab->nCol==0 ){ + if( sqlite3ViewGetColumnNames(pNC->pParse, pTab) ) return WRC_Abort; + } if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ int hit = 0; pEList = pItem->pSelect->pEList; diff --git a/test/alter.test b/test/alter.test index 520c54689e..807a8f0171 100644 --- a/test/alter.test +++ b/test/alter.test @@ -875,5 +875,23 @@ do_execsql_test alter-16.2 { SELECT * FROM t16a_rn ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} -finish_test +# 2018-09-16 ticket b41031ea2b5372378cb3d2d43cf9fe2a4a5c2510 +# +ifcapable rtree { + db close + sqlite3 db :memory: + do_execsql_test alter-17.100 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE VIRTUAL TABLE t2 USING rtree(id,x0,x1); + INSERT INTO t1 VALUES(1,'apple'),(2,'fig'),(3,'pear'); + INSERT INTO t2 VALUES(1,1.0,2.0),(2,2.0,3.0),(3,1.5,3.5); + CREATE TRIGGER r1 AFTER UPDATE ON t1 BEGIN + DELETE FROM t2 WHERE id = OLD.a; + END; + ALTER TABLE t1 RENAME TO t3; + UPDATE t3 SET b='peach' WHERE a=2; + SELECT * FROM t2 ORDER BY 1; + } {1 1.0 2.0 3 1.5 3.5} +} +finish_test From e68fe9665abfe477c1b2ebcae3554cd9a0352267 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Sep 2018 00:15:21 +0000 Subject: [PATCH 213/260] Add assert()s to the new code in the previous check-in. FossilOrigin-Name: b12f23a5c484cab3654721299ea0f05230eef6b14012b557f3bf2592fac0f00e --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/resolve.c | 5 ++++- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 03f188a18e..6fba155647 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C First\sproposed\sfix\sfor\sthe\sALTER\sTABLE\sproblem\sdescribed\sby\sticket\n[b41031ea2b5372378cb3d2d] -D 2018-09-16T23:27:37.486 +C Add\sassert()s\sto\sthe\snew\scode\sin\sthe\sprevious\scheck-in. +D 2018-09-17T00:15:21.614 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -500,7 +500,7 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c c1bc3a26460721d2cba0797f59879fd53bd6c841afa00b8b31642c0dfd1fdf3c +F src/resolve.c c32f4c9473207e0434489582161867e92548128492112e756d5b0dd248567bfe F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f @@ -1766,10 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee -R fe632daa0f368e2d5f1d4be59c87d7ab -T *branch * tkt-b41031ea -T *sym-tkt-b41031ea * -T -sym-trunk * +P 05a9d129254e01a5f6b5e4033c105190eae386575a94b020ef3e0cbd30bbf056 +R 06efc1c5b094a00f26fafeb2dea6c95e U drh -Z 491184a3fb91134029b6eaff416a99f5 +Z 392095af0ce931065bb28167458f689d diff --git a/manifest.uuid b/manifest.uuid index 4858388b5f..0422c97fde 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -05a9d129254e01a5f6b5e4033c105190eae386575a94b020ef3e0cbd30bbf056 \ No newline at end of file +b12f23a5c484cab3654721299ea0f05230eef6b14012b557f3bf2592fac0f00e \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index 017b026de3..b10843ca09 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -241,7 +241,10 @@ static int lookupName( pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); if( pTab->nCol==0 ){ - if( sqlite3ViewGetColumnNames(pNC->pParse, pTab) ) return WRC_Abort; + assert( pParse->eParseMode==PARSE_MODE_RENAME_COLUMN + || pParse->eParseMode==PARSE_MODE_RENAME_TABLE ); + assert( pNC->pParse==pParse ); + if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; } if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ int hit = 0; From 0208337c16f99a56885ad4067712b76a75019040 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Sep 2018 08:27:23 +0000 Subject: [PATCH 214/260] Add extra test for the fix on this branch. Also fix a pointer-compare-after-free problem that occurs in similar cases. FossilOrigin-Name: 1856ea63b3186c2c8fa716ffe01c731397bdbbc3fbb56dc72ad0686cb7f152ca --- manifest | 16 +++++++-------- manifest.uuid | 2 +- src/build.c | 7 +++++++ test/altertab.test | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 6fba155647..de77e631f8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sassert()s\sto\sthe\snew\scode\sin\sthe\sprevious\scheck-in. -D 2018-09-17T00:15:21.614 +C Add\sextra\stest\sfor\sthe\sfix\son\sthis\sbranch.\sAlso\sfix\sa\npointer-compare-after-free\sproblem\sthat\soccurs\sin\ssimilar\scases. +D 2018-09-17T08:27:23.927 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -446,7 +446,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 -F src/build.c 90571aa2a9eb44e04291ffe9984c814883b9eb371f89898accec384520369597 +F src/build.c 3bdd61d7ecba6f40e7efead3ffb61b2e3bad87de73f407c288035937c9b33687 F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387 @@ -607,7 +607,7 @@ F test/alterauth.test dc50064e3d57d60cf8708decefed15cfa154242f6d44069858d4c6c9b1 F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/altermalloc2.test 0231398534c494401a70a1d06a63d7849cb5b317fcc14228cbdb53039eba7eae -F test/altertab.test fe08624ef1554b85c943ac6289f591e2e9984704a6b35b94613af42cc92ba474 +F test/altertab.test 3b830144c18ae00abd2a27e3d2851c8bb1ee8fe655fa16d8a5971066dc71b58a F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8 @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 05a9d129254e01a5f6b5e4033c105190eae386575a94b020ef3e0cbd30bbf056 -R 06efc1c5b094a00f26fafeb2dea6c95e -U drh -Z 392095af0ce931065bb28167458f689d +P b12f23a5c484cab3654721299ea0f05230eef6b14012b557f3bf2592fac0f00e +R fdc93ad4d417c5a17eda517310446c18 +U dan +Z 0a0cf7b3375e76f2b517ca3739e2db01 diff --git a/manifest.uuid b/manifest.uuid index 0422c97fde..8e6555a42b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b12f23a5c484cab3654721299ea0f05230eef6b14012b557f3bf2592fac0f00e \ No newline at end of file +1856ea63b3186c2c8fa716ffe01c731397bdbbc3fbb56dc72ad0686cb7f152ca \ No newline at end of file diff --git a/src/build.c b/src/build.c index cbdfafe090..65b9107118 100644 --- a/src/build.c +++ b/src/build.c @@ -2287,6 +2287,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ assert( pTable->pSelect ); pSel = sqlite3SelectDup(db, pTable->pSelect, 0); if( pSel ){ +#ifndef SQLITE_OMIT_ALTERTABLE + u8 eParseMode = pParse->eParseMode; + pParse->eParseMode = PARSE_MODE_NORMAL; +#endif n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; @@ -2332,6 +2336,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ sqlite3DeleteTable(db, pSelTab); sqlite3SelectDelete(db, pSel); db->lookaside.bDisable--; +#ifndef SQLITE_OMIT_ALTERTABLE + pParse->eParseMode = eParseMode; +#endif } else { nErr++; } diff --git a/test/altertab.test b/test/altertab.test index a1ccccce2c..008ac1153d 100644 --- a/test/altertab.test +++ b/test/altertab.test @@ -411,5 +411,55 @@ do_catchsql_test 13.2 { ALTER TABLE t2 RENAME b TO y; } {1 {error in trigger tr1 after rename: ambiguous column name: y}} +#------------------------------------------------------------------------- +reset_db + +ifcapable rtree { + do_execsql_test 14.0 { + CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy); + + CREATE TABLE "mytable" ( "fid" INTEGER PRIMARY KEY, "geom" BLOB); + + CREATE TRIGGER tr1 AFTER UPDATE OF "geom" ON "mytable" + WHEN OLD."fid" = NEW."fid" AND NEW."geom" IS NULL BEGIN + DELETE FROM rt WHERE id = OLD."fid"; + END; + + INSERT INTO mytable VALUES(1, X'abcd'); + } + + do_execsql_test 14.1 { + UPDATE mytable SET geom = X'1234' + } + + do_execsql_test 14.2 { + ALTER TABLE mytable RENAME TO mytable_renamed; + } + + do_execsql_test 14.3 { + CREATE TRIGGER tr2 AFTER INSERT ON mytable_renamed BEGIN + DELETE FROM rt WHERE id=(SELECT min(id) FROM rt); + END; + } + + do_execsql_test 14.4 { + ALTER TABLE mytable_renamed RENAME TO mytable2; + } +} + +reset_db +do_execsql_test 14.5 { + CREATE TABLE t1(a, b, c); + CREATE VIEW v1 AS SELECT * FROM t1; + CREATE TRIGGER xyz AFTER INSERT ON t1 BEGIN + SELECT a, b FROM v1; + END; +} +do_execsql_test 14.6 { + ALTER TABLE t1 RENAME TO tt1; +} + + + finish_test From 746127e734087408aca706bee3bfc4b6889d71cc Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 17 Sep 2018 12:49:21 +0000 Subject: [PATCH 215/260] Fix missing space in 'configure.ac' reported on the mailing list. FossilOrigin-Name: 96b00a3cd2273dd3baa8e5b7a441458b142d4d2daabc679e4fcb5ab706674e76 --- autoconf/configure.ac | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 9c23492f95..82ab43dfa8 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -172,7 +172,7 @@ AC_ARG_ENABLE(session, [AS_HELP_STRING( [--enable-session], [enable the session extension [default=no]])], [], []) if test x"$enable_session" = "xyes"; then - BUILD_CFLAGS="$BUILD_CFLAGS-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" + BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" fi #----------------------------------------------------------------------- diff --git a/manifest b/manifest index 7dda1dfbb7..1c0edef142 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunreachable\sbranch\sfrom\sthe\sindex-on-expression\soptimization. -D 2018-09-16T18:23:48.660 +C Fix\smissing\sspace\sin\s'configure.ac'\sreported\son\sthe\smailing\slist. +D 2018-09-17T12:49:21.213 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -17,7 +17,7 @@ F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a F autoconf/Makefile.msc 9e73d9abaadb7a4951ddd0e947c5c791770f23bb1e04bfa50b43c01bee0575f2 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 -F autoconf/configure.ac 573b98629d6963e6d9bf2897c3f4708fb94ce49897822526ad268181875e1736 +F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43 @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d0c92b047a5355726aea87f38038e5bda3adf6137492919be94bd29bb847eddb -R 15742f49a8284f0d50788336ea1ceec8 -U drh -Z 742041dc2da982886153478b782feb91 +P 2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee +R 6ec6307d67568ac3e0091078ce4674be +U mistachkin +Z e4f2ee688b66b0e845e087bd7ec53780 diff --git a/manifest.uuid b/manifest.uuid index 3ce9051c72..8f32424f2a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee \ No newline at end of file +96b00a3cd2273dd3baa8e5b7a441458b142d4d2daabc679e4fcb5ab706674e76 \ No newline at end of file From de79e094bc1a804862e9766f70976fc4c4e97d3a Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Sep 2018 13:38:45 +0000 Subject: [PATCH 216/260] Minor modification to the fix on this branch to avoid adding extra conditional compilation macros. FossilOrigin-Name: 4d8be404dab265b51e5a6a95e83be85c22512e19a437191690c7d845c87ff259 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/alter.c | 2 +- src/resolve.c | 6 ------ 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index de77e631f8..6a164c052c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sextra\stest\sfor\sthe\sfix\son\sthis\sbranch.\sAlso\sfix\sa\npointer-compare-after-free\sproblem\sthat\soccurs\sin\ssimilar\scases. -D 2018-09-17T08:27:23.927 +C Minor\smodification\sto\sthe\sfix\son\sthis\sbranch\sto\savoid\sadding\sextra\sconditional\ncompilation\smacros. +D 2018-09-17T13:38:45.679 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -436,7 +436,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 3800f24c922dfcab2e7a05b49123e2f9c903c26fccea71a5f9ac765e91949355 +F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114 @@ -500,7 +500,7 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c c32f4c9473207e0434489582161867e92548128492112e756d5b0dd248567bfe +F src/resolve.c 4928a63b6abf6baa94efc5375004196fc8b704d4f036a4cce6e4f2e07f53c4b5 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b12f23a5c484cab3654721299ea0f05230eef6b14012b557f3bf2592fac0f00e -R fdc93ad4d417c5a17eda517310446c18 +P 1856ea63b3186c2c8fa716ffe01c731397bdbbc3fbb56dc72ad0686cb7f152ca +R 6e72766cd421e67b35e1efbd11675502 U dan -Z 0a0cf7b3375e76f2b517ca3739e2db01 +Z 8ad44f59cac49311751e10cb991dd243 diff --git a/manifest.uuid b/manifest.uuid index 8e6555a42b..e3891237b7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1856ea63b3186c2c8fa716ffe01c731397bdbbc3fbb56dc72ad0686cb7f152ca \ No newline at end of file +4d8be404dab265b51e5a6a95e83be85c22512e19a437191690c7d845c87ff259 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index c33dfdfb85..08745ccee2 100644 --- a/src/alter.c +++ b/src/alter.c @@ -1076,7 +1076,7 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){ Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb); if( pTarget==0 ){ rc = SQLITE_ERROR; - }else{ + }else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){ SrcList sSrc; memset(&sSrc, 0, sizeof(sSrc)); sSrc.nSrc = 1; diff --git a/src/resolve.c b/src/resolve.c index b10843ca09..d5c4b42ada 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -240,12 +240,6 @@ static int lookupName( for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); - if( pTab->nCol==0 ){ - assert( pParse->eParseMode==PARSE_MODE_RENAME_COLUMN - || pParse->eParseMode==PARSE_MODE_RENAME_TABLE ); - assert( pNC->pParse==pParse ); - if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; - } if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ int hit = 0; pEList = pItem->pSelect->pEList; From e597c47545aa5db5cec581542c87e4108db99d56 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Sep 2018 13:55:18 +0000 Subject: [PATCH 217/260] Restore an assert() that was present on trunk. FossilOrigin-Name: a7b572ca7867a95f49888dc95c0dc6d726afa9fea26283be147ba422639d1307 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/resolve.c | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 6a164c052c..dbf6ef6918 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\smodification\sto\sthe\sfix\son\sthis\sbranch\sto\savoid\sadding\sextra\sconditional\ncompilation\smacros. -D 2018-09-17T13:38:45.679 +C Restore\san\sassert()\sthat\swas\spresent\son\strunk. +D 2018-09-17T13:55:18.143 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -500,7 +500,7 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 4928a63b6abf6baa94efc5375004196fc8b704d4f036a4cce6e4f2e07f53c4b5 +F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1856ea63b3186c2c8fa716ffe01c731397bdbbc3fbb56dc72ad0686cb7f152ca -R 6e72766cd421e67b35e1efbd11675502 -U dan -Z 8ad44f59cac49311751e10cb991dd243 +P 4d8be404dab265b51e5a6a95e83be85c22512e19a437191690c7d845c87ff259 +R b0210376dae3a6dbba696619be40dcd0 +U drh +Z 4dfef6ec80ce5527a940e761bd4de33e diff --git a/manifest.uuid b/manifest.uuid index e3891237b7..ca60fa17a4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4d8be404dab265b51e5a6a95e83be85c22512e19a437191690c7d845c87ff259 \ No newline at end of file +a7b572ca7867a95f49888dc95c0dc6d726afa9fea26283be147ba422639d1307 \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index d5c4b42ada..9fb4d4c63f 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -240,6 +240,7 @@ static int lookupName( for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); + assert( pTab->nCol>0 ); if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ int hit = 0; pEList = pItem->pSelect->pEList; From d4cb09e3d26a2b507bf781b168922da81bb54b53 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Sep 2018 15:19:13 +0000 Subject: [PATCH 218/260] Disable the ORDER BY LIMIT optimization in queries using window functions. This fixes a problem that was introduced by check-in [206720129ed2fa8875a286] which attempted to fix ticket [9936b2fa443fec03ff25f9]. This changes is a fix for the follow-in tocket [510cde277783b5fb5de628]. FossilOrigin-Name: c6c9585f294710829ca24b64d70a36fd9f409261dd0661367c6c4198cdbc4c81 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/select.c | 1 + test/window1.test | 24 +++++++++++++++++++++++- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 3a9a996c3b..270cb9b99d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sfalse-positive\sin\sthe\spost-ALTER-TABLE\sschema\sverification\slogic\sthat\nprevents\sALTER\sTABLE\sfrom\sworking\sif\sthe\stable\sbeing\saltered\shas\sa\strigger\nthat\sreferences\sany\scolumn\sof\sa\svirtual\stable.\sTicket\s[b41031ea2b537237]. -D 2018-09-17T14:13:48.435 +C Disable\sthe\sORDER\sBY\sLIMIT\soptimization\sin\squeries\susing\swindow\sfunctions.\nThis\sfixes\sa\sproblem\sthat\swas\sintroduced\sby\scheck-in\s[206720129ed2fa8875a286]\nwhich\sattempted\sto\sfix\sticket\s[9936b2fa443fec03ff25f9].\s\sThis\schanges\sis\na\sfix\sfor\sthe\sfollow-in\stocket\s[510cde277783b5fb5de628]. +D 2018-09-17T15:19:13.491 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -502,7 +502,7 @@ F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a +F src/select.c 8afcc2b56a6ef76717bb59b6109cd3de0f6fae2803894d6f806640c0aa24dfac F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1640,7 +1640,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/window1.test 7cb260079cd88d6d6177b0f592686f2bbbc2d10f4f415c8a37cd153eb83c87ca +F test/window1.test 474bef1a6ac291755e51d1f9458dc11117c1870ac5e08b4d3938649b215f8334 F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143 F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823 @@ -1766,8 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 96b00a3cd2273dd3baa8e5b7a441458b142d4d2daabc679e4fcb5ab706674e76 a7b572ca7867a95f49888dc95c0dc6d726afa9fea26283be147ba422639d1307 -R 4daad1cccc245033b23027d4ea969738 -T +closed a7b572ca7867a95f49888dc95c0dc6d726afa9fea26283be147ba422639d1307 +P 84105ea4af98bd8bddbdf9dc6674bdf73c110c0685afe868ce9681da110144d7 +R d2a6dffbc9b7eb5b0ff50ff6a5285151 U drh -Z 5ec0041f694b3ca4e0518a2092154271 +Z 632a6055521a5e1b8d0c8917d051318b diff --git a/manifest.uuid b/manifest.uuid index 7f0a23c86d..eae237c4d8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -84105ea4af98bd8bddbdf9dc6674bdf73c110c0685afe868ce9681da110144d7 \ No newline at end of file +c6c9585f294710829ca24b64d70a36fd9f409261dd0661367c6c4198cdbc4c81 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 35dc9f1b71..bc5960fe49 100644 --- a/src/select.c +++ b/src/select.c @@ -6086,6 +6086,7 @@ int sqlite3Select( sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); sqlite3VdbeResolveLabel(v, addrGosub); VdbeNoopComment((v, "inner-loop subroutine")); + sSort.labelOBLopt = 0; selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp1(v, OP_Return, regGosub); diff --git a/test/window1.test b/test/window1.test index ee705deb0c..4980305449 100644 --- a/test/window1.test +++ b/test/window1.test @@ -526,5 +526,27 @@ do_catchsql_test 11.4 { CREATE INDEX t6i ON t6(lead(b) OVER ()); } {1 {misuse of window function lead()}} -finish_test +# 2018-09-17 ticket 510cde277783b5fb5de628393959849dff377eb3 +# Endless loop on a query with window functions and a limit +# +do_execsql_test 12.100 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(id INT, b VARCHAR, c VARCHAR); + INSERT INTO t1 VALUES(1, 'A', 'one'); + INSERT INTO t1 VALUES(2, 'B', 'two'); + INSERT INTO t1 VALUES(3, 'C', 'three'); + INSERT INTO t1 VALUES(4, 'D', 'one'); + INSERT INTO t1 VALUES(5, 'E', 'two'); + SELECT id, b, lead(c,1) OVER(ORDER BY c) AS x + FROM t1 WHERE id>1 + ORDER BY b LIMIT 1; +} {2 B two} +do_execsql_test 12.110 { + INSERT INTO t1 VALUES(6, 'F', 'three'); + INSERT INTO t1 VALUES(7, 'G', 'one'); + SELECT id, b, lead(c,1) OVER(ORDER BY c) AS x + FROM t1 WHERE id>1 + ORDER BY b LIMIT 2; +} {2 B two 3 C three} +finish_test From 40b4e7a6923cde8c5ab0b8148c3b07bbf4414e8c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Sep 2018 20:47:38 +0000 Subject: [PATCH 219/260] Further optimizations to the UPDATE logic to avoid making changes to partial indexes if none of the columns mentioned in the WHERE clause are modified by the UPDATE. FossilOrigin-Name: d1365a5bf0ee2f145427b81d2a593f539c3ad4705d579478703c1f65ae5f80bf --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/update.c | 30 ++++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 270cb9b99d..9c48557b54 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\sORDER\sBY\sLIMIT\soptimization\sin\squeries\susing\swindow\sfunctions.\nThis\sfixes\sa\sproblem\sthat\swas\sintroduced\sby\scheck-in\s[206720129ed2fa8875a286]\nwhich\sattempted\sto\sfix\sticket\s[9936b2fa443fec03ff25f9].\s\sThis\schanges\sis\na\sfix\sfor\sthe\sfollow-in\stocket\s[510cde277783b5fb5de628]. -D 2018-09-17T15:19:13.491 +C Further\soptimizations\sto\sthe\sUPDATE\slogic\sto\savoid\smaking\schanges\sto\spartial\nindexes\sif\snone\sof\sthe\scolumns\smentioned\sin\sthe\sWHERE\sclause\sare\smodified\sby\nthe\sUPDATE. +D 2018-09-17T20:47:38.243 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -568,7 +568,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd -F src/update.c 52d926be53e011050b0ed1d6d1a09d268ffb864ce875bf3a8ce4cd1b1b8b616e +F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 84105ea4af98bd8bddbdf9dc6674bdf73c110c0685afe868ce9681da110144d7 -R d2a6dffbc9b7eb5b0ff50ff6a5285151 +P c6c9585f294710829ca24b64d70a36fd9f409261dd0661367c6c4198cdbc4c81 +R 17f1502e8c93c85f4f8e209b4182086e U drh -Z 632a6055521a5e1b8d0c8917d051318b +Z a90b83813b6e6eb9b8886f53647a06d4 diff --git a/manifest.uuid b/manifest.uuid index eae237c4d8..881e98b3ea 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6c9585f294710829ca24b64d70a36fd9f409261dd0661367c6c4198cdbc4c81 \ No newline at end of file +d1365a5bf0ee2f145427b81d2a593f539c3ad4705d579478703c1f65ae5f80bf \ No newline at end of file diff --git a/src/update.c b/src/update.c index 9e76c445ea..dd2b05c3e6 100644 --- a/src/update.c +++ b/src/update.c @@ -82,7 +82,9 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ /* ** Check to see if column iCol of index pIdx references any of the ** columns defined by aXRef and chngRowid. Return true if it does -** and false if not. +** and false if not. This is an optimization. False-positives are a +** performance degradation, but false-negatives can result in a corrupt +** index and incorrect answers. ** ** aXRef[j] will be non-negative if column j of the original table is ** being updated. chngRowid will be true if the rowid of the table is @@ -106,6 +108,28 @@ static int indexColumnIsBeingUpdated( aXRef,chngRowid); } +/* +** Check to see if index pIdx is a partial index whose conditional +** expression might change values due to an UPDATE. Return true if +** the index is subject to change and false if the index is guaranteed +** to be unchanged. This is an optimization. False-positives are a +** performance degradation, but false-negatives can result in a corrupt +** index and incorrect answers. +** +** aXRef[j] will be non-negative if column j of the original table is +** being updated. chngRowid will be true if the rowid of the table is +** being updated. +*/ +static int indexWhereClauseMightChange( + Index *pIdx, /* The index to check */ + int *aXRef, /* aXRef[j]>=0 if column j is being updated */ + int chngRowid /* true if the rowid is being updated */ +){ + if( pIdx->pPartIdxWhere==0 ) return 0; + return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere, + aXRef, chngRowid); +} + /* ** Process an UPDATE statement. ** @@ -332,7 +356,9 @@ void sqlite3Update( */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; - if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){ + if( chngKey || hasFK>1 || pIdx==pPk + || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) + ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; }else{ From b1e1a0fd2ddf031c62057493e0bb5bda35101461 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 18 Sep 2018 16:06:42 +0000 Subject: [PATCH 220/260] Minor improvements to the permutations.test script. Most notably, a command like "permutations.test alter%" now runs all test scripts with names that match the LIKE pattern "alter%". Or, say, "permutations wal alter%" to run all alter% tests in wal mode. FossilOrigin-Name: 3e1a2f6614eacb65e1dffe64c6292c809fc5808be2d9d7d103cfc57d7b32fcd9 --- manifest | 14 ++--- manifest.uuid | 2 +- test/permutations.test | 130 +++++++++++++++++++++-------------------- 3 files changed, 75 insertions(+), 71 deletions(-) diff --git a/manifest b/manifest index 9c48557b54..d0a94caab8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\soptimizations\sto\sthe\sUPDATE\slogic\sto\savoid\smaking\schanges\sto\spartial\nindexes\sif\snone\sof\sthe\scolumns\smentioned\sin\sthe\sWHERE\sclause\sare\smodified\sby\nthe\sUPDATE. -D 2018-09-17T20:47:38.243 +C Minor\simprovements\sto\sthe\spermutations.test\sscript.\sMost\snotably,\sa\scommand\nlike\s"permutations.test\salter%"\snow\sruns\sall\stest\sscripts\swith\snames\sthat\nmatch\sthe\sLIKE\spattern\s"alter%".\sOr,\ssay,\s"permutations\swal\salter%"\sto\srun\sall\nalter%\stests\sin\swal\smode. +D 2018-09-18T16:06:42.548 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -1166,7 +1166,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test fdcb2d733fc21396e0300206023795463ba0d0ee5eda2042863b044933391da3 +F test/permutations.test 8749e292c8f7e98072049543da8c0fe60e1625f0a9f49068623060984c176bbf F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30 F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f @@ -1766,7 +1766,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c6c9585f294710829ca24b64d70a36fd9f409261dd0661367c6c4198cdbc4c81 -R 17f1502e8c93c85f4f8e209b4182086e -U drh -Z a90b83813b6e6eb9b8886f53647a06d4 +P d1365a5bf0ee2f145427b81d2a593f539c3ad4705d579478703c1f65ae5f80bf +R 04fce42a1b99ed4e3f6aae31501aa2b5 +U dan +Z 31ac11585131622d50cd5cff75846297 diff --git a/manifest.uuid b/manifest.uuid index 881e98b3ea..7315abcf73 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d1365a5bf0ee2f145427b81d2a593f539c3ad4705d579478703c1f65ae5f80bf \ No newline at end of file +3e1a2f6614eacb65e1dffe64c6292c809fc5808be2d9d7d103cfc57d7b32fcd9 \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index f71b0b88e2..4940e34899 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -48,6 +48,13 @@ proc test_suite {name args} { set options([lindex $o 0]) $v } + # Transform "-presql" into a "dbconfig" script + # + if {[info exists options(-presql)]} { + append options(-dbconfig) "\n\$::dbhandle eval { $options(-presql) }" + unset options(-presql) + } + set ::testspec($name) [array get options] lappend ::testsuitelist $name } @@ -289,12 +296,6 @@ test_suite "window" -prefix "" -description { test_set [glob -nocomplain $::testdir/window*.test] ] -test_suite "alter" -prefix "" -description { - All ALTER function related tests . -} -files [ - test_set [glob -nocomplain $::testdir/alter*.test] -] - test_suite "lsm1" -prefix "" -description { All LSM1 tests. } -files [glob -nocomplain $::testdir/../ext/lsm1/test/*.test] @@ -560,21 +561,12 @@ test_suite "singlethread" -description { test_suite "nomutex" -description { Tests run with the SQLITE_OPEN_MULTITHREADED flag passed to sqlite3_open(). } -initialize { - rename sqlite3 sqlite3_nomutex - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -fullmutex 0 -nomutex 1 - } - uplevel [concat sqlite3_nomutex $args] - } + set ::G(perm:sqlite3_args) [list -fullmutex 0 -nomutex 1] } -files { delete.test delete2.test insert.test rollback.test select1.test select2.test trans.test update.test vacuum.test types.test types2.test types3.test -} -shutdown { - rename sqlite3 {} - rename sqlite3_nomutex sqlite3 -} +} # Run some tests in SQLITE_CONFIG_MULTITHREAD mode. # @@ -603,20 +595,11 @@ test_suite "multithread" -description { test_suite "fullmutex" -description { Tests run in SQLITE_OPEN_FULLMUTEX mode } -initialize { - rename sqlite3 sqlite3_fullmutex - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -nomutex 0 -fullmutex 1 - } - uplevel [concat sqlite3_fullmutex $args] - } + set ::G(perm:sqlite3_args) [list -nomutex 0 -fullmutex 1] } -files { delete.test delete2.test insert.test rollback.test select1.test select2.test trans.test update.test vacuum.test types.test types2.test types3.test -} -shutdown { - rename sqlite3 {} - rename sqlite3_fullmutex sqlite3 } # Run some tests using the "onefile" demo. @@ -624,19 +607,10 @@ test_suite "fullmutex" -description { test_suite "onefile" -description { Run some tests using the "test_onefile.c" demo } -initialize { - rename sqlite3 sqlite3_onefile - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -vfs fs - } - uplevel [concat sqlite3_onefile $args] - } + set ::G(perm:sqlite3_args) [list -vfs fs] } -files { conflict.test insert.test insert2.test insert3.test rollback.test select1.test select2.test select3.test -} -shutdown { - rename sqlite3 {} - rename sqlite3_onefile sqlite3 } # Run some tests using UTF-16 databases. @@ -938,17 +912,8 @@ ifcapable threadsafe { test_suite "safe_append" -description { Run some tests on a SAFE_APPEND file-system. } -initialize { - rename sqlite3 sqlite3_safeappend - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -vfs devsym - } - uplevel [concat sqlite3_safeappend $args] - } + set ::G(perm:sqlite3_args) [list -vfs devsym] sqlite3_simulate_device -char safe_append -} -shutdown { - rename sqlite3 {} - rename sqlite3_shutdown sqlite3 } -files [ test_set $::allquicktests shared_err.test -exclude async3.test ] @@ -1115,16 +1080,20 @@ test_suite "sorterref" -prefix "" -description { # -description TITLE # -initialize SCRIPT # -shutdown SCRIPT -# -presql SQL # -files LIST-OF-FILES # -prefix NAME +# -dbconfig SCRIPT # proc run_tests {name args} { + set options(-initialize) "" + set options(-shutdown) "" + set options(-prefix) "" + set options(-dbconfig) "" + array set options $args set ::G(perm:name) $name set ::G(perm:prefix) $options(-prefix) - set ::G(perm:presql) $options(-presql) set ::G(isquick) 1 set ::G(perm:dbconfig) $options(-dbconfig) @@ -1133,11 +1102,12 @@ proc run_tests {name args} { if {[file tail $file] == $file} { set file [file join $::testdir $file] } slave_test_file $file uplevel $options(-shutdown) + + unset -nocomplain ::G(perm:sqlite3_args) } unset ::G(perm:name) unset ::G(perm:prefix) - unset ::G(perm:presql) unset ::G(perm:dbconfig) } @@ -1152,19 +1122,29 @@ proc help {} { puts "Usage: $::argv0 TESTSUITE ?TESTFILE?" puts "" puts "Available test-suites are:" + + set iPos 0 foreach k $::testsuitelist { - if {[info exists ::testspec($k)]==0} { - puts " ----------------------------------------" - puts "" - } else { - array set o $::testspec($k) - puts "Test suite: \"$k\"" - set d [string trim $o(-description)] - set d [regsub {\n *} $d "\n "] - puts " $d" - puts "" + if {[info exists ::testspec($k)]} { + switch $iPos { + 0 { + puts "" + puts -nonewline " [format %-30s $k]" + } + + 1 { + puts -nonewline [format %-30s $k] + } + + 2 { + puts -nonewline $k + } + } + + set iPos [expr (($iPos+1) % 3)] } } + puts "" exit -1 } @@ -1173,11 +1153,35 @@ if {[file tail $argv0] == "permutations.test"} { if {[llength $argv]==0} { help } else { + + # See if the first argument is a named test-suite. + # set suite [file tail [lindex $argv 0]] - if {[info exists ::testspec($suite)]==0} help + if {[info exists ::testspec($suite)]} { + set S $::testspec($suite) + set i 1 + } else { + set S [list] + set i 0 + } + set extra "" - if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] } - eval run_tests $suite $::testspec($suite) $extra + if {$i < [llength $argv] && [string range [lindex $argv $i] 0 0]!="-" } { + set files [list] + for {} {$i < [llength $argv]} {incr i} { + set pattern [string map {% *} [lindex $argv $i]] + if {[string range $pattern 0 0]=="-"} break + foreach f $::alltests { + set tail [file tail $f] + if {[lsearch $files $f]<0 && [string match $pattern $tail]} { + lappend files $f + } + } + } + set extra [list -files $files] + } + + eval run_tests $suite $S $extra } } main $argv From 253c6ee1bf6d154019435b0a64c5c3d4f681f5f4 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 18 Sep 2018 17:00:06 +0000 Subject: [PATCH 221/260] Enhance tester.tcl so that when "--malloctrace=1" is specified, the test generates self-contained Tcl scripts that present GUIs instead of *.sql files that require a separate program to interpret. FossilOrigin-Name: de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc --- manifest | 37 +++--- manifest.uuid | 2 +- src/test_config.c | 2 +- test/altermalloc.test | 2 +- test/attachmalloc.test | 2 +- test/capi3.test | 2 - test/capi3c.test | 2 - test/crash5.test | 2 +- test/fuzz_malloc.test | 5 - test/incrblob_err.test | 2 +- test/malloctraceviewer.tcl | 253 +++++++++++++++++++++++++++++++++++++ test/printf.test | 36 +++--- test/tableapi.test | 26 ++-- test/tester.tcl | 32 +++-- test/triggerA.test | 7 - test/vtab_err.test | 5 - 16 files changed, 329 insertions(+), 88 deletions(-) create mode 100644 test/malloctraceviewer.tcl diff --git a/manifest b/manifest index d0a94caab8..b3b6183f48 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\simprovements\sto\sthe\spermutations.test\sscript.\sMost\snotably,\sa\scommand\nlike\s"permutations.test\salter%"\snow\sruns\sall\stest\sscripts\swith\snames\sthat\nmatch\sthe\sLIKE\spattern\s"alter%".\sOr,\ssay,\s"permutations\swal\salter%"\sto\srun\sall\nalter%\stests\sin\swal\smode. -D 2018-09-18T16:06:42.548 +C Enhance\stester.tcl\sso\sthat\swhen\s"--malloctrace=1"\sis\sspecified,\sthe\stest\ngenerates\sself-contained\sTcl\sscripts\sthat\spresent\sGUIs\sinstead\sof\s*.sql\sfiles\nthat\srequire\sa\sseparate\sprogram\sto\sinterpret. +D 2018-09-18T17:00:06.795 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -527,7 +527,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0 F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857 F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 -F src/test_config.c 6c3f341ece48020c4ddbce055643a91c653283b3a6853c46ea18d22e5c72847d +F src/test_config.c 3bbc5e593f308cbff426bb88c9dbf75deab551e5ddcece1251b8d9a40e55aef5 F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 @@ -605,7 +605,7 @@ F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3 F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433 F test/alterauth.test dc50064e3d57d60cf8708decefed15cfa154242f6d44069858d4c6c9b1aea961 F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704 -F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc +F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 F test/altermalloc2.test 0231398534c494401a70a1d06a63d7849cb5b317fcc14228cbdb53039eba7eae F test/altertab.test 3b830144c18ae00abd2a27e3d2851c8bb1ee8fe655fa16d8a5971066dc71b58a F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f @@ -637,7 +637,7 @@ F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be82 F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce F test/attach3.test c59d92791070c59272e00183b7353eeb94915976 F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c -F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0 +F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438 F test/auth.test f0c1a8fc7f07d94e3e26ba7f77eb4a5cedda67b10d9a49275b154ab03749b6c0 F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49 @@ -693,9 +693,9 @@ F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9 F test/capi2.test 34a1a9a96d543a2ec2c209696b11b164444f57253b1f2cba1c2e53fadede6c7b -F test/capi3.test 36f5c859c91a9bb0075d6ddcfcf2476cad629b09f7bfd135776fb94b06c04706 +F test/capi3.test b299c89d80891c6c9b7f0e4b199df002b8b9f11c19f07d4a6eb7b325f1244de0 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 -F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098 +F test/capi3c.test e853c6c1f9a596e0bc58153be08706813bf5795d479d6f81581e3bda3f9d0909 F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857 @@ -749,7 +749,7 @@ F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418 F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc -F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219 +F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100 @@ -959,7 +959,7 @@ F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b -F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79 +F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2 F test/fuzzcheck.c 8074a35ed4ec3735a5e144b7e0e9123d9821a92281756c1a40d43e302dd79243 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f @@ -990,7 +990,7 @@ F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba -F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8 +F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9 F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758 F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a F test/incrvacuum.test b729aab1d4983037da57e66c20dfd7458561a85626dcf824f60175e35f4ce152 @@ -1091,6 +1091,7 @@ F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c0837 F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134 F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f +F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0fe5e411264c8a9 F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 @@ -1174,7 +1175,7 @@ F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 -F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc +F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc @@ -1332,7 +1333,7 @@ F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2 F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51 F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f -F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 +F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 F test/tclsqlite.test 5337e8890b96dad1ee541b15fbeec32e6bac2fe7fa096f91089057385aadba9b F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08 @@ -1342,7 +1343,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc -F test/tester.tcl d5138d226cc2aaacb6934cdd79acaa5edd17cad862482895b833bbf62c49aca0 +F test/tester.tcl fa5656391e3b477508abe12b3b81f019b2e71397399ab38a2f32d8d7f3bf8e56 F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1515,7 +1516,7 @@ F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9 F test/trigger7.test 93cfa9b48ab9104b2b3d87bc544ac8021405643e36f23ee84635fbfaf9b8fef5 F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4 F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41 -F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332 +F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 @@ -1575,7 +1576,7 @@ F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be4 F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783 -F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 +F test/vtab_err.test 1c476cac24c9c730f83cd7c8bf66482a30151be08d36a2283f87fc38a2dacbb1 F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477 F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918 @@ -1766,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d1365a5bf0ee2f145427b81d2a593f539c3ad4705d579478703c1f65ae5f80bf -R 04fce42a1b99ed4e3f6aae31501aa2b5 +P 3e1a2f6614eacb65e1dffe64c6292c809fc5808be2d9d7d103cfc57d7b32fcd9 +R e3886b1f8760e45d3fbfc8f6d69183e6 U dan -Z 31ac11585131622d50cd5cff75846297 +Z 0af372fccee1295faf720b1e25ced7fe diff --git a/manifest.uuid b/manifest.uuid index 7315abcf73..a5ae31da0e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3e1a2f6614eacb65e1dffe64c6292c809fc5808be2d9d7d103cfc57d7b32fcd9 \ No newline at end of file +de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc \ No newline at end of file diff --git a/src/test_config.c b/src/test_config.c index d1837d4853..f017abc307 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -124,7 +124,7 @@ static void set_options(Tcl_Interp *interp){ STRINGVALUE(SQLITE_MAX_WORKER_THREADS), TCL_GLOBAL_ONLY ); -#if 1 /* def SQLITE_MEMDEBUG */ +#ifdef SQLITE_MEMDEBUG Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY); diff --git a/test/altermalloc.test b/test/altermalloc.test index a35e7d5a34..22ea158463 100644 --- a/test/altermalloc.test +++ b/test/altermalloc.test @@ -19,7 +19,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. -ifcapable !altertable||!memdebug { +ifcapable !altertable { finish_test return } diff --git a/test/attachmalloc.test b/test/attachmalloc.test index 7fee1e1b2a..7a82f41f64 100644 --- a/test/attachmalloc.test +++ b/test/attachmalloc.test @@ -18,7 +18,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !memdebug||!attach { +ifcapable !attach { finish_test return } diff --git a/test/capi3.test b/test/capi3.test index 01ce65b6a4..4950ef245e 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -811,7 +811,6 @@ foreach {code english} $code2english { # Test the error message when a "real" out of memory occurs. if { [permutation] != "nofaultsim" } { -ifcapable memdebug { do_test capi3-10-1 { sqlite3 db test.db set DB [sqlite3_connection_pointer db] @@ -849,7 +848,6 @@ ifcapable memdebug { db close sqlite3_memdebug_fail -1 } -} # The following tests - capi3-11.* - test that a COMMIT or ROLLBACK # statement issued while there are still outstanding VMs that are part of diff --git a/test/capi3c.test b/test/capi3c.test index 5d889e3249..c275242459 100644 --- a/test/capi3c.test +++ b/test/capi3c.test @@ -757,7 +757,6 @@ foreach {code english} $code2english { # Test the error message when a "real" out of memory occurs. if { [permutation] != "nofaultsim" } { -ifcapable memdebug { do_test capi3c-10-1 { sqlite3 db test.db set DB [sqlite3_connection_pointer db] @@ -777,7 +776,6 @@ ifcapable memdebug { db close sqlite3_memdebug_fail -1 } -} # The following tests - capi3c-11.* - test that a COMMIT or ROLLBACK # statement issued while there are still outstanding VMs that are part of diff --git a/test/crash5.test b/test/crash5.test index 83d1647a84..b80b15137f 100644 --- a/test/crash5.test +++ b/test/crash5.test @@ -20,7 +20,7 @@ source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # -ifcapable !memdebug||!crashtest||!memorymanage { +ifcapable !crashtest||!memorymanage { puts "Skipping crash5 tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return diff --git a/test/fuzz_malloc.test b/test/fuzz_malloc.test index 531da55c1a..4449ea8fc4 100644 --- a/test/fuzz_malloc.test +++ b/test/fuzz_malloc.test @@ -17,11 +17,6 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !memdebug { - finish_test - return -} - source $testdir/malloc_common.tcl source $testdir/fuzz_common.tcl diff --git a/test/incrblob_err.test b/test/incrblob_err.test index 0db8b0dcba..3c523319c2 100644 --- a/test/incrblob_err.test +++ b/test/incrblob_err.test @@ -16,7 +16,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix incrblob_err -ifcapable {!incrblob || !memdebug || !tclvar} { +ifcapable {!incrblob || !tclvar} { finish_test return } diff --git a/test/malloctraceviewer.tcl b/test/malloctraceviewer.tcl new file mode 100644 index 0000000000..5bc22f34b3 --- /dev/null +++ b/test/malloctraceviewer.tcl @@ -0,0 +1,253 @@ + +package require sqlite3 +package require Tk + +############################################################################# +# Code to set up scrollbars for widgets. This is generic, boring stuff. +# +namespace eval autoscroll { + proc scrollable {widget path args} { + ::ttk::frame $path + set w [$widget ${path}.widget {*}$args] + set vs [::ttk::scrollbar ${path}.vs] + set hs [::ttk::scrollbar ${path}.hs -orient horizontal] + grid $w -row 0 -column 0 -sticky nsew + + grid rowconfigure $path 0 -weight 1 + grid columnconfigure $path 0 -weight 1 + + set grid [list grid $vs -row 0 -column 1 -sticky nsew] + $w configure -yscrollcommand [list ::autoscroll::scrollcommand $grid $vs] + $vs configure -command [list $w yview] + set grid [list grid $hs -row 1 -column 0 -sticky nsew] + $w configure -xscrollcommand [list ::autoscroll::scrollcommand $grid $hs] + $hs configure -command [list $w xview] + + return $w + } + proc scrollcommand {grid sb args} { + $sb set {*}$args + set isRequired [expr {[lindex $args 0] != 0.0 || [lindex $args 1] != 1.0}] + if {$isRequired && ![winfo ismapped $sb]} { + {*}$grid + } + if {!$isRequired && [winfo ismapped $sb]} { + grid forget $sb + } + } + namespace export scrollable +} +namespace import ::autoscroll::* +############################################################################# + +proc populate_text_widget {db} { + $::O(text) configure -state normal + set id [lindex [$::O(tree) selection] 0] + set frame [lindex $id end] + + set line [$db one {SELECT line FROM frame WHERE frame = $frame}] + if {$line ne ""} { + foreach {file line} [split $line :] {} + set content [$db one "SELECT content FROM file WHERE name = '$file'"] + $::O(text) delete 0.0 end + + set iLine 1 + foreach L [split $content "\n"] { + if {$iLine == $line} { + $::O(text) insert end "$L\n" highlight + } else { + $::O(text) insert end "$L\n" + } + incr iLine + } + $::O(text) yview -pickplace ${line}.0 + } + $::O(text) configure -state disabled +} + +proc populate_index {db} { + $::O(text) configure -state normal + + $::O(text) delete 0.0 end + $::O(text) insert end "\n\n" + + set L [format " % -40s%12s%12s\n" "Test Case" "Allocations" "Bytes"] + $::O(text) insert end $L + $::O(text) insert end " [string repeat - 64]\n" + + $db eval { + SELECT 'TOTAL' AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes + FROM malloc + UNION ALL + SELECT ztest AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes + FROM malloc + GROUP BY ztest + + ORDER BY 3 DESC + } { + set tags [list $ztest] + if {$ztest eq $::O(current)} { + lappend tags highlight + } + set L [format " % -40s%12s%12s\n" $ztest $calls $bytes] + $::O(text) insert end $L $tags + + $::O(text) tag bind $ztest <1> [list populate_tree_widget $db $ztest] + $::O(text) tag bind $ztest [list $::O(text) configure -cursor hand2] + $::O(text) tag bind $ztest [list $::O(text) configure -cursor ""] + } + + $::O(text) configure -state disabled +} + +proc sort_tree_compare {iLeft iRight} { + global O + switch -- [expr (int($O(tree_sort)/2))] { + 0 { + set left [$O(tree) item $iLeft -text] + set right [$O(tree) item $iRight -text] + set res [string compare $left $right] + } + 1 { + set left [lindex [$O(tree) item $iLeft -values] 0] + set right [lindex [$O(tree) item $iRight -values] 0] + set res [expr $left - $right] + } + 2 { + set left [lindex [$O(tree) item $iLeft -values] 1] + set right [lindex [$O(tree) item $iRight -values] 1] + set res [expr $left - $right] + } + } + if {$O(tree_sort)&0x01} { + set res [expr -1 * $res] + } + return $res +} + +proc sort_tree {iMode} { + global O + if {$O(tree_sort) == $iMode} { + incr O(tree_sort) + } else { + set O(tree_sort) $iMode + } + set T $O(tree) + set items [$T children {}] + set items [lsort -command sort_tree_compare $items] + for {set ii 0} {$ii < [llength $items]} {incr ii} { + $T move [lindex $items $ii] {} $ii + } +} + +proc trim_frames {stack} { + while {[info exists ::O(ignore.[lindex $stack 0])]} { + set stack [lrange $stack 1 end] + } + return $stack +} + +proc populate_tree_widget {db zTest} { + $::O(tree) delete [$::O(tree) children {}] + + for {set ii 0} {$ii < 15} {incr ii} { + $db eval { + SELECT + sum(ncall) AS calls, + sum(nbyte) AS bytes, + trim_frames(lrange(lstack, 0, $ii)) AS stack + FROM malloc + WHERE (zTest = $zTest OR $zTest = 'TOTAL') AND llength(lstack)>$ii + GROUP BY stack + HAVING stack != '' + } { + set parent_id [lrange $stack 0 end-1] + set frame [lindex $stack end] + set line [$db one {SELECT line FROM frame WHERE frame = $frame}] + set line [lindex [split $line /] end] + set v [list $calls $bytes] + + catch { + $::O(tree) insert $parent_id end -id $stack -text $line -values $v + } + } + } + + set ::O(current) $zTest + populate_index $db +} + + + +set O(tree_sort) 0 + +::ttk::panedwindow .pan -orient horizontal +set O(tree) [scrollable ::ttk::treeview .pan.tree] + +frame .pan.right +set O(text) [scrollable text .pan.right.text] +button .pan.right.index -command {populate_index mddb} -text "Show Index" +pack .pan.right.index -side top -fill x +pack .pan.right.text -fill both -expand true + +$O(text) tag configure highlight -background wheat +$O(text) configure -wrap none -height 35 + +.pan add .pan.tree +.pan add .pan.right + +$O(tree) configure -columns {calls bytes} +$O(tree) heading #0 -text Line -anchor w -command {sort_tree 0} +$O(tree) heading calls -text Calls -anchor w -command {sort_tree 2} +$O(tree) heading bytes -text Bytes -anchor w -command {sort_tree 4} +$O(tree) column #0 -width 150 +$O(tree) column calls -width 100 +$O(tree) column bytes -width 100 + +pack .pan -fill both -expand 1 + +#-------------------------------------------------------------------- +# Open the database containing the malloc data. The user specifies the +# database to use by passing the file-name on the command line. +# +proc open_database {} { + if {[info exists ::BUILTIN]} { + sqlite3 mddb :memory: + mddb eval $::BUILTIN + wm title . $::argv0 + } else { + set zFilename [lindex $::argv 0] + if {$zFilename eq ""} { + set zFilename mallocs.sql + } + set fd [open $zFilename] + set zHdr [read $fd 15] + if {$zHdr eq "SQLite format 3"} { + close $fd + sqlite3 mddb $zFilename + } else { + seek $fd 0 + sqlite3 mddb :memory: + mddb eval [read $fd] + close $fd + } + wm title . $zFilename + } + + mddb function lrange -argcount 3 lrange + mddb function llength -argcount 1 llength + mddb function trim_frames -argcount 1 trim_frames + + mddb eval { + SELECT frame FROM frame + WHERE line LIKE '%malloc.c:%' OR line LIKE '%mem2.c:%' + } { + set ::O(ignore.$frame) 1 + } +} + +open_database +bind $O(tree) <> [list populate_text_widget mddb] + +populate_tree_widget mddb [mddb one {SELECT zTest FROM malloc LIMIT 1}] + diff --git a/test/printf.test b/test/printf.test index 6103d8acf8..d768898fb9 100644 --- a/test/printf.test +++ b/test/printf.test @@ -3757,25 +3757,23 @@ do_test printf-15.3 { # Now test malloc() failure within a sqlite3_mprintf(): # -ifcapable memdebug { - foreach var {a b c d} { - set $var [string repeat $var 400] - } - set str1 "[string repeat A 360]%d%d%s" - set str2 [string repeat B 5000] - set zSuccess "[string repeat A 360]11[string repeat B 5000]" - foreach ::iRepeat {0 1} { - set nTestNum 1 - while {1} { - sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat - set z [sqlite3_mprintf_str $str1 1 1 $str2] - set nFail [sqlite3_memdebug_fail -1 -benign nBenign] - do_test printf-malloc-$::iRepeat.$nTestNum { - expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)} - } {1} - if {$nFail == 0} break - incr nTestNum - } +foreach var {a b c d} { + set $var [string repeat $var 400] +} +set str1 "[string repeat A 360]%d%d%s" +set str2 [string repeat B 5000] +set zSuccess "[string repeat A 360]11[string repeat B 5000]" +foreach ::iRepeat {0 1} { + set nTestNum 1 + while {1} { + sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat + set z [sqlite3_mprintf_str $str1 1 1 $str2] + set nFail [sqlite3_memdebug_fail -1 -benign nBenign] + do_test printf-malloc-$::iRepeat.$nTestNum { + expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)} + } {1} + if {$nFail == 0} break + incr nTestNum } } diff --git a/test/tableapi.test b/test/tableapi.test index 122267fea8..02633cdcac 100644 --- a/test/tableapi.test +++ b/test/tableapi.test @@ -22,9 +22,7 @@ ifcapable !gettable { return } -ifcapable memdebug { - source $testdir/malloc_common.tcl -} +source $testdir/malloc_common.tcl do_test tableapi-1.0 { set ::dbx [sqlite3_open test.db] @@ -239,18 +237,16 @@ do_test tableapi-99.0 { sqlite3_close $::dbx } {SQLITE_OK} -ifcapable memdebug { - do_malloc_test tableapi-7 -sqlprep { - DROP TABLE IF EXISTS t1; - CREATE TABLE t1(a,b); - INSERT INTO t1 VALUES(1,2); - INSERT INTO t1 VALUES(3,4); - INSERT INTO t1 SELECT a+4, b+4 FROM t1; - INSERT INTO t1 SELECT a+8, b+8 FROM t1; - } -tclbody { - set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}] - if {[llength $r]<26} {error "out of memory"} - } +do_malloc_test tableapi-7 -sqlprep { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1,2); + INSERT INTO t1 VALUES(3,4); + INSERT INTO t1 SELECT a+4, b+4 FROM t1; + INSERT INTO t1 SELECT a+8, b+8 FROM t1; +} -tclbody { + set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}] + if {[llength $r]<26} {error "out of memory"} } finish_test diff --git a/test/tester.tcl b/test/tester.tcl index 508c40c3d9..14808d9cd9 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -456,6 +456,11 @@ if {[info exists cmdlinearg]==0} { {^-+malloctrace=.+$} { foreach {dummy cmdlinearg(malloctrace)} [split $a =] break if {$cmdlinearg(malloctrace)} { + if {0==$::sqlite_options(memdebug)} { + set err "Error: --malloctrace=1 requires an SQLITE_MEMDEBUG build" + puts stderr $err + exit 1 + } sqlite3_memdebug_log start } } @@ -1258,13 +1263,13 @@ proc finalize_testing {} { output2 "Unfreed memory: [sqlite3_memory_used] bytes in\ [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations" incr nErr - ifcapable memdebug||mem5||(mem3&&debug) { + ifcapable mem5||(mem3&&debug) { output2 "Writing unfreed memory log to \"./memleak.txt\"" sqlite3_memdebug_dump ./memleak.txt } } else { output2 "All memory allocations freed - no leaks" - ifcapable memdebug||mem5 { + ifcapable mem5 { sqlite3_memdebug_dump ./memusage.txt } } @@ -1275,15 +1280,14 @@ proc finalize_testing {} { output2 "Number of malloc() : [sqlite3_memdebug_malloc_count] calls" } if {$::cmdlinearg(malloctrace)} { - output2 "Writing mallocs.sql..." - memdebug_log_sql + output2 "Writing mallocs.tcl..." + memdebug_log_sql mallocs.tcl sqlite3_memdebug_log stop sqlite3_memdebug_log clear - if {[sqlite3_memory_used]>0} { - output2 "Writing leaks.sql..." + output2 "Writing leaks.tcl..." sqlite3_memdebug_log sync - memdebug_log_sql leaks.sql + memdebug_log_sql leaks.tcl } } foreach f [glob -nocomplain test.db-*-journal] { @@ -2019,7 +2023,7 @@ proc dbcksum {db dbname} { return [md5 $txt] } -proc memdebug_log_sql {{filename mallocs.sql}} { +proc memdebug_log_sql {filename} { set data [sqlite3_memdebug_log dump] set nFrame [expr [llength [lindex $data 0]]-2] @@ -2065,8 +2069,18 @@ proc memdebug_log_sql {{filename mallocs.sql}} { append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n" } + set escaped "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;" + set escaped [string map [list "{" "\\{" "}" "\\}"] $escaped] + set fd [open $filename w] - puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;" + puts $fd "set BUILTIN {" + puts $fd $escaped + puts $fd "}" + puts $fd {set BUILTIN [string map [list "\\{" "{" "\\}" "}"] $BUILTIN]} + set mtv [open $::testdir/malloctraceviewer.tcl] + set txt [read $mtv] + close $mtv + puts $fd $txt close $fd } diff --git a/test/triggerA.test b/test/triggerA.test index 821e2d90e4..598d291295 100644 --- a/test/triggerA.test +++ b/test/triggerA.test @@ -200,13 +200,6 @@ do_test triggerA-2.11 { } } {3 305 3 9900305 4 404 4 9900404 5 504 5 9900504} -# Only run the reamining tests if memory debugging is turned on. -# -ifcapable !memdebug { - puts "Skipping triggerA malloc tests: not compiled with -DSQLITE_MEMDEBUG..." - finish_test - return -} source $testdir/malloc_common.tcl # Save a copy of the current database configuration. diff --git a/test/vtab_err.test b/test/vtab_err.test index 068386eb31..cb40acdbfc 100644 --- a/test/vtab_err.test +++ b/test/vtab_err.test @@ -40,11 +40,6 @@ do_ioerr_test vtab_err-1 -tclprep { COMMIT; } -ifcapable !memdebug { - puts "Skipping vtab_err-2 tests: not compiled with -DSQLITE_MEMDEBUG..." - finish_test - return -} source $testdir/malloc_common.tcl From c4b1e5e758dfc7f3a6d53b8a6236df5956750691 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 18 Sep 2018 17:50:34 +0000 Subject: [PATCH 222/260] Avoid incrementing the SQLITE_LOOKASIDE_MISS_SIZE stat before sqlite3_open() returns. Fix test script problem in lookaside.test. FossilOrigin-Name: e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/main.c | 1 + test/lookaside.test | 5 ++++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b3b6183f48..fdd3a7e182 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\stester.tcl\sso\sthat\swhen\s"--malloctrace=1"\sis\sspecified,\sthe\stest\ngenerates\sself-contained\sTcl\sscripts\sthat\spresent\sGUIs\sinstead\sof\s*.sql\sfiles\nthat\srequire\sa\sseparate\sprogram\sto\sinterpret. -D 2018-09-18T17:00:06.795 +C Avoid\sincrementing\sthe\sSQLITE_LOOKASIDE_MISS_SIZE\sstat\sbefore\ssqlite3_open()\nreturns.\sFix\stest\sscript\sproblem\sin\slookaside.test. +D 2018-09-18T17:50:34.415 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -466,7 +466,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 0a214201afec77880a31a59c33d86b473a160fc5cc31981eab2041ae03d8bf2f F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 30b140d0e5031924c56f802760506c0a235ced0dff9f3d95119aa86df12856e2 -F src/main.c 1f54ee71990bfbf4cdc2dc79bdc33e7c4f54eef6922447b4c910f9b5885a4478 +F src/main.c 6275ece0699a957c4709a7ebe29476f132adbe459d18a6b497e234e4669abf91 F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -1065,7 +1065,7 @@ F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38 F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5 F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431 F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035 -F test/lookaside.test b17c99ae3aef96a8c9fa6f6be33cc75b93d657cb791d3827302b6835b71941f7 +F test/lookaside.test 5a828e7256f1ee4da8e1bdaa03373a3ccdb0f1ff98dfa82e9b76cb41a45b1083 F test/main.test 6bbb3999fd461eb8fb335cbab97409a3d7f91bbb8da60635e8be3e4a04a77772 F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9 F test/malloc.test 18dd1c4188c81ca79cf123527c71b19ee0c31feb9947fdffb0dc6ceb1436816a @@ -1767,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3e1a2f6614eacb65e1dffe64c6292c809fc5808be2d9d7d103cfc57d7b32fcd9 -R e3886b1f8760e45d3fbfc8f6d69183e6 +P de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc +R 87b8b2ee28b1a1a8366c364e4fdd6314 U dan -Z 0af372fccee1295faf720b1e25ced7fe +Z 971302d914167dfdeae1d53b5caa351e diff --git a/manifest.uuid b/manifest.uuid index a5ae31da0e..54560e2976 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc \ No newline at end of file +e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634 \ No newline at end of file diff --git a/src/main.c b/src/main.c index fb7ca37c1e..8935a19d75 100644 --- a/src/main.c +++ b/src/main.c @@ -3021,6 +3021,7 @@ static int openDatabase( db->nDb = 2; db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; + db->lookaside.bDisable = 1; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); diff --git a/test/lookaside.test b/test/lookaside.test index 67a502afb2..e1d91c8543 100644 --- a/test/lookaside.test +++ b/test/lookaside.test @@ -24,7 +24,7 @@ ifcapable !lookaside { # The tests in this file configure the lookaside allocator after a # connection is opened. This will not work if there is any "presql" # configured (SQL run within the [sqlite3] wrapper in tester.tcl). -if {[info exists ::G(perm:presql)]} { +if {[info exists ::G(perm:dbconfig)] && $::G(perm:dbconfig)!=""} { finish_test return } @@ -35,7 +35,9 @@ catch {db close} sqlite3_shutdown sqlite3_initialize autoinstall_test_functions + sqlite3 db test.db +db cache size 4 # Make sure sqlite3_db_config() and sqlite3_db_status are working. # @@ -99,6 +101,7 @@ do_test lookaside-2.2 { expr {$x==0 && $y<$z && $z>10 && $z<100} } {1} do_test lookaside-2.3 { + db eval {SELECT 1} sqlite3_db_config_lookaside db 0 50 50 } {5} ;# SQLITE_BUSY do_test lookaside-2.4 { From 16f39b6e5d8010d3da305a02fc0ba85102f1c858 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 18 Sep 2018 19:40:18 +0000 Subject: [PATCH 223/260] Fix a problem building on Android with SQLITE_ENABLE_BATCH_ATOMIC_WRITE set. FossilOrigin-Name: e41e50fe7430cb79f67369fe81ac9938665bfc5db59c4faaf429ceb8ca03f584 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_unix.c | 4 ++++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index fdd3a7e182..d6df40a560 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sincrementing\sthe\sSQLITE_LOOKASIDE_MISS_SIZE\sstat\sbefore\ssqlite3_open()\nreturns.\sFix\stest\sscript\sproblem\sin\slookaside.test. -D 2018-09-18T17:50:34.415 +C Fix\sa\sproblem\sbuilding\son\sAndroid\swith\sSQLITE_ENABLE_BATCH_ATOMIC_WRITE\sset. +D 2018-09-18T19:40:18.083 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -486,7 +486,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c d8e37bc3af9b15a52c3fecd366c95416251aa8d89481dd56170bad538b421721 +F src/os_unix.c 7cfd67db0e2f926243f646db7ec1caa33ca9bee45799b0160ddfcd6ccfc175d2 F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b @@ -1767,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc -R 87b8b2ee28b1a1a8366c364e4fdd6314 +P e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634 +R 1591df294f56363f9f724bb6253e7309 U dan -Z 971302d914167dfdeae1d53b5caa351e +Z 10098ab63af32e22b41da08d00c43f90 diff --git a/manifest.uuid b/manifest.uuid index 54560e2976..ad9b1505c2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634 \ No newline at end of file +e41e50fe7430cb79f67369fe81ac9938665bfc5db59c4faaf429ceb8ca03f584 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index f4c0570cc3..6a1195041b 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -521,7 +521,11 @@ static struct unix_syscall { #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) #if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) +# ifdef __ANDROID__ + { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 }, +# else { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, +# endif #else { "ioctl", (sqlite3_syscall_ptr)0, 0 }, #endif From c6727c8342f753403303be237658acbafcd20b74 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 19 Sep 2018 15:08:21 +0000 Subject: [PATCH 224/260] Fix the "sqlite3" command in the TCL interface so that it correctly returns an error if invoked with no arguments. FossilOrigin-Name: 2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/tclsqlite.c | 1 + test/tclsqlite.test | 7 +++++++ 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index d6df40a560..cc6b0713fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sbuilding\son\sAndroid\swith\sSQLITE_ENABLE_BATCH_ATOMIC_WRITE\sset. -D 2018-09-18T19:40:18.083 +C Fix\sthe\s"sqlite3"\scommand\sin\sthe\sTCL\sinterface\sso\sthat\sit\scorrectly\sreturns\nan\serror\sif\sinvoked\swith\sno\sarguments. +D 2018-09-19T15:08:21.925 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -511,7 +511,7 @@ F src/sqliteInt.h 83ee9b55db521b70294b2858872e69b96d0a4810d8221796def3e99cca5ee6 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c e0bf71a6d24b8c23393c000abffab05979bbca2a72d0b0f79260e2cf1527fda5 +F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6 F src/test1.c 9bb042e4afedc570f78638993fc9cc1760d897d3b27dd72c20618044b2a8fa5e F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 @@ -1335,7 +1335,7 @@ F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 -F test/tclsqlite.test 5337e8890b96dad1ee541b15fbeec32e6bac2fe7fa096f91089057385aadba9b +F test/tclsqlite.test dca8aa30d84175e7d8c8fc43d3ffa11fa56e23fbdac2679d03833a0f326edf34 F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08 F test/tempdb2.test 4749545409c6d7438b435c3f05cdd139cf4145a954a6908d19e3443ffd8724b3 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900 @@ -1767,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634 -R 1591df294f56363f9f724bb6253e7309 -U dan -Z 10098ab63af32e22b41da08d00c43f90 +P e41e50fe7430cb79f67369fe81ac9938665bfc5db59c4faaf429ceb8ca03f584 +R 691b3cb84398c1c46ea373c90efa25d4 +U drh +Z 77509658814e3f4dcf09a8cc75042d85 diff --git a/manifest.uuid b/manifest.uuid index ad9b1505c2..665ac6190b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e41e50fe7430cb79f67369fe81ac9938665bfc5db59c4faaf429ceb8ca03f584 \ No newline at end of file +2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022 \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index d0b4634d45..3982ead7be 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3497,6 +3497,7 @@ static int SQLITE_TCLAPI DbMain( flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX; #endif + if( objc==1 ) return sqliteCmdUsage(interp, objv); if( objc==2 ){ zArg = Tcl_GetStringFromObj(objv[1], 0); if( strcmp(zArg,"-version")==0 ){ diff --git a/test/tclsqlite.test b/test/tclsqlite.test index fb4be3dfcb..36063bc46d 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -17,6 +17,8 @@ # # $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $ +catch {sqlite3} + set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -31,6 +33,11 @@ do_test tcl-1.1 { regsub {really_sqlite3} $msg {sqlite3} msg lappend v $msg } [list 1 "wrong # args: should be \"$r\""] +do_test tcl-1.1.1 { + set v [catch {sqlite3} msg] + regsub {really_sqlite3} $msg {sqlite3} msg + lappend v $msg +} [list 1 "wrong # args: should be \"$r\""] do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg From 85c6892aa45dc0f476aa9bd772c678215f679853 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 19 Sep 2018 17:09:09 +0000 Subject: [PATCH 225/260] Fix a compilation issue in the "userauth" extension. Also fix a few test script errors that occur with SQLITE_USER_AUTHENTICATION=1 builds. FossilOrigin-Name: 221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d --- ext/userauth/userauth.c | 2 +- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- test/alterauth.test | 2 +- test/auth.test | 3 ++- test/releasetest.tcl | 1 + test/view.test | 7 ++++--- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/ext/userauth/userauth.c b/ext/userauth/userauth.c index a3d346c05c..a8ed01ae45 100644 --- a/ext/userauth/userauth.c +++ b/ext/userauth/userauth.c @@ -210,7 +210,7 @@ int sqlite3_user_authenticate( db->auth.nAuthPW = nPW; rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel); db->auth.authLevel = authLevel; - sqlite3ExpirePreparedStatements(db); + sqlite3ExpirePreparedStatements(db, 0); if( rc ){ return rc; /* OOM error, I/O error, etc. */ } diff --git a/manifest b/manifest index cc6b0713fe..5a4a89bb0a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\s"sqlite3"\scommand\sin\sthe\sTCL\sinterface\sso\sthat\sit\scorrectly\sreturns\nan\serror\sif\sinvoked\swith\sno\sarguments. -D 2018-09-19T15:08:21.925 +C Fix\sa\scompilation\sissue\sin\sthe\s"userauth"\sextension.\sAlso\sfix\sa\sfew\stest\nscript\serrors\sthat\soccur\swith\sSQLITE_USER_AUTHENTICATION=1\sbuilds. +D 2018-09-19T17:09:09.208 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -420,7 +420,7 @@ F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b8 F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 -F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f +F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 @@ -603,7 +603,7 @@ F test/alter.test 99e72759d48d6531ac2a9f346b4a9b5fe8f89c67a0fa5e916a3990d3b1fe9d F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3 F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433 -F test/alterauth.test dc50064e3d57d60cf8708decefed15cfa154242f6d44069858d4c6c9b1aea961 +F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959 F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704 F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 F test/altermalloc2.test 0231398534c494401a70a1d06a63d7849cb5b317fcc14228cbdb53039eba7eae @@ -638,7 +638,7 @@ F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3 F test/attach3.test c59d92791070c59272e00183b7353eeb94915976 F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438 -F test/auth.test f0c1a8fc7f07d94e3e26ba7f77eb4a5cedda67b10d9a49275b154ab03749b6c0 +F test/auth.test 3310d9c08e928beca42d3eadaaf53cef619d9d275f598565a3758a21ce63138e F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49 F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec @@ -1193,7 +1193,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl 7e90ec5d2854d80e2574f70df834ef9cae705d21fe43a19dc217a3ce33a3798c x +F test/releasetest.tcl d82c35d4fa8364451b424c95c0d4f222efcd40497fabe51d85d206ef6a680263 x F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa @@ -1556,7 +1556,7 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2 F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test 226fb71e37be61854f3a01929ae0a7e14584d6aef5c459bb0a22318f0b6dd210 +F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e @@ -1767,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e41e50fe7430cb79f67369fe81ac9938665bfc5db59c4faaf429ceb8ca03f584 -R 691b3cb84398c1c46ea373c90efa25d4 -U drh -Z 77509658814e3f4dcf09a8cc75042d85 +P 2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022 +R b045d000830b7f892b6bae2ce9b528b3 +U dan +Z e635b6ecc9802f0bfb5422b4720e432b diff --git a/manifest.uuid b/manifest.uuid index 665ac6190b..9220eb9168 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022 \ No newline at end of file +221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d \ No newline at end of file diff --git a/test/alterauth.test b/test/alterauth.test index 02cd9c2336..12645b36f0 100644 --- a/test/alterauth.test +++ b/test/alterauth.test @@ -24,7 +24,7 @@ set testprefix alterauth set ::auth [list] proc xAuth {type args} { if {$type == "SQLITE_ALTER_TABLE"} { - lappend ::auth [concat $type $args] + lappend ::auth [concat $type [lrange $args 0 3]] } return SQLITE_OK } diff --git a/test/auth.test b/test/auth.test index 30c13c89ce..354acba64a 100644 --- a/test/auth.test +++ b/test/auth.test @@ -2598,7 +2598,8 @@ do_test auth-8.2 { # invocation with no column name specified, compilation fails. # set ::authargs [list] -proc auth {op a b c d} { +proc auth {op args} { + foreach {a b c d} $args break lappend ::authargs $op $a $b $c $d if {$op == "SQLITE_READ"} { return "SQLITE_DENY" } return "SQLITE_OK" diff --git a/test/releasetest.tcl b/test/releasetest.tcl index cbd4f9cad3..c323978c7a 100755 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -136,6 +136,7 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_RBU -DSQLITE_MAX_ATTACHED=125 + -DSQLITE_USER_AUTHENTICATION=1 -DLONGDOUBLE_TYPE=double --enable-session } diff --git a/test/view.test b/test/view.test index 54e6f916c1..59ff55c692 100644 --- a/test/view.test +++ b/test/view.test @@ -682,7 +682,8 @@ do_test view-25.1 { } proc authLogDelete {code arg1 arg2 arg3 arg4 args} { if {$code=="SQLITE_DELETE" && [string match sqlite_stat* $arg1]} { - lappend ::log [list $code $arg1 $arg2 $arg3 $arg4 $args] + # lappend ::log [list $code $arg1 $arg2 $arg3 $arg4 $args] + lappend ::log [list $code $arg1 $arg2 $arg3 $arg4] } return SQLITE_OK } @@ -692,8 +693,8 @@ do_test view-25.1 { set log } {} -set res [list {SQLITE_DELETE sqlite_stat1 {} main {} {}}] -ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {} {}} } +set res [list {SQLITE_DELETE sqlite_stat1 {} main {}}] +ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {}} } do_test view-25.2 { set log "" db eval {DROP TABLE t25;} From 504eba5f462595f04f8864edc536fe25e7ab4082 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 19 Sep 2018 18:17:46 +0000 Subject: [PATCH 226/260] A minor code simplification, saved in a branch for future reference. FossilOrigin-Name: 5e458f4a92743effb9a3d3249767424fed8b444a05ca136c4a55d60c4d70c2cc --- manifest | 17 ++++++++++------- manifest.uuid | 2 +- src/resolve.c | 2 -- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 5a4a89bb0a..985ef62b08 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompilation\sissue\sin\sthe\s"userauth"\sextension.\sAlso\sfix\sa\sfew\stest\nscript\serrors\sthat\soccur\swith\sSQLITE_USER_AUTHENTICATION=1\sbuilds. -D 2018-09-19T17:09:09.208 +C A\sminor\scode\ssimplification,\ssaved\sin\sa\sbranch\sfor\sfuture\sreference. +D 2018-09-19T18:17:46.824 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -500,7 +500,7 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b +F src/resolve.c 122b208b2244d421c07518a5840efe187db42cce784927386a145bdff3296bab F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c 8afcc2b56a6ef76717bb59b6109cd3de0f6fae2803894d6f806640c0aa24dfac F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f @@ -1767,7 +1767,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022 -R b045d000830b7f892b6bae2ce9b528b3 -U dan -Z e635b6ecc9802f0bfb5422b4720e432b +P 221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d +R 06f69122b065dcb083fd6f4d43d3cd4b +T *branch * minor-altertab-simplification +T *sym-minor-altertab-simplification * +T -sym-trunk * +U drh +Z dcd00dfc073f6bc45b1dd8b7dc79c474 diff --git a/manifest.uuid b/manifest.uuid index 9220eb9168..b20c03b140 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d \ No newline at end of file +5e458f4a92743effb9a3d3249767424fed8b444a05ca136c4a55d60c4d70c2cc \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index 9fb4d4c63f..8798c325fc 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -690,8 +690,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ zColumn = pRight->u.zToken; if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); - } - if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft); } } From 674b89426912a52dd1fcbe726fc94d0d70dab5ea Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 20 Sep 2018 08:28:01 +0000 Subject: [PATCH 227/260] Add a PRAGMA that restores the legacy ALTER TABLE RENAME TO behaviour. FossilOrigin-Name: 5acad2e92c11c209bedc6ac8a709595e8070eed028ffc82af61499e5ceaa5e2b --- manifest | 22 +- manifest.uuid | 2 +- src/alter.c | 44 ++-- src/pragma.h | 7 +- src/sqliteInt.h | 1 + test/alterlegacy.test | 470 ++++++++++++++++++++++++++++++++++++++++++ tool/mkpragmatab.tcl | 5 + 7 files changed, 524 insertions(+), 27 deletions(-) create mode 100644 test/alterlegacy.test diff --git a/manifest b/manifest index 5a4a89bb0a..fbd12d638d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompilation\sissue\sin\sthe\s"userauth"\sextension.\sAlso\sfix\sa\sfew\stest\nscript\serrors\sthat\soccur\swith\sSQLITE_USER_AUTHENTICATION=1\sbuilds. -D 2018-09-19T17:09:09.208 +C Add\sa\sPRAGMA\sthat\srestores\sthe\slegacy\sALTER\sTABLE\sRENAME\sTO\sbehaviour. +D 2018-09-20T08:28:01.757 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -436,7 +436,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b +F src/alter.c 5bca9ae02fb3eb52bb39da57fcbf0af249910f05d268df4797cf32c75173c9ff F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114 @@ -496,7 +496,7 @@ F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c 79abc65c08d2754048efee3ba99fe91863dfeab0ba699a4439fa5053ec87cf36 -F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 +F src/pragma.h fb46b1e663128f6827979ad8ebddb55be2a0276ea923c47adeac02144207a682 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 @@ -507,7 +507,7 @@ F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1 F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 -F src/sqliteInt.h 83ee9b55db521b70294b2858872e69b96d0a4810d8221796def3e99cca5ee663 +F src/sqliteInt.h d8a3b17c1292f9491d6437e2125b14823f281a6b58f614f47bc790c57196ee68 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -605,6 +605,7 @@ F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3 F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433 F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959 F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704 +F test/alterlegacy.test e7c07d605c2a85e7d1696c89e6bf64dfc932fc6d9320fe8708c8f5fc0b524d41 F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 F test/altermalloc2.test 0231398534c494401a70a1d06a63d7849cb5b317fcc14228cbdb53039eba7eae F test/altertab.test 3b830144c18ae00abd2a27e3d2851c8bb1ee8fe655fa16d8a5971066dc71b58a @@ -1700,7 +1701,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa -F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd +F tool/mkpragmatab.tcl 8b9b448b5eb7222d4e3f7afb3c678596784180d319eb4e01c842887ed8213b85 F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 @@ -1767,7 +1768,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022 -R b045d000830b7f892b6bae2ce9b528b3 +P 221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d +R 02fc275d8f952db75795f9c11e6b826b +T *branch * legacy-alter-table +T *sym-legacy-alter-table * +T -sym-trunk * U dan -Z e635b6ecc9802f0bfb5422b4720e432b +Z 90941688fa5331b463302b9846d758b7 diff --git a/manifest.uuid b/manifest.uuid index 9220eb9168..28d3ebfce5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d \ No newline at end of file +5acad2e92c11c209bedc6ac8a709595e8070eed028ffc82af61499e5ceaa5e2b \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 08745ccee2..5b7f43c66c 100644 --- a/src/alter.c +++ b/src/alter.c @@ -1422,17 +1422,20 @@ static void renameTableFunc( rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); if( rc==SQLITE_OK ){ + int isLegacy = (db->flags & SQLITE_LegacyAlter); if( sParse.pNewTable ){ Table *pTab = sParse.pNewTable; if( pTab->pSelect ){ - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = &sParse; + if( isLegacy==0 ){ + NameContext sNC; + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = &sParse; - sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); - if( sParse.nErr ) rc = sParse.rc; - sqlite3WalkSelect(&sWalker, pTab->pSelect); + sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); + if( sParse.nErr ) rc = sParse.rc; + sqlite3WalkSelect(&sWalker, pTab->pSelect); + } }else{ /* Modify any FK definitions to point to the new table. */ #ifndef SQLITE_OMIT_FOREIGN_KEY @@ -1451,7 +1454,9 @@ static void renameTableFunc( ** "CREATE [VIRTUAL] TABLE" bit. */ if( sqlite3_stricmp(zOld, pTab->zName)==0 ){ sCtx.pTab = pTab; - sqlite3WalkExprList(&sWalker, pTab->pCheck); + if( isLegacy==0 ){ + sqlite3WalkExprList(&sWalker, pTab->pCheck); + } renameTokenFind(&sParse, &sCtx, pTab->zName); } } @@ -1459,7 +1464,9 @@ static void renameTableFunc( else if( sParse.pNewIndex ){ renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName); - sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); + if( isLegacy==0 ){ + sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); + } } #ifndef SQLITE_OMIT_TRIGGER @@ -1472,12 +1479,14 @@ static void renameTableFunc( renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table); } - rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); - if( rc==SQLITE_OK ){ - renameWalkTrigger(&sWalker, pTrigger); - for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ - renameTokenFind(&sParse, &sCtx, pStep->zTarget); + if( isLegacy==0 ){ + rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); + if( rc==SQLITE_OK ){ + renameWalkTrigger(&sWalker, pTrigger); + for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ + if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ + renameTokenFind(&sParse, &sCtx, pStep->zTarget); + } } } } @@ -1535,6 +1544,7 @@ static void renameTableTest( char const *zDb = (const char*)sqlite3_value_text(argv[0]); char const *zInput = (const char*)sqlite3_value_text(argv[1]); int bTemp = sqlite3_value_int(argv[4]); + int isLegacy = (db->flags & SQLITE_LegacyAlter); #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth = db->xAuth; @@ -1547,7 +1557,7 @@ static void renameTableTest( Parse sParse; rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); if( rc==SQLITE_OK ){ - if( sParse.pNewTable && sParse.pNewTable->pSelect ){ + if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = &sParse; @@ -1556,7 +1566,9 @@ static void renameTableTest( } else if( sParse.pNewTrigger ){ - rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); + if( isLegacy==0 ){ + rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); + } if( rc==SQLITE_OK ){ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); int i2 = sqlite3FindDbName(db, zDb); diff --git a/src/pragma.h b/src/pragma.h index c9ece2dc87..55d9a8c746 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -393,6 +393,11 @@ static const PragmaName aPragmaName[] = { /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + {/* zName: */ "legacy_alter_table", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_LegacyAlter }, {/* zName: */ "legacy_file_format", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -646,4 +651,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema }, #endif }; -/* Number of pragmas: 60 on by default, 77 total. */ +/* Number of pragmas: 61 on by default, 78 total. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 74438b5abc..77f08fac5c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1536,6 +1536,7 @@ struct sqlite3 { #define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/ #define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ #define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ +#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ /* Flags used only if debugging */ #ifdef SQLITE_DEBUG diff --git a/test/alterlegacy.test b/test/alterlegacy.test new file mode 100644 index 0000000000..9f7777670d --- /dev/null +++ b/test/alterlegacy.test @@ -0,0 +1,470 @@ +# 2018 September 20 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix alterlegacy + +# If SQLITE_OMIT_ALTERTABLE is defined, omit this file. +ifcapable !altertable { + finish_test + return +} + +do_execsql_test 1.0 { + PRAGMA legacy_alter_table = 1; + CREATE TABLE t1(a, b, CHECK(t1.a != t1.b)); + CREATE TABLE t2(a, b); + CREATE INDEX t2expr ON t2(a) WHERE t2.b>0; +} + +do_execsql_test 1.1 { + SELECT sql FROM sqlite_master +} { + {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))} + {CREATE TABLE t2(a, b)} + {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0} +} + +# Legacy behavior is to corrupt the schema in this case, as the table name in +# the CHECK constraint is incorrect after "t1" is renamed. This version is +# slightly different - it rejects the change and rolls back the transaction. +do_catchsql_test 1.2 { + ALTER TABLE t1 RENAME TO t1new; +} {1 {no such column: t1.a}} + +do_execsql_test 1.3 { + CREATE TABLE t3(c, d); + ALTER TABLE t3 RENAME TO t3new; + DROP TABLE t3new; +} + +do_execsql_test 1.4 { + SELECT sql FROM sqlite_master +} { + {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))} + {CREATE TABLE t2(a, b)} + {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0} +} + + +do_catchsql_test 1.3 { + ALTER TABLE t2 RENAME TO t2new; +} {1 {no such column: t2.b}} +do_execsql_test 1.4 { + SELECT sql FROM sqlite_master +} { + {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))} + {CREATE TABLE t2(a, b)} + {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0} +} + + +#------------------------------------------------------------------------- +reset_db +ifcapable vtab { + register_echo_module db + + do_execsql_test 2.0 { + PRAGMA legacy_alter_table = 1; + CREATE TABLE abc(a, b, c); + INSERT INTO abc VALUES(1, 2, 3); + CREATE VIRTUAL TABLE eee USING echo('abc'); + SELECT * FROM eee; + } {1 2 3} + + do_execsql_test 2.1 { + ALTER TABLE eee RENAME TO fff; + SELECT * FROM fff; + } {1 2 3} + + db close + sqlite3 db test.db + + do_catchsql_test 2.2 { + ALTER TABLE fff RENAME TO ggg; + } {1 {no such module: echo}} +} + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 3.0 { + PRAGMA legacy_alter_table = 1; + CREATE TABLE txx(a, b, c); + INSERT INTO txx VALUES(1, 2, 3); + CREATE VIEW vvv AS SELECT main.txx.a, txx.b, c FROM txx; + CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM txx AS one; + CREATE VIEW temp.ttt AS SELECT main.txx.a, txx.b, one.b, main.one.a FROM txx AS one, txx; +} + +do_execsql_test 3.1.1 { + SELECT * FROM vvv; +} {1 2 3} +do_execsql_test 3.1.2a { + ALTER TABLE txx RENAME TO "t xx"; +} +do_catchsql_test 3.1.2b { + SELECT * FROM vvv; +} {1 {no such table: main.txx}} +do_execsql_test 3.1.3 { + SELECT sql FROM sqlite_master WHERE name='vvv'; +} {{CREATE VIEW vvv AS SELECT main.txx.a, txx.b, c FROM txx}} + + +do_catchsql_test 3.2.1 { + SELECT * FROM uuu; +} {1 {no such table: main.txx}} +do_execsql_test 3.2.2 { + SELECT sql FROM sqlite_master WHERE name='uuu';; +} {{CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM txx AS one}} + +do_catchsql_test 3.3.1 { + SELECT * FROM ttt; +} {1 {no such table: txx}} +do_execsql_test 3.3.2 { + SELECT sql FROM sqlite_temp_master WHERE name='ttt'; +} {{CREATE VIEW ttt AS SELECT main.txx.a, txx.b, one.b, main.one.a FROM txx AS one, txx}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + PRAGMA legacy_alter_table = 1; + CREATE table t1(x, y); + CREATE table t2(a, b); + + CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN + SELECT t1.x, * FROM t1, t2; + INSERT INTO t2 VALUES(new.x, new.y); + END; +} + +do_execsql_test 4.1 { + INSERT INTO t1 VALUES(1, 1); + ALTER TABLE t1 RENAME TO t11; +} +do_catchsql_test 4.1a { + INSERT INTO t11 VALUES(2, 2); +} {1 {no such table: main.t1}} +do_execsql_test 4.1b { + ALTER TABLE t11 RENAME TO t1; + ALTER TABLE t2 RENAME TO t22; +} +do_catchsql_test 4.1c { + INSERT INTO t1 VALUES(3, 3); +} {1 {no such table: main.t2}} + +proc squish {a} { + string trim [regsub -all {[[:space:]][[:space:]]*} $a { }] +} +db func squish squish +do_test 4.2 { + execsql { SELECT squish(sql) FROM sqlite_master WHERE name = 'tr1' } +} [list [squish { + CREATE TRIGGER tr1 AFTER INSERT ON "t1" BEGIN + SELECT t1.x, * FROM t1, t2; + INSERT INTO t2 VALUES(new.x, new.y); + END +}]] + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + PRAGMA legacy_alter_table = 1; + CREATE TABLE t9(a, b, c); + CREATE TABLE t10(a, b, c); + CREATE TEMP TABLE t9(a, b, c); + + CREATE TRIGGER temp.t9t AFTER INSERT ON temp.t9 BEGIN + INSERT INTO t10 VALUES(new.a, new.b, new.c); + END; + + INSERT INTO temp.t9 VALUES(1, 2, 3); + SELECT * FROM t10; +} {1 2 3} + +do_execsql_test 5.1 { + ALTER TABLE temp.t9 RENAME TO 't1234567890' +} + +do_execsql_test 5.2 { + CREATE TABLE t1(a, b); + CREATE TABLE t2(a, b); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES(3, 4); + CREATE VIEW v AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2; + SELECT * FROM v; +} {1 2 3 4} + +do_execsql_test 5.3 { + ALTER TABLE t2 RENAME TO one; +} {} + +do_catchsql_test 5.4 { + SELECT * FROM v +} {1 {no such table: main.t2}} + +do_execsql_test 5.5 { + ALTER TABLE one RENAME TO t2; + DROP VIEW v; + CREATE VIEW temp.vv AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2; + SELECT * FROM vv; +} {1 2 3 4} + +do_execsql_test 5.6 { + ALTER TABLE t2 RENAME TO one; +} {} +do_catchsql_test 5.7 { + SELECT * FROM vv +} {1 {no such table: t2}} + +#------------------------------------------------------------------------- + +ifcapable vtab { + register_tcl_module db + proc tcl_command {method args} { + switch -- $method { + xConnect { + return "CREATE TABLE t1(a, b, c)" + } + } + return {} + } + + do_execsql_test 6.0 { + CREATE VIRTUAL TABLE x1 USING tcl(tcl_command); + } + + do_execsql_test 6.1 { + ALTER TABLE x1 RENAME TO x2; + SELECT sql FROM sqlite_master WHERE name = 'x2' + } {{CREATE VIRTUAL TABLE "x2" USING tcl(tcl_command)}} + + do_execsql_test 7.1 { + CREATE TABLE ddd(db, sql, zOld, zNew, bTemp); + INSERT INTO ddd VALUES( + 'main', 'CREATE TABLE x1(i INTEGER, t TEXT)', 'ddd', NULL, 0 + ), ( + 'main', 'CREATE TABLE x1(i INTEGER, t TEXT)', NULL, 'eee', 0 + ), ( + 'main', NULL, 'ddd', 'eee', 0 + ); + } {} +} + +#------------------------------------------------------------------------- +# +reset_db +forcedelete test.db2 +do_execsql_test 8.1 { + PRAGMA legacy_alter_table = 1; + ATTACH 'test.db2' AS aux; + PRAGMA foreign_keys = on; + CREATE TABLE aux.p1(a INTEGER PRIMARY KEY, b); + CREATE TABLE aux.c1(x INTEGER PRIMARY KEY, y REFERENCES p1(a)); + INSERT INTO aux.p1 VALUES(1, 1); + INSERT INTO aux.p1 VALUES(2, 2); + INSERT INTO aux.c1 VALUES(NULL, 2); + CREATE TABLE aux.c2(x INTEGER PRIMARY KEY, y REFERENCES c1(a)); +} + +do_execsql_test 8.2 { + ALTER TABLE aux.p1 RENAME TO ppp; +} + +do_execsql_test 8.2 { + INSERT INTO aux.c1 VALUES(NULL, 1); + SELECT sql FROM aux.sqlite_master WHERE name = 'c1'; +} {{CREATE TABLE c1(x INTEGER PRIMARY KEY, y REFERENCES "ppp"(a))}} + +reset_db +do_execsql_test 9.0 { + PRAGMA legacy_alter_table = 1; + CREATE TABLE t1(a, b, c); + CREATE VIEW v1 AS SELECT * FROM t2; +} +do_execsql_test 9.1 { + ALTER TABLE t1 RENAME TO t3; +} {} +do_execsql_test 9.1b { + ALTER TABLE t3 RENAME TO t1; +} {} +do_execsql_test 9.2 { + DROP VIEW v1; + CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN + INSERT INTO t2 VALUES(new.a); + END; +} +do_execsql_test 9.3 { + ALTER TABLE t1 RENAME TO t3; +} {} + +forcedelete test.db2 +do_execsql_test 9.4 { + ALTER TABLE t3 RENAME TO t1; + DROP TRIGGER tr; + + ATTACH 'test.db2' AS aux; + CREATE TRIGGER tr AFTER INSERT ON t1 WHEN new.a IS NULL BEGIN SELECT 1, 2, 3; END; + + CREATE TABLE aux.t1(x); + CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END; +} +do_execsql_test 9.5 { + ALTER TABLE main.t1 RENAME TO t3; +} +do_execsql_test 9.6 { + SELECT sql FROM sqlite_temp_master; + SELECT sql FROM sqlite_master WHERE type='trigger'; +} { + {CREATE TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END} + {CREATE TRIGGER tr AFTER INSERT ON "t3" WHEN new.a IS NULL BEGIN SELECT 1, 2, 3; END} +} + +#------------------------------------------------------------------------- +reset_db +ifcapable fts5 { + do_execsql_test 10.0 { + PRAGMA legacy_alter_table = 1; + CREATE VIRTUAL TABLE fff USING fts5(x, y, z); + } + + do_execsql_test 10.1 { + BEGIN; + INSERT INTO fff VALUES('a', 'b', 'c'); + ALTER TABLE fff RENAME TO ggg; + COMMIT; + } + + do_execsql_test 10.2 { + SELECT * FROM ggg; + } {a b c} +} + +#------------------------------------------------------------------------- +reset_db +forcedelete test.db2 +db func trigger trigger +set ::trigger [list] +proc trigger {args} { + lappend ::trigger $args +} +do_execsql_test 11.0 { + PRAGMA legacy_alter_table = 1; + ATTACH 'test.db2' AS aux; + CREATE TABLE aux.t1(a, b, c); + CREATE TABLE main.t1(a, b, c); + CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN + SELECT trigger(new.a, new.b, new.c); + END; +} + +do_execsql_test 11.1 { + INSERT INTO main.t1 VALUES(1, 2, 3); + INSERT INTO aux.t1 VALUES(4, 5, 6); +} +do_test 11.2 { set ::trigger } {{4 5 6}} + +do_execsql_test 11.3 { + SELECT name, tbl_name FROM sqlite_temp_master; +} {tr t1} + +do_execsql_test 11.4 { + ALTER TABLE main.t1 RENAME TO t2; + SELECT name, tbl_name FROM sqlite_temp_master; +} {tr t1} + +do_execsql_test 11.5 { + ALTER TABLE aux.t1 RENAME TO t2; + SELECT name, tbl_name FROM sqlite_temp_master; +} {tr t2} + +do_execsql_test 11.6 { + INSERT INTO aux.t2 VALUES(7, 8, 9); +} +do_test 11.7 { set ::trigger } {{4 5 6} {7 8 9}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 12.0 { + PRAGMA legacy_alter_table = 1; + CREATE TABLE t1(a); + CREATE TABLE t2(w); + CREATE TRIGGER temp.r1 AFTER INSERT ON main.t2 BEGIN + INSERT INTO t1(a) VALUES(new.w); + END; + CREATE TEMP TABLE t2(x); +} + +do_execsql_test 12.1 { + ALTER TABLE main.t2 RENAME TO t3; +} + +do_execsql_test 12.2 { + INSERT INTO t3 VALUES('WWW'); + SELECT * FROM t1; +} {WWW} + + +#------------------------------------------------------------------------- +reset_db + +ifcapable rtree { + do_execsql_test 14.0 { + PRAGMA legacy_alter_table = 1; + CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy); + + CREATE TABLE "mytable" ( "fid" INTEGER PRIMARY KEY, "geom" BLOB); + + CREATE TRIGGER tr1 AFTER UPDATE OF "geom" ON "mytable" + WHEN OLD."fid" = NEW."fid" AND NEW."geom" IS NULL BEGIN + DELETE FROM rt WHERE id = OLD."fid"; + END; + + INSERT INTO mytable VALUES(1, X'abcd'); + } + + do_execsql_test 14.1 { + UPDATE mytable SET geom = X'1234' + } + + do_execsql_test 14.2 { + ALTER TABLE mytable RENAME TO mytable_renamed; + } + + do_execsql_test 14.3 { + CREATE TRIGGER tr2 AFTER INSERT ON mytable_renamed BEGIN + DELETE FROM rt WHERE id=(SELECT min(id) FROM rt); + END; + } + + do_execsql_test 14.4 { + ALTER TABLE mytable_renamed RENAME TO mytable2; + } +} + +reset_db +do_execsql_test 14.5 { + PRAGMA legacy_alter_table = 1; + CREATE TABLE t1(a, b, c); + CREATE VIEW v1 AS SELECT * FROM t1; + CREATE TRIGGER xyz AFTER INSERT ON t1 BEGIN + SELECT a, b FROM v1; + END; +} +do_execsql_test 14.6 { + ALTER TABLE t1 RENAME TO tt1; +} + + +finish_test + diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index 1bfbeb7c58..8b5a63d9cc 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -382,6 +382,11 @@ set pragma_def { NAME: optimize FLAG: Result1 NeedSchema + + NAME: legacy_alter_table + TYPE: FLAG + ARG: SQLITE_LegacyAlter + IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) } # Open the output file From 34566c4434203fe6ff2421af1c192b0b3ac4d410 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 20 Sep 2018 17:21:21 +0000 Subject: [PATCH 228/260] By default, make all "ALTER TABLE RENAME" statements executed within a virtual table xRename() method exhibit the legacy behaviour. FossilOrigin-Name: 71947337e98b90debb13b390119bc2a6b39dd41535151b836071ee327a31e45d --- manifest | 20 +++++++++--------- manifest.uuid | 2 +- src/alter.c | 28 ++++++++++++------------- src/vdbe.c | 6 +++++- test/altermalloc2.test | 26 ++++++++++++++++++++++++ test/altertab2.test | 46 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 test/altertab2.test diff --git a/manifest b/manifest index fbd12d638d..8bb18d6bf8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\sPRAGMA\sthat\srestores\sthe\slegacy\sALTER\sTABLE\sRENAME\sTO\sbehaviour. -D 2018-09-20T08:28:01.757 +C By\sdefault,\smake\sall\s"ALTER\sTABLE\sRENAME"\sstatements\sexecuted\swithin\sa\svirtual\ntable\sxRename()\smethod\sexhibit\sthe\slegacy\sbehaviour. +D 2018-09-20T17:21:21.872 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -436,7 +436,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 5bca9ae02fb3eb52bb39da57fcbf0af249910f05d268df4797cf32c75173c9ff +F src/alter.c 70dd115eb1f949f69f61773733dc89d6494915ec6a736f259c7a7de4aeb51726 F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114 @@ -573,7 +573,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 -F src/vdbe.c 80603eb66708c2f27879912a4e9456900e66491c3409ca5e392109114e8f6337 +F src/vdbe.c 7433ac76608b80b745f57b8544416dc0178db52ce2cc806a10353309e5f781fb F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907 F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827 F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611 @@ -607,8 +607,9 @@ F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256b F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704 F test/alterlegacy.test e7c07d605c2a85e7d1696c89e6bf64dfc932fc6d9320fe8708c8f5fc0b524d41 F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 -F test/altermalloc2.test 0231398534c494401a70a1d06a63d7849cb5b317fcc14228cbdb53039eba7eae +F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b F test/altertab.test 3b830144c18ae00abd2a27e3d2851c8bb1ee8fe655fa16d8a5971066dc71b58a +F test/altertab2.test 159fd5f7b23ddc841fe678f579f9b1b8e69f44296f3ff75d1b4c155d37a59832 F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8 @@ -1768,10 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d -R 02fc275d8f952db75795f9c11e6b826b -T *branch * legacy-alter-table -T *sym-legacy-alter-table * -T -sym-trunk * +P 5acad2e92c11c209bedc6ac8a709595e8070eed028ffc82af61499e5ceaa5e2b +R 8383c830cd4c7d4950233283e48dfa70 U dan -Z 90941688fa5331b463302b9846d758b7 +Z 4aaec95aa70166b0f73ffe68586010e1 diff --git a/manifest.uuid b/manifest.uuid index 28d3ebfce5..41a08d75ba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5acad2e92c11c209bedc6ac8a709595e8070eed028ffc82af61499e5ceaa5e2b \ No newline at end of file +71947337e98b90debb13b390119bc2a6b39dd41535151b836071ee327a31e45d \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 5b7f43c66c..6833a8c10b 100644 --- a/src/alter.c +++ b/src/alter.c @@ -169,20 +169,6 @@ void sqlite3AlterRenameTable( goto exit_rename_table; } - /* If this is a virtual table, invoke the xRename() function if - ** one is defined. The xRename() callback will modify the names - ** of any resources used by the v-table implementation (including other - ** SQLite tables) that are identified by the name of the virtual table. - */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pVTab ){ - int i = ++pParse->nMem; - sqlite3VdbeLoadString(v, i, zName); - sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); - sqlite3MayAbort(pParse); - } -#endif - /* figure out how many UTF-8 characters are in zName */ zTabName = pTab->zName; nTabName = sqlite3Utf8CharLen(zTabName, -1); @@ -240,6 +226,20 @@ void sqlite3AlterRenameTable( , zDb, zTabName, zName, zTabName, zDb, zName); } + /* If this is a virtual table, invoke the xRename() function if + ** one is defined. The xRename() callback will modify the names + ** of any resources used by the v-table implementation (including other + ** SQLite tables) that are identified by the name of the virtual table. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pVTab ){ + int i = ++pParse->nMem; + sqlite3VdbeLoadString(v, i, zName); + sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); + sqlite3MayAbort(pParse); + } +#endif + renameReloadSchema(pParse, iDb); renameTestSchema(pParse, zDb, iDb==1); diff --git a/src/vdbe.c b/src/vdbe.c index 0e6d7484b2..e57a197975 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -7059,7 +7059,10 @@ case OP_VNext: { /* jump */ case OP_VRename: { sqlite3_vtab *pVtab; Mem *pName; - + int isLegacy; + + isLegacy = (db->flags & SQLITE_LegacyAlter); + db->flags |= SQLITE_LegacyAlter; pVtab = pOp->p4.pVtab->pVtab; pName = &aMem[pOp->p1]; assert( pVtab->pModule->xRename ); @@ -7073,6 +7076,7 @@ case OP_VRename: { rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); if( rc ) goto abort_due_to_error; rc = pVtab->pModule->xRename(pVtab, pName->z); + if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter; sqlite3VtabImportErrmsg(p, pVtab); p->expired = 0; if( rc ) goto abort_due_to_error; diff --git a/test/altermalloc2.test b/test/altermalloc2.test index b23d1c7170..610b3f6bf0 100644 --- a/test/altermalloc2.test +++ b/test/altermalloc2.test @@ -72,4 +72,30 @@ do_faultsim_test 3 -prep { } -test { faultsim_test_result {0 {}} } + +reset_db +do_execsql_test 4.0 { + CREATE TABLE rr(a, b); + CREATE VIEW vv AS SELECT * FROM rr; + + CREATE TRIGGER vv1 INSTEAD OF INSERT ON vv BEGIN + SELECT 1, 2, 3; + END; + CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN + INSERT INTO vv VALUES(new.a, new.b); + END; +} {} + +faultsim_save_and_close +do_faultsim_test 4 -faults oom-* -prep { + faultsim_restore_and_reopen + execsql { SELECT * FROM sqlite_master } +} -body { + execsql { + ALTER TABLE rr RENAME a TO c; + } +} -test { + faultsim_test_result {0 {}} +} + finish_test diff --git a/test/altertab2.test b/test/altertab2.test new file mode 100644 index 0000000000..5656def81a --- /dev/null +++ b/test/altertab2.test @@ -0,0 +1,46 @@ +# 2018 September 30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix altertab + +# If SQLITE_OMIT_ALTERTABLE is defined, omit this file. +ifcapable !altertable { + finish_test + return +} + +ifcapable fts5 { + do_execsql_test 1.0 { + CREATE TABLE rr(a, b); + CREATE VIRTUAL TABLE ff USING fts5(a, b); + CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN + INSERT INTO ff VALUES(new.a, new.b); + END; + INSERT INTO rr VALUES('hello', 'world'); + SELECT * FROM ff; + } {hello world} + + do_execsql_test 1.1 { + ALTER TABLE ff RENAME TO ffff; + } + + do_execsql_test 1.2 { + INSERT INTO rr VALUES('in', 'tcl'); + SELECT * FROM ffff; + } {hello world in tcl} +} + + +finish_test + From eda079cd2c8ac1217574cd372c7bbcf6f651ccab Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 20 Sep 2018 19:02:15 +0000 Subject: [PATCH 229/260] Combine the Expr.pTab and Expr.pWin fields into a union named "y". Add a new EP_WinFunc property that is only true if Expr.y.pWin is a valid pointer. This reduces the size of the Expr object by 8 bytes, reduces the overall amount of code, and shaves over 1 million cycles off of the speed test. FossilOrigin-Name: ad130bb86e74e6ce165fdbdce3a19699510f0e62071c1c7923b5a4538d888c7c --- manifest | 38 ++++++++++++------------ manifest.uuid | 2 +- src/alter.c | 6 ++-- src/expr.c | 79 +++++++++++++++++++++++++------------------------ src/fkey.c | 2 +- src/parse.y | 5 +--- src/resolve.c | 53 ++++++++++++++++----------------- src/select.c | 14 ++++----- src/sqliteInt.h | 11 +++---- src/treeview.c | 2 +- src/vtab.c | 2 +- src/walker.c | 4 +-- src/wherecode.c | 2 +- src/whereexpr.c | 14 ++++----- src/window.c | 10 ++++--- 15 files changed, 123 insertions(+), 121 deletions(-) diff --git a/manifest b/manifest index 5a4a89bb0a..3eddc02306 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompilation\sissue\sin\sthe\s"userauth"\sextension.\sAlso\sfix\sa\sfew\stest\nscript\serrors\sthat\soccur\swith\sSQLITE_USER_AUTHENTICATION=1\sbuilds. -D 2018-09-19T17:09:09.208 +C Combine\sthe\sExpr.pTab\sand\sExpr.pWin\sfields\sinto\sa\sunion\snamed\s"y".\s\sAdd\sa\snew\nEP_WinFunc\sproperty\sthat\sis\sonly\strue\sif\sExpr.y.pWin\sis\sa\svalid\spointer.\nThis\sreduces\sthe\ssize\sof\sthe\sExpr\sobject\sby\s8\sbytes,\sreduces\sthe\soverall\namount\sof\scode,\sand\sshaves\sover\s1\smillion\scycles\soff\sof\sthe\sspeed\stest. +D 2018-09-20T19:02:15.729 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -436,7 +436,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b +F src/alter.c e561794b3175930f25b0177e4a1c42f6696f200d261519913b3615d9ae97516d F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114 @@ -454,9 +454,9 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2 -F src/expr.c 92dc4e104b06d06ffeacbd1a4dc0a520daf37f6156278fb6ece5e90e2ca6b610 +F src/expr.c 610eea078f240e8d55e81666a65b05a42e52008d24059c59093dd18b3d15b565 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a +F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812 F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128 F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a @@ -491,7 +491,7 @@ F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963 -F src/parse.y 4118dbf9c37c410e5c4775c033b1aaf67ac8ff7965df7a4bb429dd5db2dbe374 +F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 @@ -500,14 +500,14 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b +F src/resolve.c 3f99bbea840d917acd530c75a180d00415fc6e06d1b693c32fd9a4fe91023a91 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c 8afcc2b56a6ef76717bb59b6109cd3de0f6fae2803894d6f806640c0aa24dfac +F src/select.c 1b7ade8fabb85ccd3369683a7951fda37b2843aa1e4ef1fa866b09596a8bfec3 F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 -F src/sqliteInt.h 83ee9b55db521b70294b2858872e69b96d0a4810d8221796def3e99cca5ee663 +F src/sqliteInt.h 214e56845ff775d1b53529d3d9488afa12d190d4b5ae56abd0a04ecfcf5f9097 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -566,7 +566,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b -F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f +F src/treeview.c 0ef7dc77d6fe03172ba65dddfd3b3c557b7b7e217ca1963b7665beb266a0e2c0 F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 @@ -582,16 +582,16 @@ F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c9419 F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641 F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392 -F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594 +F src/vtab.c 9ada8a26ffc17c27ab27a06b23599faeb2e0c487ad9ef53903917ac973b42170 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a -F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4 +F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66 F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 -F src/wherecode.c 4f88f5b39ad4aeb5bdd47a546d74149bb902ef49ca9f02a45b2a5bd2dd70b6bd -F src/whereexpr.c eb462ebe085f6cbb6bdda797a041fbd7e3724586203344043d1088a2117d8e44 -F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65 +F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893 +F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00 +F src/window.c a28d8d42c51c7e31136a42f3e245282049d4a9466b36d7bd765772991472df41 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1767,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022 -R b045d000830b7f892b6bae2ce9b528b3 -U dan -Z e635b6ecc9802f0bfb5422b4720e432b +P 221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d +R a205fb07eb91b652f9b260657ba75a88 +U drh +Z 462af2fea172a873521f037816957a1f diff --git a/manifest.uuid b/manifest.uuid index 9220eb9168..775847a563 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d \ No newline at end of file +ad130bb86e74e6ce165fdbdce3a19699510f0e62071c1c7923b5a4538d888c7c \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 08745ccee2..1cf778b000 100644 --- a/src/alter.c +++ b/src/alter.c @@ -803,7 +803,7 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ renameTokenFind(pWalker->pParse, p, (void*)pExpr); }else if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol - && p->pTab==pExpr->pTab + && p->pTab==pExpr->y.pTab ){ renameTokenFind(pWalker->pParse, p, (void*)pExpr); } @@ -1341,8 +1341,8 @@ renameColumnFunc_done: */ static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){ - renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab); + if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){ + renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); } return WRC_Continue; } diff --git a/src/expr.c b/src/expr.c index 4777244024..1692822840 100644 --- a/src/expr.c +++ b/src/expr.c @@ -58,8 +58,8 @@ char sqlite3ExprAffinity(Expr *pExpr){ return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif - if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){ - return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){ + return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); } if( op==TK_SELECT_COLUMN ){ assert( pExpr->pLeft->flags&EP_xIsSelect ); @@ -143,13 +143,13 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ if( p->flags & EP_Generic ) break; if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) - && p->pTab!=0 + && p->y.pTab!=0 ){ - /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally + /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if( j>=0 ){ - const char *zColl = p->pTab->aCol[j].zColl; + const char *zColl = p->y.pTab->aCol[j].zColl; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); } break; @@ -1052,6 +1052,10 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ assert( p!=0 ); /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); + + assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed ); + assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced) + || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) ); #ifdef SQLITE_DEBUG if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); @@ -1070,8 +1074,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ }else{ sqlite3ExprListDelete(db, p->x.pList); } - if( !ExprHasProperty(p, EP_Reduced) ){ - sqlite3WindowDelete(db, p->pWin); + if( ExprHasProperty(p, EP_WinFunc) ){ + assert( p->op==TK_FUNCTION ); + sqlite3WindowDelete(db, p->y.pWin); } } if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); @@ -1135,7 +1140,7 @@ static int dupedExprStructSize(Expr *p, int flags){ assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); if( 0==flags || p->op==TK_SELECT_COLUMN #ifndef SQLITE_OMIT_WINDOWFUNC - || p->pWin + || ExprHasProperty(p, EP_WinFunc) #endif ){ nSize = EXPR_FULLSIZE; @@ -1278,10 +1283,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ } }else{ #ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){ - pNew->pWin = 0; - }else{ - pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin); + if( ExprHasProperty(p, EP_WinFunc) ){ + pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); + assert( ExprHasProperty(pNew, EP_WinFunc) ); } #endif /* SQLITE_OMIT_WINDOWFUNC */ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ @@ -2089,8 +2093,8 @@ int sqlite3ExprCanBeNull(const Expr *p){ return 0; case TK_COLUMN: return ExprHasProperty(p, EP_CanBeNull) || - p->pTab==0 || /* Reference to column of index on expression */ - (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); + p->y.pTab==0 || /* Reference to column of index on expression */ + (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; } @@ -3378,7 +3382,7 @@ expr_code_doover: ** constant. */ int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); - int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); if( aff!=SQLITE_AFF_BLOB ){ static const char zAff[] = "B\000C\000D\000E"; assert( SQLITE_AFF_BLOB=='A' ); @@ -3402,7 +3406,7 @@ expr_code_doover: iTab = pParse->iSelfTab - 1; } } - return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, pExpr->iColumn, iTab, target, pExpr->op2); } @@ -3616,8 +3620,8 @@ expr_code_doover: CollSeq *pColl = 0; /* A collating sequence */ #ifndef SQLITE_OMIT_WINDOWFUNC - if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){ - return pExpr->pWin->regResult; + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + return pExpr->y.pWin->regResult; } #endif @@ -3860,7 +3864,7 @@ expr_code_doover: ** p1==1 -> old.a p1==4 -> new.a ** p1==2 -> old.b p1==5 -> new.b */ - Table *pTab = pExpr->pTab; + Table *pTab = pExpr->y.pTab; int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; assert( pExpr->iTable==0 || pExpr->iTable==1 ); @@ -3871,7 +3875,7 @@ expr_code_doover: sqlite3VdbeAddOp2(v, OP_Param, p1, target); VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName) + (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName) )); #ifndef SQLITE_OMIT_FLOATING_POINT @@ -4722,6 +4726,20 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ if( pA->op==TK_FUNCTION ){ if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; +#ifndef SQLITE_OMIT_WINDOWFUNC + /* Justification for the assert(): + ** window functions have p->op==TK_FUNCTION but aggregate functions + ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate + ** function and a window function should have failed before reaching + ** this point. And, it is not possible to have a window function and + ** a scalar function with the same name and number of arguments. So + ** if we reach this point, either A and B both window functions or + ** neither are a window functions. */ + assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) ); + if( ExprHasProperty(pA,EP_WinFunc) ){ + if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2; + } +#endif }else if( pA->op==TK_COLLATE ){ if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ @@ -4741,21 +4759,6 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; } -#ifndef SQLITE_OMIT_WINDOWFUNC - /* Justification for the assert(): - ** window functions have p->op==TK_FUNCTION but aggregate functions - ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate - ** function and a window function should have failed before reaching - ** this point. And, it is not possible to have a window function and - ** a scalar function with the same name and number of arguments. So - ** if we reach this point, either A and B both window functions or - ** neither are a window functions. */ - assert( (pA->pWin==0)==(pB->pWin==0) ); - - if( pA->pWin!=0 ){ - if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2; - } -#endif } return 0; } @@ -4899,8 +4902,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); - if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) - || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) + if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) + || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) ){ return WRC_Prune; } @@ -5131,7 +5134,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 ){ pCol = &pAggInfo->aCol[k]; - pCol->pTab = pExpr->pTab; + pCol->pTab = pExpr->y.pTab; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iMem = ++pParse->nMem; diff --git a/src/fkey.c b/src/fkey.c index 0f5248fea2..6777d71eaf 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -502,7 +502,7 @@ static Expr *exprTableColumn( ){ Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); if( pExpr ){ - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; pExpr->iTable = iCursor; pExpr->iColumn = iCol; } diff --git a/src/parse.y b/src/parse.y index f2cb072948..b150c73e1f 100644 --- a/src/parse.y +++ b/src/parse.y @@ -941,13 +941,10 @@ idlist(A) ::= nm(Y). p->pLeft = p->pRight = 0; p->x.pList = 0; p->pAggInfo = 0; - p->pTab = 0; + p->y.pTab = 0; p->op2 = 0; p->iTable = 0; p->iColumn = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - p->pWin = 0; -#endif p->u.zToken = (char*)&p[1]; memcpy(p->u.zToken, t.z, t.n); p->u.zToken[t.n] = 0; diff --git a/src/resolve.c b/src/resolve.c index 9fb4d4c63f..da9ead625d 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -159,7 +159,7 @@ int sqlite3MatchSpanName( ** (even if X is implied). ** pExpr->iTable Set to the cursor number for the table obtained ** from pSrcList. -** pExpr->pTab Points to the Table structure of X.Y (even if +** pExpr->y.pTab Points to the Table structure of X.Y (even if ** X and/or Y are implied.) ** pExpr->iColumn Set to the column number within the table. ** pExpr->op Set to TK_COLUMN. @@ -203,7 +203,6 @@ static int lookupName( /* Initialize the node to no-match */ pExpr->iTable = -1; - pExpr->pTab = 0; ExprSetVVAProperty(pExpr, EP_NoReduce); /* Translate the schema name in zDb into a pointer to the corresponding @@ -265,7 +264,7 @@ static int lookupName( continue; } if( IN_RENAME_OBJECT && pItem->zAlias ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab); + sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); } } if( 0==(cntTab++) ){ @@ -291,13 +290,13 @@ static int lookupName( } if( pMatch ){ pExpr->iTable = pMatch->iCursor; - pExpr->pTab = pMatch->pTab; + pExpr->y.pTab = pMatch->pTab; /* RIGHT JOIN not (yet) supported */ assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } - pSchema = pExpr->pTab->pSchema; + pSchema = pExpr->y.pTab->pSchema; } } /* if( pSrcList ) */ @@ -354,7 +353,7 @@ static int lookupName( testcase( iCol==(-1) ); if( IN_RENAME_OBJECT ){ pExpr->iColumn = iCol; - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; eNewExprOp = TK_COLUMN; }else{ pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; @@ -376,7 +375,7 @@ static int lookupName( testcase( iCol==32 ); pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<pTab = pTab; + pExpr->y.pTab = pTab; pExpr->iColumn = (i16)iCol; eNewExprOp = TK_TRIGGER; #endif /* SQLITE_OMIT_TRIGGER */ @@ -476,7 +475,7 @@ static int lookupName( assert( pExpr->op==TK_ID ); if( ExprHasProperty(pExpr,EP_DblQuoted) ){ pExpr->op = TK_STRING; - pExpr->pTab = 0; + pExpr->y.pTab = 0; return WRC_Prune; } if( sqlite3ExprIdToTrueFalse(pExpr) ){ @@ -554,9 +553,9 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){ Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); if( p ){ struct SrcList_item *pItem = &pSrc->a[iSrc]; - p->pTab = pItem->pTab; + p->y.pTab = pItem->pTab; p->iTable = pItem->iCursor; - if( p->pTab->iPKey==iCol ){ + if( p->y.pTab->iPKey==iCol ){ p->iColumn = -1; }else{ p->iColumn = (ynVar)iCol; @@ -646,7 +645,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pItem = pSrcList->a; assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 ); pExpr->op = TK_COLUMN; - pExpr->pTab = pItem->pTab; + pExpr->y.pTab = pItem->pTab; pExpr->iTable = pItem->iCursor; pExpr->iColumn = -1; pExpr->affinity = SQLITE_AFF_INTEGER; @@ -692,7 +691,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); } if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft); + sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); } } return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); @@ -782,18 +781,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ || (pDef->xValue==0 && pDef->xInverse==0) || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) ); - if( pDef && pDef->xValue==0 && pExpr->pWin ){ + if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ sqlite3ErrorMsg(pParse, "%.*s() may not be used as a window function", nId, zId ); pNC->nErr++; }else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) - || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin) - || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0) + || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin) + || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0) ){ const char *zType; - if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){ + if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){ zType = "window"; }else{ zType = "aggregate"; @@ -823,7 +822,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg); + pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg); #else pNC->ncFlags &= ~NC_AllowAgg; #endif @@ -832,17 +831,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ sqlite3WalkExprList(pWalker, pList); if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pExpr->pWin ){ + if( pExpr->y.pWin ){ Select *pSel = pNC->pWinSelect; - sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition); - sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy); - sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter); - sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef); + sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); + sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); + sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); + sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); if( 0==pSel->pWin - || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin) + || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) ){ - pExpr->pWin->pNextWin = pSel->pWin; - pSel->pWin = pExpr->pWin; + pExpr->y.pWin->pNextWin = pSel->pWin; + pSel->pWin = pExpr->y.pWin; } pNC->ncFlags |= NC_AllowWin; }else @@ -1265,13 +1264,13 @@ static int resolveOrderGroupBy( for(j=0; jpEList->nExpr; j++){ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pE->pWin ){ + if( ExprHasProperty(pE, EP_WinFunc) ){ /* Since this window function is being changed into a reference ** to the same window function the result set, remove the instance ** of this window function from the Select.pWin list. */ Window **pp; for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ - if( *pp==pE->pWin ){ + if( *pp==pE->y.pWin ){ *pp = (*pp)->pNextWin; } } diff --git a/src/select.c b/src/select.c index bc5960fe49..d300798069 100644 --- a/src/select.c +++ b/src/select.c @@ -803,7 +803,7 @@ static void selectExprDefer( struct ExprList_item *pItem = &pEList->a[i]; if( pItem->u.x.iOrderByCol==0 ){ Expr *pExpr = pItem->pExpr; - Table *pTab = pExpr->pTab; + Table *pTab = pExpr->y.pTab; if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab) && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) ){ @@ -826,12 +826,12 @@ static void selectExprDefer( Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0); if( pNew ){ pNew->iTable = pExpr->iTable; - pNew->pTab = pExpr->pTab; + pNew->y.pTab = pExpr->y.pTab; pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); } } - pSort->aDefer[nDefer].pTab = pExpr->pTab; + pSort->aDefer[nDefer].pTab = pExpr->y.pTab; pSort->aDefer[nDefer].iCsr = pExpr->iTable; pSort->aDefer[nDefer].nKey = nKey; nDefer++; @@ -1680,7 +1680,7 @@ static const char *columnTypeImpl( break; } - assert( pTab && pExpr->pTab==pTab ); + assert( pTab && pExpr->y.pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin @@ -1865,7 +1865,7 @@ static void generateColumnNames( assert( p!=0 ); assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ - assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */ + assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */ if( pEList->a[i].zName ){ /* An AS clause always takes first priority */ char *zName = pEList->a[i].zName; @@ -1873,7 +1873,7 @@ static void generateColumnNames( }else if( srcName && p->op==TK_COLUMN ){ char *zCol; int iCol = p->iColumn; - pTab = p->pTab; + pTab = p->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iColnCol) ); @@ -1964,7 +1964,7 @@ int sqlite3ColumnsFromExprList( if( pColExpr->op==TK_COLUMN ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; - Table *pTab = pColExpr->pTab; + Table *pTab = pColExpr->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 74438b5abc..ba24c07aa6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2459,11 +2459,11 @@ struct Expr { ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL - ** for a column of an index on an expression */ -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin; /* Window definition for window functions */ -#endif + union { + Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL + ** for a column of an index on an expression */ + Window *pWin; /* TK_FUNCTION: Window definition for the func */ + } y; }; /* @@ -2493,6 +2493,7 @@ struct Expr { #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ #define EP_Alias 0x400000 /* Is an alias for a result set column */ #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ +#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ /* ** The EP_Propagate mask is a set of properties that automatically propagate diff --git a/src/treeview.c b/src/treeview.c index cde776d0fa..c8c3b90be1 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -497,7 +497,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ }else{ pFarg = pExpr->x.pList; #ifndef SQLITE_OMIT_WINDOWFUNC - pWin = pExpr->pWin; + pWin = pExpr->y.pWin; #else pWin = 0; #endif diff --git a/src/vtab.c b/src/vtab.c index 7b459be7b6..f5501e198a 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -1053,7 +1053,7 @@ FuncDef *sqlite3VtabOverloadFunction( /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; - pTab = pExpr->pTab; + pTab = pExpr->y.pTab; if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; diff --git a/src/walker.c b/src/walker.c index b3d4cd805d..c31d94f0bf 100644 --- a/src/walker.c +++ b/src/walker.c @@ -55,8 +55,8 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; } #ifndef SQLITE_OMIT_WINDOWFUNC - if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){ - Window *pWin = pExpr->pWin; + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + Window *pWin = pExpr->y.pWin; if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort; diff --git a/src/wherecode.c b/src/wherecode.c index 65cbc4ca2c..f337006b97 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1117,7 +1117,7 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; - pExpr->pTab = 0; + pExpr->y.pTab = 0; return WRC_Prune; }else{ return WRC_Continue; diff --git a/src/whereexpr.c b/src/whereexpr.c index 808c0d21c7..8f3791e798 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -281,7 +281,7 @@ static int isLikeOrGlob( ){ if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) /* Value might be numeric */ + || IsVirtual(pLeft->y.pTab) /* Value might be numeric */ ){ sqlite3ExprDelete(db, pPrefix); sqlite3ValueFree(pVal); @@ -382,7 +382,7 @@ static int isAuxiliaryVtabOperator( ** MATCH(expression,vtab_column) */ pCol = pList->a[1].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ for(i=0; iu.zToken, aOp[i].zOp)==0 ){ *peOp2 = aOp[i].eOp2; @@ -404,12 +404,12 @@ static int isAuxiliaryVtabOperator( ** with function names in an arbitrary case. */ pCol = pList->a[0].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ sqlite3_vtab *pVtab; sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; - pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab; + pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; @@ -427,10 +427,10 @@ static int isAuxiliaryVtabOperator( int res = 0; Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pRight; - if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ + if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ res++; } - if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){ + if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ res++; SWAP(Expr*, pLeft, pRight); } @@ -1583,7 +1583,7 @@ void sqlite3WhereTabFuncArgs( if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; - pColRef->pTab = pTab; + pColRef->y.pTab = pTab; pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); diff --git a/src/window.c b/src/window.c index ce51de790f..36cfc1c280 100644 --- a/src/window.c +++ b/src/window.c @@ -624,12 +624,12 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ switch( pExpr->op ){ case TK_FUNCTION: - if( pExpr->pWin==0 ){ + if( !ExprHasProperty(pExpr, EP_WinFunc) ){ break; }else{ Window *pWin; for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ - if( pExpr->pWin==pWin ){ + if( pExpr->y.pWin==pWin ){ assert( pWin->pOwner==pExpr ); return WRC_Prune; } @@ -959,11 +959,13 @@ windowAllocErr: */ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ if( p ){ + assert( p->op==TK_FUNCTION ); /* This routine is only called for the parser. If pWin was not ** allocated due to an OOM, then the parser would fail before ever ** invoking this routine */ if( ALWAYS(pWin) ){ - p->pWin = pWin; + p->y.pWin = pWin; + ExprSetProperty(p, EP_WinFunc); pWin->pOwner = p; if( p->flags & EP_Distinct ){ sqlite3ErrorMsg(pParse, @@ -2126,7 +2128,7 @@ static void windowCodeDefaultStep( */ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ Window *pNew = 0; - if( p ){ + if( ALWAYS(p) ){ pNew = sqlite3DbMallocZero(db, sizeof(Window)); if( pNew ){ pNew->zName = sqlite3DbStrDup(db, p->zName); From 0d7f0ccd966442b4d887b40e84e6b005a38e9803 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 21 Sep 2018 13:07:14 +0000 Subject: [PATCH 230/260] Optimization to the OP_MakeRecord opcode makes speed-check.sh run about 1.1 million cycles faster, and results in a slightly smaller library. FossilOrigin-Name: d10e63629183f6daf0c263cd4dae052a3786c8c1480b3b6a73124b3315e41951 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 18 +++++++++++++----- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index c7f29e6415..20bfd8e4f6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\scode\ssimplification. -D 2018-09-20T20:43:28.118 +C Optimization\sto\sthe\sOP_MakeRecord\sopcode\smakes\sspeed-check.sh\srun\sabout\n1.1\smillion\scycles\sfaster,\sand\sresults\sin\sa\sslightly\ssmaller\slibrary. +D 2018-09-21T13:07:14.225 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -573,7 +573,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 -F src/vdbe.c 7433ac76608b80b745f57b8544416dc0178db52ce2cc806a10353309e5f781fb +F src/vdbe.c c7416f6b5e47efbdf09c73a3984ecc68666151ae894c27fb1e51d51bbba62082 F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907 F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827 F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7edd26ed27ed1e7eab603058f7d55f2eac45e7bd1908bfa5f32293611883b157 5e458f4a92743effb9a3d3249767424fed8b444a05ca136c4a55d60c4d70c2cc -R 6e3668e1a9453a68a64669c9f81648e7 +P 22ae8a52dd2fb744f467c7dccf1d7fe7c7cef0e1dcc897dd492f897e84c9facb +R 33a3ccc9bec749141fe1417d8f2213ed U drh -Z 479e3a8163395f3eaf4fbec67bf9b33f +Z 4fef5bba9e51ca59b92e81f3a1e63e07 diff --git a/manifest.uuid b/manifest.uuid index 782e07d0aa..9e827d388a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -22ae8a52dd2fb744f467c7dccf1d7fe7c7cef0e1dcc897dd492f897e84c9facb \ No newline at end of file +d10e63629183f6daf0c263cd4dae052a3786c8c1480b3b6a73124b3315e41951 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index e57a197975..6a50fa2f99 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2894,17 +2894,25 @@ case OP_MakeRecord: { if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } /* Make sure the output register has a buffer large enough to store ** the new record. The output register (pOp->p3) is not allowed to ** be one of the input registers (because the following call to ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). */ - if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ - goto no_mem; + if( nByte+nZero<=pOut->szMalloc ){ + /* The output register is already large enough to hold the record. + ** No error checks or buffer enlargement is required */ + pOut->z = pOut->zMalloc; + }else{ + /* Need to make sure that the output is not too big and then enlarge + ** the output register to hold the full result */ + if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ + goto no_mem; + } } zNewRecord = (u8 *)pOut->z; From fc9098a45edd457b143cee75abb708fef440a34d Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 21 Sep 2018 18:43:51 +0000 Subject: [PATCH 231/260] Put a limit counter on the query planner that restricts the number of index+constraint options that can be considered for each table in a join. This prevents certain pathological queries from taking up too much time in the query planner. FossilOrigin-Name: 8690b5a0cc08eeb175230de45d4ca9b9f7b9b22aeebea70b8b7151f10b130969 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 21 ++++++++++++++++++++- src/whereInt.h | 1 + 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 20bfd8e4f6..8c8cc6575e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimization\sto\sthe\sOP_MakeRecord\sopcode\smakes\sspeed-check.sh\srun\sabout\n1.1\smillion\scycles\sfaster,\sand\sresults\sin\sa\sslightly\ssmaller\slibrary. -D 2018-09-21T13:07:14.225 +C Put\sa\slimit\scounter\son\sthe\squery\splanner\sthat\srestricts\sthe\snumber\sof\nindex+constraint\soptions\sthat\scan\sbe\sconsidered\sfor\seach\stable\sin\sa\sjoin.\nThis\sprevents\scertain\spathological\squeries\sfrom\staking\sup\stoo\smuch\stime\nin\sthe\squery\splanner. +D 2018-09-21T18:43:51.308 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -587,8 +587,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66 -F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b -F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 +F src/where.c e5c4f5ab05e5112d971510bfd4cc673657e02673ac8a76db4296d703237a2461 +F src/whereInt.h 2c4d99faf71c35339a33b20d11c5cb8921416a21d6816d830b85df320303e5bd F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893 F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00 F src/window.c a28d8d42c51c7e31136a42f3e245282049d4a9466b36d7bd765772991472df41 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 22ae8a52dd2fb744f467c7dccf1d7fe7c7cef0e1dcc897dd492f897e84c9facb -R 33a3ccc9bec749141fe1417d8f2213ed +P d10e63629183f6daf0c263cd4dae052a3786c8c1480b3b6a73124b3315e41951 +R 56d8cd6e634d174344ffe41fce1a9ac6 U drh -Z 4fef5bba9e51ca59b92e81f3a1e63e07 +Z a5b6a9aaf70c834d7cee7cb5aaf91158 diff --git a/manifest.uuid b/manifest.uuid index 9e827d388a..3543112358 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d10e63629183f6daf0c263cd4dae052a3786c8c1480b3b6a73124b3315e41951 \ No newline at end of file +8690b5a0cc08eeb175230de45d4ca9b9f7b9b22aeebea70b8b7151f10b130969 \ No newline at end of file diff --git a/src/where.c b/src/where.c index d8d577d521..f8727b0620 100644 --- a/src/where.c +++ b/src/where.c @@ -2126,6 +2126,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ sqlite3 *db = pWInfo->pParse->db; int rc; + /* Stop the search once we hit the query planner search limit */ + if( pBuilder->iPlanLimit==0 ) return SQLITE_DONE; + pBuilder->iPlanLimit--; + /* If pBuilder->pOrSet is defined, then only keep track of the costs ** and prereqs. */ @@ -3532,9 +3536,17 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; whereLoopInit(pNew); + /* Some pathological queries provide an unreasonable number of indexing + ** options. The iPlanLimit value prevents these queries from taking up + ** too much time in the planner. When iPlanLimit reaches zero, no further + ** index+constraint options are considered. Seed iPlanLimit to 10K but + ** also add an extra 1K to each table of the join, to ensure that each + ** table at least gets 1K opportunities. */ + pBuilder->iPlanLimit = 10000; for(iTab=0, pItem=pTabList->a; pItemiTab = iTab; + pBuilder->iPlanLimit += 1000; /* 1000 bonus for each table in the join */ pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ /* This condition is true when pItem is the FROM clause term on the @@ -3560,7 +3572,14 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); } mPrior |= pNew->maskSelf; - if( rc || db->mallocFailed ) break; + if( rc || db->mallocFailed ){ + if( rc==SQLITE_DONE ){ + /* We hit the query planner search limit set by iPlanLimit */ + rc = SQLITE_OK; + }else{ + break; + } + } } whereLoopClear(db, pNew); diff --git a/src/whereInt.h b/src/whereInt.h index 8c87effac0..a34708df40 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -402,6 +402,7 @@ struct WhereLoopBuilder { int nRecValid; /* Number of valid fields currently in pRec */ #endif unsigned int bldFlags; /* SQLITE_BLDF_* flags */ + unsigned int iPlanLimit; /* Search limiter */ }; /* Allowed values for WhereLoopBuider.bldFlags */ From 5eaebf3a63162a75dd5cc9e5e33e4852701f4ab1 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 21 Sep 2018 19:06:09 +0000 Subject: [PATCH 232/260] Comment typo fixed. No code changes. FossilOrigin-Name: 7e68cdab20f50cf776b92b2138bb4aba7cb070f2bd855dd4cbbf46d447f2dc88 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pcache.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8c8cc6575e..6046f9cdf9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Put\sa\slimit\scounter\son\sthe\squery\splanner\sthat\srestricts\sthe\snumber\sof\nindex+constraint\soptions\sthat\scan\sbe\sconsidered\sfor\seach\stable\sin\sa\sjoin.\nThis\sprevents\scertain\spathological\squeries\sfrom\staking\sup\stoo\smuch\stime\nin\sthe\squery\splanner. -D 2018-09-21T18:43:51.308 +C Comment\stypo\sfixed.\s\sNo\scode\schanges. +D 2018-09-21T19:06:09.667 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -492,7 +492,7 @@ F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963 F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179 -F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd +F src/pcache.c 4196eb6ed3bbf00b80596c8e0b4f50e57eb7d890c19fb27a7354306abb7f983d F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c 79abc65c08d2754048efee3ba99fe91863dfeab0ba699a4439fa5053ec87cf36 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d10e63629183f6daf0c263cd4dae052a3786c8c1480b3b6a73124b3315e41951 -R 56d8cd6e634d174344ffe41fce1a9ac6 +P 8690b5a0cc08eeb175230de45d4ca9b9f7b9b22aeebea70b8b7151f10b130969 +R 97ab244d3dc6ac850dabfd9f2e0eadc3 U drh -Z a5b6a9aaf70c834d7cee7cb5aaf91158 +Z 7f8590ad5b26658db9da1b3476a27528 diff --git a/manifest.uuid b/manifest.uuid index 3543112358..995c7b8cd7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8690b5a0cc08eeb175230de45d4ca9b9f7b9b22aeebea70b8b7151f10b130969 \ No newline at end of file +7e68cdab20f50cf776b92b2138bb4aba7cb070f2bd855dd4cbbf46d447f2dc88 \ No newline at end of file diff --git a/src/pcache.c b/src/pcache.c index 41fb03100c..7415378b4f 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -32,7 +32,7 @@ ** The PCache.pSynced variable is used to optimize searching for a dirty ** page to eject from the cache mid-transaction. It is better to eject ** a page that does not require a journal sync than one that does. -** Therefore, pSynced is maintained to that it *almost* always points +** Therefore, pSynced is maintained so that it *almost* always points ** to either the oldest page in the pDirty/pDirtyTail list that has a ** clear PGHDR_NEED_SYNC flag or to a page that is older than this one ** (so that the right page to eject can be found by following pDirtyPrev From 7cc5595a015bd984773338f5736c1147b698c1c4 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 21 Sep 2018 23:41:18 +0000 Subject: [PATCH 233/260] Fix harmless compiler warning when compiled with SQLITE_OMIT_AUTHORIZATION. FossilOrigin-Name: 50f2fa19532e0f849d61d9e2a97427cfbf64cfb787ca481ef8c860d0f24f6cfe --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vtab.c | 5 ++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 6046f9cdf9..81476e114c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Comment\stypo\sfixed.\s\sNo\scode\schanges. -D 2018-09-21T19:06:09.667 +C Fix\sharmless\scompiler\swarning\swhen\scompiled\swith\sSQLITE_OMIT_AUTHORIZATION. +D 2018-09-21T23:41:18.790 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -582,7 +582,7 @@ F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c9419 F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641 F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392 -F src/vtab.c 9ada8a26ffc17c27ab27a06b23599faeb2e0c487ad9ef53903917ac973b42170 +F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8690b5a0cc08eeb175230de45d4ca9b9f7b9b22aeebea70b8b7151f10b130969 -R 97ab244d3dc6ac850dabfd9f2e0eadc3 -U drh -Z 7f8590ad5b26658db9da1b3476a27528 +P 7e68cdab20f50cf776b92b2138bb4aba7cb070f2bd855dd4cbbf46d447f2dc88 +R f3a0451266f2033e81023f13808aa5f9 +U mistachkin +Z 5d853d359db40385908df44f900ea5af diff --git a/manifest.uuid b/manifest.uuid index 995c7b8cd7..dfc09107fe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7e68cdab20f50cf776b92b2138bb4aba7cb070f2bd855dd4cbbf46d447f2dc88 \ No newline at end of file +50f2fa19532e0f849d61d9e2a97427cfbf64cfb787ca481ef8c860d0f24f6cfe \ No newline at end of file diff --git a/src/vtab.c b/src/vtab.c index f5501e198a..1b8d283239 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -328,7 +328,6 @@ void sqlite3VtabBeginParse( Token *pModuleName, /* Name of the module for the virtual table */ int ifNotExists /* No error if the table already exists */ ){ - int iDb; /* The database the table is being created in */ Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ @@ -338,8 +337,6 @@ void sqlite3VtabBeginParse( assert( 0==pTable->pIndex ); db = pParse->db; - iDb = sqlite3SchemaToIndex(db, pTable->pSchema); - assert( iDb>=0 ); assert( pTable->nModuleArg==0 ); addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); @@ -359,6 +356,8 @@ void sqlite3VtabBeginParse( ** The second call, to obtain permission to create the table, is made now. */ if( pTable->azModuleArg ){ + int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); + assert( iDb>=0 ); /* The database the table is being created in */ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } From 2c3ba949697f5e4d2fe657c6bc49275a94ee2a25 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 22 Sep 2018 15:05:32 +0000 Subject: [PATCH 234/260] Enhance WhereLoopBuilder.iPlanLimit to handle a case involving the OR optimization discovered overnight by OSSFuzz. FossilOrigin-Name: 7b59930a1d7b664b54d5a2bc9fa385925b5f4c8f34bf401c798307e3e2dae2c6 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/where.c | 6 +++++- test/fuzzdata5.db | Bin 7196672 -> 7197696 bytes 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 81476e114c..71ed8fba04 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarning\swhen\scompiled\swith\sSQLITE_OMIT_AUTHORIZATION. -D 2018-09-21T23:41:18.790 +C Enhance\sWhereLoopBuilder.iPlanLimit\sto\shandle\sa\scase\sinvolving\sthe\sOR\noptimization\sdiscovered\sovernight\sby\sOSSFuzz. +D 2018-09-22T15:05:32.605 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -587,7 +587,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66 -F src/where.c e5c4f5ab05e5112d971510bfd4cc673657e02673ac8a76db4296d703237a2461 +F src/where.c 9e2cccc1d0cd89d0e2aa403146646f247bb89c459151d0893493daa7793bc9ad F src/whereInt.h 2c4d99faf71c35339a33b20d11c5cb8921416a21d6816d830b85df320303e5bd F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893 F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00 @@ -967,7 +967,7 @@ F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2 -F test/fuzzdata5.db 7a3467a24e7112c1f1041ae9ad1e7060c2074da82d420ce786953cc3d3dd20b5 +F test/fuzzdata5.db 181aa05f8ca1e4f43a3618ddd4193dfca4499e81bbb9b3e03bce46961a670891 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7e68cdab20f50cf776b92b2138bb4aba7cb070f2bd855dd4cbbf46d447f2dc88 -R f3a0451266f2033e81023f13808aa5f9 -U mistachkin -Z 5d853d359db40385908df44f900ea5af +P 50f2fa19532e0f849d61d9e2a97427cfbf64cfb787ca481ef8c860d0f24f6cfe +R a522b9d1d3efe4bffcf66fba31076dce +U drh +Z cead1160ed2d9cc4ef006a761294eca9 diff --git a/manifest.uuid b/manifest.uuid index dfc09107fe..490bf19931 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -50f2fa19532e0f849d61d9e2a97427cfbf64cfb787ca481ef8c860d0f24f6cfe \ No newline at end of file +7b59930a1d7b664b54d5a2bc9fa385925b5f4c8f34bf401c798307e3e2dae2c6 \ No newline at end of file diff --git a/src/where.c b/src/where.c index f8727b0620..0357d98de4 100644 --- a/src/where.c +++ b/src/where.c @@ -2127,7 +2127,11 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ int rc; /* Stop the search once we hit the query planner search limit */ - if( pBuilder->iPlanLimit==0 ) return SQLITE_DONE; + if( pBuilder->iPlanLimit==0 ){ + WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); + if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; + return SQLITE_DONE; + } pBuilder->iPlanLimit--; /* If pBuilder->pOrSet is defined, then only keep track of the costs diff --git a/test/fuzzdata5.db b/test/fuzzdata5.db index bf63944a54afe2c929d2de0ec1771aedfef60fa3..2cf125414c6da8a566a947a6caa4a73b4fcd66fb 100644 GIT binary patch delta 158341 zcmb@v2V7Lg_Bg(?yO*|02eD8V6}WA8@7=Xi1Oz+H-T`|M6{y!ZWo|6e}dv-i%NIdkUB+?g}yoVk|O zQC-@g%s+p_hXU1O26k4-(`Njg4h^eWKh%y>@JXu_hN zo}$r&HlB>rXhP_T1sYB8jpJsGCg|5Acpv!r6CN5(z|V&!Bh()((rEmC+MlM;_%=PF zXf(!u)s53=3{GdhM&mQj;j!j*!-m%l1TQUKI=u9Fad>&)<%yRUUfy{5;Kgu_c=_Vx zhnGKI0eA)C6@*tXULkme;?)kXFudC1)d8=Lcy+=n9IptxBJqmC%Y;`nUY+skf>&3( zV(9CJ*o>5@AY?ME$`fHbC`A|wD-njkGK9fUu%SmrEbWmIci~sicQe{Np+K+M8ft>; zFBU{WOcEbfYVt9e`VC7@8If)pl$n-3##F36zt5DFiNE}0As%ywrw>i zz+}_tf$782O_LMjma3h*4okm{^1LIy6}7J|iTzVwaK#T_7RN}K%?0^LytCB#PnFH} z&tHfX)6)B=4;z+}Iy4>TC-Ut|rxm*KGDi*_Dw~!T7cb2+nWklqFtG%0M(`HLBUlkr zaW{U+(&8oeFpD^*+YI}do9Pj4%|8Ez}`@4GoubPUlPB&ZctYN0f32{q(DhKkPam)0YHJu=3`jk#EB#SqI z{~-Pm{ZgG~S!-I;AU={Tp)G@Wo^XrxnsV>f^j<^wn7NB|nhqwbXcDdMpjfA|vwQb5 zPKDO4JbCZtO%GV8(*$FpCoIruLQQ7X6beN;jcST3o>ef7Uw-q}-(0IF6f%ss{5Wrz z&nQPH#>Z0x{fl;rSnWEIqn;tL=m8D(M~ z#(%(-AnL-q2;QzQ8swL|`N6E={ByycI!z2VQxuy%cQ>4`@_;@gc*%#;YgV%ylL&#u zA>HB85&Vcay-w4~op$1cf0eGaD2mZ7%bVpzRa&fZhRF)~qxjxXIEpvI)RFvSgn-{D zzCv52p~&G*!UZ9k0mxXs9`eTV-agB2nhFYrtzJkr{nlU;tSE^d4U*V$aubE2LtOXY!~u&;1-y* zusE*D2Ua1L-dm?Bf%5Tudw5|y-sa2eDwrnb^1D1d!t|Pr87BC?DrL&{v0Y=K;SIvk`P2E0 zT75^IW+Vj8<-2;9cdzPza-HwSTL8(=CMfXwEI!bq{e4T%<_~j0(K<~RQ)>EvL7B*n zIo@1l0=ba4#zZmkr)1_29Xl>PK2i1YuZp}oB|6b3wJHM23i-64aMrG*#6FJ+TVks^ z={1fVitNPdqHxuV@I?i|N7GNE-K(w8F4iV#JCLu*(_|wVrGf9QJ%YhxB%xlb{i`G# zpIsnj8UHYpP440e4OUzrBd$w9Fn%#VUN7o2(;#vQ-w`e^=0o&C+oQ)4K7{blX$fy7 zaWG^FZy~X;dgsV-o%Nb^z1<6P;AE3Y7(Hmjz^suYOvAE94@!e;IU}P=#lI}PaVeQ;YyrOKH$SQM zIX@w8MBioZthwSya5pk}id;%ddOdVU#vzmo4ytkA23mpF@Fvuy?I)hI9> z!wIo|86Vkp7i7e-(RpoXl^MsUl_Hi0Y3p}S=(U31Oe;$H!Jb5=AFRi@7Q1xMYrR&| zvW@&29d`4vL;T_GWmCMMWmca-uFbsSMQl{v$zRZNU6Hgv%PaX61PVXwJqvU530!!9 zr+Um0;aDXm5N&kMjcw?X;Kwia^RkAsuP` zL4KK*B9+;M;hO25N`8D>1-)>B()d{D)ouI*LVdRJ7OktEKkUKT^_m|GXwftLP@@XJE&qsjic^vss&*M_` zX#+oo^oE49d@a{Yui2nuSd-w~^Lz}=eV*?_NKZyW@av;4;8j&f>Z4{@t9n4w3w#wx zqO)J*%{qNIOI0G&zQQXcfgwxuU$5{Z^hr57jrGIcZPwt$TAyxH*6Bl?hNrg`?@Lfm>cwFS;Niw8f~GLvlfA zNNOk}*eQWXNLrrcGdnxG1Gj|WywzB^6E`7k4}D*v7|hUZ_EcQ-YeS8+`DhUjgi&4bI} z%w=4!k9HA4A?wHlKWO|6`#$@~1Yc{dB--c+|njo};kG|twq!@Ny-3}_l!pk(w8Bfc ztcB}gLLjUPM%vjv*rMhjVGUqTT&0)b3*&^aP?jV^V;8{->N#N+v~(0Qp}||&3T2@} z3GLt^d`)o79}5zM%3xs%BfC(C@50$=A%;D~Xc>3j6v>##U3BWSLi@@P6d2}uLW>?N zPwFH*4|PVt$kKe;7&5U(KSm&gKtN|95^_C+fo)W~5YV;9MoiKRM;Qqx%?lMC(Sj}< z6WbcaSUE!&&*vD@OJp$Q2x0B+MQA`Vc?i?tW{@zINntU4I!btj^H{=Z%B!ucf74mD zzJHPlMVSPU`*7aR3x{SZUKw!lExsM?$P0(PxTSi{}R>1~^ zsn~TN^KC`w5rH2)Jq!y3&S3;XF#% zF8D*9Rp|2H33<5&3aVFZiB5xalv{z}ZDJps(wQ#PdOI^?YfKet{=2d$vigViZ^<)u z2D9a9q-%uWLx>j6j}unF`jNsZZ8ffLql6*aY7J}|C9EQ);5%BFPFB(4(ZVL8_%Qu0 zJu@v{<6DiIZS*Z(`l>enYOgzUMIWX@m4{S&f-+X9?BH?NTC!1%y@~&B4lEy9&B4cG znegGrI3begD6-Lmka2Kzju1tYmkSBF6i*cT(!!0xWUVVtSfb~Qdd-Opx^0#q6V?|K zcBEAsX#F%HOUsSL=ZQ3bqA-s@?k1rQ8dnJ)Kx2sL19_W--B2-Gm;@D*1SFyHnMBEQ zVGg153xpjWB#)|Vg^M~UoFt(Bq4CM5>PCF7oZR|2nW~#uwrOtb^AxI9u;+#et11Be!Cz@D5AwNL&@d(|Y0u)@tDj)IEy3 zyNX;PiDuUb^+ew=wAvRcK$uT*T~&gG5PynzgLQ1bvLz6{pD1jj{!U@Kj)cMDIvjQF z;ORQy011UvdvOlgvPT$CLg4E?!gk2tBbedPUST}j46XKsZI1{dESfzc3<@U;-cY|s z=%HI!9SEBr5q{>PaCQxalEXq6*d7yt;LNZvFF5_Eu#-eW&ORIu5zx3#7)-*U(|%zh zhZ;WaccbYu?;H%Ug_8$<|5)q_>LT?V$^sy$`mWK1(s)Irh z>gn4K3aO~4<4+XaIEZgS#X+2Lx;-Yuc*L-!-YK2yVTPuDPeyXVQ4@;~+iSWYe5fWI;kueIgk?31_f<8F>yjGQ;+55_5U!|ZrqSiqg$S2a zGlmvd=OQew9)oaUHLG|*HLJ3yIv!zRb#H|8t9v3WsP2YvZncPTPBm^eOMPZnv&v>w zGqKF9W}==^&4e?)n(Z{kR5RI(u4eKWRaJs8r)mYltSZJtX4O)JL#mb_Osrar@atNJ z^N(7V`(-W5{k)dtep1VFuhufAn``qBeq77gE&Zr=F#dd4+Xvy5TBbLBP|HO0er+_u z_i7^$zFo_t@@8!ZgiW=K-Gr(+2zyqsF6dFkTHn1Y2cf+x38AfuwOg&~j?h}g#2!~= zL)fK?(T}cD5SprFgi&c#tS2I?SY_c=9T9%xU?ZSY6|1I06%I_F_ErDIMh$OM!9w-* zf){QisP8d+4Y?kuC1*h3F@Zwe+hMtW-lmb+!!qJiGE>TLy&#N*`e$)==tBdZ6TG#kns;mvqER(ZXb{5n$;_~ZH8&>Q`_s=m*ceB5dcz zpw&PJ>KmwD%)KOpgHj$E2z9RtH@MMQQD|$cN5RLh3F+KOR4!DOJcSL(MZK$W z8?cN$cZB-aaaly&|8*flmcTpJ+-MIwF18&4036zB&ie&IuC9riJH( z20iX))JEYEj_qgMbaBVnglbBaoaDYck6W5+O~P<)g1h0woMeLOZ{k`zp79e6UY8Jg zj*=AQl@Z^&dfY8$B3OF39ydB`K$VjsS>t@^@JqrXf_naImxbA$OM6$(V%X$ur1J4w z0&4Pa2|-NnFZaDS(EtbE5(3E#`28)Msu48;7fHPDN2Wo_+rqPCD%^ZqNDy)7Vm1v+ zce_8_mcL@F7*LISm$=)hmJ|4wTb&Qn-VyTkxLa{cE}VYxj*#fZ6=K!iaQ;iIB%@jA zq(`G^QQMoylJV#bkel0vkmeWID3r`VZfV^*o z!9Z`|3i;Z%xUlDb+j1f4guRj zBH%^~_9bc`8=|4;hR~iR`cV0M;SlO3t!PO%1V11*aPQ&QmS7>iZTAM)aRY0NzJagC z%5PEg&A1_W(Qj@Db2u(ouQ@uPjW7>|J%$Frrb8jYY_cxjWUE2lrD|3iLNwL=if{4gf<3>b}iWm`8}+?X<0|HjOp^$WsvuR zWeL+bW9g-KqJq1na501-_aZdgCf1`x>-jmK;=aZj$tL3mp=fd!w1b6-+0Zg0eFqw!3OLqX5ouX~xEDp%or!E4G)ZFAe`y}t`E5*!-j#!`sjT`n zggpFzB&%dGPfxng{50_u!l8w?yf2fP3Fc>txGDT?jxS8_FLq{{B+eZ7DwhW{lt_4gfanin28iuZOD-B9_U9sQcSa<|yhDVG)oa!-bkn0)lP>|+ zU~wZeVGa=o!I05n0Mr@ga{8BZYr3+u7SxU}ju36o@Y@`3Xc#2^voc5Q0F8sip%5?_ z?@awg5B-|%HF1AN8zru-oFM8!pDnIH^|UNoq@0K=fv&YNQM$RYP?&|zrp%F|3jX7< zj+Viqd^gqf8Uau~J)wCh62i&@>4stA04=dnt=z1dLy zV5sb^3T8z!D5@qI@+XO*aB8AxL`A@T{{h~^BNN5;aC0K=>t4b;gI#VdV5>=hhDl;O zNS%az;*EC!irsE+&FoXt2P*+9BUn30?22Yn#O+3U!B3OKXta}t<%)es4;aRNy2EDn z(~bQ^L2?X=VSbSmTA3%ta%pb(G%pI5Sf`!g7KLluj3`?v$a8i^VdIWI@hKoL(~F!Ik)$qw!;<7=;SX^_8NE3Qly1 z$fNmXaETZ}2Eoh{L>UNAl!%e2)x5zH`@`2IqQa%?HSa|IsZnQ$!&N5MYPk`5P0L7V zdRhzt<5OZ5)7T$Lt{IMlfP(Ojn#8N}y@EV+6(Oi7z(FoVq zAQ9b0>^`MJEQaiAF#)pIiWd6ITG2;G_Cd;8%xl~#`hjv(R9K!F8V(~hL=B#M!LG;rkXV+ag|Jcu&Athd2hF zJB<7@q7;epgppZrZ{dFA2vzrsv2GFFsq8J*^l@%fns*fIMicdgr%|SfC&UcaW&Ctcxtbo)nu4d{lCMhMO#b2dQE&x zTdRTk@5S!W$J5%0ir2+;TB4_zA`nza@wXBRZ-{T8_KL+a;h`VJCRAZ3{v_TY9L@Qs z*iB1(X#Fo@CxR6j^s8fQz1bs{M*H~pqMiEwTa49mzV03A)l?}Iju@m&Fo{wuWUG=H z8i~{w8ugMtB>W*pG1K9iI7s;sSNpO*P#H5&^(MBE_&t>(C3`d7wkjC@hK?CN)=IBI z-S4=vWE&9ur45T~{V`;#sI5c}dBJ6r-t^)E(e0hZlEWztmtH6I*>+MYAuqeyOO<+N zgmVsP%N?jAuewaqOCC%E-Z85!y`5V%dmV?*c}NkZv2-FY?bmS^x_9p$vol{RfO<(n zEwR7EK?{*0AV4R1L4znArMt}16%VGuK0BXL>kQ$d6w{htW|me$yGmit0TyWlPC#(T@)iW9OHuId5D7K>L6RRt zrAaT)@Ig|lCt4J9v!&VGJLNvLo!~;Yw3+LO4x@~=3KD5^j?_g<-USjUO{L8vB$E!5 zkMjL$HV^VQaqYFKbbBG=&v@;KpHWSGehd!9>Wr> zx1;$?MT_PaPvcdgcWoDVXa*MP46n?Prl8+jnkh}!GK1y1d}^I3btCZcY)OKj<{(pj zAZf1DmFtb2z=At=JS15(UxrLISmx-nJ!pVEi zLLB*>7E0~)NjlAZn70szMD9Y#KoVJ2A9Qu^Unq6g$Llm%Oj@15l$GdFSu9N>W1yv2 z>Ix4QOD0?u-S-#S{U~;y28W7~|Iv%2&U&|*rhJ7I3AKx)j%cRAe0g zBFTqYZI*!>2{SsvQ;RTn@M1|N*|2gk4uC8;yI2~G>YH&1iYNmcjSA)bv?P??PzFMnzqP)bU*r1laGjLOl#O+9ZHZXvIFyfVOHP8k zy^_(Z+)}&ho~8|lxmZYr2kHa2_(?u2Rr?7>^oO&5#_~J|M@@&NX9)46A3iSq z;6=Ql@hRy`@0JG>9A4NtC9I~G;g7S@Vz&3YhS&FSHUu|A^-trJT=p==H<{j)nxXMD zzPuGLpzNDx`gpPe`|d)ie+lO$mO(KilDM9cFlgWg3~es16>9`5%y>5B?#c z)%@lTd4SuUyXZfcIe_(RNf4yyq%&>IkZZMQpPHL3Gru+#M>`vQmo1M*GaLSN zhvhkPXQF^JM;;AnIkF6iEa7eC93=cHTnupYL=gwL<$$>!+=mWdWwE>

    JV5;I{NzqXUNIWI8Gi3g>&S! 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 delta 156934 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%0Dl3 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%0D@-gbLCVz)Tqi8xpvKr!cB(9?F+ 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 From f8937f9034e4df499734ec7bb330616a49ad6d1f Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 23 Sep 2018 02:01:42 +0000 Subject: [PATCH 235/260] Fix a faulty assert() in the validation logic for the LEFT JOIN strength reduction optimization. Problem found by OSSFuzz. FossilOrigin-Name: 2fd62fccd13e326dbd7dd730112542c6faa56e466bf4f7b8e22ced543031280c --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/expr.c | 15 ++++++--------- test/fuzzdata5.db | Bin 7197696 -> 7197696 bytes 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 71ed8fba04..d693735ef8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sWhereLoopBuilder.iPlanLimit\sto\shandle\sa\scase\sinvolving\sthe\sOR\noptimization\sdiscovered\sovernight\sby\sOSSFuzz. -D 2018-09-22T15:05:32.605 +C Fix\sa\sfaulty\sassert()\sin\sthe\svalidation\slogic\sfor\sthe\sLEFT\sJOIN\sstrength\nreduction\soptimization.\s\sProblem\sfound\sby\sOSSFuzz. +D 2018-09-23T02:01:42.716 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -454,7 +454,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2 -F src/expr.c 610eea078f240e8d55e81666a65b05a42e52008d24059c59093dd18b3d15b565 +F src/expr.c cd7a294bff49641032e2a5511a8e77bfa7e71fd0a2f714de8f3c560d31d273d9 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812 F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f @@ -967,7 +967,7 @@ F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2 -F test/fuzzdata5.db 181aa05f8ca1e4f43a3618ddd4193dfca4499e81bbb9b3e03bce46961a670891 +F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 50f2fa19532e0f849d61d9e2a97427cfbf64cfb787ca481ef8c860d0f24f6cfe -R a522b9d1d3efe4bffcf66fba31076dce +P 7b59930a1d7b664b54d5a2bc9fa385925b5f4c8f34bf401c798307e3e2dae2c6 +R f03877dafbf8630475fd3e62d89e76e5 U drh -Z cead1160ed2d9cc4ef006a761294eca9 +Z b1773f19e1d7fe0cd47b4aa3fa8da701 diff --git a/manifest.uuid b/manifest.uuid index 490bf19931..f4bb602f2d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7b59930a1d7b664b54d5a2bc9fa385925b5f4c8f34bf401c798307e3e2dae2c6 \ No newline at end of file +2fd62fccd13e326dbd7dd730112542c6faa56e466bf4f7b8e22ced543031280c \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 1692822840..fa0bcd86af 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4849,18 +4849,15 @@ int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){ /* ** This is the Expr node callback for sqlite3ExprImpliesNotNullRow(). ** If the expression node requires that the table at pWalker->iCur -** have a non-NULL column, then set pWalker->eCode to 1 and abort. +** have one or more non-NULL column, then set pWalker->eCode to 1 and abort. +** +** This routine controls an optimization. False positives (setting +** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives +** (never setting pWalker->eCode) is a harmless missed optimization. */ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ - /* This routine is only called for WHERE clause expressions and so it - ** cannot have any TK_AGG_COLUMN entries because those are only found - ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause, - ** but that is an illegal construct and the query will be rejected at - ** a later stage of processing, so the TK_AGG_FUNCTION case does not - ** need to be considered here. */ - assert( pExpr->op!=TK_AGG_COLUMN ); + testcase( pExpr->op==TK_AGG_COLUMN ); testcase( pExpr->op==TK_AGG_FUNCTION ); - if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; switch( pExpr->op ){ case TK_ISNOT: diff --git a/test/fuzzdata5.db b/test/fuzzdata5.db index 2cf125414c6da8a566a947a6caa4a73b4fcd66fb..cfb0ebe7d8cf01899814f38e21c30b62acd9184c 100644 GIT binary patch delta 6146 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 Date: Mon, 24 Sep 2018 10:47:33 +0000 Subject: [PATCH 236/260] Increase the initial value of WhereLoopBuilder.iPlanLimit to 20K. Issue a warning if the iPlanLimit reaches zero. FossilOrigin-Name: 3dd35f51187574f47f860405309877cdbf9dc5710703dfd98cf98073b771140c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index d693735ef8..ddb5e7f461 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sfaulty\sassert()\sin\sthe\svalidation\slogic\sfor\sthe\sLEFT\sJOIN\sstrength\nreduction\soptimization.\s\sProblem\sfound\sby\sOSSFuzz. -D 2018-09-23T02:01:42.716 +C Increase\sthe\sinitial\svalue\sof\sWhereLoopBuilder.iPlanLimit\sto\s20K.\s\sIssue\na\swarning\sif\sthe\siPlanLimit\sreaches\szero. +D 2018-09-24T10:47:33.898 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -587,7 +587,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66 -F src/where.c 9e2cccc1d0cd89d0e2aa403146646f247bb89c459151d0893493daa7793bc9ad +F src/where.c 49022d3c155a3af14298459d6990c0c9f096f42afa1edb6d86e8f4ac45a6301e F src/whereInt.h 2c4d99faf71c35339a33b20d11c5cb8921416a21d6816d830b85df320303e5bd F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893 F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7b59930a1d7b664b54d5a2bc9fa385925b5f4c8f34bf401c798307e3e2dae2c6 -R f03877dafbf8630475fd3e62d89e76e5 +P 2fd62fccd13e326dbd7dd730112542c6faa56e466bf4f7b8e22ced543031280c +R 1d4c0a2fb381695de9f503d180db0edc U drh -Z b1773f19e1d7fe0cd47b4aa3fa8da701 +Z 063489dbcea38420d3799029994c4f5a diff --git a/manifest.uuid b/manifest.uuid index f4bb602f2d..5460533242 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2fd62fccd13e326dbd7dd730112542c6faa56e466bf4f7b8e22ced543031280c \ No newline at end of file +3dd35f51187574f47f860405309877cdbf9dc5710703dfd98cf98073b771140c \ No newline at end of file diff --git a/src/where.c b/src/where.c index 0357d98de4..c911dcc9c2 100644 --- a/src/where.c +++ b/src/where.c @@ -3543,10 +3543,10 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ /* Some pathological queries provide an unreasonable number of indexing ** options. The iPlanLimit value prevents these queries from taking up ** too much time in the planner. When iPlanLimit reaches zero, no further - ** index+constraint options are considered. Seed iPlanLimit to 10K but + ** index+constraint options are considered. Seed iPlanLimit to 20K but ** also add an extra 1K to each table of the join, to ensure that each ** table at least gets 1K opportunities. */ - pBuilder->iPlanLimit = 10000; + pBuilder->iPlanLimit = 20000; for(iTab=0, pItem=pTabList->a; pItemiTab = iTab; @@ -3579,6 +3579,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ if( rc || db->mallocFailed ){ if( rc==SQLITE_DONE ){ /* We hit the query planner search limit set by iPlanLimit */ + sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); rc = SQLITE_OK; }else{ break; From 6fb5d358a8e35481e19ba20b27e75922a41b3fb4 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 24 Sep 2018 12:37:01 +0000 Subject: [PATCH 237/260] Use compile-time options SQLITE_QUERY_PLANNER_LIMIT and SQLITE_QUERY_PLANNER_LIMIT_INCR to control the value for WhereLoopBuilder.iPlanLimit, rather than embedding magic numbers in the code. FossilOrigin-Name: 903e501894b2a5dd7055b5154d74d4a47a619f76e66485a4d62b6259f10723d6 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 10 ++-------- src/whereInt.h | 20 ++++++++++++++++++++ 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index ddb5e7f461..fced9da4c1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sinitial\svalue\sof\sWhereLoopBuilder.iPlanLimit\sto\s20K.\s\sIssue\na\swarning\sif\sthe\siPlanLimit\sreaches\szero. -D 2018-09-24T10:47:33.898 +C Use\scompile-time\soptions\sSQLITE_QUERY_PLANNER_LIMIT\sand\nSQLITE_QUERY_PLANNER_LIMIT_INCR\sto\scontrol\sthe\svalue\sfor\nWhereLoopBuilder.iPlanLimit,\srather\sthan\sembedding\smagic\snumbers\sin\sthe\ncode. +D 2018-09-24T12:37:01.477 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -587,8 +587,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66 -F src/where.c 49022d3c155a3af14298459d6990c0c9f096f42afa1edb6d86e8f4ac45a6301e -F src/whereInt.h 2c4d99faf71c35339a33b20d11c5cb8921416a21d6816d830b85df320303e5bd +F src/where.c a54a3d639bcd751d1474deff58e239b2e475a96e1b8f9178aa7864df8782a4e3 +F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893 F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00 F src/window.c a28d8d42c51c7e31136a42f3e245282049d4a9466b36d7bd765772991472df41 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2fd62fccd13e326dbd7dd730112542c6faa56e466bf4f7b8e22ced543031280c -R 1d4c0a2fb381695de9f503d180db0edc +P 3dd35f51187574f47f860405309877cdbf9dc5710703dfd98cf98073b771140c +R 0a5c287a2221a9c37c274db4cfcb24c3 U drh -Z 063489dbcea38420d3799029994c4f5a +Z d1e830ee2a4fd61d34b42065fcc1584a diff --git a/manifest.uuid b/manifest.uuid index 5460533242..7a3767f11f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3dd35f51187574f47f860405309877cdbf9dc5710703dfd98cf98073b771140c \ No newline at end of file +903e501894b2a5dd7055b5154d74d4a47a619f76e66485a4d62b6259f10723d6 \ No newline at end of file diff --git a/src/where.c b/src/where.c index c911dcc9c2..bfc11eec18 100644 --- a/src/where.c +++ b/src/where.c @@ -3540,17 +3540,11 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; whereLoopInit(pNew); - /* Some pathological queries provide an unreasonable number of indexing - ** options. The iPlanLimit value prevents these queries from taking up - ** too much time in the planner. When iPlanLimit reaches zero, no further - ** index+constraint options are considered. Seed iPlanLimit to 20K but - ** also add an extra 1K to each table of the join, to ensure that each - ** table at least gets 1K opportunities. */ - pBuilder->iPlanLimit = 20000; + pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; for(iTab=0, pItem=pTabList->a; pItemiTab = iTab; - pBuilder->iPlanLimit += 1000; /* 1000 bonus for each table in the join */ + pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ /* This condition is true when pItem is the FROM clause term on the diff --git a/src/whereInt.h b/src/whereInt.h index a34708df40..209ac42ee2 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -409,6 +409,26 @@ struct WhereLoopBuilder { #define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ #define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ +/* The WhereLoopBuilder.iPlanLimit is used to limit the number of +** index+constraint combinations the query planner will consider for a +** particular query. If this parameter is unlimited, then certain +** pathological queries can spend excess time in the sqlite3WhereBegin() +** routine. The limit is high enough that is should not impact real-world +** queries. +** +** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is +** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM +** clause is processed, so that every table in a join is guaranteed to be +** able to propose a some index+constraint combinations even if the initial +** baseline limit was exhausted by prior tables of the join. +*/ +#ifndef SQLITE_QUERY_PLANNER_LIMIT +# define SQLITE_QUERY_PLANNER_LIMIT 20000 +#endif +#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR +# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000 +#endif + /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second From 6314eeaeb3162173265b8ed316b61644b4fd7806 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 24 Sep 2018 14:10:55 +0000 Subject: [PATCH 238/260] Allow a writable virtual table to have a schema with an INTEGER PRIMARY KEY and WITHOUT ROWID. This fixes ticket [f25d5ceebe1d710ff61a571e395356869d8272ef]. FossilOrigin-Name: 5a38d9281b4ad63b853efa5cdd5ad4a64b19dfaf8250ef8e0e186684df1211ea --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/build.c | 4 ---- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index fced9da4c1..d488351753 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\scompile-time\soptions\sSQLITE_QUERY_PLANNER_LIMIT\sand\nSQLITE_QUERY_PLANNER_LIMIT_INCR\sto\scontrol\sthe\svalue\sfor\nWhereLoopBuilder.iPlanLimit,\srather\sthan\sembedding\smagic\snumbers\sin\sthe\ncode. -D 2018-09-24T12:37:01.477 +C Allow\sa\swritable\svirtual\stable\sto\shave\sa\sschema\swith\san\sINTEGER\sPRIMARY\sKEY\nand\sWITHOUT\sROWID.\s\sThis\sfixes\sticket\n[f25d5ceebe1d710ff61a571e395356869d8272ef]. +D 2018-09-24T14:10:55.272 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -446,7 +446,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 -F src/build.c 3bdd61d7ecba6f40e7efead3ffb61b2e3bad87de73f407c288035937c9b33687 +F src/build.c 0b3d422770877d74ee6d54f4c122d82c48f7d04ee3bfb91702e402de7f5c45ac F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3dd35f51187574f47f860405309877cdbf9dc5710703dfd98cf98073b771140c -R 0a5c287a2221a9c37c274db4cfcb24c3 +P 903e501894b2a5dd7055b5154d74d4a47a619f76e66485a4d62b6259f10723d6 +R dab440745222c8e8c505d734c9dc73d5 U drh -Z d1e830ee2a4fd61d34b42065fcc1584a +Z 7595a8f9101a9bccfc4e2f08e98b0a7c diff --git a/manifest.uuid b/manifest.uuid index 7a3767f11f..5a80f80a9b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -903e501894b2a5dd7055b5154d74d4a47a619f76e66485a4d62b6259f10723d6 \ No newline at end of file +5a38d9281b4ad63b853efa5cdd5ad4a64b19dfaf8250ef8e0e186684df1211ea \ No newline at end of file diff --git a/src/build.c b/src/build.c index 65b9107118..b4041389ba 100644 --- a/src/build.c +++ b/src/build.c @@ -1771,10 +1771,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ } } - /* The remaining transformations only apply to b-tree tables, not to - ** virtual tables */ - if( IN_DECLARE_VTAB ) return; - /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY ** into BTREE_BLOBKEY. */ From 2fae1504024f9f9f0b66b24f17e9c6c3ddca2062 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 24 Sep 2018 14:51:59 +0000 Subject: [PATCH 239/260] Fix a problem with views that use window functions as part of complex expressions. FossilOrigin-Name: 507d892c3a40a0bacbd47ed3c4fe2d8925a82716ae08da8401750a42782ba454 --- manifest | 18 ++++++------- manifest.uuid | 2 +- src/expr.c | 8 +++--- test/window4.tcl | 26 +++++++++++++++++++ test/window4.test | 66 ++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 97 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index d488351753..b8c0fc1b82 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sa\swritable\svirtual\stable\sto\shave\sa\sschema\swith\san\sINTEGER\sPRIMARY\sKEY\nand\sWITHOUT\sROWID.\s\sThis\sfixes\sticket\n[f25d5ceebe1d710ff61a571e395356869d8272ef]. -D 2018-09-24T14:10:55.272 +C Fix\sa\sproblem\swith\sviews\sthat\suse\swindow\sfunctions\sas\spart\sof\scomplex\sexpressions. +D 2018-09-24T14:51:59.424 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -454,7 +454,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2 -F src/expr.c cd7a294bff49641032e2a5511a8e77bfa7e71fd0a2f714de8f3c560d31d273d9 +F src/expr.c 781afe52002d84b6b8ae2873bbd2fd7825a8bc80e4e21333ab354c9c492bdb4a F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812 F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f @@ -1648,8 +1648,8 @@ F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3 F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823 F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98 -F test/window4.tcl 871364059b7d320d556ec6ef804d604a4e8cc1547a3102c5d56067371bb200af -F test/window4.test 323b118eb592932036388643ca6dcaead87f699bbea2984bbca49ba4ad6c2509 +F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb +F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62 F test/window5.test 8187f46597c90b73e8f96659e893353cbda337479cc582f7a488eab351ba08d3 F test/window6.test 7574778c79cae89f1781df237bf9ff5063886deca91a36efc53934315f0e7612 F test/windowfault.test 23abad97b72c6f609002255ddd41ef5c8922408f918f9b98ad6005ab316e482f @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 903e501894b2a5dd7055b5154d74d4a47a619f76e66485a4d62b6259f10723d6 -R dab440745222c8e8c505d734c9dc73d5 -U drh -Z 7595a8f9101a9bccfc4e2f08e98b0a7c +P 5a38d9281b4ad63b853efa5cdd5ad4a64b19dfaf8250ef8e0e186684df1211ea +R 0305fb00a242bdc9e08655efd2c57d30 +U dan +Z e20c6e2011d089069671f2c306dc6b24 diff --git a/manifest.uuid b/manifest.uuid index 5a80f80a9b..6052026b2a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5a38d9281b4ad63b853efa5cdd5ad4a64b19dfaf8250ef8e0e186684df1211ea \ No newline at end of file +507d892c3a40a0bacbd47ed3c4fe2d8925a82716ae08da8401750a42782ba454 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index fa0bcd86af..4d92ab8a1c 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1270,17 +1270,14 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ } /* Fill in pNew->pLeft and pNew->pRight. */ + zAlloc += dupedExprNodeSize(p, dupFlags); if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ - zAlloc += dupedExprNodeSize(p, dupFlags); if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; pNew->pRight = p->pRight ? exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; } - if( pzBuffer ){ - *pzBuffer = zAlloc; - } }else{ #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(p, EP_WinFunc) ){ @@ -1299,6 +1296,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } } + if( pzBuffer ){ + *pzBuffer = zAlloc; + } } return pNew; } diff --git a/test/window4.tcl b/test/window4.tcl index ea36735a09..33b3a8c0e8 100644 --- a/test/window4.tcl +++ b/test/window4.tcl @@ -358,6 +358,32 @@ execsql_test 10.3 { SELECT id, lag(b, -1) OVER (PARTITION BY a ORDER BY id) FROM t7; } +execsql_test 11.0 { + DROP VIEW IF EXISTS v8; + DROP TABLE IF EXISTS t8; + CREATE TABLE t8(t INT, total INT); + INSERT INTO t8 VALUES(0,2); + INSERT INTO t8 VALUES(5,1); + INSERT INTO t8 VALUES(10,1); +} + +execsql_test 11.1 { + SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8; +} + +execsql_test 11.2 { + CREATE VIEW v8 AS SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8; +} + +execsql_test 11.3 { + SELECT * FROM v8; +} + +execsql_test 11.4 { + SELECT * FROM ( + SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8 + ) sub; +} finish_test diff --git a/test/window4.test b/test/window4.test index 1933a32d09..e914c7826c 100644 --- a/test/window4.test +++ b/test/window4.test @@ -1217,13 +1217,20 @@ do_execsql_test 9.2 { SELECT dense_rank() OVER (PARTITION BY x) FROM t2 } {1 1 1 1 1 1 1} + do_test 9.3 { set myres {} foreach r [db eval {SELECT x, percent_rank() OVER (PARTITION BY x ORDER BY x) FROM t2}] { - lappend myres [format %.2f [set r]] + lappend myres [format %.4f [set r]] } - set myres -} {1.00 0.00 1.00 0.00 1.00 0.00 4.00 0.00 4.00 0.00 6.00 0.00 7.00 0.00} + set res2 {1.0000 0.0000 1.0000 0.0000 1.0000 0.0000 4.0000 0.0000 4.0000 0.0000 6.0000 0.0000 7.0000 0.0000} + foreach r [set myres] r2 [set res2] { + if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + } + set {} {} +} {} do_execsql_test 9.4 { SELECT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2 @@ -1233,21 +1240,35 @@ do_execsql_test 9.5 { SELECT DISTINCT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2 } {1 1 4 4 6 6 7 7} + do_test 9.6 { set myres {} foreach r [db eval {SELECT percent_rank() OVER () FROM t1}] { - lappend myres [format %.2f [set r]] + lappend myres [format %.4f [set r]] } - set myres -} {0.00 0.00 0.00} + set res2 {0.0000 0.0000 0.0000} + foreach r [set myres] r2 [set res2] { + if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + } + set {} {} +} {} + do_test 9.7 { set myres {} foreach r [db eval {SELECT cume_dist() OVER () FROM t1}] { - lappend myres [format %.2f [set r]] + lappend myres [format %.4f [set r]] } - set myres -} {1.00 1.00 1.00} + set res2 {1.0000 1.0000 1.0000} + foreach r [set myres] r2 [set res2] { + if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + } + set {} {} +} {} do_execsql_test 10.0 { DROP TABLE IF EXISTS t7; @@ -1269,4 +1290,31 @@ do_execsql_test 10.3 { SELECT id, lag(b, -1) OVER (PARTITION BY a ORDER BY id) FROM t7; } {1 {} 2 4 3 {} 4 8 5 1 6 {}} +do_execsql_test 11.0 { + DROP VIEW IF EXISTS v8; + DROP TABLE IF EXISTS t8; + CREATE TABLE t8(t INT, total INT); + INSERT INTO t8 VALUES(0,2); + INSERT INTO t8 VALUES(5,1); + INSERT INTO t8 VALUES(10,1); +} {} + +do_execsql_test 11.1 { + SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8; +} {0 1 2} + +do_execsql_test 11.2 { + CREATE VIEW v8 AS SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8; +} {} + +do_execsql_test 11.3 { + SELECT * FROM v8; +} {0 1 2} + +do_execsql_test 11.4 { + SELECT * FROM ( + SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8 + ) sub; +} {0 1 2} + finish_test From 53988068894e24ff1bf7749b0efdb80be34fef78 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 24 Sep 2018 15:39:30 +0000 Subject: [PATCH 240/260] Slightly smaller and faster alternative to [507d892c3a40a0bacbd47] that fixes a problem with views that use window function as part of complex expressions. FossilOrigin-Name: d7c816ae15f05f21b9b213161e1044aaefc56f17e7bc4b7b551a9e04efc05855 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/expr.c | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index b8c0fc1b82..48b3191003 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sviews\sthat\suse\swindow\sfunctions\sas\spart\sof\scomplex\sexpressions. -D 2018-09-24T14:51:59.424 +C Slightly\ssmaller\sand\sfaster\salternative\sto\s[507d892c3a40a0bacbd47]\sthat\nfixes\sa\sproblem\swith\sviews\sthat\suse\swindow\sfunction\sas\spart\sof\scomplex\nexpressions. +D 2018-09-24T15:39:30.526 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -454,7 +454,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2 -F src/expr.c 781afe52002d84b6b8ae2873bbd2fd7825a8bc80e4e21333ab354c9c492bdb4a +F src/expr.c 5cee8fb79b1952689af80ed71ed16ad295f29d85de30c7592993b05cf1ec1e06 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812 F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5a38d9281b4ad63b853efa5cdd5ad4a64b19dfaf8250ef8e0e186684df1211ea -R 0305fb00a242bdc9e08655efd2c57d30 -U dan -Z e20c6e2011d089069671f2c306dc6b24 +P 507d892c3a40a0bacbd47ed3c4fe2d8925a82716ae08da8401750a42782ba454 +R c727b58cbf0dbd5e0c71bca27b5dfee5 +U drh +Z 5f623b5b79346b935df34b1ceb527a47 diff --git a/manifest.uuid b/manifest.uuid index 6052026b2a..593b4b1434 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -507d892c3a40a0bacbd47ed3c4fe2d8925a82716ae08da8401750a42782ba454 \ No newline at end of file +d7c816ae15f05f21b9b213161e1044aaefc56f17e7bc4b7b551a9e04efc05855 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 4d92ab8a1c..b2854f9a5d 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1270,21 +1270,24 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ } /* Fill in pNew->pLeft and pNew->pRight. */ - zAlloc += dupedExprNodeSize(p, dupFlags); - if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ + zAlloc += dupedExprNodeSize(p, dupFlags); if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; pNew->pRight = p->pRight ? exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; } - }else{ #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(p, EP_WinFunc) ){ pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); assert( ExprHasProperty(pNew, EP_WinFunc) ); } #endif /* SQLITE_OMIT_WINDOWFUNC */ + if( pzBuffer ){ + *pzBuffer = zAlloc; + } + }else{ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; @@ -1296,9 +1299,6 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } } - if( pzBuffer ){ - *pzBuffer = zAlloc; - } } return pNew; } From 6705584a5b944f6a4424fb09d081dfbe6d9d574d Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 25 Sep 2018 13:51:31 +0000 Subject: [PATCH 241/260] Fix a problem in releasetest.tcl causing configuration "Fast-One" to fail. FossilOrigin-Name: 42e04fefbc241dd33f12abd66344a87720ae4cda6d82f2882217b3cb71be8733 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/releasetest.tcl | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 48b3191003..eb41a73d39 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Slightly\ssmaller\sand\sfaster\salternative\sto\s[507d892c3a40a0bacbd47]\sthat\nfixes\sa\sproblem\swith\sviews\sthat\suse\swindow\sfunction\sas\spart\sof\scomplex\nexpressions. -D 2018-09-24T15:39:30.526 +C Fix\sa\sproblem\sin\sreleasetest.tcl\scausing\sconfiguration\s"Fast-One"\sto\sfail. +D 2018-09-25T13:51:31.431 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -1195,7 +1195,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl d82c35d4fa8364451b424c95c0d4f222efcd40497fabe51d85d206ef6a680263 x +F test/releasetest.tcl c5b474f9880073fc3b69729ee05d5284653a9ee101af572204917d9dcb1d9015 x F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 507d892c3a40a0bacbd47ed3c4fe2d8925a82716ae08da8401750a42782ba454 -R c727b58cbf0dbd5e0c71bca27b5dfee5 -U drh -Z 5f623b5b79346b935df34b1ceb527a47 +P d7c816ae15f05f21b9b213161e1044aaefc56f17e7bc4b7b551a9e04efc05855 +R b83a686c725ad70fbb0586b025a156f8 +U dan +Z 8305c165fab0e9e40fbcffd125669fd0 diff --git a/manifest.uuid b/manifest.uuid index 593b4b1434..f16270a0cb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d7c816ae15f05f21b9b213161e1044aaefc56f17e7bc4b7b551a9e04efc05855 \ No newline at end of file +42e04fefbc241dd33f12abd66344a87720ae4cda6d82f2882217b3cb71be8733 \ No newline at end of file diff --git a/test/releasetest.tcl b/test/releasetest.tcl index c323978c7a..3d51b7a812 100755 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -79,6 +79,7 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_UNLOCK_NOTIFY -DSQLITE_THREADSAFE -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 + -DSQLITE_USER_AUTHENTICATION=1 } "Secure-Delete" { -O2 @@ -136,7 +137,6 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_RBU -DSQLITE_MAX_ATTACHED=125 - -DSQLITE_USER_AUTHENTICATION=1 -DLONGDOUBLE_TYPE=double --enable-session } From 6b26a7b950e5f870079dc15e995c971cf293bb09 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 26 Sep 2018 03:43:42 +0000 Subject: [PATCH 242/260] Fix typos in the header comment for the sha1 and sha3 hash extensions in the ext/misc folder. FossilOrigin-Name: 4ed9d83a0b14a22b3ecf25785b03b5a824d260e01a608aea85231df9b816421d --- ext/misc/sha1.c | 2 +- ext/misc/shathree.c | 2 +- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ext/misc/sha1.c b/ext/misc/sha1.c index e2843bdefa..886b1db7bd 100644 --- a/ext/misc/sha1.c +++ b/ext/misc/sha1.c @@ -10,7 +10,7 @@ ** ****************************************************************************** ** -** This SQLite extension implements a functions that compute SHA1 hashes. +** This SQLite extension implements functions that compute SHA1 hashes. ** Two SQL functions are implemented: ** ** sha1(X) diff --git a/ext/misc/shathree.c b/ext/misc/shathree.c index e5c95407d6..e35fa49477 100644 --- a/ext/misc/shathree.c +++ b/ext/misc/shathree.c @@ -10,7 +10,7 @@ ** ****************************************************************************** ** -** This SQLite extension implements a functions that compute SHA1 hashes. +** This SQLite extension implements functions that compute SHA3 hashes. ** Two SQL functions are implemented: ** ** sha3(X,SIZE) diff --git a/manifest b/manifest index eb41a73d39..d218b5a38c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sreleasetest.tcl\scausing\sconfiguration\s"Fast-One"\sto\sfail. -D 2018-09-25T13:51:31.431 +C Fix\stypos\sin\sthe\sheader\scomment\sfor\sthe\ssha1\sand\ssha3\shash\sextensions\nin\sthe\sext/misc\sfolder. +D 2018-09-26T03:43:42.287 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -296,8 +296,8 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6 F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77 F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad F ext/misc/series.c c7197db304f7009b08d6459a9de02e7f51ad0e1a3fdacbc1ebf5252a9a346959 -F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56 -F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0 +F ext/misc/sha1.c df0a667211baa2c0612d8486acbf6331b9f8633fd4d605c17c7cccd26d59c6bd +F ext/misc/shathree.c 22ba7ca84a433d6466a7d05dcc876910b435a715da8cc462517db9351412b8c8 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5 F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d7c816ae15f05f21b9b213161e1044aaefc56f17e7bc4b7b551a9e04efc05855 -R b83a686c725ad70fbb0586b025a156f8 -U dan -Z 8305c165fab0e9e40fbcffd125669fd0 +P 42e04fefbc241dd33f12abd66344a87720ae4cda6d82f2882217b3cb71be8733 +R 92eda9b59b5f7b8017d32d8a53b3da1f +U drh +Z 2b310859c5d1311e53f97d9b0e4a7ea0 diff --git a/manifest.uuid b/manifest.uuid index f16270a0cb..a34c8625ce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -42e04fefbc241dd33f12abd66344a87720ae4cda6d82f2882217b3cb71be8733 \ No newline at end of file +4ed9d83a0b14a22b3ecf25785b03b5a824d260e01a608aea85231df9b816421d \ No newline at end of file From 2e5e0e10f229378d6a36c1e7604ccff5b6825a7b Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 26 Sep 2018 16:05:07 +0000 Subject: [PATCH 243/260] Tweak spellfix.c so that if SQLITE_SPELLFIX_5BYTE_MAPPINGS is defined at compile time the Transliteration structure has space for 5 byte (instead of 4 byte) mappings. FossilOrigin-Name: cbaf5b6c1b07b29b2c83fa01618de856d81cc1174769cb9770cb5c894cc87ace --- ext/misc/spellfix.c | 12 ++++++++++++ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index faceea189c..81bef139a3 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -1295,6 +1295,9 @@ typedef struct Transliteration Transliteration; struct Transliteration { unsigned short int cFrom; unsigned char cTo0, cTo1, cTo2, cTo3; +#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS + unsigned char cTo4; +#endif }; /* @@ -1708,7 +1711,11 @@ static const Transliteration *spellfixFindTranslit(int c, int *pxTop){ ** should be freed by the caller. */ static unsigned char *transliterate(const unsigned char *zIn, int nIn){ +#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS + unsigned char *zOut = sqlite3_malloc64( nIn*5 + 1 ); +#else unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 ); +#endif int c, sz, nOut; if( zOut==0 ) return 0; nOut = 0; @@ -1732,6 +1739,11 @@ static unsigned char *transliterate(const unsigned char *zIn, int nIn){ zOut[nOut++] = tbl[x].cTo2; if( tbl[x].cTo3 ){ zOut[nOut++] = tbl[x].cTo3; +#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS + if( tbl[x].cTo4 ){ + zOut[nOut++] = tbl[x].cTo4; + } +#endif /* SQLITE_SPELLFIX_5BYTE_MAPPINGS */ } } } diff --git a/manifest b/manifest index d218b5a38c..1633aff5e2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypos\sin\sthe\sheader\scomment\sfor\sthe\ssha1\sand\ssha3\shash\sextensions\nin\sthe\sext/misc\sfolder. -D 2018-09-26T03:43:42.287 +C Tweak\sspellfix.c\sso\sthat\sif\sSQLITE_SPELLFIX_5BYTE_MAPPINGS\sis\sdefined\sat\ncompile\stime\sthe\sTransliteration\sstructure\shas\sspace\sfor\s5\sbyte\s(instead\sof\s4\nbyte)\smappings. +D 2018-09-26T16:05:07.074 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -299,7 +299,7 @@ F ext/misc/series.c c7197db304f7009b08d6459a9de02e7f51ad0e1a3fdacbc1ebf5252a9a34 F ext/misc/sha1.c df0a667211baa2c0612d8486acbf6331b9f8633fd4d605c17c7cccd26d59c6bd F ext/misc/shathree.c 22ba7ca84a433d6466a7d05dcc876910b435a715da8cc462517db9351412b8c8 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 -F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5 +F ext/misc/spellfix.c f88ecb2c0294453ce8b7704b211f5350c41b085b38c8e056852e3a08b0f5e484 F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74 F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11 F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 42e04fefbc241dd33f12abd66344a87720ae4cda6d82f2882217b3cb71be8733 -R 92eda9b59b5f7b8017d32d8a53b3da1f -U drh -Z 2b310859c5d1311e53f97d9b0e4a7ea0 +P 4ed9d83a0b14a22b3ecf25785b03b5a824d260e01a608aea85231df9b816421d +R 2a230066ddda64ec07bfbaa2b5132b83 +U dan +Z c0be36e2bfd8d1131ae6f2d60c444b01 diff --git a/manifest.uuid b/manifest.uuid index a34c8625ce..501e0b8710 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4ed9d83a0b14a22b3ecf25785b03b5a824d260e01a608aea85231df9b816421d \ No newline at end of file +cbaf5b6c1b07b29b2c83fa01618de856d81cc1174769cb9770cb5c894cc87ace \ No newline at end of file From 98aa2abc450b844d3da57644ffca8000d27e628b Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 26 Sep 2018 16:53:51 +0000 Subject: [PATCH 244/260] Begin revamping the ".help" command in the command-line shell so that it can accept an argument and will do a search for commands that match that argument. FossilOrigin-Name: 209afb8d06466536863b89a8acb9a1a18477a06331d8cce95fc6380e1666b6f5 --- manifest | 16 +-- manifest.uuid | 2 +- src/shell.c.in | 297 +++++++++++++++++++++++++++++------------------ test/shell1.test | 2 +- 4 files changed, 192 insertions(+), 125 deletions(-) diff --git a/manifest b/manifest index 1633aff5e2..e8a918eb71 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tweak\sspellfix.c\sso\sthat\sif\sSQLITE_SPELLFIX_5BYTE_MAPPINGS\sis\sdefined\sat\ncompile\stime\sthe\sTransliteration\sstructure\shas\sspace\sfor\s5\sbyte\s(instead\sof\s4\nbyte)\smappings. -D 2018-09-26T16:05:07.074 +C Begin\srevamping\sthe\s".help"\scommand\sin\sthe\scommand-line\sshell\sso\sthat\sit\ncan\saccept\san\sargument\sand\swill\sdo\sa\ssearch\sfor\scommands\sthat\smatch\sthat\nargument. +D 2018-09-26T16:53:51.572 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -503,7 +503,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bc8c79e56439b111e7d9415e44940951f7087e9466c3a9d664558ef0faf31073 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c 1b7ade8fabb85ccd3369683a7951fda37b2843aa1e4ef1fa866b09596a8bfec3 -F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f +F src/shell.c.in 03d87b063174919f97d18d7272b41e387667de7876dee24f97245cb50a6b54db F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 @@ -1265,7 +1265,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 707c03fbd07ac506cfb6fa09da4ee22e2b50453c3db2f404694116eb990168f3 +F test/shell1.test d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494 F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4ed9d83a0b14a22b3ecf25785b03b5a824d260e01a608aea85231df9b816421d -R 2a230066ddda64ec07bfbaa2b5132b83 -U dan -Z c0be36e2bfd8d1131ae6f2d60c444b01 +P cbaf5b6c1b07b29b2c83fa01618de856d81cc1174769cb9770cb5c894cc87ace +R f78ccf48cad379f9ff8d08a24576cd4d +U drh +Z ffa405c420bd31d67403441934b061ad diff --git a/manifest.uuid b/manifest.uuid index 501e0b8710..a8bcf98609 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cbaf5b6c1b07b29b2c83fa01618de856d81cc1174769cb9770cb5c894cc87ace \ No newline at end of file +209afb8d06466536863b89a8acb9a1a18477a06331d8cce95fc6380e1666b6f5 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 8f6ef7ff62..16c33f59ce 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3335,113 +3335,197 @@ static int run_schema_dump_query( } /* -** Text of a help message +** Text of help messages. +** +** The help text for each individual command begins with a line that starts +** with ".". Subsequent lines are supplimental information. +** +** There must be two or more spaces between the end of the command and the +** start of the description of what that command does. */ -static char zHelp[] = +static const char *(azHelp[]) = { #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) - ".archive ... Manage SQL archives: \".archive --help\" for details\n" + ".archive ... Manage SQL archives", + " Each command must have exactly one of the following options:", + " -c, --create Create a new archive", + " -u, --update Update or add files to an existing archive", + " -t, --list List contents of archive", + " -x, --extract Extract files from archive", + " Optional arguments:", + " -v, --verbose Print each filename as it is processed", + " -f FILE, --file FILE Operate on archive FILE (default is current db)", + " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS", + " -C DIR, --directory DIR Change to directory DIR to read/extract files", + " -n, --dryrun Show the SQL that would have occurred", + " Examples:", + " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar", + " .ar -tf archive.sar # List members of archive.sar", + " .ar -xvf archive.sar # Verbosely extract files from archive.sar", + " See also:", + " http://sqlite.org/cli.html#sqlar_archive_support", #endif #ifndef SQLITE_OMIT_AUTHORIZATION - ".auth ON|OFF Show authorizer callbacks\n" + ".auth ON|OFF Show authorizer callbacks", #endif - ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" - " Add \"--append\" to open using appendvfs.\n" - ".bail on|off Stop after hitting an error. Default OFF\n" - ".binary on|off Turn binary output on or off. Default OFF\n" - ".cd DIRECTORY Change the working directory to DIRECTORY\n" - ".changes on|off Show number of rows changed by SQL\n" - ".check GLOB Fail if output since .testcase does not match\n" - ".clone NEWDB Clone data into NEWDB from the existing database\n" - ".databases List names and files of attached databases\n" - ".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n" - ".dbinfo ?DB? Show status information about the database\n" - ".dump ?TABLE? ... Dump the database in an SQL text format\n" - " If TABLE specified, only dump tables matching\n" - " LIKE pattern TABLE.\n" - ".echo on|off Turn command echo on or off\n" - ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" - ".excel Display the output of next command in a spreadsheet\n" - ".exit Exit this program\n" - ".expert EXPERIMENTAL. Suggest indexes for specified queries\n" + ".backup ?DB? FILE Backup DB (default \"main\") to FILE", + " --append Use the appendvfs", + ".bail on|off Stop after hitting an error. Default OFF", + ".binary on|off Turn binary output on or off. Default OFF", + ".cd DIRECTORY Change the working directory to DIRECTORY", + ".changes on|off Show number of rows changed by SQL", + ".check GLOB Fail if output since .testcase does not match", + ".clone NEWDB Clone data into NEWDB from the existing database", + ".databases List names and files of attached databases", + ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", + ".dbinfo ?DB? Show status information about the database", + ".dump ?TABLE? ... Dump the database in an SQL text format", + " TABLE is LIKE pattern for the tables to dump", + ".echo on|off Turn command echo on or off", + ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN", + ".excel Display the output of next command in a spreadsheet", + ".exit Exit this program", + ".expert EXPERIMENTAL. Suggest indexes for specified queries", /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ -/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/ - ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" - ".headers on|off Turn display of headers on or off\n" - ".help Show this message\n" - ".import FILE TABLE Import data from FILE into TABLE\n" +/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ + ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", + ".headers on|off Turn display of headers on or off", + ".help ?-all? ?PATTERN? Show help text for PATTERN", + ".import FILE TABLE Import data from FILE into TABLE", #ifndef SQLITE_OMIT_TEST_CONTROL - ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n" + ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", #endif - ".indexes ?TABLE? Show names of all indexes\n" - " If TABLE specified, only show indexes for tables\n" - " matching LIKE pattern TABLE.\n" + ".indexes ?TABLE? Show names of indexes", + " If TABLE is specified, only show indexes for", + " tables matching TABLE using the LIKE operator.", #ifdef SQLITE_ENABLE_IOTRACE - ".iotrace FILE Enable I/O diagnostic logging to FILE\n" + ".iotrace FILE Enable I/O diagnostic logging to FILE", #endif - ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" - ".lint OPTIONS Report potential schema issues. Options:\n" - " fkey-indexes Find missing foreign key indexes\n" + ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", + ".lint OPTIONS Report potential schema issues.", + " Options:", + " fkey-indexes Find missing foreign key indexes", #ifndef SQLITE_OMIT_LOAD_EXTENSION - ".load FILE ?ENTRY? Load an extension library\n" + ".load FILE ?ENTRY? Load an extension library", #endif - ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" - ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" - " ascii Columns/rows delimited by 0x1F and 0x1E\n" - " csv Comma-separated values\n" - " column Left-aligned columns. (See .width)\n" - " html HTML code\n" - " insert SQL insert statements for TABLE\n" - " line One value per line\n" - " list Values delimited by \"|\"\n" - " quote Escape answers as for SQL\n" - " tabs Tab-separated values\n" - " tcl TCL list elements\n" - ".nullvalue STRING Use STRING in place of NULL values\n" - ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n" - " or invoke system text editor (-e) or spreadsheet (-x)\n" - " on the output.\n" - ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" - " The --new option starts with an empty file\n" - " Other options: --readonly --append --zip\n" - ".output ?FILE? Send output to FILE or stdout\n" - ".print STRING... Print literal STRING\n" - ".prompt MAIN CONTINUE Replace the standard prompts\n" - ".quit Exit this program\n" - ".read FILENAME Execute SQL in FILENAME\n" - ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" - ".save FILE Write in-memory database into FILE\n" - ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" - ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n" - " Add --indent for pretty-printing\n" - ".selftest ?--init? Run tests defined in the SELFTEST table\n" - ".separator COL ?ROW? Change the column separator and optionally the row\n" - " separator for both the output mode and .import\n" + ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", + ".mode MODE ?TABLE? Set output mode", + " MODE is one of:", + " ascii Columns/rows delimited by 0x1F and 0x1E", + " csv Comma-separated values", + " column Left-aligned columns. (See .width)", + " html HTML
    code", + " insert SQL insert statements for TABLE", + " line One value per line", + " list Values delimited by \"|\"", + " quote Escape answers as for SQL", + " tabs Tab-separated values", + " tcl TCL list elements", + ".nullvalue STRING Use STRING in place of NULL values", + ".once (-e|-x|FILE) Output for the next SQL command only to FILE", + " If FILE begins with '|' then open as a pipe", + " Other options:", + " -e Invoke system text editor", + " -x Open in a spreadsheet", + ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", + " Options:", + " --append Use appendvfs to append database to the end of FILE", + " --new Initialize FILE to an empty database", + " --readonly Open FILE readonly", + " --zip FILE is a ZIP archive", + ".output ?FILE? Send output to FILE or stdout if FILE is omitted", + " If FILE begins with '|' then open it as a pipe.", + ".print STRING... Print literal STRING", + ".prompt MAIN CONTINUE Replace the standard prompts", + ".quit Exit this program", + ".read FILE Read input from FILE", + ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", + ".save FILE Write in-memory database into FILE", + ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", + ".schema ?PATTERN? Show the CREATE statements matching PATTERN", + " Options:", + " --indent Try to pretty-print the schema", + ".selftest ?--init? Run tests defined in the SELFTEST table", + ".separator COL ?ROW? Change the column and row separators", #if defined(SQLITE_ENABLE_SESSION) - ".session CMD ... Create or control sessions\n" + ".session CMD ... Create or control sessions", #endif - ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n" + ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content", #ifndef SQLITE_NOHAVE_SYSTEM - ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" + ".shell CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".show Show the current values for various settings\n" - ".stats ?on|off? Show stats or turn stats on or off\n" + ".show Show the current values for various settings", + ".stats ?on|off? Show stats or turn stats on or off", #ifndef SQLITE_NOHAVE_SYSTEM - ".system CMD ARGS... Run CMD ARGS... in a system shell\n" + ".system CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".tables ?TABLE? List names of tables\n" - " If TABLE specified, only list tables matching\n" - " LIKE pattern TABLE.\n" - ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n" - ".timeout MS Try opening locked tables for MS milliseconds\n" - ".timer on|off Turn SQL timer on or off\n" - ".trace FILE|off Output each SQL statement as it is run\n" - ".vfsinfo ?AUX? Information about the top-level VFS\n" - ".vfslist List all available VFSes\n" - ".vfsname ?AUX? Print the name of the VFS stack\n" - ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" - " Negative values right-justify\n" -; + ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", + ".testcase NAME Begin redirecting output to 'testcase-out.txt'", + ".timeout MS Try opening locked tables for MS milliseconds", + ".timer on|off Turn SQL timer on or off", + ".trace FILE|off Output each SQL statement as it is run", + ".vfsinfo ?AUX? Information about the top-level VFS", + ".vfslist List all available VFSes", + ".vfsname ?AUX? Print the name of the VFS stack", + ".width NUM1 NUM2 ... Set column widths for \"column\" mode", + " Negative values right-justify", +}; + +/* +** Output help text. +** +** zPattern describes the set of commands for which help text is provided. +** If zPattern is NULL, then show all commands, but only give a one-line +** description of each. +** +** Return the number of matches. +*/ +static int showHelp(FILE *out, const char *zPattern){ + int i, j; + int n = 0; + char *zPat; + if( zPattern==0 || zPattern[0]=='0' ){ + /* Show all commands, but only one line per command */ + for(i=0; iout, "%s", zHelp); + if( nArg>=2 ){ + int n = showHelp(p->out, azArg[1]); + if( n==0 ){ + utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); + } + }else{ + showHelp(p->out, 0); + } }else if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ diff --git a/test/shell1.test b/test/shell1.test index 1bd7fbea76..aaf7addf5c 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -378,7 +378,7 @@ do_test shell1-3.10.1 { } {1 1 1} do_test shell1-3.10.2 { # we allow .help to take extra args (it is help after all) - set res [catchcmd "test.db" ".help BAD"] + set res [catchcmd "test.db" ".help *"] # look for a few of the possible help commands list [regexp {.help} $res] \ [regexp {.quit} $res] \ From eb7f2a0fc51d306a581f341108a7f2c34c788502 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 26 Sep 2018 18:02:32 +0000 Subject: [PATCH 245/260] Further improvements to the ".help" command in the CLI. FossilOrigin-Name: edc3d18ecbda32d6a55de76ee7335342425c57d917e9b48814a7301a012263b2 --- manifest | 12 +++---- manifest.uuid | 2 +- src/shell.c.in | 89 ++++++++++++++++++++++++++++---------------------- 3 files changed, 57 insertions(+), 46 deletions(-) diff --git a/manifest b/manifest index e8a918eb71..613ca098a2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\srevamping\sthe\s".help"\scommand\sin\sthe\scommand-line\sshell\sso\sthat\sit\ncan\saccept\san\sargument\sand\swill\sdo\sa\ssearch\sfor\scommands\sthat\smatch\sthat\nargument. -D 2018-09-26T16:53:51.572 +C Further\simprovements\sto\sthe\s".help"\scommand\sin\sthe\sCLI. +D 2018-09-26T18:02:32.772 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -503,7 +503,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bc8c79e56439b111e7d9415e44940951f7087e9466c3a9d664558ef0faf31073 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c 1b7ade8fabb85ccd3369683a7951fda37b2843aa1e4ef1fa866b09596a8bfec3 -F src/shell.c.in 03d87b063174919f97d18d7272b41e387667de7876dee24f97245cb50a6b54db +F src/shell.c.in 2162b1dc99b806298207c9c202aa7b49ac8553b8b1e73bb28cd80d5a1861df39 F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P cbaf5b6c1b07b29b2c83fa01618de856d81cc1174769cb9770cb5c894cc87ace -R f78ccf48cad379f9ff8d08a24576cd4d +P 209afb8d06466536863b89a8acb9a1a18477a06331d8cce95fc6380e1666b6f5 +R 2bbe28ad2c8e39198abb575c136c791e U drh -Z ffa405c420bd31d67403441934b061ad +Z 46449abd20dff7d89e070088562c2521 diff --git a/manifest.uuid b/manifest.uuid index a8bcf98609..cd32c03a80 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -209afb8d06466536863b89a8acb9a1a18477a06331d8cce95fc6380e1666b6f5 \ No newline at end of file +edc3d18ecbda32d6a55de76ee7335342425c57d917e9b48814a7301a012263b2 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 16c33f59ce..9bfc3d12cf 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3378,12 +3378,15 @@ static const char *(azHelp[]) = { ".databases List names and files of attached databases", ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", ".dbinfo ?DB? Show status information about the database", - ".dump ?TABLE? ... Dump the database in an SQL text format", - " TABLE is LIKE pattern for the tables to dump", + ".dump ?TABLE? ... Render all database content as SQL", + " Options:", + " --preserve-rowids Include ROWID values in the output", + " --newlines Allow unescaped newline characters in output", + " TABLE is LIKE pattern for the tables to dump", ".echo on|off Turn command echo on or off", ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN", ".excel Display the output of next command in a spreadsheet", - ".exit Exit this program", + ".exit ?CODE? Exit this program with return-code CODE", ".expert EXPERIMENTAL. Suggest indexes for specified queries", /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ @@ -3445,12 +3448,34 @@ static const char *(azHelp[]) = { ".schema ?PATTERN? Show the CREATE statements matching PATTERN", " Options:", " --indent Try to pretty-print the schema", - ".selftest ?--init? Run tests defined in the SELFTEST table", + ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", + " Options:", + " --init Create a new SELFTEST table", + " -v Verbose output", ".separator COL ?ROW? Change the column and row separators", #if defined(SQLITE_ENABLE_SESSION) - ".session CMD ... Create or control sessions", + ".session ?NAME? CMD ... Create or control sessions", + " Subcommands:", + " attach TABLE Attach TABLE", + " changeset FILE Write a changeset into FILE", + " close Close one session", + " enable ?BOOLEAN? Set or query the enable bit", + " filter GLOB... Reject tables matching GLOBs", + " indirect ?BOOLEAN? Mark or query the indirect status", + " isempty Query whether the session is empty", + " list List currently open session names", + " open DB NAME Open a new session on DB", + " patchset FILE Write a patchset into FILE", + " If ?NAME? is omitted, the first defined session is used.", #endif - ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content", + ".sha3sum ... Compute a SHA3 hash of database content", + " Options:", + " --schema Also hash the sqlite_master table", + " --sha3-224 Use the sha3-224 algorithm", + " --sha3-256 Use the sha3-256 algorithm. This is the default.", + " --sha3-384 Use the sha3-384 algorithm", + " --sha3-512 Use the sha3-512 algorithm", + " Any other argument is a LIKE pattern for tables to hash", #ifndef SQLITE_NOHAVE_SYSTEM ".shell CMD ARGS... Run CMD ARGS... in a system shell", #endif @@ -3498,17 +3523,24 @@ static int showHelp(FILE *out, const char *zPattern){ for(i=0; iout, - ".session ?NAME? SUBCOMMAND ?ARGS...?\n" - "If ?NAME? is omitted, the first defined session is used.\n" - "Subcommands:\n" - " attach TABLE Attach TABLE\n" - " changeset FILE Write a changeset into FILE\n" - " close Close one session\n" - " enable ?BOOLEAN? Set or query the enable bit\n" - " filter GLOB... Reject tables matching GLOBs\n" - " indirect ?BOOLEAN? Mark or query the indirect status\n" - " isempty Query whether the session is empty\n" - " list List currently open session names\n" - " open DB NAME Open a new session on DB\n" - " patchset FILE Write a patchset into FILE\n" - ); -} -#endif - - /* Forward reference */ static int process_input(ShellState *p, FILE *in); @@ -5904,7 +5912,10 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ - static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = { + static const struct DbConfigChoices { + const char *zName; + int op; + } aDbConfig[] = { { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, @@ -7162,7 +7173,7 @@ static int do_meta_command(char *zLine, ShellState *p){ }else /* If no command name matches, show a syntax error */ session_syntax_error: - session_help(p); + showHelp(p->out, "session"); }else #endif From 1c06b47864cd957f7ad15ef0e0f41ceb9a729847 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 27 Sep 2018 00:04:31 +0000 Subject: [PATCH 246/260] Minor simplification: In OP_ParseSchema, read the p1 register once. FossilOrigin-Name: bd250533a06e4a11c1f548c3de66b8562fc627383848570d7d030cf132fd336f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 613ca098a2..2cec351ab7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprovements\sto\sthe\s".help"\scommand\sin\sthe\sCLI. -D 2018-09-26T18:02:32.772 +C Minor\ssimplification:\sIn\sOP_ParseSchema,\sread\sthe\sp1\sregister\sonce. +D 2018-09-27T00:04:31.454 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -573,7 +573,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 -F src/vdbe.c c7416f6b5e47efbdf09c73a3984ecc68666151ae894c27fb1e51d51bbba62082 +F src/vdbe.c 35844c264d638f2e0ce334c79cf964ce40f9d1609aa5aaf2d62f376de380c938 F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907 F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827 F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 209afb8d06466536863b89a8acb9a1a18477a06331d8cce95fc6380e1666b6f5 -R 2bbe28ad2c8e39198abb575c136c791e -U drh -Z 46449abd20dff7d89e070088562c2521 +P edc3d18ecbda32d6a55de76ee7335342425c57d917e9b48814a7301a012263b2 +R 2f9baca90efb27d47414a12e20eb21a3 +U mistachkin +Z 543a7f79652a90c3248b7edf31061012 diff --git a/manifest.uuid b/manifest.uuid index cd32c03a80..c5f0fd52df 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -edc3d18ecbda32d6a55de76ee7335342425c57d917e9b48814a7301a012263b2 \ No newline at end of file +bd250533a06e4a11c1f548c3de66b8562fc627383848570d7d030cf132fd336f \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 6a50fa2f99..76e27f2603 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5768,7 +5768,7 @@ case OP_ParseSchema: { { zMaster = MASTER_NAME; initData.db = db; - initData.iDb = pOp->p1; + initData.iDb = iDb; initData.pzErrMsg = &p->zErrMsg; initData.mInitFlags = 0; zSql = sqlite3MPrintf(db, From 6afa35c98565b94311ac22b4d6c1755a1f1f83b3 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 27 Sep 2018 12:14:15 +0000 Subject: [PATCH 247/260] Disallow the use of window functions in the recursive part of a recursive CTE. FossilOrigin-Name: 7fc2994434c7d9ed29c96a69c07e8eb4e97be776473c170c63f9a1bbaa09fa68 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/select.c | 7 +++++++ test/with1.test | 21 +++++++++++++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2cec351ab7..afd4f4d11e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification:\sIn\sOP_ParseSchema,\sread\sthe\sp1\sregister\sonce. -D 2018-09-27T00:04:31.454 +C Disallow\sthe\suse\sof\swindow\sfunctions\sin\sthe\srecursive\spart\sof\sa\srecursive\sCTE. +D 2018-09-27T12:14:15.056 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -502,7 +502,7 @@ F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bc8c79e56439b111e7d9415e44940951f7087e9466c3a9d664558ef0faf31073 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c 1b7ade8fabb85ccd3369683a7951fda37b2843aa1e4ef1fa866b09596a8bfec3 +F src/select.c 33aacf1c17c64a00788c779b23d0875dd0d90eb4c08f867ebc31139ef3a67c95 F src/shell.c.in 2162b1dc99b806298207c9c202aa7b49ac8553b8b1e73bb28cd80d5a1861df39 F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1653,7 +1653,7 @@ F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c19 F test/window5.test 8187f46597c90b73e8f96659e893353cbda337479cc582f7a488eab351ba08d3 F test/window6.test 7574778c79cae89f1781df237bf9ff5063886deca91a36efc53934315f0e7612 F test/windowfault.test 23abad97b72c6f609002255ddd41ef5c8922408f918f9b98ad6005ab316e482f -F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96 +F test/with1.test 2465d98ffce80d00553ac7135697c18b0369275b6ecc750daa2af320b8c812ca F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205 @@ -1769,7 +1769,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P edc3d18ecbda32d6a55de76ee7335342425c57d917e9b48814a7301a012263b2 -R 2f9baca90efb27d47414a12e20eb21a3 -U mistachkin -Z 543a7f79652a90c3248b7edf31061012 +P bd250533a06e4a11c1f548c3de66b8562fc627383848570d7d030cf132fd336f +R f859da5dfe791e15b8e90067f7a4610e +U dan +Z 08a7f25691627dd6eb8a24e372187fa8 diff --git a/manifest.uuid b/manifest.uuid index c5f0fd52df..cddb301ade 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd250533a06e4a11c1f548c3de66b8562fc627383848570d7d030cf132fd336f \ No newline at end of file +7fc2994434c7d9ed29c96a69c07e8eb4e97be776473c170c63f9a1bbaa09fa68 \ No newline at end of file diff --git a/src/select.c b/src/select.c index d300798069..1d2cd1a969 100644 --- a/src/select.c +++ b/src/select.c @@ -2318,6 +2318,13 @@ static void generateWithRecursiveQuery( Expr *pLimit; /* Saved LIMIT and OFFSET */ int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ +#ifndef SQLITE_OMIT_WINDOWFUNC + if( p->pWin ){ + sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries"); + return; + } +#endif + /* Obtain authorization to do a recursive query */ if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; diff --git a/test/with1.test b/test/with1.test index f8965399fc..f9b41ff615 100644 --- a/test/with1.test +++ b/test/with1.test @@ -865,6 +865,27 @@ do_catchsql_test 16.1 { SELECT * FROM i; } {1 {recursive aggregate queries not supported}} +# Or window-function recursive queries. Ticket e8275b41. +# +ifcapable windowfunc { + do_catchsql_test 16.2 { + WITH RECURSIVE + i(x) AS (VALUES(1) UNION SELECT count(*) OVER () FROM i) + SELECT * FROM i; + } {1 {cannot use window functions in recursive queries}} + do_catchsql_test 16.3 { + WITH RECURSIVE + t(id, parent) AS (VALUES(1,2)), + q(id, parent, rn) AS ( + VALUES(1,2,3) + UNION ALL + SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn + FROM q JOIN t ON t.parent = q.id + ) + SELECT * FROM q; + } {1 {cannot use window functions in recursive queries}} +} + #------------------------------------------------------------------------- do_execsql_test 17.1 { WITH x(a) AS ( From d7fda6cfc5bc1aebf3ff2420aaaa8d9d27068410 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Sep 2018 15:21:13 +0000 Subject: [PATCH 248/260] Initial prototype of a eponymous virtual table that accesses sqlite3_status64() and sqlite3_db_status(). FossilOrigin-Name: 0b44e1f68e0c8349367e3f929d4734c3df96338ec8d6fb652565bf894e8b8343 --- ext/misc/memstat.c | 316 +++++++++++++++++++++++++++++++++++++++++++++ manifest | 16 ++- manifest.uuid | 2 +- 3 files changed, 327 insertions(+), 7 deletions(-) create mode 100644 ext/misc/memstat.c diff --git a/ext/misc/memstat.c b/ext/misc/memstat.c new file mode 100644 index 0000000000..036f0e6502 --- /dev/null +++ b/ext/misc/memstat.c @@ -0,0 +1,316 @@ +/* +** 2018-09-27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file demonstrates an eponymous virtual table that returns information +** from sqlite3_status64() and sqlite3_db_status(). +** +** Usage example: +** +** .load ./memstat +** .mode quote +** .header on +** SELECT * FROM memstat; +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) +#if !defined(SQLITEINT_H) +#include "sqlite3ext.h" +#endif +SQLITE_EXTENSION_INIT1 +#include +#include + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* memstat_vtab is a subclass of sqlite3_vtab which will +** serve as the underlying representation of a memstat virtual table +*/ +typedef struct memstat_vtab memstat_vtab; +struct memstat_vtab { + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this memstat vtab */ +}; + +/* memstat_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result +*/ +typedef struct memstat_cursor memstat_cursor; +struct memstat_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this cursor */ + sqlite3_int64 iRowid; /* The rowid */ + sqlite3_int64 iCur; /* Current value */ + sqlite3_int64 iHiwtr; /* High-water mark */ +}; + +/* +** The memstatConnect() method is invoked to create a new +** memstat_vtab that describes the memstat virtual table. +** +** Think of this routine as the constructor for memstat_vtab objects. +** +** All this routine needs to do is: +** +** (1) Allocate the memstat_vtab object and initialize all fields. +** +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the +** result set of queries against memstat will look like. +*/ +static int memstatConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + memstat_vtab *pNew; + int rc; + +/* Column numbers */ +#define MSV_COLUMN_NAME 0 /* Name of quantity being measured */ +#define MSV_COLUMN_CURRENT 1 /* Current value */ +#define MSV_COLUMN_HIWTR 2 /* Highwater mark */ + + rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,current,hiwtr)"); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); + *ppVtab = (sqlite3_vtab*)pNew; + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + pNew->db = db; + } + return rc; +} + +/* +** This method is the destructor for memstat_cursor objects. +*/ +static int memstatDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** Constructor for a new memstat_cursor object. +*/ +static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + memstat_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + pCur->db = ((memstat_vtab*)p)->db; + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Destructor for a memstat_cursor. +*/ +static int memstatClose(sqlite3_vtab_cursor *cur){ + sqlite3_free(cur); + return SQLITE_OK; +} + + +/* +** Allowed values for aMemstatColumn[].eType +*/ +#define MSV_GSTAT 0 /* sqlite3_status64() information */ +#define MSV_DBSTAT 1 /* sqlite3_db_status() information */ + +/* +** An array of quantities that can be measured and reported by +** this virtual table +*/ +static const struct MemstatColumns { + const char *zName; /* Symbolic name */ + int eType; /* Type of interface */ + int eOp; /* Opcode */ +} aMemstatColumn[] = { + { "MEMORY_USED", MSV_GSTAT, SQLITE_STATUS_MEMORY_USED }, + { "MALLOC_SIZE", MSV_GSTAT, SQLITE_STATUS_MALLOC_SIZE }, + { "MALLOC_COUNT", MSV_GSTAT, SQLITE_STATUS_MALLOC_COUNT }, + { "PAGECACHE_USED", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_USED }, + { "PAGECACHE_OVERFLOW", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_OVERFLOW }, + { "PAGECACHE_SIZE", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_SIZE }, + { "PARSER_STACK", MSV_GSTAT, SQLITE_STATUS_PARSER_STACK }, + { "LOOKASIDE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_USED }, + { "CACHE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED }, + { "SCHEMA_USED", MSV_DBSTAT, SQLITE_DBSTATUS_SCHEMA_USED }, + { "STMT_USED", MSV_DBSTAT, SQLITE_DBSTATUS_STMT_USED }, + { "LOOKASIDE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_HIT }, + { "LOOKASIDE_MISS_SIZE", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, + { "LOOKASIDE_MISS_FULL", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, + { "CACHE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_HIT }, + { "CACHE_MISS", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_MISS }, + { "CACHE_WRITE", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_WRITE }, + { "DEFERRED_FKS", MSV_DBSTAT, SQLITE_DBSTATUS_DEFERRED_FKS }, + { "CACHE_USED_SHARED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED_SHARED }, + { "CACHE_SPILL", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_SPILL }, +}; +#define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0])) + +/* +** Advance a memstat_cursor to its next row of output. +*/ +static int memstatNext(sqlite3_vtab_cursor *cur){ + memstat_cursor *pCur = (memstat_cursor*)cur; + pCur->iRowid++; + return SQLITE_OK; +} + + +/* +** Return values of columns for the row at which the memstat_cursor +** is currently pointing. +*/ +static int memstatColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int iCol /* Which column to return */ +){ + memstat_cursor *pCur = (memstat_cursor*)cur; + int i; + sqlite3_int64 iCur = 0, iHiwtr = 0; + + assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW ); + i = (int)pCur->iRowid - 1; + if( iCol==MSV_COLUMN_NAME ){ + sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC); + return SQLITE_OK; + } + switch( aMemstatColumn[i].eType ){ + case MSV_GSTAT: { + sqlite3_status64(aMemstatColumn[i].eOp, &iCur, &iHiwtr, 0); + break; + } + case MSV_DBSTAT: { + int xCur, xHiwtr; + sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0); + iCur = xCur; + iHiwtr = xHiwtr; + break; + } + } + if( iCol==MSV_COLUMN_HIWTR ) iCur = iHiwtr; + sqlite3_result_int64(ctx, iCur); + return SQLITE_OK; +} + +/* +** Return the rowid for the current row. In this implementation, the +** rowid is the same as the output value. +*/ +static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + memstat_cursor *pCur = (memstat_cursor*)cur; + *pRowid = pCur->iRowid; + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int memstatEof(sqlite3_vtab_cursor *cur){ + memstat_cursor *pCur = (memstat_cursor*)cur; + return pCur->iRowid>=MSV_NROW; +} + +/* +** This method is called to "rewind" the memstat_cursor object back +** to the first row of output. This method is always called at least +** once prior to any call to memstatColumn() or memstatRowid() or +** memstatEof(). +*/ +static int memstatFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + memstat_cursor *pCur = (memstat_cursor *)pVtabCursor; + pCur->iRowid = 0; + return memstatNext(pVtabCursor); +} + +/* +** SQLite will invoke this method one or more times while planning a query +** that uses the memstat virtual table. This routine needs to create +** a query plan for each invocation and compute an estimated cost for that +** plan. +*/ +static int memstatBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + pIdxInfo->estimatedCost = (double)500; + pIdxInfo->estimatedRows = 500; + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the +** memstat virtual table. +*/ +static sqlite3_module memstatModule = { + 0, /* iVersion */ + 0, /* xCreate */ + memstatConnect, /* xConnect */ + memstatBestIndex, /* xBestIndex */ + memstatDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + memstatOpen, /* xOpen - open a cursor */ + memstatClose, /* xClose - close a cursor */ + memstatFilter, /* xFilter - configure scan constraints */ + memstatNext, /* xNext - advance a cursor */ + memstatEof, /* xEof - check for end of scan */ + memstatColumn, /* xColumn - read data */ + memstatRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +int sqlite3MemstatVtabInit(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "sqlite_memstat", &memstatModule, 0); +#endif + return rc; +} + +#ifndef SQLITE_CORE +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_memstat_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3MemstatVtabInit(db); +#endif + return rc; +} +#endif /* SQLITE_CORE */ +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ diff --git a/manifest b/manifest index afd4f4d11e..23436c2aa7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disallow\sthe\suse\sof\swindow\sfunctions\sin\sthe\srecursive\spart\sof\sa\srecursive\sCTE. -D 2018-09-27T12:14:15.056 +C Initial\sprototype\sof\sa\seponymous\svirtual\stable\sthat\saccesses\ssqlite3_status64()\nand\ssqlite3_db_status(). +D 2018-09-27T15:21:13.771 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -286,6 +286,7 @@ F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f830 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363 +F ext/misc/memstat.c 1e36cfd77f528066df164f8f9bec3481f6b570cf92e27a9e43229c75a4baffa1 F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 @@ -1769,7 +1770,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bd250533a06e4a11c1f548c3de66b8562fc627383848570d7d030cf132fd336f -R f859da5dfe791e15b8e90067f7a4610e -U dan -Z 08a7f25691627dd6eb8a24e372187fa8 +P 7fc2994434c7d9ed29c96a69c07e8eb4e97be776473c170c63f9a1bbaa09fa68 +R dc5bab36f0540d8a30e5739e455f50c5 +T *branch * memstat-vtab +T *sym-memstat-vtab * +T -sym-trunk * +U drh +Z f687dcf36195771d0f69625cb386777d diff --git a/manifest.uuid b/manifest.uuid index cddb301ade..6d75410cab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7fc2994434c7d9ed29c96a69c07e8eb4e97be776473c170c63f9a1bbaa09fa68 \ No newline at end of file +0b44e1f68e0c8349367e3f929d4734c3df96338ec8d6fb652565bf894e8b8343 \ No newline at end of file From 7c5577acdcbdf5f8845605fa8d4dd4c1c6383a90 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Sep 2018 15:45:03 +0000 Subject: [PATCH 249/260] Add initial ZIPVFS support for the "main" database to the sqlite_memstat virtual table. FossilOrigin-Name: 9cd27350b0f62debfe3238c57c3ab51079699142e82c05a7ec8460a8429f55f2 --- ext/misc/memstat.c | 55 ++++++++++++++++++++++++++++------------------ manifest | 15 +++++-------- manifest.uuid | 2 +- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/ext/misc/memstat.c b/ext/misc/memstat.c index 036f0e6502..ebfeb3235c 100644 --- a/ext/misc/memstat.c +++ b/ext/misc/memstat.c @@ -126,6 +126,7 @@ static int memstatClose(sqlite3_vtab_cursor *cur){ */ #define MSV_GSTAT 0 /* sqlite3_status64() information */ #define MSV_DBSTAT 1 /* sqlite3_db_status() information */ +#define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */ /* ** An array of quantities that can be measured and reported by @@ -136,26 +137,34 @@ static const struct MemstatColumns { int eType; /* Type of interface */ int eOp; /* Opcode */ } aMemstatColumn[] = { - { "MEMORY_USED", MSV_GSTAT, SQLITE_STATUS_MEMORY_USED }, - { "MALLOC_SIZE", MSV_GSTAT, SQLITE_STATUS_MALLOC_SIZE }, - { "MALLOC_COUNT", MSV_GSTAT, SQLITE_STATUS_MALLOC_COUNT }, - { "PAGECACHE_USED", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_USED }, - { "PAGECACHE_OVERFLOW", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_OVERFLOW }, - { "PAGECACHE_SIZE", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_SIZE }, - { "PARSER_STACK", MSV_GSTAT, SQLITE_STATUS_PARSER_STACK }, - { "LOOKASIDE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_USED }, - { "CACHE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED }, - { "SCHEMA_USED", MSV_DBSTAT, SQLITE_DBSTATUS_SCHEMA_USED }, - { "STMT_USED", MSV_DBSTAT, SQLITE_DBSTATUS_STMT_USED }, - { "LOOKASIDE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_HIT }, - { "LOOKASIDE_MISS_SIZE", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, - { "LOOKASIDE_MISS_FULL", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, - { "CACHE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_HIT }, - { "CACHE_MISS", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_MISS }, - { "CACHE_WRITE", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_WRITE }, - { "DEFERRED_FKS", MSV_DBSTAT, SQLITE_DBSTATUS_DEFERRED_FKS }, - { "CACHE_USED_SHARED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED_SHARED }, - { "CACHE_SPILL", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_SPILL }, + { "MEMORY_USED", MSV_GSTAT, SQLITE_STATUS_MEMORY_USED }, + { "MALLOC_SIZE", MSV_GSTAT, SQLITE_STATUS_MALLOC_SIZE }, + { "MALLOC_COUNT", MSV_GSTAT, SQLITE_STATUS_MALLOC_COUNT }, + { "PAGECACHE_USED", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_USED }, + { "PAGECACHE_OVERFLOW", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_OVERFLOW }, + { "PAGECACHE_SIZE", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_SIZE }, + { "PARSER_STACK", MSV_GSTAT, SQLITE_STATUS_PARSER_STACK }, + { "DB_LOOKASIDE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_USED }, + { "DB_CACHE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED }, + { "DB_SCHEMA_USED", MSV_DBSTAT, SQLITE_DBSTATUS_SCHEMA_USED }, + { "DB_STMT_USED", MSV_DBSTAT, SQLITE_DBSTATUS_STMT_USED }, + { "DB_LOOKASIDE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_HIT }, + { "DB_LOOKASIDE_MISS_SIZE", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, + { "DB_LOOKASIDE_MISS_FULL", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, + { "DB_CACHE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_HIT }, + { "DB_CACHE_MISS", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_MISS }, + { "DB_CACHE_WRITE", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_WRITE }, + { "DB_DEFERRED_FKS", MSV_DBSTAT, SQLITE_DBSTATUS_DEFERRED_FKS }, + { "DB_CACHE_USED_SHARED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED_SHARED }, + { "DB_CACHE_SPILL", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_SPILL }, +#ifdef SQLITE_ENABLE_ZIPVFS + { "ZIPVFS_CACHE_USED", MSV_ZIPVFS, 231454 }, + { "ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 231455 }, + { "ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 231456 }, + { "ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 231457 }, + { "ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 231458 }, + { "ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 231459 }, +#endif /* SQLITE_ENABLE_ZIPVFS */ }; #define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0])) @@ -200,6 +209,10 @@ static int memstatColumn( iHiwtr = xHiwtr; break; } + case MSV_ZIPVFS: { + sqlite3_file_control(pCur->db, 0, aMemstatColumn[i].eOp, (void*)&iCur); + break; + } } if( iCol==MSV_COLUMN_HIWTR ) iCur = iHiwtr; sqlite3_result_int64(ctx, iCur); @@ -222,7 +235,7 @@ static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ */ static int memstatEof(sqlite3_vtab_cursor *cur){ memstat_cursor *pCur = (memstat_cursor*)cur; - return pCur->iRowid>=MSV_NROW; + return pCur->iRowid>MSV_NROW; } /* diff --git a/manifest b/manifest index 23436c2aa7..3300211b2e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\sprototype\sof\sa\seponymous\svirtual\stable\sthat\saccesses\ssqlite3_status64()\nand\ssqlite3_db_status(). -D 2018-09-27T15:21:13.771 +C Add\sinitial\sZIPVFS\ssupport\sfor\sthe\s"main"\sdatabase\sto\sthe\ssqlite_memstat\nvirtual\stable. +D 2018-09-27T15:45:03.985 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -286,7 +286,7 @@ F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f830 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363 -F ext/misc/memstat.c 1e36cfd77f528066df164f8f9bec3481f6b570cf92e27a9e43229c75a4baffa1 +F ext/misc/memstat.c 09bfa9a16be3d44932233fd1aa95cdd09d7b3f72d3f36805483bfe23b48fe8ec F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 @@ -1770,10 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7fc2994434c7d9ed29c96a69c07e8eb4e97be776473c170c63f9a1bbaa09fa68 -R dc5bab36f0540d8a30e5739e455f50c5 -T *branch * memstat-vtab -T *sym-memstat-vtab * -T -sym-trunk * +P 0b44e1f68e0c8349367e3f929d4734c3df96338ec8d6fb652565bf894e8b8343 +R eeaa8104d4a2a8c673af2ed0c882ed24 U drh -Z f687dcf36195771d0f69625cb386777d +Z 5dadcc7b0adb63e8fb1777ba189f8dd3 diff --git a/manifest.uuid b/manifest.uuid index 6d75410cab..e9f468b470 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0b44e1f68e0c8349367e3f929d4734c3df96338ec8d6fb652565bf894e8b8343 \ No newline at end of file +9cd27350b0f62debfe3238c57c3ab51079699142e82c05a7ec8460a8429f55f2 \ No newline at end of file From d7134fe0c1f96a715d76b9bad5cae614289f4e2b Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Sep 2018 16:57:42 +0000 Subject: [PATCH 250/260] Enhancements to sqlite_memstat: (1) Add an extra "schema" column to show the schema name for ZIPVFS stats. (2) Only show ZIPVFS stats to schema that use ZIPVFS (3) Put a NULL in unused columns of the output. FossilOrigin-Name: 9351135b4331107be2f2bda7b6adbd5436381f4f9a68340e8a172b6517ec3f12 --- ext/misc/memstat.c | 197 ++++++++++++++++++++++++++++++++------------- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 148 insertions(+), 63 deletions(-) diff --git a/ext/misc/memstat.c b/ext/misc/memstat.c index ebfeb3235c..84078c9ceb 100644 --- a/ext/misc/memstat.c +++ b/ext/misc/memstat.c @@ -20,7 +20,7 @@ ** .header on ** SELECT * FROM memstat; */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) #if !defined(SQLITEINT_H) #include "sqlite3ext.h" #endif @@ -47,9 +47,11 @@ typedef struct memstat_cursor memstat_cursor; struct memstat_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ sqlite3 *db; /* Database connection for this cursor */ - sqlite3_int64 iRowid; /* The rowid */ - sqlite3_int64 iCur; /* Current value */ - sqlite3_int64 iHiwtr; /* High-water mark */ + int iRowid; /* Current row in aMemstatColumn[] */ + int iDb; /* Which schema we are looking at */ + int nDb; /* Number of schemas */ + char **azDb; /* Names of all schemas */ + sqlite3_int64 aVal[2]; /* Result values */ }; /* @@ -77,10 +79,11 @@ static int memstatConnect( /* Column numbers */ #define MSV_COLUMN_NAME 0 /* Name of quantity being measured */ -#define MSV_COLUMN_CURRENT 1 /* Current value */ -#define MSV_COLUMN_HIWTR 2 /* Highwater mark */ +#define MSV_COLUMN_SCHEMA 1 /* schema name */ +#define MSV_COLUMN_VALUE 2 /* Current value */ +#define MSV_COLUMN_HIWTR 3 /* Highwater mark */ - rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,current,hiwtr)"); + rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,schema,value,hiwtr)"); if( rc==SQLITE_OK ){ pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; @@ -112,10 +115,59 @@ static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ return SQLITE_OK; } +/* +** Clear all the schema names from a cursor +*/ +static void memstatClearSchema(memstat_cursor *pCur){ + int i; + if( pCur->azDb==0 ) return; + for(i=0; inDb; i++){ + sqlite3_free(pCur->azDb[i]); + } + sqlite3_free(pCur->azDb); + pCur->azDb = 0; + pCur->nDb = 0; +} + +/* +** Fill in the azDb[] array for the cursor. +*/ +static int memstatFindSchemas(memstat_cursor *pCur){ + sqlite3_stmt *pStmt = 0; + int rc; + if( pCur->nDb ) return SQLITE_OK; + rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0); + if( rc ){ + sqlite3_finalize(pStmt); + return rc; + } + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + char **az, *z; + az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1)); + if( az==0 ){ + memstatClearSchema(pCur); + return SQLITE_NOMEM; + } + pCur->azDb = az; + z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + if( z==0 ){ + memstatClearSchema(pCur); + return SQLITE_NOMEM; + } + pCur->azDb[pCur->nDb] = z; + pCur->nDb++; + } + sqlite3_finalize(pStmt); + return SQLITE_OK; +} + + /* ** Destructor for a memstat_cursor. */ static int memstatClose(sqlite3_vtab_cursor *cur){ + memstat_cursor *pCur = (memstat_cursor*)cur; + memstatClearSchema(pCur); sqlite3_free(cur); return SQLITE_OK; } @@ -125,7 +177,7 @@ static int memstatClose(sqlite3_vtab_cursor *cur){ ** Allowed values for aMemstatColumn[].eType */ #define MSV_GSTAT 0 /* sqlite3_status64() information */ -#define MSV_DBSTAT 1 /* sqlite3_db_status() information */ +#define MSV_DB 1 /* sqlite3_db_status() information */ #define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */ /* @@ -134,36 +186,38 @@ static int memstatClose(sqlite3_vtab_cursor *cur){ */ static const struct MemstatColumns { const char *zName; /* Symbolic name */ - int eType; /* Type of interface */ + unsigned char eType; /* Type of interface */ + unsigned char mNull; /* Bitmask of which columns are NULL */ + /* 2: dbname, 4: current, 8: hiwtr */ int eOp; /* Opcode */ } aMemstatColumn[] = { - { "MEMORY_USED", MSV_GSTAT, SQLITE_STATUS_MEMORY_USED }, - { "MALLOC_SIZE", MSV_GSTAT, SQLITE_STATUS_MALLOC_SIZE }, - { "MALLOC_COUNT", MSV_GSTAT, SQLITE_STATUS_MALLOC_COUNT }, - { "PAGECACHE_USED", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_USED }, - { "PAGECACHE_OVERFLOW", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_OVERFLOW }, - { "PAGECACHE_SIZE", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_SIZE }, - { "PARSER_STACK", MSV_GSTAT, SQLITE_STATUS_PARSER_STACK }, - { "DB_LOOKASIDE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_USED }, - { "DB_CACHE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED }, - { "DB_SCHEMA_USED", MSV_DBSTAT, SQLITE_DBSTATUS_SCHEMA_USED }, - { "DB_STMT_USED", MSV_DBSTAT, SQLITE_DBSTATUS_STMT_USED }, - { "DB_LOOKASIDE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_HIT }, - { "DB_LOOKASIDE_MISS_SIZE", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, - { "DB_LOOKASIDE_MISS_FULL", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, - { "DB_CACHE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_HIT }, - { "DB_CACHE_MISS", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_MISS }, - { "DB_CACHE_WRITE", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_WRITE }, - { "DB_DEFERRED_FKS", MSV_DBSTAT, SQLITE_DBSTATUS_DEFERRED_FKS }, - { "DB_CACHE_USED_SHARED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED_SHARED }, - { "DB_CACHE_SPILL", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_SPILL }, + {"MEMORY_USED", MSV_GSTAT, 2, SQLITE_STATUS_MEMORY_USED }, + {"MALLOC_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_MALLOC_SIZE }, + {"MALLOC_COUNT", MSV_GSTAT, 2, SQLITE_STATUS_MALLOC_COUNT }, + {"PAGECACHE_USED", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_USED }, + {"PAGECACHE_OVERFLOW", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_OVERFLOW }, + {"PAGECACHE_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_PAGECACHE_SIZE }, + {"PARSER_STACK", MSV_GSTAT, 6, SQLITE_STATUS_PARSER_STACK }, + {"DB_LOOKASIDE_USED", MSV_DB, 2, SQLITE_DBSTATUS_LOOKASIDE_USED }, + {"DB_LOOKASIDE_HIT", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_HIT }, + {"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE}, + {"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL}, + {"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED }, + {"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED }, + {"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED }, + {"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED }, + {"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT }, + {"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS }, + {"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE }, + {"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL }, + {"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS }, #ifdef SQLITE_ENABLE_ZIPVFS - { "ZIPVFS_CACHE_USED", MSV_ZIPVFS, 231454 }, - { "ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 231455 }, - { "ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 231456 }, - { "ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 231457 }, - { "ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 231458 }, - { "ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 231459 }, + {"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 }, + {"ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 8, 231455 }, + {"ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 8, 231456 }, + {"ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 8, 231457 }, + {"ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 8, 231458 }, + {"ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 8, 231459 }, #endif /* SQLITE_ENABLE_ZIPVFS */ }; #define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0])) @@ -173,7 +227,41 @@ static const struct MemstatColumns { */ static int memstatNext(sqlite3_vtab_cursor *cur){ memstat_cursor *pCur = (memstat_cursor*)cur; - pCur->iRowid++; + int i; + assert( pCur->iRowid<=MSV_NROW ); + while(1){ + i = (int)pCur->iRowid - 1; + if( (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){ + pCur->iRowid++; + if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */ + pCur->iDb = 0; + i++; + } + pCur->aVal[0] = 0; + pCur->aVal[1] = 0; + switch( aMemstatColumn[i].eType ){ + case MSV_GSTAT: { + sqlite3_status64(aMemstatColumn[i].eOp, + &pCur->aVal[0], &pCur->aVal[1],0); + break; + } + case MSV_DB: { + int xCur, xHiwtr; + sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0); + pCur->aVal[0] = xCur; + pCur->aVal[1] = xHiwtr; + break; + } + case MSV_ZIPVFS: { + int rc; + rc = sqlite3_file_control(pCur->db, pCur->azDb[pCur->iDb], + aMemstatColumn[i].eOp, (void*)&pCur->aVal[0]); + if( rc!=SQLITE_OK ) continue; + break; + } + } + break; + } return SQLITE_OK; } @@ -189,33 +277,29 @@ static int memstatColumn( ){ memstat_cursor *pCur = (memstat_cursor*)cur; int i; - sqlite3_int64 iCur = 0, iHiwtr = 0; - assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW ); i = (int)pCur->iRowid - 1; - if( iCol==MSV_COLUMN_NAME ){ - sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC); + if( (aMemstatColumn[i].mNull & (1<db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0); - iCur = xCur; - iHiwtr = xHiwtr; + case MSV_COLUMN_SCHEMA: { + sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0); break; } - case MSV_ZIPVFS: { - sqlite3_file_control(pCur->db, 0, aMemstatColumn[i].eOp, (void*)&iCur); + case MSV_COLUMN_VALUE: { + sqlite3_result_int64(ctx, pCur->aVal[0]); + break; + } + case MSV_COLUMN_HIWTR: { + sqlite3_result_int64(ctx, pCur->aVal[1]); break; } } - if( iCol==MSV_COLUMN_HIWTR ) iCur = iHiwtr; - sqlite3_result_int64(ctx, iCur); return SQLITE_OK; } @@ -225,7 +309,7 @@ static int memstatColumn( */ static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ memstat_cursor *pCur = (memstat_cursor*)cur; - *pRowid = pCur->iRowid; + *pRowid = pCur->iRowid*1000 + pCur->iDb; return SQLITE_OK; } @@ -250,8 +334,9 @@ static int memstatFilter( int argc, sqlite3_value **argv ){ memstat_cursor *pCur = (memstat_cursor *)pVtabCursor; - pCur->iRowid = 0; - return memstatNext(pVtabCursor); + pCur->iRowid = 1; + pCur->iDb = 0; + return memstatFindSchemas(pCur); } /* @@ -326,4 +411,4 @@ int sqlite3_memstat_init( return rc; } #endif /* SQLITE_CORE */ -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) */ diff --git a/manifest b/manifest index 3300211b2e..330f25ebf9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sinitial\sZIPVFS\ssupport\sfor\sthe\s"main"\sdatabase\sto\sthe\ssqlite_memstat\nvirtual\stable. -D 2018-09-27T15:45:03.985 +C Enhancements\sto\ssqlite_memstat:\n(1)\sAdd\san\sextra\s"schema"\scolumn\sto\sshow\sthe\sschema\sname\sfor\sZIPVFS\sstats.\n(2)\sOnly\sshow\sZIPVFS\sstats\sto\sschema\sthat\suse\sZIPVFS\n(3)\sPut\sa\sNULL\sin\sunused\scolumns\sof\sthe\soutput. +D 2018-09-27T16:57:42.381 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -286,7 +286,7 @@ F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f830 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363 -F ext/misc/memstat.c 09bfa9a16be3d44932233fd1aa95cdd09d7b3f72d3f36805483bfe23b48fe8ec +F ext/misc/memstat.c 1db91b25c9a4a1b73696c14d32a5b39adf6d2e9b11d0cdb5a9f35e86e3da7d36 F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0b44e1f68e0c8349367e3f929d4734c3df96338ec8d6fb652565bf894e8b8343 -R eeaa8104d4a2a8c673af2ed0c882ed24 +P 9cd27350b0f62debfe3238c57c3ab51079699142e82c05a7ec8460a8429f55f2 +R 3b442b9685bf2fd6f2b22a8d8be22779 U drh -Z 5dadcc7b0adb63e8fb1777ba189f8dd3 +Z 2fa27b2796fd3980348a5b531bf6823d diff --git a/manifest.uuid b/manifest.uuid index e9f468b470..97e5040947 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9cd27350b0f62debfe3238c57c3ab51079699142e82c05a7ec8460a8429f55f2 \ No newline at end of file +9351135b4331107be2f2bda7b6adbd5436381f4f9a68340e8a172b6517ec3f12 \ No newline at end of file From 6dd5f07d3d30494ef8a9ffe6cd3238c62982baef Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Sep 2018 17:15:21 +0000 Subject: [PATCH 251/260] Modify the memstat virtual table so that it works with SQLite version 3.9.2. FossilOrigin-Name: 7171d8ae6b1e7c97b0cf06bcca2262674c9ce557c85666b4b77c16cbac508502 --- ext/misc/memstat.c | 11 +++++++++-- manifest | 13 ++++++------- manifest.uuid | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ext/misc/memstat.c b/ext/misc/memstat.c index 84078c9ceb..e594d1de21 100644 --- a/ext/misc/memstat.c +++ b/ext/misc/memstat.c @@ -241,8 +241,15 @@ static int memstatNext(sqlite3_vtab_cursor *cur){ pCur->aVal[1] = 0; switch( aMemstatColumn[i].eType ){ case MSV_GSTAT: { - sqlite3_status64(aMemstatColumn[i].eOp, - &pCur->aVal[0], &pCur->aVal[1],0); + if( sqlite3_libversion_number()>=3010000 ){ + sqlite3_status64(aMemstatColumn[i].eOp, + &pCur->aVal[0], &pCur->aVal[1],0); + }else{ + int xCur, xHiwtr; + sqlite3_status(aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0); + pCur->aVal[0] = xCur; + pCur->aVal[1] = xHiwtr; + } break; } case MSV_DB: { diff --git a/manifest b/manifest index 420b264088..dfad76e2c1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite_memstat\sextension\s-\san\seponymous\svirtual\stable\sthat\sshows\nmemory\susages\sstatistics\sfor\sSQLite. -D 2018-09-27T17:03:03.584 +C Modify\sthe\smemstat\svirtual\stable\sso\sthat\sit\sworks\swith\sSQLite\sversion\s3.9.2. +D 2018-09-27T17:15:21.554 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -286,7 +286,7 @@ F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f830 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363 -F ext/misc/memstat.c 1db91b25c9a4a1b73696c14d32a5b39adf6d2e9b11d0cdb5a9f35e86e3da7d36 +F ext/misc/memstat.c ce3234df2be6afb02729f62533314857835c3fd140ef48592fc78b9152c2fa17 F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 @@ -1770,8 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7fc2994434c7d9ed29c96a69c07e8eb4e97be776473c170c63f9a1bbaa09fa68 9351135b4331107be2f2bda7b6adbd5436381f4f9a68340e8a172b6517ec3f12 -R 3b442b9685bf2fd6f2b22a8d8be22779 -T +closed 9351135b4331107be2f2bda7b6adbd5436381f4f9a68340e8a172b6517ec3f12 +P 954ef61f6a02532e72c815208ec839310f1e00d69e0003cc6f5426f0559229d1 +R 766859725d09447be1e489bf0682d831 U drh -Z aae6139285457822a13630c1c5df83e8 +Z 1657115b7ebcf651e92fc89a965c8bf1 diff --git a/manifest.uuid b/manifest.uuid index 007d68f9e4..a9e3e1047d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -954ef61f6a02532e72c815208ec839310f1e00d69e0003cc6f5426f0559229d1 \ No newline at end of file +7171d8ae6b1e7c97b0cf06bcca2262674c9ce557c85666b4b77c16cbac508502 \ No newline at end of file From 0efb6f51353fcb3bd688d5f1a23c92981079f106 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 27 Sep 2018 17:33:06 +0000 Subject: [PATCH 252/260] Another minor tweak to memstat.c so that it may be built against older versions of SQLite. FossilOrigin-Name: 4c1fed60b9b35ac2f5d2f2533b54db429d72bdbc0aad0dd5af52ff851789d4ae --- ext/misc/memstat.c | 4 ++++ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ext/misc/memstat.c b/ext/misc/memstat.c index e594d1de21..59a5547ce9 100644 --- a/ext/misc/memstat.c +++ b/ext/misc/memstat.c @@ -203,13 +203,17 @@ static const struct MemstatColumns { {"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE}, {"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL}, {"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED }, +#if SQLITE_VERSION_NUMBER >= 3140000 {"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED }, +#endif {"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED }, {"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED }, {"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT }, {"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS }, {"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE }, +#if SQLITE_VERSION_NUMBER >= 3230000 {"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL }, +#endif {"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS }, #ifdef SQLITE_ENABLE_ZIPVFS {"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 }, diff --git a/manifest b/manifest index dfad76e2c1..6fbc136ad0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\smemstat\svirtual\stable\sso\sthat\sit\sworks\swith\sSQLite\sversion\s3.9.2. -D 2018-09-27T17:15:21.554 +C Another\sminor\stweak\sto\smemstat.c\sso\sthat\sit\smay\sbe\sbuilt\sagainst\solder\sversions\nof\sSQLite. +D 2018-09-27T17:33:06.027 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -286,7 +286,7 @@ F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f830 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363 -F ext/misc/memstat.c ce3234df2be6afb02729f62533314857835c3fd140ef48592fc78b9152c2fa17 +F ext/misc/memstat.c 5bf79f86be9c6ccdcdd3529155a65f64b6fe54fa87553307580fb650125e586a F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 954ef61f6a02532e72c815208ec839310f1e00d69e0003cc6f5426f0559229d1 -R 766859725d09447be1e489bf0682d831 -U drh -Z 1657115b7ebcf651e92fc89a965c8bf1 +P 7171d8ae6b1e7c97b0cf06bcca2262674c9ce557c85666b4b77c16cbac508502 +R d47d3de5f232ba29cfc2c94e9ebf7e02 +U dan +Z f1664a0a39511f75bda0cd3cd52c22bb diff --git a/manifest.uuid b/manifest.uuid index a9e3e1047d..473dde99a2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7171d8ae6b1e7c97b0cf06bcca2262674c9ce557c85666b4b77c16cbac508502 \ No newline at end of file +4c1fed60b9b35ac2f5d2f2533b54db429d72bdbc0aad0dd5af52ff851789d4ae \ No newline at end of file From 09d00b2f4f60829fca2d05695d0cc54b70246638 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Sep 2018 20:20:01 +0000 Subject: [PATCH 253/260] Ensure that the OP_VColumn opcode does set sqlite3_vtab_nochange() unless the OPFLAG_NOCHNG bit is set in P5. Fix for ticket [69d642332d25aa3b7315a6d385] FossilOrigin-Name: 322ab1fc613f616e9f07dc94ef74a29572a21cc476d88e97b4ce865500a47b62 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/sqliteInt.h | 1 + src/update.c | 2 +- src/vdbe.c | 12 +++++++----- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 6fbc136ad0..95d4083ba5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\sminor\stweak\sto\smemstat.c\sso\sthat\sit\smay\sbe\sbuilt\sagainst\solder\sversions\nof\sSQLite. -D 2018-09-27T17:33:06.027 +C Ensure\sthat\sthe\sOP_VColumn\sopcode\sdoes\sset\ssqlite3_vtab_nochange()\sunless\nthe\sOPFLAG_NOCHNG\sbit\sis\sset\sin\sP5.\s\sFix\sfor\sticket\n[69d642332d25aa3b7315a6d385] +D 2018-09-27T20:20:01.637 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -508,7 +508,7 @@ F src/shell.c.in 2162b1dc99b806298207c9c202aa7b49ac8553b8b1e73bb28cd80d5a1861df3 F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 -F src/sqliteInt.h 29ac7a59845826fb6523a6b2b77474c954ddedb8368526901b0c7b8df5c2f56e +F src/sqliteInt.h 75d8266b27c287aeada717a541cf7b7543383fccdb1d7d45a5620f666e864c55 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -569,12 +569,12 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b F src/treeview.c 0ef7dc77d6fe03172ba65dddfd3b3c557b7b7e217ca1963b7665beb266a0e2c0 F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd -F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff +F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 -F src/vdbe.c 35844c264d638f2e0ce334c79cf964ce40f9d1609aa5aaf2d62f376de380c938 +F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907 F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827 F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7171d8ae6b1e7c97b0cf06bcca2262674c9ce557c85666b4b77c16cbac508502 -R d47d3de5f232ba29cfc2c94e9ebf7e02 -U dan -Z f1664a0a39511f75bda0cd3cd52c22bb +P 4c1fed60b9b35ac2f5d2f2533b54db429d72bdbc0aad0dd5af52ff851789d4ae +R 4de9cd6272060b40e8360d9dcb419bf1 +U drh +Z 328571ee81991b66e5e9a58d87f0ffc1 diff --git a/manifest.uuid b/manifest.uuid index 473dde99a2..d48100cfa2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c1fed60b9b35ac2f5d2f2533b54db429d72bdbc0aad0dd5af52ff851789d4ae \ No newline at end of file +322ab1fc613f616e9f07dc94ef74a29572a21cc476d88e97b4ce865500a47b62 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index bdde5a9b26..f0ed023c6d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3180,6 +3180,7 @@ struct AuthContext { */ #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ /* Also used in P2 (not P5) of OP_Delete */ +#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */ #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ #define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ diff --git a/src/update.c b/src/update.c index dd2b05c3e6..70f4f676da 100644 --- a/src/update.c +++ b/src/update.c @@ -913,7 +913,7 @@ static void updateVirtualTable( sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); }else{ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); - sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */ + sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */ } } if( HasRowid(pTab) ){ diff --git a/src/vdbe.c b/src/vdbe.c index 76e27f2603..14f3e1bd3c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -6965,10 +6965,11 @@ case OP_VFilter: { /* jump */ ** ** If the VColumn opcode is being used to fetch the value of ** an unchanging column during an UPDATE operation, then the P5 -** value is 1. Otherwise, P5 is 0. The P5 value is returned -** by sqlite3_vtab_nochange() routine and can be used -** by virtual table implementations to return special "no-change" -** marks which can be more efficient, depending on the virtual table. +** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange() +** function to return true inside the xColumn method of the virtual +** table implementation. The P5 column might also contain other +** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are +** unused by OP_VColumn. */ case OP_VColumn: { sqlite3_vtab *pVtab; @@ -6990,7 +6991,8 @@ case OP_VColumn: { assert( pModule->xColumn ); memset(&sContext, 0, sizeof(sContext)); sContext.pOut = pDest; - if( pOp->p5 ){ + testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 ); + if( pOp->p5 & OPFLAG_NOCHNG ){ sqlite3VdbeMemSetNull(pDest); pDest->flags = MEM_Null|MEM_Zero; pDest->u.nZero = 0; From 50db3e8d5108f3796d845a02d8d6aa2f221cafa1 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Sep 2018 20:37:52 +0000 Subject: [PATCH 254/260] Enhance the GeoPOLY extension so that it always stores its polygons in the binary format, which is faster and more compact. FossilOrigin-Name: dc35f7b1754a78fa0d70c92754de07bb3c28d0d31cb929ee8a3a47ac4f3d446e --- ext/rtree/geopoly.c | 11 ++++++++++- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index a34ca12fc7..bbbbf3e7d5 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -1548,7 +1548,16 @@ static int geopolyUpdate( if( sqlite3_value_nochange(aData[2]) ){ sqlite3_bind_null(pUp, 2); }else{ - sqlite3_bind_value(pUp, 2, aData[2]); + GeoPoly *p = 0; + if( sqlite3_value_type(aData[2])==SQLITE_TEXT + && (p = geopolyFuncParam(0, aData[2], &rc))!=0 + && rc==SQLITE_OK + ){ + sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); + }else{ + sqlite3_bind_value(pUp, 2, aData[2]); + } + sqlite3_free(p); nChange = 1; } for(jj=1; jjnAux; jj++){ diff --git a/manifest b/manifest index 95d4083ba5..2ecfedf071 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\sthe\sOP_VColumn\sopcode\sdoes\sset\ssqlite3_vtab_nochange()\sunless\nthe\sOPFLAG_NOCHNG\sbit\sis\sset\sin\sP5.\s\sFix\sfor\sticket\n[69d642332d25aa3b7315a6d385] -D 2018-09-27T20:20:01.637 +C Enhance\sthe\sGeoPOLY\sextension\sso\sthat\sit\salways\sstores\sits\spolygons\sin\sthe\nbinary\sformat,\swhich\sis\sfaster\sand\smore\scompact. +D 2018-09-27T20:37:52.082 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -361,7 +361,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c 415a8ca5dfab54eea779e0bf31a859afb0b869a5147a726df4aec4b57c1bad57 +F ext/rtree/geopoly.c 470c928b8d28321f46620eef1cf986a769b46f39e2175c74b8affa8df2a293ad F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4c1fed60b9b35ac2f5d2f2533b54db429d72bdbc0aad0dd5af52ff851789d4ae -R 4de9cd6272060b40e8360d9dcb419bf1 +P 322ab1fc613f616e9f07dc94ef74a29572a21cc476d88e97b4ce865500a47b62 +R 8f3d6e164234f97a7fd2cd2e24f8d737 U drh -Z 328571ee81991b66e5e9a58d87f0ffc1 +Z ff6e72fa7555d5408cc034538f340086 diff --git a/manifest.uuid b/manifest.uuid index d48100cfa2..4e78013d81 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -322ab1fc613f616e9f07dc94ef74a29572a21cc476d88e97b4ce865500a47b62 \ No newline at end of file +dc35f7b1754a78fa0d70c92754de07bb3c28d0d31cb929ee8a3a47ac4f3d446e \ No newline at end of file From 17e65ae4c08ce1e3c52a6deeefed0a6a9e26fd98 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Sep 2018 23:57:45 +0000 Subject: [PATCH 255/260] Small performance optimization in the JSON parser of Geopoly. FossilOrigin-Name: fb520e71035258d5490be33ee28575df2caefa5d5a301c8bbdf1471551c96282 --- ext/rtree/geopoly.c | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index bbbbf3e7d5..44df401783 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -138,7 +138,7 @@ static void geopolySwab32(unsigned char *a){ /* Skip whitespace. Return the next non-whitespace character. */ static char geopolySkipSpace(GeoParse *p){ - while( p->z[0] && safe_isspace(p->z[0]) ) p->z++; + while( safe_isspace(p->z[0]) ) p->z++; return p->z[0]; } diff --git a/manifest b/manifest index 2ecfedf071..125f71ca76 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sGeoPOLY\sextension\sso\sthat\sit\salways\sstores\sits\spolygons\sin\sthe\nbinary\sformat,\swhich\sis\sfaster\sand\smore\scompact. -D 2018-09-27T20:37:52.082 +C Small\sperformance\soptimization\sin\sthe\sJSON\sparser\sof\sGeopoly. +D 2018-09-27T23:57:45.810 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -361,7 +361,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c 470c928b8d28321f46620eef1cf986a769b46f39e2175c74b8affa8df2a293ad +F ext/rtree/geopoly.c 596a1eb54134d608e70be16ec6b0d5c6b61ff3316840acee854774cb54feb1c9 F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 322ab1fc613f616e9f07dc94ef74a29572a21cc476d88e97b4ce865500a47b62 -R 8f3d6e164234f97a7fd2cd2e24f8d737 +P dc35f7b1754a78fa0d70c92754de07bb3c28d0d31cb929ee8a3a47ac4f3d446e +R 2619909ebdff858be51d935d42b98921 U drh -Z ff6e72fa7555d5408cc034538f340086 +Z 5cad22a26f09f6e60075ff9733cf6357 diff --git a/manifest.uuid b/manifest.uuid index 4e78013d81..c4729cd428 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dc35f7b1754a78fa0d70c92754de07bb3c28d0d31cb929ee8a3a47ac4f3d446e \ No newline at end of file +fb520e71035258d5490be33ee28575df2caefa5d5a301c8bbdf1471551c96282 \ No newline at end of file From b2d83494d3f727d7be442fac1ad016a0544edb1c Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 28 Sep 2018 00:16:57 +0000 Subject: [PATCH 256/260] Rig geopoly to use sqlite3AtoF() if it is available, as that routine is much faster than atof(). FossilOrigin-Name: 470c6c07d0eb70806ac257c1c8ad877e041bbc14ff9a5c490edb51b2956ae726 --- ext/rtree/geopoly.c | 14 ++++++++++++-- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 44df401783..3f1b89ad46 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -158,7 +158,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; for(;; j++){ c = z[j]; - if( c>='0' && c<='9' ) continue; + if( safe_isdigit(c) ) continue; if( c=='.' ){ if( z[j-1]=='-' ) return 0; if( seenDP ) return 0; @@ -180,7 +180,17 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ break; } if( z[j-1]<'0' ) return 0; - if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z); + if( pVal ){ +#ifdef SQLITE_AMALGAMATION + /* The sqlite3AtoF() routine is much much faster than atof(), if it + ** is available */ + double r; + (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); + *pVal = r; +#else + *pVal = (GeoCoord)atof((const char*)p->z); +#endif + } p->z += j; return 1; } diff --git a/manifest b/manifest index 125f71ca76..c7305bb3bd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\sperformance\soptimization\sin\sthe\sJSON\sparser\sof\sGeopoly. -D 2018-09-27T23:57:45.810 +C Rig\sgeopoly\sto\suse\ssqlite3AtoF()\sif\sit\sis\savailable,\sas\sthat\sroutine\sis\smuch\nfaster\sthan\satof(). +D 2018-09-28T00:16:57.366 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -361,7 +361,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c 596a1eb54134d608e70be16ec6b0d5c6b61ff3316840acee854774cb54feb1c9 +F ext/rtree/geopoly.c d8eb33517c2d1a3f5ab3a8a8502d3182e4a11115749c03e969c162b47112c06a F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dc35f7b1754a78fa0d70c92754de07bb3c28d0d31cb929ee8a3a47ac4f3d446e -R 2619909ebdff858be51d935d42b98921 +P fb520e71035258d5490be33ee28575df2caefa5d5a301c8bbdf1471551c96282 +R 47c3c7c1359809e24fc02c3047f697ad U drh -Z 5cad22a26f09f6e60075ff9733cf6357 +Z ad03ded0c726f90176bebeb637053950 diff --git a/manifest.uuid b/manifest.uuid index c4729cd428..015826b446 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb520e71035258d5490be33ee28575df2caefa5d5a301c8bbdf1471551c96282 \ No newline at end of file +470c6c07d0eb70806ac257c1c8ad877e041bbc14ff9a5c490edb51b2956ae726 \ No newline at end of file From 601c8f2829b98fa1a70bdb06530a0959cb78ce2f Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 28 Sep 2018 13:18:24 +0000 Subject: [PATCH 257/260] Make most geopoly functions pure. FossilOrigin-Name: 944e167a98e995c5750c1fcd44df857d6b10c1cbb91731fad2849415c42b2cfc --- ext/rtree/geopoly.c | 26 ++++++++++++++------------ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 3f1b89ad46..66a0ce2487 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -1640,19 +1640,20 @@ static int sqlite3_geopoly_init(sqlite3 *db){ int rc = SQLITE_OK; static const struct { void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - int nArg; + signed char nArg; + unsigned char bPure; const char *zName; } aFunc[] = { - { geopolyAreaFunc, 1, "geopoly_area" }, - { geopolyBlobFunc, 1, "geopoly_blob" }, - { geopolyJsonFunc, 1, "geopoly_json" }, - { geopolySvgFunc, -1, "geopoly_svg" }, - { geopolyWithinFunc, 2, "geopoly_within" }, - { geopolyContainsPointFunc, 3, "geopoly_contains_point" }, - { geopolyOverlapFunc, 2, "geopoly_overlap" }, - { geopolyDebugFunc, 1, "geopoly_debug" }, - { geopolyBBoxFunc, 1, "geopoly_bbox" }, - { geopolyXformFunc, 7, "geopoly_xform" }, + { geopolyAreaFunc, 1, 1, "geopoly_area" }, + { geopolyBlobFunc, 1, 1, "geopoly_blob" }, + { geopolyJsonFunc, 1, 1, "geopoly_json" }, + { geopolySvgFunc, -1, 1, "geopoly_svg" }, + { geopolyWithinFunc, 2, 1, "geopoly_within" }, + { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" }, + { geopolyOverlapFunc, 2, 1, "geopoly_overlap" }, + { geopolyDebugFunc, 1, 0, "geopoly_debug" }, + { geopolyBBoxFunc, 1, 1, "geopoly_bbox" }, + { geopolyXformFunc, 7, 1, "geopoly_xform" }, }; static const struct { void (*xStep)(sqlite3_context*,int,sqlite3_value**); @@ -1663,8 +1664,9 @@ static int sqlite3_geopoly_init(sqlite3 *db){ }; int i; for(i=0; i Date: Fri, 28 Sep 2018 14:01:17 +0000 Subject: [PATCH 258/260] Add the geopoly_regular(X,Y,R,N) function to the geopoly extension. FossilOrigin-Name: 4505bbae58357eacab262b642b2a56d6dd380de72faceb5bbfd042eb94a12c06 --- ext/rtree/geopoly.c | 59 ++++++++++++++++++++++++++++++++++++++++++ ext/rtree/visual01.txt | 13 ++++++++++ manifest | 14 +++++----- manifest.uuid | 2 +- 4 files changed, 80 insertions(+), 8 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 66a0ce2487..7eea11c48c 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -486,6 +486,64 @@ static void geopolyAreaFunc( } } +#define GEOPOLY_PI 3.1415926535897932385 + +/* Fast approximation for cosine(X) for X between -0.5*pi and 2*pi +*/ +static double geopolyCosine(double r){ + assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); + if( r>=1.5*GEOPOLY_PI ){ + r -= 2.0*GEOPOLY_PI; + } + if( r>=0.5*GEOPOLY_PI ){ + return -geopolyCosine(r-GEOPOLY_PI); + }else{ + double r2 = r*r; + double r3 = r2*r; + double r5 = r3*r2; + return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; + } +} + +/* +** Function: geopoly_regular(X,Y,R,N) +** +** Construct a simple, convex, regular polygon centered at X, Y +** with circumradius R and with N sides. +*/ +static void geopolyRegularFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + double x = sqlite3_value_double(argv[0]); + double y = sqlite3_value_double(argv[1]); + double r = sqlite3_value_double(argv[2]); + int n = sqlite3_value_int(argv[3]); + int i; + GeoPoly *p; + + if( n<3 || r<=0.0 ) return; + if( n>1000 ) n = 1000; + p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); + if( p==0 ){ + sqlite3_result_error_nomem(context); + return; + } + i = 1; + p->hdr[0] = *(unsigned char*)&i; + p->hdr[1] = 0; + p->hdr[2] = (n>>8)&0xff; + p->hdr[3] = n&0xff; + for(i=0; ia[i*2] = x - r*geopolyCosine(rAngle-0.5*GEOPOLY_PI); + p->a[i*2+1] = y + r*geopolyCosine(rAngle); + } + sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT); + sqlite3_free(p); +} + /* ** If pPoly is a polygon, compute its bounding box. Then: ** @@ -1654,6 +1712,7 @@ static int sqlite3_geopoly_init(sqlite3 *db){ { geopolyDebugFunc, 1, 0, "geopoly_debug" }, { geopolyBBoxFunc, 1, 1, "geopoly_bbox" }, { geopolyXformFunc, 7, 1, "geopoly_xform" }, + { geopolyRegularFunc, 4, 1, "geopoly_regular" }, }; static const struct { void (*xStep)(sqlite3_context*,int,sqlite3_value**); diff --git a/ext/rtree/visual01.txt b/ext/rtree/visual01.txt index 90ae92403d..281d610842 100644 --- a/ext/rtree/visual01.txt +++ b/ext/rtree/visual01.txt @@ -586,4 +586,17 @@ SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"') ROLLBACK; .print '' +.print '

    Regular Polygons

    ' +.print '' +SELECT geopoly_svg(geopoly_regular(100,100,40,3),'style="fill:none;stroke:red;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(200,100,40,4),'style="fill:none;stroke:orange;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(300,100,40,5),'style="fill:none;stroke:green;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(400,100,40,6),'style="fill:none;stroke:blue;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(500,100,40,7),'style="fill:none;stroke:purple;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(600,100,40,8),'style="fill:none;stroke:red;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(700,100,40,10),'style="fill:none;stroke:orange;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(800,100,40,20),'style="fill:none;stroke:green;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(900,100,40,30),'style="fill:none;stroke:blue;stroke-width:1"'); +.print '' + .print '' diff --git a/manifest b/manifest index 364404f98f..d3b8622456 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\smost\sgeopoly\sfunctions\spure. -D 2018-09-28T13:18:24.886 +C Add\sthe\sgeopoly_regular(X,Y,R,N)\sfunction\sto\sthe\sgeopoly\sextension. +D 2018-09-28T14:01:17.539 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -361,7 +361,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c c92eb2c5df436c0be3cffceb00769794ed8a28b38fe6e40cde2c68b026d20c8c +F ext/rtree/geopoly.c cdf7972736f6c60e4309debad504de52ccd2dbe29e02bc8afc7912923ee68059 F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 @@ -389,7 +389,7 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/rtree/visual01.txt 17c3afefc208c375607aa82242e97fa79c316e539bcd0b7b3e59344c69445d05 +F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 470c6c07d0eb70806ac257c1c8ad877e041bbc14ff9a5c490edb51b2956ae726 -R fa3505d48ffa9af9252dfb9f6f5b940e +P 944e167a98e995c5750c1fcd44df857d6b10c1cbb91731fad2849415c42b2cfc +R 9e3d22ac82d673a7d5cc41392de57d72 U drh -Z 9e0a18a5e5cb49bc10f6b45134fb4708 +Z d2b850e1c73ac3950129550f18e00569 diff --git a/manifest.uuid b/manifest.uuid index f492a69ede..4a7c37464b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -944e167a98e995c5750c1fcd44df857d6b10c1cbb91731fad2849415c42b2cfc \ No newline at end of file +4505bbae58357eacab262b642b2a56d6dd380de72faceb5bbfd042eb94a12c06 \ No newline at end of file From 09b523c99b760adf05422fc8d805313a2271cd3a Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 28 Sep 2018 18:51:18 +0000 Subject: [PATCH 259/260] Fix a bug in the sqlite_memstat virtual table that was causing it to report the amount of memory used as zero bytes. FossilOrigin-Name: 8a758a872175b0c74e631c231240c5c733fbec708d0cff23eb9c4025e4a800ec --- ext/misc/memstat.c | 6 ++++-- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ext/misc/memstat.c b/ext/misc/memstat.c index 59a5547ce9..27cb404df5 100644 --- a/ext/misc/memstat.c +++ b/ext/misc/memstat.c @@ -345,9 +345,11 @@ static int memstatFilter( int argc, sqlite3_value **argv ){ memstat_cursor *pCur = (memstat_cursor *)pVtabCursor; - pCur->iRowid = 1; + int rc = memstatFindSchemas(pCur); + if( rc ) return rc; + pCur->iRowid = 0; pCur->iDb = 0; - return memstatFindSchemas(pCur); + return memstatNext(pVtabCursor); } /* diff --git a/manifest b/manifest index d3b8622456..9787027a1d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sgeopoly_regular(X,Y,R,N)\sfunction\sto\sthe\sgeopoly\sextension. -D 2018-09-28T14:01:17.539 +C Fix\sa\sbug\sin\sthe\ssqlite_memstat\svirtual\stable\sthat\swas\scausing\sit\sto\sreport\nthe\samount\sof\smemory\sused\sas\szero\sbytes. +D 2018-09-28T18:51:18.258 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -286,7 +286,7 @@ F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f830 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363 -F ext/misc/memstat.c 5bf79f86be9c6ccdcdd3529155a65f64b6fe54fa87553307580fb650125e586a +F ext/misc/memstat.c 2780712e90765b810645227578438d972b76a089210901bfe9ec88f6a45b0570 F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 944e167a98e995c5750c1fcd44df857d6b10c1cbb91731fad2849415c42b2cfc -R 9e3d22ac82d673a7d5cc41392de57d72 +P 4505bbae58357eacab262b642b2a56d6dd380de72faceb5bbfd042eb94a12c06 +R a4d832eb9ce30fc99095dc863dfe84b6 U drh -Z d2b850e1c73ac3950129550f18e00569 +Z fa1cdba8568610c894d1ce677cdd3927 diff --git a/manifest.uuid b/manifest.uuid index 4a7c37464b..2cdbb9977f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4505bbae58357eacab262b642b2a56d6dd380de72faceb5bbfd042eb94a12c06 \ No newline at end of file +8a758a872175b0c74e631c231240c5c733fbec708d0cff23eb9c4025e4a800ec \ No newline at end of file From f8248c42f97fdfd27d1b92280314100233653074 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 28 Sep 2018 20:46:41 +0000 Subject: [PATCH 260/260] Have sqlite3changegroup_output_strm() call its output function more regularly. FossilOrigin-Name: 8467c31aa0bf24e597f680748460a99f425c49f5ab741c3574c339aa56857146 --- ext/session/sqlite3session.c | 9 ++++----- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index e432b894ca..abbf16dc75 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -4866,13 +4866,12 @@ static int sessionChangegroupOutput( sessionAppendByte(&buf, p->op, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ + rc = xOutput(pOut, buf.aBuf, buf.nBuf); + buf.nBuf = 0; + } } } - - if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ - rc = xOutput(pOut, buf.aBuf, buf.nBuf); - buf.nBuf = 0; - } } if( rc==SQLITE_OK ){ diff --git a/manifest b/manifest index 9787027a1d..dfdb94b268 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\sthe\ssqlite_memstat\svirtual\stable\sthat\swas\scausing\sit\sto\sreport\nthe\samount\sof\smemory\sused\sas\szero\sbytes. -D 2018-09-28T18:51:18.258 +C Have\ssqlite3changegroup_output_strm()\scall\sits\soutput\sfunction\smore\sregularly. +D 2018-09-28T20:46:41.755 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -416,7 +416,7 @@ F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc45 F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8 F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc -F ext/session/sqlite3session.c 2d29bbd888599b94b2c8b31ff433675e008273a4d225b336508b18e6187fec1d +F ext/session/sqlite3session.c ba76c7f01d4c71ab4d134cfda0ba43faae04bff01b8e81d1279a6101c706e3b5 F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b864028a0400ceccf F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 @@ -1770,7 +1770,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4505bbae58357eacab262b642b2a56d6dd380de72faceb5bbfd042eb94a12c06 -R a4d832eb9ce30fc99095dc863dfe84b6 -U drh -Z fa1cdba8568610c894d1ce677cdd3927 +P 8a758a872175b0c74e631c231240c5c733fbec708d0cff23eb9c4025e4a800ec +R bc7e7923bdbbf4167e1d0ea65b2cbd1a +U dan +Z 4710e29744ea4e9b01b11660462afc67 diff --git a/manifest.uuid b/manifest.uuid index 2cdbb9977f..687004ba90 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a758a872175b0c74e631c231240c5c733fbec708d0cff23eb9c4025e4a800ec \ No newline at end of file +8467c31aa0bf24e597f680748460a99f425c49f5ab741c3574c339aa56857146 \ No newline at end of file