1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Merge recent enhancements from trunk.

FossilOrigin-Name: cb77236673e30af1e8749d984dedecc8f901b255
This commit is contained in:
drh
2015-09-01 18:52:35 +00:00
40 changed files with 2976 additions and 356 deletions

View File

@@ -423,6 +423,7 @@ TESTSRC += \
$(TOP)/ext/fts5/fts5_tcl.c \ $(TOP)/ext/fts5/fts5_tcl.c \
$(TOP)/ext/fts5/fts5_test_mi.c \ $(TOP)/ext/fts5/fts5_test_mi.c \
$(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/json1.c \
$(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/percentile.c \ $(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/regexp.c \
@@ -572,9 +573,9 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la
-version-info "8:6:8" \ -version-info "8:6:8" \
-avoid-version -avoid-version
sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h $(TOP)/ext/misc/json1.c
$(LTLINK) $(READLINE_FLAGS) \ $(LTLINK) $(READLINE_FLAGS) -DSQLITE_ENABLE_JSON1 -o $@ \
-o $@ $(TOP)/src/shell.c libsqlite3.la \ $(TOP)/src/shell.c $(TOP)/ext/misc/json1.c libsqlite3.la \
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)" $(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h

View File

@@ -390,9 +390,9 @@ CORE_LINK_OPTS = /DEF:sqlite3.def
# #
!IFNDEF SHELL_COMPILE_OPTS !IFNDEF SHELL_COMPILE_OPTS
!IF $(DYNAMIC_SHELL)!=0 !IF $(DYNAMIC_SHELL)!=0
SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
!ELSE !ELSE
SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS)
!ENDIF !ENDIF
!ENDIF !ENDIF
@@ -1097,6 +1097,7 @@ TESTEXT = \
$(TOP)\ext\fts5\fts5_tcl.c \ $(TOP)\ext\fts5\fts5_tcl.c \
$(TOP)\ext\fts5\fts5_test_mi.c \ $(TOP)\ext\fts5\fts5_test_mi.c \
$(TOP)\ext\misc\ieee754.c \ $(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\json1.c \
$(TOP)\ext\misc\nextchar.c \ $(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\percentile.c \ $(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \ $(TOP)\ext\misc\regexp.c \
@@ -1247,8 +1248,8 @@ libsqlite3.lib: $(LIBOBJ)
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS) $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h sqlite3.exe: $(TOP)\src\shell.c $(TOP)\ext\misc\json1.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \ $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(TOP)\ext\misc\json1.c \
/link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) /link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h

1947
ext/misc/json1.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -334,19 +334,21 @@ static int seriesBestIndex(
pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg;
pIdxInfo->aConstraintUsage[stepIdx].omit = 1; pIdxInfo->aConstraintUsage[stepIdx].omit = 1;
} }
if( pIdxInfo->nOrderBy==1 ){
if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
pIdxInfo->orderByConsumed = 1;
}
if( (idxNum & 3)==3 ){ if( (idxNum & 3)==3 ){
/* Both start= and stop= boundaries are available. This is the /* Both start= and stop= boundaries are available. This is the
** the preferred case */ ** the preferred case */
pIdxInfo->estimatedCost = (double)1; pIdxInfo->estimatedCost = (double)1;
pIdxInfo->estimatedRows = 1000;
if( pIdxInfo->nOrderBy==1 ){
if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
pIdxInfo->orderByConsumed = 1;
}
}else{ }else{
/* If either boundary is missing, we have to generate a huge span /* If either boundary is missing, we have to generate a huge span
** of numbers. Make this case very expensive so that the query ** of numbers. Make this case very expensive so that the query
** planner will work hard to avoid it. */ ** planner will work hard to avoid it. */
pIdxInfo->estimatedCost = (double)2000000000; pIdxInfo->estimatedCost = (double)2147483647;
pIdxInfo->estimatedRows = 2147483647;
} }
pIdxInfo->idxNum = idxNum; pIdxInfo->idxNum = idxNum;
return SQLITE_OK; return SQLITE_OK;

View File

@@ -489,7 +489,7 @@ static int rbuDeltaApply(
/* ERROR: copy exceeds output file size */ /* ERROR: copy exceeds output file size */
return -1; return -1;
} }
if( ofst+cnt > lenSrc ){ if( (int)(ofst+cnt) > lenSrc ){
/* ERROR: copy extends past end of input */ /* ERROR: copy extends past end of input */
return -1; return -1;
} }
@@ -504,7 +504,7 @@ static int rbuDeltaApply(
/* ERROR: insert command gives an output larger than predicted */ /* ERROR: insert command gives an output larger than predicted */
return -1; return -1;
} }
if( cnt>lenDelta ){ if( (int)cnt>lenDelta ){
/* ERROR: insert count exceeds size of delta */ /* ERROR: insert count exceeds size of delta */
return -1; return -1;
} }
@@ -1117,7 +1117,7 @@ static void rbuTableType(
} }
rbuTableType_end: { rbuTableType_end: {
int i; unsigned int i;
for(i=0; i<sizeof(aStmt)/sizeof(aStmt[0]); i++){ for(i=0; i<sizeof(aStmt)/sizeof(aStmt[0]); i++){
rbuFinalize(p, aStmt[i]); rbuFinalize(p, aStmt[i]);
} }
@@ -1530,7 +1530,7 @@ static char *rbuObjIterGetSetlist(
if( p->rc==SQLITE_OK ){ if( p->rc==SQLITE_OK ){
int i; int i;
if( strlen(zMask)!=pIter->nTblCol ){ if( (int)strlen(zMask)!=pIter->nTblCol ){
rbuBadControlError(p); rbuBadControlError(p);
}else{ }else{
const char *zSep = ""; const char *zSep = "";
@@ -3680,7 +3680,8 @@ static int rbuVfsOpen(
rbuVfsShmMap, /* xShmMap */ rbuVfsShmMap, /* xShmMap */
rbuVfsShmLock, /* xShmLock */ rbuVfsShmLock, /* xShmLock */
rbuVfsShmBarrier, /* xShmBarrier */ rbuVfsShmBarrier, /* xShmBarrier */
rbuVfsShmUnmap /* xShmUnmap */ rbuVfsShmUnmap, /* xShmUnmap */
0, 0 /* xFetch, xUnfetch */
}; };
rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs; rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs;
sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs; sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs;

View File

@@ -75,8 +75,6 @@ LIBOBJ+= vdbe.o parse.o \
LIBOBJ += sqlite3session.o LIBOBJ += sqlite3session.o
LIBOBJ += fts5.o
# All of the source code files. # All of the source code files.
# #
SRC = \ SRC = \
@@ -304,6 +302,7 @@ TESTSRC += \
$(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/misc/fuzzer.c \
$(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/json1.c \
$(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/percentile.c \ $(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/regexp.c \
@@ -447,9 +446,9 @@ libsqlite3.a: $(LIBOBJ)
$(AR) libsqlite3.a $(LIBOBJ) $(AR) libsqlite3.a $(LIBOBJ)
$(RANLIB) libsqlite3.a $(RANLIB) libsqlite3.a
sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(TOP)/ext/misc/json1.c
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) \ $(TCCX) $(READLINE_FLAGS) -DSQLITE_ENABLE_JSON1 -o sqlite3$(EXE) \
$(TOP)/src/shell.c \ $(TOP)/src/shell.c $(TOP)/ext/misc/json1.c \
libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h

View File

@@ -1,9 +1,9 @@
C Merge\srecent\strunk\senhancements,\sinclude\stable-valued\sfunctions. C Merge\srecent\senhancements\sfrom\strunk.
D 2015-08-20T23:54:25.007 D 2015-09-01T18:52:35.271
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 7c77beda9c1e956ff754ff12141b4b2ed033686b F Makefile.in 00b690660681c22e7ce3a9cbebd69894766ebbd8
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc e978ec57e8eb6e2f5b8a5114fa8cb320626337ca F Makefile.msc a71cfab97780281290f01b212f907d6d438b7e2d
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION ccfc4d1576dbfdeece0a4372a2e6a2e37d3e7975 F VERSION ccfc4d1576dbfdeece0a4372a2e6a2e37d3e7975
@@ -192,11 +192,12 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
F ext/misc/json1.c bd51e8c1e8ce580e6f21493bd8e94ed5aca3d777
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/series.c 6f94daf590d0668187631dee2a4d7e1d8f3095c3 F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 86998fb73aefb7b5dc346ba8a58912f312da4996 F ext/misc/spellfix.c 86998fb73aefb7b5dc346ba8a58912f312da4996
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
@@ -225,7 +226,7 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
F ext/rbu/sqlite3rbu.c 1650e682b3568db0ed97ff2c7ba5d1c8ea060a84 F ext/rbu/sqlite3rbu.c 4ba82bd850aa012f73c31dd242d570f18c9cc35a
F ext/rbu/sqlite3rbu.h 5357f070cd8c0bcad459b620651ec1656859e4d0 F ext/rbu/sqlite3rbu.h 5357f070cd8c0bcad459b620651ec1656859e4d0
F ext/rbu/test_rbu.c 2a3652241fa45d5eaa141775e4ae68c1d3582c03 F ext/rbu/test_rbu.c 2a3652241fa45d5eaa141775e4ae68c1d3582c03
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
@@ -276,7 +277,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 2d090a509da78d5dde9da7062ff0c104a4bb3023 F main.mk be6f386422ef2d203455cd8b0b7aef148a881718
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -300,22 +301,22 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c f48b3ef91676c06a90a8832987ecef6b94c931ee F src/btree.c f48b3ef91676c06a90a8832987ecef6b94c931ee
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
F src/build.c 5eb5d055a1d1cdaaea25e01b12607aa894bc0911 F src/build.c 511b02138eddc3cf68dab1016da4998260093e9f
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58 F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c b998fbc3c55e8331a5f40aa7ff80972254de8de1 F src/delete.c 6ecf6e84ad3013adbc996c3fe1b77d5f72f36562
F src/expr.c 9b9fa7f825290dee945007edc9fe8fdd9b8ce49e F src/expr.c 5944e529891416f482250e16c598d8c26e149eb0
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869 F src/fkey.c 3ce33dd49f12c72376cec9adc7a4d8e7111cedcc
F src/func.c 824bea430d3a2b7dbc62806ad54da8fdb8ed9e3f F src/func.c 824bea430d3a2b7dbc62806ad54da8fdb8ed9e3f
F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9 F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 43e48fa63c9b9b5f195a13c40ddf7fd112370bb2 F src/insert.c 9301b3ddffa1d9f14e6e750b26d5cc86fb028831
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 92bafa308607dd985ca389a788cd9e0a2b608712 F src/lempar.c 92bafa308607dd985ca389a788cd9e0a2b608712
@@ -344,28 +345,28 @@ F src/os_win.c 40b3af7a47eb1107d0d69e592bec345a3b7b798a
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f
F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2 F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
F src/parse.y ad9af8552f6f340bd646577ca63356a6f82b6a7e F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
F src/pcache1.c d08939800abf3031bd0affd5a13fbc4d7ba3fb68 F src/pcache1.c a3fe31b17e841ec70beee72a2c960e9c787a8857
F src/pragma.c 669bc0fdb3fb5554e18330e8dd9743319bac16f4 F src/pragma.c a239d2c8c6d87d589927547f234b0f6259c69f62
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c 2bc439ff20a4aad0e0ad50a37a67b5eae7d20edc F src/printf.c 2bc439ff20a4aad0e0ad50a37a67b5eae7d20edc
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 7a67cd2aebc9a9eeecd1d104eb6a9237388eb452 F src/resolve.c f2ef256786a6435efddd64a632fea89c8be62215
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c c46de38c1b66355f02a839bb72eb13f277e6d19c F src/select.c b52c80f2b1bdb62491f9ce40eea0c5f80c78d105
F src/shell.c 534f332318f1cff781e07d82a952f22e644e8f6f F src/shell.c af164c3e8c5d187305fb9187f3b6dd7618aa5726
F src/sqlite.h.in a25d949fd0714136d574e18738defa893baf14bb F src/sqlite.h.in 4afdc59b5e5cc9938107144997153a812aa8b5ca
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h a0b948ebc89bac13941254641326a6aa248c2cc4 F src/sqlite3ext.h f700e6a9dd1fdcccc9951ab022b366fb66b9e413
F src/sqliteInt.h 198917e2122c33b43412efedc2b055a82a212225 F src/sqliteInt.h 5dda67f9d2d2a2ada0d28d59b7d18a510aa61942
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc
F src/test1.c c12ed85c22ac95f87f79de2ec9553334d115f71e F src/test1.c c96508c835979bf15dc0e3146e2c7a51a2333d3c
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622 F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@@ -412,9 +413,9 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481 F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
F src/tokenize.c 57cb3720f53f84d811def2069c2b169b6be539a5 F src/tokenize.c 57cb3720f53f84d811def2069c2b169b6be539a5
F src/treeview.c c15df00728034549ff92d78ae851b44952736d3b F src/treeview.c 46036cbbceada0836833531b2d963edbca3d9cfa
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
F src/update.c 24dd6a45b8b3470e62702128ebf11be1f2693145 F src/update.c b551ee2dadf47b34312a5cfb5a7139ead3d47bc5
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c bc9dd64b5db544218b871b66243871c202b2781f F src/util.c bc9dd64b5db544218b871b66243871c202b2781f
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
@@ -429,13 +430,13 @@ F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c d31174e4c8f592febab3fa7f69e18320b4fd657a F src/vtab.c d31174e4c8f592febab3fa7f69e18320b4fd657a
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 6fb6b68969e4692593c2552c4e7bff5882de2cb8 F src/wal.c 8cd07f1f99e1a81346db1c9da879bef6c6f97cf6
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
F src/where.c 66518a14a1238611aa0744d6980b6b7f544f4816 F src/where.c 91e73ffc699c140a59baa03a6b7b060db02bed81
F src/whereInt.h 880a8599226ac1c00203490d934f3ed79b292572 F src/whereInt.h 901c17c1e3c82745ad9b85b4471543fa59c980e9
F src/wherecode.c 69f19535a6de0cceb10e16b31a3a03463e31bc24 F src/wherecode.c 3d9113cc307ffeed58db41fe9f2d807c94787ab5
F src/whereexpr.c f9dbd159127452150c92b558e184827ecb8f9229 F src/whereexpr.c 1a308d1ee5144890d21ea9cf70d49bc96a83432b
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -820,7 +821,7 @@ F test/join.test f9d4a28dec81c6e9dc21b73518e024d73b5ebf57
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324 F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 5df23eba184f159ed9705a954957e765a10c141d F test/join5.test 8a5c0be6f0c260a5c7177c3b8f07c7856141038a
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577 F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1 F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
@@ -828,6 +829,7 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json101.test 11535d8986184500f4c30cc2f0b154b4ab05cc4e
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
@@ -916,6 +918,7 @@ F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859 F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 88a330ea5fc7bed7e407b28beb0d2b79485ae2cc
F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7 F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799 F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
@@ -927,6 +930,7 @@ F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6 F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
@@ -1051,7 +1055,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6 F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
F test/tabfunc01.test d556af2def6af10b0a759b2f8a8f41135c2b634e F test/tabfunc01.test a12eba3f48a03a6626f985734ecc28132381fa9b
F test/table.test 33bf0d1fd07f304582695184b8e6feb017303816 F test/table.test 33bf0d1fd07f304582695184b8e6feb017303816
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1256,7 +1260,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9 F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test f44014f78d7650fb4bfb8ef96a5e4dc8f25eb083 F test/view.test 3930ae94042d702ab15a6a0ef692cfa5c9f9b68b
F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
@@ -1280,7 +1284,7 @@ F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
F test/wal3.test 2b5445e5da44780b9b44712f5a38523f7aeb0941 F test/wal3.test 2b5445e5da44780b9b44712f5a38523f7aeb0941
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c
F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e F test/wal6.test 4421cd5a2fa99d29cc91ef12fb23bed171ed3a4c
F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216 F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216
@@ -1303,7 +1307,7 @@ F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test 1ff3d9f8da0a6c0dc5ccfd38d9225b2cdb5b6afb F test/where.test 1ff3d9f8da0a6c0dc5ccfd38d9225b2cdb5b6afb
F test/where2.test 23fdb5d8e756554aad4ca7ae03de9dd8367a2c6e F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
F test/where4.test 68aa5ad796e33816db2078bc0f6de719c7a0e21f F test/where4.test 68aa5ad796e33816db2078bc0f6de719c7a0e21f
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
@@ -1329,7 +1333,7 @@ F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/with1.test a1e8660be88e2eb4648f8860f831d1e38b5b5443 F test/with1.test a1e8660be88e2eb4648f8860f831d1e38b5b5443
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775 F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991 F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701 F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1340,7 +1344,7 @@ F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
F tool/build-all-msvc.bat 60dbf6021d3de0a98575f6dfe4e12bd80b3edcf0 x F tool/build-all-msvc.bat 761d8c82a1a529261291812732a853a1b4256d85 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
@@ -1396,7 +1400,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 0298a9a780695b666e7c683700d9f2f889d6f826 64d13339d44d1b7ec6768a33421f2138cb7872d8 P e9196d566690de0e9815f8cd85be7844322b5a79 1da60c3dda4254620052a83c853c2d2b6dd5009f
R 68454f4230fc116d30b90969f8a680d7 R f39b8d67fa472811f667c334c4e1ce72
U drh U drh
Z c9e6b5cac5d4ca7f98b94a1f656dcb53 Z 760ecb4a8ede1ee2af06746289d94396

View File

@@ -1 +1 @@
e9196d566690de0e9815f8cd85be7844322b5a79 cb77236673e30af1e8749d984dedecc8f901b255

View File

@@ -356,7 +356,7 @@ Table *sqlite3LocateTable(
p = sqlite3FindTable(pParse->db, zName, zDbase); p = sqlite3FindTable(pParse->db, zName, zDbase);
if( p==0 ){ if( p==0 ){
const char *zMsg = isView ? "no such view" : "no such table"; const char *zMsg = isView ? "no such view" : "no such table";
#ifndef SQLITE_OMIT_VIRTUAL_TABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
/* If zName is the not the name of a table in the schema created using /* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that ** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */ ** can be an eponymous virtual table. */
@@ -640,9 +640,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
sqlite3DbFree(db, pTable->zName); sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff); sqlite3DbFree(db, pTable->zColAff);
sqlite3SelectDelete(db, pTable->pSelect); sqlite3SelectDelete(db, pTable->pSelect);
#ifndef SQLITE_OMIT_CHECK
sqlite3ExprListDelete(db, pTable->pCheck); sqlite3ExprListDelete(db, pTable->pCheck);
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3VtabClear(db, pTable); sqlite3VtabClear(db, pTable);
#endif #endif
@@ -1310,8 +1308,11 @@ void sqlite3AddPrimaryKey(
}else{ }else{
nTerm = pList->nExpr; nTerm = pList->nExpr;
for(i=0; i<nTerm; i++){ for(i=0; i<nTerm; i++){
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
if( pCExpr && pCExpr->op==TK_ID ){
const char *zCName = pCExpr->u.zToken;
for(iCol=0; iCol<pTab->nCol; iCol++){ for(iCol=0; iCol<pTab->nCol; iCol++){
if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
zType = pTab->aCol[iCol].zType; zType = pTab->aCol[iCol].zType;
break; break;
@@ -1319,9 +1320,10 @@ void sqlite3AddPrimaryKey(
} }
} }
} }
}
if( nTerm==1 if( nTerm==1
&& zType && sqlite3StrICmp(zType, "INTEGER")==0 && zType && sqlite3StrICmp(zType, "INTEGER")==0
&& sortOrder==SQLITE_SO_ASC && sortOrder!=SQLITE_SO_DESC
){ ){
pTab->iPKey = iCol; pTab->iPKey = iCol;
pTab->keyConf = (u8)onError; pTab->keyConf = (u8)onError;
@@ -1696,10 +1698,12 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
*/ */
if( pTab->iPKey>=0 ){ if( pTab->iPKey>=0 ){
ExprList *pList; ExprList *pList;
pList = sqlite3ExprListAppend(pParse, 0, 0); Token ipkToken;
ipkToken.z = pTab->aCol[pTab->iPKey].zName;
ipkToken.n = sqlite3Strlen30(ipkToken.z);
pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
if( pList==0 ) return; if( pList==0 ) return;
pList->a[0].zName = sqlite3DbStrDup(pParse->db,
pTab->aCol[pTab->iPKey].zName);
pList->a[0].sortOrder = pParse->iPkSortOrder; pList->a[0].sortOrder = pParse->iPkSortOrder;
assert( pParse->pNewTable==pTab ); assert( pParse->pNewTable==pTab );
pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
@@ -2056,6 +2060,7 @@ void sqlite3CreateView(
Token *pBegin, /* The CREATE token that begins the statement */ Token *pBegin, /* The CREATE token that begins the statement */
Token *pName1, /* The token that holds the name of the view */ Token *pName1, /* The token that holds the name of the view */
Token *pName2, /* The token that holds the name of the view */ Token *pName2, /* The token that holds the name of the view */
ExprList *pCNames, /* Optional list of view column names */
Select *pSelect, /* A SELECT statement that will become the new view */ Select *pSelect, /* A SELECT statement that will become the new view */
int isTemp, /* TRUE for a TEMPORARY view */ int isTemp, /* TRUE for a TEMPORARY view */
int noErr /* Suppress error messages if VIEW already exists */ int noErr /* Suppress error messages if VIEW already exists */
@@ -2076,17 +2081,11 @@ void sqlite3CreateView(
} }
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable; p = pParse->pNewTable;
if( p==0 || pParse->nErr ){ if( p==0 || pParse->nErr ) goto create_view_fail;
sqlite3SelectDelete(db, pSelect);
return;
}
sqlite3TwoPartName(pParse, pName1, pName2, &pName); sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema); iDb = sqlite3SchemaToIndex(db, p->pSchema);
sqlite3FixInit(&sFix, pParse, iDb, "view", pName); sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
if( sqlite3FixSelect(&sFix, pSelect) ){ if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
sqlite3SelectDelete(db, pSelect);
return;
}
/* Make a copy of the entire SELECT statement that defines the view. /* Make a copy of the entire SELECT statement that defines the view.
** This will force all the Expr.token.z values to be dynamically ** This will force all the Expr.token.z values to be dynamically
@@ -2094,27 +2093,31 @@ void sqlite3CreateView(
** they will persist after the current sqlite3_exec() call returns. ** they will persist after the current sqlite3_exec() call returns.
*/ */
p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
sqlite3SelectDelete(db, pSelect); p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
if( db->mallocFailed ){ if( db->mallocFailed ) goto create_view_fail;
return;
}
/* Locate the end of the CREATE VIEW statement. Make sEnd point to /* Locate the end of the CREATE VIEW statement. Make sEnd point to
** the end. ** the end.
*/ */
sEnd = pParse->sLastToken; sEnd = pParse->sLastToken;
if( ALWAYS(sEnd.z[0]!=0) && sEnd.z[0]!=';' ){ assert( sEnd.z[0]!=0 );
if( sEnd.z[0]!=';' ){
sEnd.z += sEnd.n; sEnd.z += sEnd.n;
} }
sEnd.n = 0; sEnd.n = 0;
n = (int)(sEnd.z - pBegin->z); n = (int)(sEnd.z - pBegin->z);
assert( n>0 );
z = pBegin->z; z = pBegin->z;
while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; } while( sqlite3Isspace(z[n-1]) ){ n--; }
sEnd.z = &z[n-1]; sEnd.z = &z[n-1];
sEnd.n = 1; sEnd.n = 1;
/* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
sqlite3EndTable(pParse, 0, &sEnd, 0, 0); sqlite3EndTable(pParse, 0, &sEnd, 0, 0);
create_view_fail:
sqlite3SelectDelete(db, pSelect);
sqlite3ExprListDelete(db, pCNames);
return; return;
} }
#endif /* SQLITE_OMIT_VIEW */ #endif /* SQLITE_OMIT_VIEW */
@@ -2132,6 +2135,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
int n; /* Temporarily holds the number of cursors assigned */ int n; /* Temporarily holds the number of cursors assigned */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */
sqlite3_xauth xAuth; /* Saved xAuth pointer */ sqlite3_xauth xAuth; /* Saved xAuth pointer */
u8 bEnabledLA; /* Saved db->lookaside.bEnabled state */
assert( pTable ); assert( pTable );
@@ -2177,9 +2181,14 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** statement that defines the view. ** statement that defines the view.
*/ */
assert( pTable->pSelect ); assert( pTable->pSelect );
bEnabledLA = db->lookaside.bEnabled;
if( pTable->pCheck ){
db->lookaside.bEnabled = 0;
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
}else{
pSel = sqlite3SelectDup(db, pTable->pSelect, 0); pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){ if( pSel ){
u8 enableLookaside = db->lookaside.bEnabled;
n = pParse->nTab; n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc); sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1; pTable->nCol = -1;
@@ -2192,7 +2201,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
#else #else
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
#endif #endif
db->lookaside.bEnabled = enableLookaside;
pParse->nTab = n; pParse->nTab = n;
if( pSelTab ){ if( pSelTab ){
assert( pTable->aCol==0 ); assert( pTable->aCol==0 );
@@ -2202,7 +2210,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pSelTab->aCol = 0; pSelTab->aCol = 0;
sqlite3DeleteTable(db, pSelTab); sqlite3DeleteTable(db, pSelTab);
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
pTable->pSchema->schemaFlags |= DB_UnresetViews;
}else{ }else{
pTable->nCol = 0; pTable->nCol = 0;
nErr++; nErr++;
@@ -2211,6 +2218,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
} else { } else {
nErr++; nErr++;
} }
}
db->lookaside.bEnabled = bEnabledLA;
pTable->pSchema->schemaFlags |= DB_UnresetViews;
#endif /* SQLITE_OMIT_VIEW */ #endif /* SQLITE_OMIT_VIEW */
return nErr; return nErr;
} }
@@ -3034,11 +3044,16 @@ Index *sqlite3CreateIndex(
** So create a fake list to simulate this. ** So create a fake list to simulate this.
*/ */
if( pList==0 ){ if( pList==0 ){
pList = sqlite3ExprListAppend(pParse, 0, 0); Token prevCol;
prevCol.z = pTab->aCol[pTab->nCol-1].zName;
prevCol.n = sqlite3Strlen30(prevCol.z);
pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
if( pList==0 ) goto exit_create_index; if( pList==0 ) goto exit_create_index;
pList->a[0].zName = sqlite3DbStrDup(pParse->db, assert( pList->nExpr==1 );
pTab->aCol[pTab->nCol-1].zName); sqlite3ExprListSetSortOrder(pList, sortOrder);
pList->a[0].sortOrder = (u8)sortOrder; }else{
sqlite3ExprListCheckLength(pParse, pList, "index");
} }
/* Figure out how many bytes of space are required to store explicitly /* Figure out how many bytes of space are required to store explicitly
@@ -3046,8 +3061,7 @@ Index *sqlite3CreateIndex(
*/ */
for(i=0; i<pList->nExpr; i++){ for(i=0; i<pList->nExpr; i++){
Expr *pExpr = pList->a[i].pExpr; Expr *pExpr = pList->a[i].pExpr;
if( pExpr ){ if( pExpr && pExpr->op==TK_COLLATE ){
assert( pExpr->op==TK_COLLATE );
nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken)); nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
} }
} }
@@ -3099,10 +3113,17 @@ Index *sqlite3CreateIndex(
** break backwards compatibility - it needs to be a warning. ** break backwards compatibility - it needs to be a warning.
*/ */
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
const char *zColName = pListItem->zName; const char *zColName;
Expr *pCExpr;
int requestedSortOrder; int requestedSortOrder;
char *zColl; /* Collation sequence name */ char *zColl; /* Collation sequence name */
pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr);
if( pCExpr->op!=TK_ID ){
sqlite3ErrorMsg(pParse, "indexes on expressions not yet supported");
continue;
}
zColName = pCExpr->u.zToken;
for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
} }
@@ -3114,9 +3135,8 @@ Index *sqlite3CreateIndex(
} }
assert( j<=0x7fff ); assert( j<=0x7fff );
pIndex->aiColumn[i] = (i16)j; pIndex->aiColumn[i] = (i16)j;
if( pListItem->pExpr ){ if( pListItem->pExpr->op==TK_COLLATE ){
int nColl; int nColl;
assert( pListItem->pExpr->op==TK_COLLATE );
zColl = pListItem->pExpr->u.zToken; zColl = pListItem->pExpr->u.zToken;
nColl = sqlite3Strlen30(zColl) + 1; nColl = sqlite3Strlen30(zColl) + 1;
assert( nExtra>=nColl ); assert( nExtra>=nColl );
@@ -4329,7 +4349,7 @@ With *sqlite3WithAdd(
pNew->a[pNew->nCte].pSelect = pQuery; pNew->a[pNew->nCte].pSelect = pQuery;
pNew->a[pNew->nCte].pCols = pArglist; pNew->a[pNew->nCte].pCols = pArglist;
pNew->a[pNew->nCte].zName = zName; pNew->a[pNew->nCte].zName = zName;
pNew->a[pNew->nCte].zErr = 0; pNew->a[pNew->nCte].zCteErr = 0;
pNew->nCte++; pNew->nCte++;
} }

View File

@@ -450,7 +450,7 @@ void sqlite3DeleteFrom(
iKey = ++pParse->nMem; iKey = ++pParse->nMem;
nKey = 0; /* Zero tells OP_Found to use a composite key */ nKey = 0; /* Zero tells OP_Found to use a composite key */
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
sqlite3IndexAffinityStr(v, pPk), nPk); sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
}else{ }else{
/* Get the rowid of the row to be deleted and remember it in the RowSet */ /* Get the rowid of the row to be deleted and remember it in the RowSet */

View File

@@ -433,7 +433,7 @@ void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
** is responsible for making sure the node eventually gets freed. ** is responsible for making sure the node eventually gets freed.
** **
** If dequote is true, then the token (if it exists) is dequoted. ** If dequote is true, then the token (if it exists) is dequoted.
** If dequote is false, no dequoting is performance. The deQuote ** If dequote is false, no dequoting is performed. The deQuote
** parameter is ignored if pToken is NULL or if the token does not ** parameter is ignored if pToken is NULL or if the token does not
** appear to be quoted. If the quotes were of the form "..." (double-quotes) ** appear to be quoted. If the quotes were of the form "..." (double-quotes)
** then the EP_DblQuoted flag is set on the expression node. ** then the EP_DblQuoted flag is set on the expression node.
@@ -1160,6 +1160,20 @@ no_mem:
return 0; return 0;
} }
/*
** Set the sort order for the last element on the given ExprList.
*/
void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){
if( p==0 ) return;
assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 );
assert( p->nExpr>0 );
if( iSortOrder<0 ){
assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC );
return;
}
p->a[p->nExpr-1].sortOrder = (u8)iSortOrder;
}
/* /*
** Set the ExprList.a[].zName element of the most recently added item ** Set the ExprList.a[].zName element of the most recently added item
** on the expression list. ** on the expression list.
@@ -2898,7 +2912,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
} }
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCodeExprList(pParse, pFarg, r1, sqlite3ExprCodeExprList(pParse, pFarg, r1, 0,
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
}else{ }else{
@@ -3314,11 +3328,13 @@ int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */ Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */ ExprList *pList, /* The expression list to be coded */
int target, /* Where to write results */ int target, /* Where to write results */
int srcReg, /* Source registers if SQLITE_ECEL_REF */
u8 flags /* SQLITE_ECEL_* flags */ u8 flags /* SQLITE_ECEL_* flags */
){ ){
struct ExprList_item *pItem; struct ExprList_item *pItem;
int i, n; int i, j, n;
u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy; u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
Vdbe *v = pParse->pVdbe;
assert( pList!=0 ); assert( pList!=0 );
assert( target>0 ); assert( target>0 );
assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
@@ -3326,13 +3342,14 @@ int sqlite3ExprCodeExprList(
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; i<n; i++, pItem++){ for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr; Expr *pExpr = pItem->pExpr;
if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
}else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
}else{ }else{
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
if( inReg!=target+i ){ if( inReg!=target+i ){
VdbeOp *pOp; VdbeOp *pOp;
Vdbe *v = pParse->pVdbe;
if( copyOp==OP_Copy if( copyOp==OP_Copy
&& (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
&& pOp->p1+pOp->p3+1==inReg && pOp->p1+pOp->p3+1==inReg

View File

@@ -416,7 +416,7 @@ static void fkLookupParent(
} }
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,
sqlite3IndexAffinityStr(v,pIdx), nCol); sqlite3IndexAffinityStr(pParse->db,pIdx), nCol);
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regRec);

View File

@@ -69,7 +69,7 @@ void sqlite3OpenTable(
** is managed along with the rest of the Index structure. It will be ** is managed along with the rest of the Index structure. It will be
** released when sqlite3DeleteIndex() is called. ** released when sqlite3DeleteIndex() is called.
*/ */
const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
if( !pIdx->zColAff ){ if( !pIdx->zColAff ){
/* The first time a column affinity string for a particular index is /* The first time a column affinity string for a particular index is
** required, it is allocated and populated here. It is then stored as ** required, it is allocated and populated here. It is then stored as
@@ -81,7 +81,6 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
*/ */
int n; int n;
Table *pTab = pIdx->pTable; Table *pTab = pIdx->pTable;
sqlite3 *db = sqlite3VdbeDb(v);
pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
if( !pIdx->zColAff ){ if( !pIdx->zColAff ){
db->mallocFailed = 1; db->mallocFailed = 1;
@@ -705,11 +704,13 @@ void sqlite3Insert(
sNC.pParse = pParse; sNC.pParse = pParse;
srcTab = -1; srcTab = -1;
assert( useTempTable==0 ); assert( useTempTable==0 );
nColumn = pList ? pList->nExpr : 0; if( pList ){
for(i=0; i<nColumn; i++){ nColumn = pList->nExpr;
if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){ if( sqlite3ResolveExprListNames(&sNC, pList) ){
goto insert_cleanup; goto insert_cleanup;
} }
}else{
nColumn = 0;
} }
} }

View File

@@ -301,7 +301,7 @@ ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
{sqlite3AddPrimaryKey(pParse,0,R,I,Z);} {sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);}
ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X.pExpr);} ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X.pExpr);}
ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
{sqlite3CreateForeignKey(pParse,0,&T,TA,R);} {sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);} ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);}
@@ -345,14 +345,14 @@ conslist ::= tcons.
tconscomma ::= COMMA. {pParse->constraintName.n = 0;} tconscomma ::= COMMA. {pParse->constraintName.n = 0;}
tconscomma ::= . tconscomma ::= .
tcons ::= CONSTRAINT nm(X). {pParse->constraintName = X;} tcons ::= CONSTRAINT nm(X). {pParse->constraintName = X;}
tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP onconf(R).
{sqlite3AddPrimaryKey(pParse,X,R,I,0);} {sqlite3AddPrimaryKey(pParse,X,R,I,0);}
tcons ::= UNIQUE LP idxlist(X) RP onconf(R). tcons ::= UNIQUE LP sortlist(X) RP onconf(R).
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);} {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);}
tcons ::= CHECK LP expr(E) RP onconf. tcons ::= CHECK LP expr(E) RP onconf.
{sqlite3AddCheckConstraint(pParse,E.pExpr);} {sqlite3AddCheckConstraint(pParse,E.pExpr);}
tcons ::= FOREIGN KEY LP idxlist(FA) RP tcons ::= FOREIGN KEY LP eidlist(FA) RP
REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
sqlite3CreateForeignKey(pParse, FA, &T, TA, R); sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
sqlite3DeferForeignKey(pParse, D); sqlite3DeferForeignKey(pParse, D);
} }
@@ -386,8 +386,9 @@ ifexists(A) ::= . {A = 0;}
///////////////////// The CREATE VIEW statement ///////////////////////////// ///////////////////// The CREATE VIEW statement /////////////////////////////
// //
%ifndef SQLITE_OMIT_VIEW %ifndef SQLITE_OMIT_VIEW
cmd ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) AS select(S). { cmd ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) eidlist_opt(C)
sqlite3CreateView(pParse, &X, &Y, &Z, S, T, E); AS select(S). {
sqlite3CreateView(pParse, &X, &Y, &Z, C, S, T, E);
} }
cmd ::= DROP VIEW ifexists(E) fullname(X). { cmd ::= DROP VIEW ifexists(E) fullname(X). {
sqlite3DropTable(pParse, X, 1, E); sqlite3DropTable(pParse, X, 1, E);
@@ -673,6 +674,11 @@ using_opt(U) ::= . {U = 0;}
%type orderby_opt {ExprList*} %type orderby_opt {ExprList*}
%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);} %destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);}
// the sortlist non-terminal stores a list of expression where each
// expression is optionally followed by ASC or DESC to indicate the
// sort order.
//
%type sortlist {ExprList*} %type sortlist {ExprList*}
%destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);} %destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);}
@@ -680,18 +686,18 @@ orderby_opt(A) ::= . {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). { sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {
A = sqlite3ExprListAppend(pParse,X,Y.pExpr); A = sqlite3ExprListAppend(pParse,X,Y.pExpr);
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; sqlite3ExprListSetSortOrder(A,Z);
} }
sortlist(A) ::= expr(Y) sortorder(Z). { sortlist(A) ::= expr(Y) sortorder(Z). {
A = sqlite3ExprListAppend(pParse,0,Y.pExpr); A = sqlite3ExprListAppend(pParse,0,Y.pExpr);
if( A && ALWAYS(A->a) ) A->a[0].sortOrder = (u8)Z; sqlite3ExprListSetSortOrder(A,Z);
} }
%type sortorder {int} %type sortorder {int}
sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;} sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;}
sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;} sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;}
sortorder(A) ::= . {A = SQLITE_SO_ASC;} sortorder(A) ::= . {A = SQLITE_SO_UNDEFINED;}
%type groupby_opt {ExprList*} %type groupby_opt {ExprList*}
%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);} %destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
@@ -784,11 +790,11 @@ setlist(A) ::= nm(X) EQ expr(Y). {
////////////////////////// The INSERT command ///////////////////////////////// ////////////////////////// The INSERT command /////////////////////////////////
// //
cmd ::= with(W) insert_cmd(R) INTO fullname(X) inscollist_opt(F) select(S). { cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) select(S). {
sqlite3WithPush(pParse, W, 1); sqlite3WithPush(pParse, W, 1);
sqlite3Insert(pParse, X, S, F, R); sqlite3Insert(pParse, X, S, F, R);
} }
cmd ::= with(W) insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES. cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) DEFAULT VALUES.
{ {
sqlite3WithPush(pParse, W, 1); sqlite3WithPush(pParse, W, 1);
sqlite3Insert(pParse, X, 0, F, R); sqlite3Insert(pParse, X, 0, F, R);
@@ -798,13 +804,13 @@ cmd ::= with(W) insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES.
insert_cmd(A) ::= INSERT orconf(R). {A = R;} insert_cmd(A) ::= INSERT orconf(R). {A = R;}
insert_cmd(A) ::= REPLACE. {A = OE_Replace;} insert_cmd(A) ::= REPLACE. {A = OE_Replace;}
%type inscollist_opt {IdList*} %type idlist_opt {IdList*}
%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);} %destructor idlist_opt {sqlite3IdListDelete(pParse->db, $$);}
%type idlist {IdList*} %type idlist {IdList*}
%destructor idlist {sqlite3IdListDelete(pParse->db, $$);} %destructor idlist {sqlite3IdListDelete(pParse->db, $$);}
inscollist_opt(A) ::= . {A = 0;} idlist_opt(A) ::= . {A = 0;}
inscollist_opt(A) ::= LP idlist(X) RP. {A = X;} idlist_opt(A) ::= LP idlist(X) RP. {A = X;}
idlist(A) ::= idlist(X) COMMA nm(Y). idlist(A) ::= idlist(X) COMMA nm(Y).
{A = sqlite3IdListAppend(pParse->db,X,&Y);} {A = sqlite3IdListAppend(pParse->db,X,&Y);}
idlist(A) ::= nm(Y). idlist(A) ::= nm(Y).
@@ -1207,7 +1213,7 @@ nexprlist(A) ::= expr(Y).
///////////////////////////// The CREATE INDEX command /////////////////////// ///////////////////////////// The CREATE INDEX command ///////////////////////
// //
cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D) cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
ON nm(Y) LP idxlist(Z) RP where_opt(W). { ON nm(Y) LP sortlist(Z) RP where_opt(W). {
sqlite3CreateIndex(pParse, &X, &D, sqlite3CreateIndex(pParse, &X, &D,
sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U, sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U,
&S, W, SQLITE_SO_ASC, NE); &S, W, SQLITE_SO_ASC, NE);
@@ -1217,31 +1223,64 @@ cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
uniqueflag(A) ::= UNIQUE. {A = OE_Abort;} uniqueflag(A) ::= UNIQUE. {A = OE_Abort;}
uniqueflag(A) ::= . {A = OE_None;} uniqueflag(A) ::= . {A = OE_None;}
%type idxlist {ExprList*}
%destructor idxlist {sqlite3ExprListDelete(pParse->db, $$);}
%type idxlist_opt {ExprList*}
%destructor idxlist_opt {sqlite3ExprListDelete(pParse->db, $$);}
idxlist_opt(A) ::= . {A = 0;} // The eidlist non-terminal (Expression Id List) generates an ExprList
idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} // from a list of identifiers. The identifier names are in ExprList.a[].zName.
idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). { // This list is stored in an ExprList rather than an IdList so that it
Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); // can be easily sent to sqlite3ColumnsExprList().
A = sqlite3ExprListAppend(pParse,X, p); //
sqlite3ExprListSetName(pParse,A,&Y,1); // eidlist is grouped with CREATE INDEX because it used to be the non-terminal
sqlite3ExprListCheckLength(pParse, A, "index"); // used for the arguments to an index. That is just an historical accident.
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; //
// IMPORTANT COMPATIBILITY NOTE: Some prior versions of SQLite accepted
// COLLATE clauses and ASC or DESC keywords on ID lists in inappropriate
// places - places that might have been stored in the sqlite_master schema.
// Those extra features were ignored. But because they might be in some
// (busted) old databases, we need to continue parsing them when loading
// historical schemas.
//
%type eidlist {ExprList*}
%destructor eidlist {sqlite3ExprListDelete(pParse->db, $$);}
%type eidlist_opt {ExprList*}
%destructor eidlist_opt {sqlite3ExprListDelete(pParse->db, $$);}
%include {
/* Add a single new term to an ExprList that is used to store a
** list of identifiers. Report an error if the ID list contains
** a COLLATE clause or an ASC or DESC keyword, except ignore the
** error while parsing a legacy schema.
*/
static ExprList *parserAddExprIdListTerm(
Parse *pParse,
ExprList *pPrior,
Token *pIdToken,
int hasCollate,
int sortOrder
){
ExprList *p = sqlite3ExprListAppend(pParse, pPrior, 0);
if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED)
&& pParse->db->init.busy==0
){
sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"",
pIdToken->n, pIdToken->z);
}
sqlite3ExprListSetName(pParse, p, pIdToken, 1);
return p;
}
} // end %include
eidlist_opt(A) ::= . {A = 0;}
eidlist_opt(A) ::= LP eidlist(X) RP. {A = X;}
eidlist(A) ::= eidlist(X) COMMA nm(Y) collate(C) sortorder(Z). {
A = parserAddExprIdListTerm(pParse, X, &Y, C, Z);
} }
idxlist(A) ::= nm(Y) collate(C) sortorder(Z). { eidlist(A) ::= nm(Y) collate(C) sortorder(Z). {
Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z);
A = sqlite3ExprListAppend(pParse,0, p);
sqlite3ExprListSetName(pParse, A, &Y, 1);
sqlite3ExprListCheckLength(pParse, A, "index");
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
} }
%type collate {Token} %type collate {int}
collate(C) ::= . {C.z = 0; C.n = 0;} collate(C) ::= . {C = 0;}
collate(C) ::= COLLATE ids(X). {C = X;} collate(C) ::= COLLATE ids. {C = 1;}
///////////////////////////// The DROP INDEX command ///////////////////////// ///////////////////////////// The DROP INDEX command /////////////////////////
@@ -1369,7 +1408,7 @@ trigger_cmd(A) ::=
{ A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); } { A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); }
// INSERT // INSERT
trigger_cmd(A) ::= insert_cmd(R) INTO trnm(X) inscollist_opt(F) select(S). trigger_cmd(A) ::= insert_cmd(R) INTO trnm(X) idlist_opt(F) select(S).
{A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);} {A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);}
// DELETE // DELETE
@@ -1489,10 +1528,10 @@ with(A) ::= . {A = 0;}
with(A) ::= WITH wqlist(W). { A = W; } with(A) ::= WITH wqlist(W). { A = W; }
with(A) ::= WITH RECURSIVE wqlist(W). { A = W; } with(A) ::= WITH RECURSIVE wqlist(W). { A = W; }
wqlist(A) ::= nm(X) idxlist_opt(Y) AS LP select(Z) RP. { wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
A = sqlite3WithAdd(pParse, 0, &X, Y, Z); A = sqlite3WithAdd(pParse, 0, &X, Y, Z);
} }
wqlist(A) ::= wqlist(W) COMMA nm(X) idxlist_opt(Y) AS LP select(Z) RP. { wqlist(A) ::= wqlist(W) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
A = sqlite3WithAdd(pParse, W, &X, Y, Z); A = sqlite3WithAdd(pParse, W, &X, Y, Z);
} }
%endif SQLITE_OMIT_CTE %endif SQLITE_OMIT_CTE

View File

@@ -65,7 +65,7 @@
** that is allocated when the page cache is created. The size of the local ** that is allocated when the page cache is created. The size of the local
** bulk allocation can be adjusted using ** bulk allocation can be adjusted using
** **
** sqlite3_config(SQLITE_CONFIG_PCACHE, 0, 0, N). ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, N).
** **
** If N is positive, then N pages worth of memory are allocated using a single ** If N is positive, then N pages worth of memory are allocated using a single
** sqlite3Malloc() call and that memory is used for the first N pages allocated. ** sqlite3Malloc() call and that memory is used for the first N pages allocated.

View File

@@ -1342,7 +1342,7 @@ void sqlite3Pragma(
} }
if( pParent ){ if( pParent ){
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
sqlite3IndexAffinityStr(v,pIdx), pFK->nCol); sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
VdbeCoverage(v); VdbeCoverage(v);
} }

View File

@@ -407,9 +407,9 @@ static int lookupName(
** resolved by the time the WHERE clause is resolved. ** resolved by the time the WHERE clause is resolved.
** **
** The ability to use an output result-set column in the WHERE, GROUP BY, ** The ability to use an output result-set column in the WHERE, GROUP BY,
** or HAVING clauses, or as part of a larger expression in the ORDRE BY ** or HAVING clauses, or as part of a larger expression in the ORDER BY
** clause is not standard SQL. This is a (goofy) SQLite extension, that ** clause is not standard SQL. This is a (goofy) SQLite extension, that
** is supported for backwards compatibility only. TO DO: Issue a warning ** is supported for backwards compatibility only. Hence, we issue a warning
** on sqlite3_log() whenever the capability is used. ** on sqlite3_log() whenever the capability is used.
*/ */
if( (pEList = pNC->pEList)!=0 if( (pEList = pNC->pEList)!=0
@@ -1507,7 +1507,6 @@ void sqlite3ResolveSelfReference(
){ ){
SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */
int i; /* Loop counter */
assert( type==NC_IsCheck || type==NC_PartIdx ); assert( type==NC_IsCheck || type==NC_PartIdx );
memset(&sNC, 0, sizeof(sNC)); memset(&sNC, 0, sizeof(sNC));
@@ -1520,11 +1519,5 @@ void sqlite3ResolveSelfReference(
sNC.pSrcList = &sSrc; sNC.pSrcList = &sSrc;
sNC.ncFlags = type; sNC.ncFlags = type;
if( sqlite3ResolveExprNames(&sNC, pExpr) ) return; if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
if( pList ){ if( pList ) sqlite3ResolveExprListNames(&sNC, pList);
for(i=0; i<pList->nExpr; i++){
if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
return;
}
}
}
} }

View File

@@ -496,6 +496,7 @@ static void pushOntoSorter(
SortCtx *pSort, /* Information about the ORDER BY clause */ SortCtx *pSort, /* Information about the ORDER BY clause */
Select *pSelect, /* The whole SELECT statement */ Select *pSelect, /* The whole SELECT statement */
int regData, /* First register holding data to be sorted */ int regData, /* First register holding data to be sorted */
int regOrigData, /* First register holding data before packing */
int nData, /* Number of elements in the data array */ int nData, /* Number of elements in the data array */
int nPrefixReg /* No. of reg prior to regData available for use */ int nPrefixReg /* No. of reg prior to regData available for use */
){ ){
@@ -509,6 +510,7 @@ static void pushOntoSorter(
int op; /* Opcode to add sorter record to sorter */ int op; /* Opcode to add sorter record to sorter */
assert( bSeq==0 || bSeq==1 ); assert( bSeq==0 || bSeq==1 );
assert( nData==1 || regData==regOrigData );
if( nPrefixReg ){ if( nPrefixReg ){
assert( nPrefixReg==nExpr+bSeq ); assert( nPrefixReg==nExpr+bSeq );
regBase = regData - nExpr - bSeq; regBase = regData - nExpr - bSeq;
@@ -516,7 +518,8 @@ static void pushOntoSorter(
regBase = pParse->nMem + 1; regBase = pParse->nMem + 1;
pParse->nMem += nBase; pParse->nMem += nBase;
} }
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, SQLITE_ECEL_DUP); sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
if( bSeq ){ if( bSeq ){
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
} }
@@ -726,7 +729,7 @@ static void selectInnerLoop(
}else{ }else{
ecelFlags = 0; ecelFlags = 0;
} }
sqlite3ExprCodeExprList(pParse, pEList, regResult, ecelFlags); sqlite3ExprCodeExprList(pParse, pEList, regResult, 0, ecelFlags);
} }
/* If the DISTINCT keyword was present on the SELECT statement /* If the DISTINCT keyword was present on the SELECT statement
@@ -842,7 +845,7 @@ static void selectInnerLoop(
} }
#endif #endif
if( pSort ){ if( pSort ){
pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, 1, nPrefixReg); pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg);
}else{ }else{
int r2 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
@@ -868,7 +871,7 @@ static void selectInnerLoop(
** ORDER BY in this case since the order of entries in the set ** ORDER BY in this case since the order of entries in the set
** does not matter. But there might be a LIMIT clause, in which ** does not matter. But there might be a LIMIT clause, in which
** case the order does matter */ ** case the order does matter */
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg); pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg);
}else{ }else{
int r1 = sqlite3GetTempReg(pParse); int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
@@ -894,7 +897,7 @@ static void selectInnerLoop(
case SRT_Mem: { case SRT_Mem: {
assert( nResultCol==1 ); assert( nResultCol==1 );
if( pSort ){ if( pSort ){
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg); pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg);
}else{ }else{
assert( regResult==iParm ); assert( regResult==iParm );
/* The LIMIT clause will jump out of the loop for us */ /* The LIMIT clause will jump out of the loop for us */
@@ -908,7 +911,8 @@ static void selectInnerLoop(
testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output ); testcase( eDest==SRT_Output );
if( pSort ){ if( pSort ){
pushOntoSorter(pParse, pSort, p, regResult, nResultCol, nPrefixReg); pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol,
nPrefixReg);
}else if( eDest==SRT_Coroutine ){ }else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}else{ }else{
@@ -1587,7 +1591,7 @@ static void generateColumnNames(
** Return SQLITE_OK on success. If a memory allocation error occurs, ** Return SQLITE_OK on success. If a memory allocation error occurs,
** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. ** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
*/ */
static int selectColumnsFromExprList( int sqlite3ColumnsFromExprList(
Parse *pParse, /* Parsing context */ Parse *pParse, /* Parsing context */
ExprList *pEList, /* Expr list from which to derive column names */ ExprList *pEList, /* Expr list from which to derive column names */
i16 *pnCol, /* Write the number of columns here */ i16 *pnCol, /* Write the number of columns here */
@@ -1754,7 +1758,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
pTab->nRef = 1; pTab->nRef = 1;
pTab->zName = 0; pTab->zName = 0;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
selectAddColumnTypeAndCollation(pParse, pTab, pSelect); selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
pTab->iPKey = -1; pTab->iPKey = -1;
if( db->mallocFailed ){ if( db->mallocFailed ){
@@ -3757,6 +3761,9 @@ static int flattenSubquery(
** enforces this restriction since this routine does not have enough ** enforces this restriction since this routine does not have enough
** information to know.) ** information to know.)
** **
** (5) The WHERE clause expression originates in the ON or USING clause
** of a LEFT JOIN.
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause ** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery. ** terms are duplicated into the subquery.
*/ */
@@ -3779,6 +3786,7 @@ static int pushDownWhereTerms(
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor); nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft; pWhere = pWhere->pLeft;
} }
if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++; nChng++;
while( pSubq ){ while( pSubq ){
@@ -4049,12 +4057,12 @@ static int withExpand(
int bMayRecursive; /* True if compound joined by UNION [ALL] */ int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */ With *pSavedWith; /* Initial value of pParse->pWith */
/* If pCte->zErr is non-NULL at this point, then this is an illegal /* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return ** recursive reference to CTE pCte. Leave an error in pParse and return
** early. If pCte->zErr is NULL, then this is not a recursive reference. ** early. If pCte->zCteErr is NULL, then this is not a recursive reference.
** In this case, proceed. */ ** In this case, proceed. */
if( pCte->zErr ){ if( pCte->zCteErr ){
sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName); sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName);
return SQLITE_ERROR; return SQLITE_ERROR;
} }
@@ -4099,7 +4107,7 @@ static int withExpand(
} }
assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 )); assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 ));
pCte->zErr = "circular reference: %s"; pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith; pSavedWith = pParse->pWith;
pParse->pWith = pWith; pParse->pWith = pWith;
sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
@@ -4117,16 +4125,16 @@ static int withExpand(
pEList = pCte->pCols; pEList = pCte->pCols;
} }
selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol);
if( bMayRecursive ){ if( bMayRecursive ){
if( pSel->selFlags & SF_Recursive ){ if( pSel->selFlags & SF_Recursive ){
pCte->zErr = "multiple recursive references: %s"; pCte->zCteErr = "multiple recursive references: %s";
}else{ }else{
pCte->zErr = "recursive reference in a subquery: %s"; pCte->zCteErr = "recursive reference in a subquery: %s";
} }
sqlite3WalkSelect(pWalker, pSel); sqlite3WalkSelect(pWalker, pSel);
} }
pCte->zErr = 0; pCte->zCteErr = 0;
pParse->pWith = pSavedWith; pParse->pWith = pSavedWith;
} }
@@ -4240,7 +4248,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pTab->nRef = 1; pTab->nRef = 1;
pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
while( pSel->pPrior ){ pSel = pSel->pPrior; } while( pSel->pPrior ){ pSel = pSel->pPrior; }
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1; pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral; pTab->tabFlags |= TF_Ephemeral;
@@ -4663,7 +4671,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( pList ){ if( pList ){
nArg = pList->nExpr; nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg); regAgg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP); sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
}else{ }else{
nArg = 0; nArg = 0;
regAgg = 0; regAgg = 0;
@@ -5283,7 +5291,7 @@ int sqlite3Select(
} }
regBase = sqlite3GetTempRange(pParse, nCol); regBase = sqlite3GetTempRange(pParse, nCol);
sqlite3ExprCacheClear(pParse); sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
j = nGroupBy; j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){ for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i]; struct AggInfo_col *pCol = &sAggInfo.aCol[i];

View File

@@ -4900,6 +4900,13 @@ int SQLITE_CDECL main(int argc, char **argv){
} }
data.out = stdout; data.out = stdout;
#ifdef SQLITE_ENABLE_JSON1
{
extern int sqlite3_json_init(sqlite3*);
sqlite3_auto_extension((void(*)(void))sqlite3_json_init);
}
#endif
/* Go ahead and open the database file if it already exists. If the /* Go ahead and open the database file if it already exists. If the
** file does not exist, delay opening it. This prevents empty database ** file does not exist, delay opening it. This prevents empty database
** files from being created if a user mistypes the database name argument ** files from being created if a user mistypes the database name argument

View File

@@ -477,6 +477,7 @@ int sqlite3_exec(
#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) #define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))

View File

@@ -412,6 +412,7 @@ struct sqlite3_api_routines {
#define sqlite3_value_text16le sqlite3_api->value_text16le #define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type #define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf #define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function #define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 #define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2

View File

@@ -1533,6 +1533,7 @@ struct CollSeq {
*/ */
#define SQLITE_SO_ASC 0 /* Sort in ascending order */ #define SQLITE_SO_ASC 0 /* Sort in ascending order */
#define SQLITE_SO_DESC 1 /* Sort in ascending order */ #define SQLITE_SO_DESC 1 /* Sort in ascending order */
#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */
/* /*
** Column affinity types. ** Column affinity types.
@@ -1639,9 +1640,8 @@ struct Table {
Select *pSelect; /* NULL for tables. Points to definition if a view. */ Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */ FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */ char *zColAff; /* String defining the affinity of each column */
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */ ExprList *pCheck; /* All CHECK constraints */
#endif /* ... also used as column name list in a VIEW */
int tnum; /* Root BTree page for this table */ int tnum; /* Root BTree page for this table */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */ i16 nCol; /* Number of columns in this table */
@@ -3042,7 +3042,7 @@ struct With {
char *zName; /* Name of this CTE */ char *zName; /* Name of this CTE */
ExprList *pCols; /* List of explicit column names, or NULL */ ExprList *pCols; /* List of explicit column names, or NULL */
Select *pSelect; /* The definition of this CTE */ Select *pSelect; /* The definition of this CTE */
const char *zErr; /* Error message for circular references */ const char *zCteErr; /* Error message for circular references */
} a[1]; } a[1];
}; };
@@ -3256,6 +3256,7 @@ Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*); void sqlite3ExprAssignVarNumber(Parse*, Expr*);
void sqlite3ExprDelete(sqlite3*, Expr*); void sqlite3ExprDelete(sqlite3*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
void sqlite3ExprListDelete(sqlite3*, ExprList*); void sqlite3ExprListDelete(sqlite3*, ExprList*);
@@ -3269,6 +3270,7 @@ void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3BeginParse(Parse*,int); void sqlite3BeginParse(Parse*,int);
void sqlite3CommitInternalChanges(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*); void sqlite3DeleteColumnNames(sqlite3*,Table*);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
Table *sqlite3ResultSetOfSelect(Parse*,Select*); Table *sqlite3ResultSetOfSelect(Parse*,Select*);
void sqlite3OpenMasterTable(Parse *, int); void sqlite3OpenMasterTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*); Index *sqlite3PrimaryKeyIndex(Table*);
@@ -3310,7 +3312,7 @@ void sqlite3RowSetInsert(RowSet*, i64);
int sqlite3RowSetTest(RowSet*, int iBatch, i64); int sqlite3RowSetTest(RowSet*, int iBatch, i64);
int sqlite3RowSetNext(RowSet*, i64*); int sqlite3RowSetNext(RowSet*, i64*);
void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
int sqlite3ViewGetColumnNames(Parse*,Table*); int sqlite3ViewGetColumnNames(Parse*,Table*);
@@ -3386,9 +3388,10 @@ void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int); int sqlite3ExprCodeTarget(Parse*, Expr*, int);
void sqlite3ExprCodeAndCache(Parse*, Expr*, int); void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8); int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
#define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */
void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
@@ -3560,7 +3563,7 @@ int sqlite3VarintLen(u64 v);
#define putVarint sqlite3PutVarint #define putVarint sqlite3PutVarint
const char *sqlite3IndexAffinityStr(Vdbe *, Index *); const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
void sqlite3TableAffinity(Vdbe*, Table*, int); void sqlite3TableAffinity(Vdbe*, Table*, int);
char sqlite3CompareAffinity(Expr *pExpr, char aff2); char sqlite3CompareAffinity(Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);

View File

@@ -6377,6 +6377,7 @@ static int tclLoadStaticExtensionCmd(
extern int sqlite3_fileio_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_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_json_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
@@ -6398,6 +6399,7 @@ static int tclLoadStaticExtensionCmd(
{ "fileio", sqlite3_fileio_init }, { "fileio", sqlite3_fileio_init },
{ "fuzzer", sqlite3_fuzzer_init }, { "fuzzer", sqlite3_fuzzer_init },
{ "ieee754", sqlite3_ieee_init }, { "ieee754", sqlite3_ieee_init },
{ "json", sqlite3_json_init },
{ "nextchar", sqlite3_nextchar_init }, { "nextchar", sqlite3_nextchar_init },
{ "percentile", sqlite3_percentile_init }, { "percentile", sqlite3_percentile_init },
{ "regexp", sqlite3_regexp_init }, { "regexp", sqlite3_regexp_init },

View File

@@ -85,11 +85,18 @@ static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
*/ */
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0; int n = 0;
int cnt = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow); pView = sqlite3TreeViewPush(pView, moreToFollow);
do{
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x", sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags
); );
if( cnt++ ) sqlite3TreeViewPop(pView);
if( p->pPrior ){
n = 1000;
}else{
n = 0;
if( p->pSrc && p->pSrc->nSrc ) n++; if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++; if( p->pWhere ) n++;
if( p->pGroupBy ) n++; if( p->pGroupBy ) n++;
@@ -97,7 +104,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
if( p->pOrderBy ) n++; if( p->pOrderBy ) n++;
if( p->pLimit ) n++; if( p->pLimit ) n++;
if( p->pOffset ) n++; if( p->pOffset ) n++;
if( p->pPrior ) n++; }
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){ if( p->pSrc && p->pSrc->nSrc ){
int i; int i;
@@ -168,10 +175,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
case TK_INTERSECT: zOp = "INTERSECT"; break; case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break; case TK_EXCEPT: zOp = "EXCEPT"; break;
} }
sqlite3TreeViewItem(pView, zOp, (n--)>0); sqlite3TreeViewItem(pView, zOp, 1);
sqlite3TreeViewSelect(pView, p->pPrior, 0);
sqlite3TreeViewPop(pView);
} }
p = p->pPrior;
}while( p!=0 );
sqlite3TreeViewPop(pView); sqlite3TreeViewPop(pView);
} }
@@ -425,7 +432,13 @@ void sqlite3TreeViewExprList(
}else{ }else{
sqlite3TreeViewLine(pView, "%s", zLabel); sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){ for(i=0; i<pList->nExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
if( j ){
sqlite3TreeViewPush(pView, 0);
sqlite3TreeViewLine(pView, "iOrderByCol=%d", j);
}
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1); sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
if( j ) sqlite3TreeViewPop(pView);
} }
} }
sqlite3TreeViewPop(pView); sqlite3TreeViewPop(pView);

View File

@@ -390,7 +390,7 @@ void sqlite3Update(
regKey = iPk; regKey = iPk;
}else{ }else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
sqlite3IndexAffinityStr(v, pPk), nPk); sqlite3IndexAffinityStr(db, pPk), nPk);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey);
} }
sqlite3WhereEnd(pWInfo); sqlite3WhereEnd(pWInfo);

View File

@@ -428,6 +428,7 @@ struct Wal {
u8 syncHeader; /* Fsync the WAL header if true */ u8 syncHeader; /* Fsync the WAL header if true */
u8 padToSectorBoundary; /* Pad transactions out to the next sector */ u8 padToSectorBoundary; /* Pad transactions out to the next sector */
WalIndexHdr hdr; /* Wal-index header for current transaction */ WalIndexHdr hdr; /* Wal-index header for current transaction */
u32 minFrame; /* Ignore wal frames before this one */
const char *zWalName; /* Name of WAL file */ const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
@@ -2296,12 +2297,27 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
** instead. ** instead.
** **
** This does not guarantee that the copy of the wal-index header is up to ** Before checking that the live wal-index header has not changed
** date before proceeding. That would not be possible without somehow ** since it was read, set Wal.minFrame to the first frame in the wal
** blocking writers. It only guarantees that a dangerous checkpoint or ** file that has not yet been checkpointed. This client will not need
** log-wrap (either of which would require an exclusive lock on ** to read any frames earlier than minFrame from the wal file - they
** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid. ** can be safely read directly from the database file.
**
** Because a ShmBarrier() call is made between taking the copy of
** nBackfill and checking that the wal-header in shared-memory still
** matches the one cached in pWal->hdr, it is guaranteed that the
** checkpointer that set nBackfill was not working with a wal-index
** header newer than that cached in pWal->hdr. If it were, that could
** cause a problem. The checkpointer could omit to checkpoint
** a version of page X that lies before pWal->minFrame (call that version
** A) on the basis that there is a newer version (version B) of the same
** page later in the wal file. But if version B happens to like past
** frame pWal->hdr.mxFrame - then the client would incorrectly assume
** that it can read version A from the database file. However, since
** we can guarantee that the checkpointer that set nBackfill could not
** see any pages past pWal->hdr.mxFrame, this problem does not come up.
*/ */
pWal->minFrame = pInfo->nBackfill+1;
walShmBarrier(pWal); walShmBarrier(pWal);
if( pInfo->aReadMark[mxI]!=mxReadMark if( pInfo->aReadMark[mxI]!=mxReadMark
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
@@ -2372,6 +2388,7 @@ int sqlite3WalFindFrame(
u32 iRead = 0; /* If !=0, WAL frame to return data from */ u32 iRead = 0; /* If !=0, WAL frame to return data from */
u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */ u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */
int iHash; /* Used to loop through N hash tables */ int iHash; /* Used to loop through N hash tables */
int iMinHash;
/* This routine is only be called from within a read transaction. */ /* This routine is only be called from within a read transaction. */
assert( pWal->readLock>=0 || pWal->lockError ); assert( pWal->readLock>=0 || pWal->lockError );
@@ -2412,7 +2429,8 @@ int sqlite3WalFindFrame(
** This condition filters out entries that were added to the hash ** This condition filters out entries that were added to the hash
** table after the current read-transaction had started. ** table after the current read-transaction had started.
*/ */
for(iHash=walFramePage(iLast); iHash>=0 && iRead==0; iHash--){ iMinHash = walFramePage(pWal->minFrame);
for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){
volatile ht_slot *aHash; /* Pointer to hash table */ volatile ht_slot *aHash; /* Pointer to hash table */
volatile u32 *aPgno; /* Pointer to array of page numbers */ volatile u32 *aPgno; /* Pointer to array of page numbers */
u32 iZero; /* Frame number corresponding to aPgno[0] */ u32 iZero; /* Frame number corresponding to aPgno[0] */
@@ -2427,7 +2445,7 @@ int sqlite3WalFindFrame(
nCollide = HASHTABLE_NSLOT; nCollide = HASHTABLE_NSLOT;
for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
u32 iFrame = aHash[iKey] + iZero; u32 iFrame = aHash[iKey] + iZero;
if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){
assert( iFrame>iRead || CORRUPT_DB ); assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame; iRead = iFrame;
} }

View File

@@ -171,37 +171,37 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
*/ */
static WhereTerm *whereScanNext(WhereScan *pScan){ static WhereTerm *whereScanNext(WhereScan *pScan){
int iCur; /* The cursor on the LHS of the term */ int iCur; /* The cursor on the LHS of the term */
int iColumn; /* The column on the LHS of the term. -1 for IPK */ i16 iColumn; /* The column on the LHS of the term. -1 for IPK */
Expr *pX; /* An expression being tested */ Expr *pX; /* An expression being tested */
WhereClause *pWC; /* Shorthand for pScan->pWC */ WhereClause *pWC; /* Shorthand for pScan->pWC */
WhereTerm *pTerm; /* The term being tested */ WhereTerm *pTerm; /* The term being tested */
int k = pScan->k; /* Where to start scanning */ int k = pScan->k; /* Where to start scanning */
while( pScan->iEquiv<=pScan->nEquiv ){ while( pScan->iEquiv<=pScan->nEquiv ){
iCur = pScan->aEquiv[pScan->iEquiv-2]; iCur = pScan->aiCur[pScan->iEquiv-1];
iColumn = pScan->aEquiv[pScan->iEquiv-1]; iColumn = pScan->aiColumn[pScan->iEquiv-1];
while( (pWC = pScan->pWC)!=0 ){ while( (pWC = pScan->pWC)!=0 ){
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur if( pTerm->leftCursor==iCur
&& pTerm->u.leftColumn==iColumn && pTerm->u.leftColumn==iColumn
&& (pScan->iEquiv<=2 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){ ){
if( (pTerm->eOperator & WO_EQUIV)!=0 if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aEquiv) && pScan->nEquiv<ArraySize(pScan->aiCur)
){ ){
int j; int j;
pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight); pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
assert( pX->op==TK_COLUMN ); assert( pX->op==TK_COLUMN );
for(j=0; j<pScan->nEquiv; j+=2){ for(j=0; j<pScan->nEquiv; j++){
if( pScan->aEquiv[j]==pX->iTable if( pScan->aiCur[j]==pX->iTable
&& pScan->aEquiv[j+1]==pX->iColumn ){ && pScan->aiColumn[j]==pX->iColumn ){
break; break;
} }
} }
if( j==pScan->nEquiv ){ if( j==pScan->nEquiv ){
pScan->aEquiv[j] = pX->iTable; pScan->aiCur[j] = pX->iTable;
pScan->aEquiv[j+1] = pX->iColumn; pScan->aiColumn[j] = pX->iColumn;
pScan->nEquiv += 2; pScan->nEquiv++;
} }
} }
if( (pTerm->eOperator & pScan->opMask)!=0 ){ if( (pTerm->eOperator & pScan->opMask)!=0 ){
@@ -223,8 +223,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
} }
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0 if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
&& (pX = pTerm->pExpr->pRight)->op==TK_COLUMN && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
&& pX->iTable==pScan->aEquiv[0] && pX->iTable==pScan->aiCur[0]
&& pX->iColumn==pScan->aEquiv[1] && pX->iColumn==pScan->aiColumn[0]
){ ){
testcase( pTerm->eOperator & WO_IS ); testcase( pTerm->eOperator & WO_IS );
continue; continue;
@@ -239,7 +239,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
} }
pScan->pWC = pScan->pOrigWC; pScan->pWC = pScan->pOrigWC;
k = 0; k = 0;
pScan->iEquiv += 2; pScan->iEquiv++;
} }
return 0; return 0;
} }
@@ -285,10 +285,10 @@ static WhereTerm *whereScanInit(
} }
pScan->opMask = opMask; pScan->opMask = opMask;
pScan->k = 0; pScan->k = 0;
pScan->aEquiv[0] = iCur; pScan->aiCur[0] = iCur;
pScan->aEquiv[1] = iColumn; pScan->aiColumn[0] = iColumn;
pScan->nEquiv = 2; pScan->nEquiv = 1;
pScan->iEquiv = 2; pScan->iEquiv = 1;
return whereScanNext(pScan); return whereScanNext(pScan);
} }
@@ -301,12 +301,10 @@ static WhereTerm *whereScanInit(
** The term returned might by Y=<expr> if there is another constraint in ** The term returned might by Y=<expr> if there is another constraint in
** the WHERE clause that specifies that X=Y. Any such constraints will be ** the WHERE clause that specifies that X=Y. Any such constraints will be
** identified by the WO_EQUIV bit in the pTerm->eOperator field. The ** identified by the WO_EQUIV bit in the pTerm->eOperator field. The
** aEquiv[] array holds X and all its equivalents, with each SQL variable ** aiCur[]/iaColumn[] arrays hold X and all its equivalents. There are 11
** taking up two slots in aEquiv[]. The first slot is for the cursor number ** slots in aiCur[]/aiColumn[] so that means we can look for X plus up to 10
** and the second is for the column number. There are 22 slots in aEquiv[] ** other equivalent values. Hence a search for X will return <expr> if X=A1
** so that means we can look for X plus up to 10 other equivalent values. ** and A1=A2 and A2=A3 and ... and A9=A10 and A10=<expr>.
** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
** and ... and A9=A10 and A10=<expr>.
** **
** If there are multiple terms in the WHERE clause of the form "X <op> <expr>" ** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
** then try for the one with no dependencies on <expr> - in other words where ** then try for the one with no dependencies on <expr> - in other words where
@@ -1127,6 +1125,20 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){
return nRet; return nRet;
} }
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Return the affinity for a single column of an index.
*/
static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
if( !pIdx->zColAff ){
if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
}
return pIdx->zColAff[iCol];
}
#endif
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/* /*
** This function is called to estimate the number of rows visited by a ** This function is called to estimate the number of rows visited by a
@@ -1177,7 +1189,7 @@ static int whereRangeSkipScanEst(
int nUpper = p->nSample+1; int nUpper = p->nSample+1;
int rc = SQLITE_OK; int rc = SQLITE_OK;
int iCol = p->aiColumn[nEq]; int iCol = p->aiColumn[nEq];
u8 aff = iCol>=0 ? p->pTable->aCol[iCol].affinity : SQLITE_AFF_INTEGER; u8 aff = sqlite3IndexColumnAffinity(db, p, iCol);
CollSeq *pColl; CollSeq *pColl;
sqlite3_value *p1 = 0; /* Value extracted from pLower */ sqlite3_value *p1 = 0; /* Value extracted from pLower */
@@ -1325,11 +1337,8 @@ static int whereRangeScanEst(
testcase( pRec->nField!=pBuilder->nRecValid ); testcase( pRec->nField!=pBuilder->nRecValid );
pRec->nField = pBuilder->nRecValid; pRec->nField = pBuilder->nRecValid;
} }
if( nEq==p->nKeyCol ){ aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq);
aff = SQLITE_AFF_INTEGER; assert( nEq!=p->nKeyCol || aff==SQLITE_AFF_INTEGER );
}else{
aff = p->pTable->aCol[p->aiColumn[nEq]].affinity;
}
/* Determine iLower and iUpper using ($P) only. */ /* Determine iLower and iUpper using ($P) only. */
if( nEq==0 ){ if( nEq==0 ){
iLower = 0; iLower = 0;
@@ -1487,7 +1496,7 @@ static int whereEqualScanEst(
return SQLITE_OK; return SQLITE_OK;
} }
aff = p->pTable->aCol[p->aiColumn[nEq-1]].affinity; aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq-1);
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk);
pBuilder->pRec = pRec; pBuilder->pRec = pRec;
if( rc!=SQLITE_OK ) return rc; if( rc!=SQLITE_OK ) return rc;
@@ -1914,6 +1923,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
** and prereqs. ** and prereqs.
*/ */
if( pBuilder->pOrSet!=0 ){ if( pBuilder->pOrSet!=0 ){
if( pTemplate->nLTerm ){
#if WHERETRACE_ENABLED #if WHERETRACE_ENABLED
u16 n = pBuilder->pOrSet->n; u16 n = pBuilder->pOrSet->n;
int x = int x =
@@ -1926,6 +1936,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
whereLoopPrint(pTemplate, pBuilder->pWC); whereLoopPrint(pTemplate, pBuilder->pWC);
} }
#endif #endif
}
return SQLITE_OK; return SQLITE_OK;
} }

View File

@@ -291,7 +291,8 @@ struct WhereScan {
unsigned char iEquiv; /* Next unused slot in aEquiv[] */ unsigned char iEquiv; /* Next unused slot in aEquiv[] */
u32 opMask; /* Acceptable operators */ u32 opMask; /* Acceptable operators */
int k; /* Resume scanning at this->pWC->a[this->k] */ int k; /* Resume scanning at this->pWC->a[this->k] */
int aEquiv[22]; /* Cursor,Column pairs for equivalence classes */ int aiCur[11]; /* Cursors in the equivalence class */
i16 aiColumn[11]; /* Corresponding column number in the eq-class */
}; };
/* /*

View File

@@ -492,7 +492,7 @@ static int codeAllEqualityTerms(
nReg = pLoop->u.btree.nEq + nExtraReg; nReg = pLoop->u.btree.nEq + nExtraReg;
pParse->nMem += nReg; pParse->nMem += nReg;
zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx)); zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx));
if( !zAff ){ if( !zAff ){
pParse->db->mallocFailed = 1; pParse->db->mallocFailed = 1;
} }

View File

@@ -1281,6 +1281,7 @@ void sqlite3WhereTabFuncArgs(
if( pColRef==0 ) return; if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor; pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++; pColRef->iColumn = k++;
pColRef->pTab = pTab;
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);

View File

@@ -161,4 +161,27 @@ do_execsql_test join5-3.3 {
SELECT * FROM x1 LEFT JOIN x2 JOIN x3 WHERE x3.d = x2.b; SELECT * FROM x1 LEFT JOIN x2 JOIN x3 WHERE x3.d = x2.b;
} {} } {}
# Ticket https://www.sqlite.org/src/tktview/c2a19d81652f40568c770c43 on
# 2015-08-20. LEFT JOIN and the push-down optimization.
#
do_execsql_test join6-4.1 {
SELECT *
FROM (
SELECT 'apple' fruit
UNION ALL SELECT 'banana'
) a
JOIN (
SELECT 'apple' fruit
UNION ALL SELECT 'banana'
) b ON a.fruit=b.fruit
LEFT JOIN (
SELECT 1 isyellow
) c ON b.fruit='banana';
} {apple apple {} banana banana 1}
do_execsql_test join6-4.2 {
SELECT *
FROM (SELECT 'apple' fruit UNION ALL SELECT 'banana')
LEFT JOIN (SELECT 1) ON fruit='banana';
} {apple {} banana 1}
finish_test finish_test

295
test/json101.test Normal file
View File

@@ -0,0 +1,295 @@
# 2015-08-12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements tests for JSON SQL functions extension to the
# SQLite library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
load_static_extension db json
do_execsql_test json1-1.1 {
SELECT json_array(1,2.5,null,'hello');
} {[1,2.5,null,"hello"]}
do_execsql_test json1-1.2 {
SELECT hex(json_array('String "\ Test'));
} {5B22537472696E67205C225C5C2054657374225D}
do_catchsql_test json1-1.3 {
SELECT json_array(1,2,x'abcd',3);
} {1 {JSON cannot hold BLOB values}}
do_execsql_test json1-1.4 {
SELECT json_array(-9223372036854775808,9223372036854775807,0,1,-1,
0.0, 1.0, -1.0, -1e99, +2e100,
'one','two','three',
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, NULL, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
'abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ',
99);
} {[-9223372036854775808,9223372036854775807,0,1,-1,0.0,1.0,-1.0,-1.0e+99,2.0e+100,"one","two","three",4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,null,21,22,23,24,25,26,27,28,29,30,31,"abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ",99]}
do_execsql_test json1-2.1 {
SELECT json_object('a',1,'b',2.5,'c',null,'d','String Test');
} {{{"a":1,"b":2.5,"c":null,"d":"String Test"}}}
do_catchsql_test json1-2.2 {
SELECT json_object('a',1,2,2.5);
} {1 {json_object() labels must be TEXT}}
do_catchsql_test json1-2.3 {
SELECT json_object('a',1,'b');
} {1 {json_object() requires an even number of arguments}}
do_catchsql_test json1-2.4 {
SELECT json_object('a',1,'b',x'abcd');
} {1 {JSON cannot hold BLOB values}}
do_execsql_test json1-3.1 {
SELECT json_replace('{"a":1,"b":2}','$.a','[3,4,5]');
} {{{"a":"[3,4,5]","b":2}}}
do_execsql_test json1-3.2 {
SELECT json_replace('{"a":1,"b":2}','$$.a','[3,4,5]');
} {{{"a":[3,4,5],"b":2}}}
do_execsql_test json1-3.3 {
SELECT json_type(json_set('{"a":1,"b":2}','$.b','{"x":3,"y":4}'),'$.b');
} {text}
do_execsql_test json1-3.4 {
SELECT json_type(json_set('{"a":1,"b":2}','$$.b','{"x":3,"y":4}'),'$.b');
} {object}
# Per rfc7159, any JSON value is allowed at the top level, and whitespace
# is permitting before and/or after that value.
#
do_execsql_test json1-4.1 {
CREATE TABLE j1(x);
INSERT INTO j1(x)
VALUES('true'),('false'),('null'),('123'),('-234'),('34.5e+6'),
('""'),('"\""'),('"\\"'),('"abcdefghijlmnopqrstuvwxyz"'),
('[]'),('{}'),('[true,false,null,123,-234,34.5e+6,{},[]]'),
('{"a":true,"b":{"c":false}}');
SELECT * FROM j1 WHERE NOT json_valid(x);
} {}
do_execsql_test json1-4.2 {
SELECT * FROM j1 WHERE NOT json_valid(char(0x20,0x09,0x0a,0x0d)||x);
} {}
do_execsql_test json1-4.3 {
SELECT * FROM j1 WHERE NOT json_valid(x||char(0x20,0x09,0x0a,0x0d));
} {}
# But an empty string, or a string of pure whitespace is not valid JSON.
#
do_execsql_test json1-4.4 {
SELECT json_valid(''), json_valid(char(0x20,0x09,0x0a,0x0d));
} {0 0}
# json_remove() and similar functions with no edit operations return their
# input unchanged.
#
do_execsql_test json1-4.5 {
SELECT x FROM j1 WHERE json_remove(x)<>x;
} {}
do_execsql_test json1-4.6 {
SELECT x FROM j1 WHERE json_replace(x)<>x;
} {}
do_execsql_test json1-4.7 {
SELECT x FROM j1 WHERE json_set(x)<>x;
} {}
do_execsql_test json1-4.8 {
SELECT x FROM j1 WHERE json_insert(x)<>x;
} {}
# json_extract(JSON,'$') will return objects and arrays without change.
#
do_execsql_test json-4.10 {
SELECT count(*) FROM j1 WHERE json_type(x) IN ('object','array');
SELECT x FROM j1
WHERE json_extract(x,'$')<>x
AND json_type(x) IN ('object','array');
} {4}
do_execsql_test json-5.1 {
CREATE TABLE j2(id INTEGER PRIMARY KEY, json, src);
INSERT INTO j2(id,json,src)
VALUES(1,'{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null
}','https://en.wikipedia.org/wiki/JSON');
INSERT INTO j2(id,json,src)
VALUES(2, '{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil''s Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}','https://adobe.github.io/Spry/samples/data_region/JSONDataSetSample.html');
INSERT INTO j2(id,json,src)
VALUES(3,'[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil''s Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0002",
"type": "donut",
"name": "Raised",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0003",
"type": "donut",
"name": "Old Fashioned",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
]','https://adobe.github.io/Spry/samples/data_region/JSONDataSetSample.html');
SELECT count(*) FROM j2;
} {3}
do_execsql_test json-5.2 {
SELECT id, json_valid(json), json_type(json), '|' FROM j2 ORDER BY id;
} {1 1 object | 2 1 object | 3 1 array |}
ifcapable !vtab {
finish_test
return
}
# fullkey is always the same as path+key (with appropriate formatting)
#
do_execsql_test json-5.3 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_tree(j2.json) AS jx
WHERE fullkey!=(path || CASE WHEN typeof(key)=='integer' THEN '['||key||']'
ELSE '.'||key END);
} {}
do_execsql_test json-5.4 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_each(j2.json) AS jx
WHERE fullkey!=(path || CASE WHEN typeof(key)=='integer' THEN '['||key||']'
ELSE '.'||key END);
} {}
# Verify that the json_each.json and json_tree.json output is always the
# same as input.
#
do_execsql_test json-5.5 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_each(j2.json) AS jx
WHERE jx.json<>j2.json;
} {}
do_execsql_test json-5.6 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_tree(j2.json) AS jx
WHERE jx.json<>j2.json;
} {}
do_execsql_test json-5.7 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_each(j2.json) AS jx
WHERE jx.value<>jx.atom AND type NOT IN ('array','object');
} {}
do_execsql_test json-5.8 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_tree(j2.json) AS jx
WHERE jx.value<>jx.atom AND type NOT IN ('array','object');
} {}
finish_test

52
test/orderby9.test Normal file
View File

@@ -0,0 +1,52 @@
# 2015-08-26
#
# 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.
#
# This file seeks to verify that expressions (and especially functions)
# that are in both the ORDER BY clause and the result set are only
# evaluated once.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix orderby9
do_execsql_test setup {
-- create a table with many entries
CREATE TABLE t1(x);
WITH RECURSIVE
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1 SELECT x FROM c;
}
do_test 1.0 {
set l1 {}
# If random() is only evaluated once and then reused for each row, then
# the output should appear in sorted order. If random() is evaluated
# separately for the result set and the ORDER BY clause, then the output
# order will be random.
db eval {SELECT random() AS y FROM t1 ORDER BY 1;} {lappend l1 $y}
expr {$l1==[lsort -int $l1]}
} {1}
do_test 1.1 {
set l1 {}
db eval {SELECT random() AS y FROM t1 ORDER BY random();} {lappend l1 $y}
expr {$l1==[lsort -int $l1]}
} {1}
do_test 1.2 {
set l1 {}
db eval {SELECT random() AS y FROM t1 ORDER BY +random();} {lappend l1 $y}
expr {$l1==[lsort -int $l1]}
} {0}
finish_test

79
test/parser1.test Normal file
View File

@@ -0,0 +1,79 @@
# 2014-08-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.
# The focus of this script is testing details of the SQL language parser.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_catchsql_test parser1-1.1 {
CREATE TABLE t1(
a TEXT PRIMARY KEY,
b TEXT,
FOREIGN KEY(b COLLATE nocase DESC) REFERENCES t1(a COLLATE binary ASC)
);
} {1 {syntax error after column name "b"}}
# Verify that a legacy schema in the sqlite_master file is allowed to have
# COLLATE, ASC, and DESC keywords on the id list of a FK constraint, and that
# those keywords are silently ignored.
#
do_execsql_test parser1-1.2 {
CREATE TABLE t1(
a TEXT PRIMARY KEY,
b TEXT,
FOREIGN KEY(b) REFERENCES t1(a)
);
INSERT INTO t1 VALUES('abc',NULL),('xyz','abc');
PRAGMA writable_schema=on;
UPDATE sqlite_master SET sql='CREATE TABLE t1(
a TEXT PRIMARY KEY,
b TEXT,
FOREIGN KEY(b COLLATE nocase) REFERENCES t1(a)
)' WHERE name='t1';
SELECT name FROM sqlite_master WHERE sql LIKE '%collate%';
} {t1}
sqlite3 db2 test.db
do_test parser1-1.3 {
sqlite3 db2 test.db
db2 eval {SELECT * FROM t1 ORDER BY 1}
} {abc {} xyz abc}
db2 close
do_execsql_test parser1-1.4 {
UPDATE sqlite_master SET sql='CREATE TABLE t1(
a TEXT PRIMARY KEY,
b TEXT,
FOREIGN KEY(b ASC) REFERENCES t1(a)
)' WHERE name='t1';
SELECT name FROM sqlite_master WHERE sql LIKE '%ASC%';
} {t1}
sqlite3 db2 test.db
do_test parser1-1.5 {
sqlite3 db2 test.db
db2 eval {SELECT * FROM t1 ORDER BY 1}
} {abc {} xyz abc}
db2 close
do_catchsql_test parser1-2.1 {
WITH RECURSIVE
c(x COLLATE binary) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<5)
SELECT x FROM c;
} {1 {syntax error after column name "x"}}
do_catchsql_test parser1-2.2 {
WITH RECURSIVE
c(x ASC) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<5)
SELECT x FROM c;
} {1 {syntax error after column name "x"}}
finish_test

View File

@@ -65,5 +65,9 @@ do_execsql_test tabfunc01-2.2 {
SELECT * FROM generate_series() LIMIT 5; SELECT * FROM generate_series() LIMIT 5;
} {0 1 2 3 4} } {0 1 2 3 4}
do_execsql_test tabfunc01-3.1 {
SELECT DISTINCT value FROM generate_series(1,x), t1 ORDER BY 1;
} {1 2 3}
finish_test finish_test

View File

@@ -152,6 +152,15 @@ do_test view-3.3.2 {
SELECT * FROM v1b LIMIT 1 SELECT * FROM v1b LIMIT 1
} }
} {a 2 b+c 7 c 4} } {a 2 b+c 7 c 4}
do_test view-3.3.3 {
execsql2 {
CREATE VIEW v1c(x,y,z) AS SELECT a, b+c, c-b FROM t1;
SELECT * FROM v1c LIMIT 1;
}
} {x 2 y 7 z 1}
do_catchsql_test view-3.3.4 {
CREATE VIEW v1err(x,y DESC,z) AS SELECT a, b+c, c-b FROM t1;
} {1 {syntax error after column name "y"}}
ifcapable compound { ifcapable compound {
do_test view-3.4 { do_test view-3.4 {
@@ -337,7 +346,7 @@ do_test view-8.2 {
} {7 2 13 5 19 8 27 12} } {7 2 13 5 19 8 27 12}
do_test view-8.3 { do_test view-8.3 {
execsql { execsql {
CREATE VIEW v7 AS SELECT pqr+xyz AS a FROM v6; CREATE VIEW v7(a) AS SELECT pqr+xyz FROM v6;
SELECT * FROM v7 ORDER BY a; SELECT * FROM v7 ORDER BY a;
} }
} {9 18 27 39} } {9 18 27 39}

View File

@@ -193,5 +193,47 @@ do_test 3.x {
db2 close db2 close
} {} } {}
#-------------------------------------------------------------------------
# Check that if a wal file has been partially checkpointed, no frames are
# read from the checkpointed part.
#
reset_db
do_execsql_test 4.1 {
PRAGMA page_size = 1024;
PRAGMA journal_mode = wal;
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
PRAGMA wal_checkpoint = truncate;
} {wal 0 0 0}
do_test 4.2 {
execsql { INSERT INTO t1 VALUES(1, 2) }
file size test.db-wal
} [wal_file_size 1 1024]
do_test 4.3 {
sqlite3 db2 test.db
execsql {
BEGIN;
INSERT INTO t2 VALUES(3, 4);
}
execsql { PRAGMA wal_checkpoint = passive } db2
} {0 1 1}
do_test 4.3 {
execsql { COMMIT }
db2 close
hexio_write test.db-wal 0 [string repeat 00 2000]
sqlite3 db2 test.db
} {}
do_test 4.4.1 {
catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}
do_test 4.4.2 {
catchsql { SELECT * FROM t2 } db2
} {1 {database disk image is malformed}}
finish_test finish_test

View File

@@ -322,9 +322,14 @@ do_test where2-6.3 {
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *} } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *}
do_test where2-6.4 { do_test where2-6.4 {
queryplan { queryplan {
SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w SELECT *, '|' FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w
} }
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *} } {6 2 49 51 | 99 6 10000 10006 | 100 6 10201 10207 | sort t1 *}
do_test where2-6.5 {
queryplan {
SELECT *, '|' FROM t1 WHERE w=99 OR y=10201 OR 6=w ORDER BY +w
}
} {6 2 49 51 | 99 6 10000 10006 | 100 6 10201 10207 | sort t1 *}
set ::idx {} set ::idx {}
ifcapable subquery {set ::idx i1zyx} ifcapable subquery {set ::idx i1zyx}

View File

@@ -250,7 +250,8 @@ do_execsql_test 4.4 [genstmt 255] 1
set nLimit [sqlite3_limit db SQLITE_LIMIT_COLUMN -1] set nLimit [sqlite3_limit db SQLITE_LIMIT_COLUMN -1]
do_execsql_test 4.5 [genstmt [expr $nLimit-1]] 1 do_execsql_test 4.5 [genstmt [expr $nLimit-1]] 1
do_execsql_test 4.6 [genstmt $nLimit] 1 do_execsql_test 4.6 [genstmt $nLimit] 1
do_catchsql_test 4.7 [genstmt [expr $nLimit+1]] {1 {too many columns in index}} do_catchsql_test 4.7 [genstmt [expr $nLimit+1]] \
{1 {too many columns in result set}}
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Check that adding a WITH clause to an INSERT disables the xfer # Check that adding a WITH clause to an INSERT disables the xfer
@@ -415,4 +416,3 @@ do_execsql_test 8.3 {
finish_test finish_test

View File

@@ -312,12 +312,26 @@ IF "%VisualStudioVersion%" == "11.0" (
) )
) )
REM
REM NOTE: This is the name of the sub-directory where the UCRT libraries may
REM be found. It is only used when compiling against the UCRT.
REM
IF DEFINED UCRTVersion (
SET NUCRTVER=%UCRTVersion%
) ELSE (
SET NUCRTVER=10.0.10240.0
)
REM REM
REM NOTE: This is the name of the sub-directory where the Windows 10.0 SDK REM NOTE: This is the name of the sub-directory where the Windows 10.0 SDK
REM libraries may be found. It is only used when compiling with the REM libraries may be found. It is only used when compiling with the
REM Windows 10.0 SDK. REM Windows 10.0 SDK.
REM REM
SET WIN10LIBDIR=10.0.10240.0 IF DEFINED WindowsSDKLibVersion (
SET WIN10SDKVER=%WindowsSDKLibVersion:\=%
) ELSE (
SET WIN10SDKVER=%NUCRTVER%
)
REM REM
REM NOTE: Check if this is the Windows Phone SDK. If so, a different batch REM NOTE: Check if this is the Windows Phone SDK. If so, a different batch
@@ -361,6 +375,7 @@ FOR %%P IN (%PLATFORMS%) DO (
REM REM
CALL :fn_UnsetVariable CommandPromptType CALL :fn_UnsetVariable CommandPromptType
CALL :fn_UnsetVariable DevEnvDir CALL :fn_UnsetVariable DevEnvDir
CALL :fn_UnsetVariable DNX_HOME
CALL :fn_UnsetVariable ExtensionSdkDir CALL :fn_UnsetVariable ExtensionSdkDir
CALL :fn_UnsetVariable Framework35Version CALL :fn_UnsetVariable Framework35Version
CALL :fn_UnsetVariable Framework40Version CALL :fn_UnsetVariable Framework40Version
@@ -372,14 +387,19 @@ FOR %%P IN (%PLATFORMS%) DO (
CALL :fn_UnsetVariable INCLUDE CALL :fn_UnsetVariable INCLUDE
CALL :fn_UnsetVariable LIB CALL :fn_UnsetVariable LIB
CALL :fn_UnsetVariable LIBPATH CALL :fn_UnsetVariable LIBPATH
CALL :fn_UnsetVariable NETFXSDKDir
CALL :fn_UnsetVariable Platform CALL :fn_UnsetVariable Platform
CALL :fn_UnsetVariable UCRTVersion
CALL :fn_UnsetVariable UniversalCRTSdkDir CALL :fn_UnsetVariable UniversalCRTSdkDir
REM CALL :fn_UnsetVariable VCINSTALLDIR REM CALL :fn_UnsetVariable VCINSTALLDIR
CALL :fn_UnsetVariable VSINSTALLDIR CALL :fn_UnsetVariable VSINSTALLDIR
CALL :fn_UnsetVariable WindowsLibPath
CALL :fn_UnsetVariable WindowsPhoneKitDir CALL :fn_UnsetVariable WindowsPhoneKitDir
CALL :fn_UnsetVariable WindowsSdkDir CALL :fn_UnsetVariable WindowsSdkDir
CALL :fn_UnsetVariable WindowsSdkDir_35 CALL :fn_UnsetVariable WindowsSdkDir_35
CALL :fn_UnsetVariable WindowsSdkDir_old CALL :fn_UnsetVariable WindowsSdkDir_old
CALL :fn_UnsetVariable WindowsSDKLibVersion
CALL :fn_UnsetVariable WindowsSDKVersion
CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x86 CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x86
CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x64 CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x64
@@ -489,9 +509,9 @@ FOR %%P IN (%PLATFORMS%) DO (
REM different directory naming conventions. REM different directory naming conventions.
REM REM
IF DEFINED USE_WINV100_NSDKLIBPATH ( IF DEFINED USE_WINV100_NSDKLIBPATH (
CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\%WIN10LIBDIR%\um\x86 CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\%WIN10SDKVER%\um\x86
CALL :fn_CopyVariable UniversalCRTSdkDir PSDKLIBPATH CALL :fn_CopyVariable WindowsSdkDir PSDKLIBPATH
CALL :fn_AppendVariable PSDKLIBPATH Lib\%WIN10LIBDIR%\um\%%D CALL :fn_AppendVariable PSDKLIBPATH lib\%WIN10SDKVER%\um\%%D
) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH ( ) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH (
CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86 CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
) ELSE IF "%VisualStudioVersion%" == "12.0" ( ) ELSE IF "%VisualStudioVersion%" == "12.0" (
@@ -514,7 +534,7 @@ FOR %%P IN (%PLATFORMS%) DO (
IF DEFINED SET_NUCRTLIBPATH ( IF DEFINED SET_NUCRTLIBPATH (
IF DEFINED UniversalCRTSdkDir ( IF DEFINED UniversalCRTSdkDir (
CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH
CALL :fn_AppendVariable NUCRTLIBPATH \lib\%WIN10LIBDIR%\ucrt\x86 CALL :fn_AppendVariable NUCRTLIBPATH \lib\%NUCRTVER%\ucrt\x86
) )
) )