Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the latest trunk changes (PRAGMA busy_timeout and the ORDER BY query planner enhancements) into the apple-osx branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
6a5c59dd7e0de9b5a2136f1c333afe52 |
User & Date: | drh 2012-09-28 10:57:42.795 |
Context
2014-05-08
| ||
23:01 | Initial attempt to merge in all trunk changes over the previous 1.5 years. This check-in compiles but there are compiler warnings and "make test" segfaults after only running a few test modules. (check-in: 9411d7dc6f user: drh tags: apple-osx) | |
2012-09-28
| ||
10:57 | Merge the latest trunk changes (PRAGMA busy_timeout and the ORDER BY query planner enhancements) into the apple-osx branch. (check-in: 6a5c59dd7e user: drh tags: apple-osx) | |
00:44 | Query planner enhancements to be more agressive about optimizing out ORDER BY clauses - in particular the query planner now has the ability to omit ORDER BY clauses that span multiple tables in a join. (check-in: 1e874629d7 user: drh tags: trunk) | |
2012-08-31
| ||
14:10 | Merge in latest trunk changes. (check-in: bc9b9cd058 user: dan tags: apple-osx) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
897 898 899 900 901 902 903 904 905 906 907 908 909 910 | fulltest: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/all.test soaktest: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 test: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/veryquick.test sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl echo "#define TCLSH 2" > $@ cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@ | > > > | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 | fulltest: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/all.test soaktest: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 fulltestonly: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/full.test test: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/veryquick.test sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl echo "#define TCLSH 2" > $@ cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@ |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 | # Check for the command macro LD. This should point to the linker binary for # the target platform. If it is not defined, simply define it to the legacy # default value 'link.exe'. # !IFNDEF LD LD = link.exe !ENDIF # Check for the command macro NCC. This should point to the compiler binary # for the platform the compilation process is taking place on. If it is not # defined, simply define it to have the same value as the CC macro. When # cross-compiling, it is suggested that this macro be modified via the command # line (since nmake itself does not provide a built-in method to guess it). # For example, to use the x86 compiler when cross-compiling for x64, a command | > > > > > > > > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | # Check for the command macro LD. This should point to the linker binary for # the target platform. If it is not defined, simply define it to the legacy # default value 'link.exe'. # !IFNDEF LD LD = link.exe !ENDIF # Check for the predefined command macro RC. This should point to the resource # compiler binary for the target platform. If it is not defined, simply define # it to the legacy default value 'rc.exe'. # !IFNDEF RC RC = rc.exe !ENDIF # Check for the command macro NCC. This should point to the compiler binary # for the platform the compilation process is taking place on. If it is not # defined, simply define it to have the same value as the CC macro. When # cross-compiling, it is suggested that this macro be modified via the command # line (since nmake itself does not provide a built-in method to guess it). # For example, to use the x86 compiler when cross-compiling for x64, a command |
︙ | ︙ | |||
145 146 147 148 149 150 151 | NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)" !ENDIF # C compiler and options for use in building executables that # will run on the target platform. (BCC and TCC are usually the # same unless your are cross-compiling.) # | | > > > | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)" !ENDIF # C compiler and options for use in building executables that # will run on the target platform. (BCC and TCC are usually the # same unless your are cross-compiling.) # TCC = $(CC) -W3 -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src -fp:precise RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src # When compiling the library for use in the WinRT environment, # the following compile-time options must be used as well to # disable use of Win32 APIs that are not available and to enable # use of Win32 APIs that are specific to Windows 8 and/or WinRT. # !IF $(FOR_WINRT)!=0 TCC = $(TCC) -DSQLITE_OS_WINRT=1 RCC = $(RCC) -DSQLITE_OS_WINRT=1 TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_PARTITION_APP RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_PARTITION_APP !ENDIF # Also, we need to dynamically link to the correct MSVC runtime # when compiling for WinRT (e.g. debug or release) OR if the # USE_CRT_DLL option is set to force dynamically linking to the # MSVC runtime library. # |
︙ | ︙ | |||
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | # The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in # any extension header files by default. For non-amalgamation # builds, we need to make sure the compiler can find these. # !IF $(USE_AMALGAMATION)==0 TCC = $(TCC) -I$(TOP)\ext\fts3 TCC = $(TCC) -I$(TOP)\ext\rtree !ENDIF # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and # includes extra comments when "EXPLAIN stmt" is used. # !IF $(DEBUG)==0 TCC = $(TCC) -DNDEBUG BCC = $(BCC) -DNDEBUG !ENDIF !IF $(DEBUG)>1 TCC = $(TCC) -DSQLITE_DEBUG !ENDIF !IF $(DEBUG)>3 TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1 !ENDIF !IF $(DEBUG)>4 TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE !ENDIF # # Prevent warnings about "insecure" MSVC runtime library functions # being used. # TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS # # Prevent warnings about "deprecated" POSIX functions being used. # TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS # # Use the SQLite debugging heap subsystem? # !IF $(MEMDEBUG)!=0 TCC = $(TCC) -DSQLITE_MEMDEBUG=1 # # Use native Win32 heap subsystem instead of malloc/free? # !ELSEIF $(WIN32HEAP)!=0 TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1 # # Validate the heap on every call into the native Win32 heap subsystem? # !IF $(DEBUG)>2 TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 !ENDIF !ENDIF # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment # prior to running nmake in order to match the actual installed location and | > > > > > > > > > > > | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | # The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in # any extension header files by default. For non-amalgamation # builds, we need to make sure the compiler can find these. # !IF $(USE_AMALGAMATION)==0 TCC = $(TCC) -I$(TOP)\ext\fts3 RCC = $(RCC) -I$(TOP)\ext\fts3 TCC = $(TCC) -I$(TOP)\ext\rtree RCC = $(RCC) -I$(TOP)\ext\rtree !ENDIF # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and # includes extra comments when "EXPLAIN stmt" is used. # !IF $(DEBUG)==0 TCC = $(TCC) -DNDEBUG BCC = $(BCC) -DNDEBUG RCC = $(RCC) -DNDEBUG !ENDIF !IF $(DEBUG)>1 TCC = $(TCC) -DSQLITE_DEBUG RCC = $(RCC) -DSQLITE_DEBUG !ENDIF !IF $(DEBUG)>3 TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1 RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1 !ENDIF !IF $(DEBUG)>4 TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE !ENDIF # # Prevent warnings about "insecure" MSVC runtime library functions # being used. # TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS # # Prevent warnings about "deprecated" POSIX functions being used. # TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS # # Use the SQLite debugging heap subsystem? # !IF $(MEMDEBUG)!=0 TCC = $(TCC) -DSQLITE_MEMDEBUG=1 RCC = $(RCC) -DSQLITE_MEMDEBUG=1 # # Use native Win32 heap subsystem instead of malloc/free? # !ELSEIF $(WIN32HEAP)!=0 TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1 RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1 # # Validate the heap on every call into the native Win32 heap subsystem? # !IF $(DEBUG)>2 TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 !ENDIF !ENDIF # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment # prior to running nmake in order to match the actual installed location and |
︙ | ︙ | |||
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | # The library that programs using readline() must link against. # LIBREADLINE = # Should the database engine be compiled threadsafe # TCC = $(TCC) -DSQLITE_THREADSAFE=1 # Do threads override each others locks by default (1), or do we test (-1) # TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1 # Any target libraries which libsqlite must be linked against # !IFNDEF TLIBS TLIBS = !ENDIF # Flags controlling use of the in memory btree implementation # # SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to # default to file, 2 to default to memory, and 3 to force temporary # tables to always be in memory. # TCC = $(TCC) -DSQLITE_TEMP_STORE=1 # Enable/disable loadable extensions, and other optional features # based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*). # The same set of OMIT and ENABLE flags should be passed to the # LEMON parser generator and the mkkeywordhash tool as well. # BEGIN standard options OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 # END standard options # BEGIN required Windows option OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100 # END required Windows option TCC = $(TCC) $(OPT_FEATURE_FLAGS) # Add in any optional parameters specified on the make commane line # ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1". TCC = $(TCC) $(OPTS) # If symbols are enabled, enable PDBs. # If debugging is enabled, disable all optimizations and enable PDBs. !IF $(DEBUG)>0 TCC = $(TCC) -Od -D_DEBUG BCC = $(BCC) -Od -D_DEBUG !ELSE TCC = $(TCC) -O2 BCC = $(BCC) -O2 !ENDIF !IF $(DEBUG)>0 || $(SYMBOLS)!=0 TCC = $(TCC) -Zi BCC = $(BCC) -Zi !ENDIF # If ICU support is enabled, add the compiler options for it. !IF $(USE_ICU)!=0 TCC = $(TCC) -DSQLITE_ENABLE_ICU=1 TCC = $(TCC) -I$(TOP)\ext\icu TCC = $(TCC) -I$(ICUINCDIR) !ENDIF | > > > > > > > > > > | > | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | # The library that programs using readline() must link against. # LIBREADLINE = # Should the database engine be compiled threadsafe # TCC = $(TCC) -DSQLITE_THREADSAFE=1 RCC = $(RCC) -DSQLITE_THREADSAFE=1 # Do threads override each others locks by default (1), or do we test (-1) # TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1 RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1 # Any target libraries which libsqlite must be linked against # !IFNDEF TLIBS TLIBS = !ENDIF # Flags controlling use of the in memory btree implementation # # SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to # default to file, 2 to default to memory, and 3 to force temporary # tables to always be in memory. # TCC = $(TCC) -DSQLITE_TEMP_STORE=1 RCC = $(RCC) -DSQLITE_TEMP_STORE=1 # Enable/disable loadable extensions, and other optional features # based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*). # The same set of OMIT and ENABLE flags should be passed to the # LEMON parser generator and the mkkeywordhash tool as well. # BEGIN standard options OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 # END standard options # BEGIN required Windows option OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100 # END required Windows option TCC = $(TCC) $(OPT_FEATURE_FLAGS) RCC = $(RCC) $(OPT_FEATURE_FLAGS) # Add in any optional parameters specified on the make commane line # ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1". TCC = $(TCC) $(OPTS) RCC = $(RCC) $(OPTS) # If symbols are enabled, enable PDBs. # If debugging is enabled, disable all optimizations and enable PDBs. !IF $(DEBUG)>0 TCC = $(TCC) -Od -D_DEBUG BCC = $(BCC) -Od -D_DEBUG RCC = $(RCC) -D_DEBUG !ELSE TCC = $(TCC) -O2 BCC = $(BCC) -O2 !ENDIF !IF $(DEBUG)>0 || $(SYMBOLS)!=0 TCC = $(TCC) -Zi BCC = $(BCC) -Zi !ENDIF # If ICU support is enabled, add the compiler options for it. !IF $(USE_ICU)!=0 TCC = $(TCC) -DSQLITE_ENABLE_ICU=1 RCC = $(RCC) -DSQLITE_ENABLE_ICU=1 TCC = $(TCC) -I$(TOP)\ext\icu RCC = $(RCC) -I$(TOP)\ext\icu TCC = $(TCC) -I$(ICUINCDIR) RCC = $(RCC) -I$(ICUINCDIR) !ENDIF # Command line prefixes for compiling code, compiling resources, # linking, etc. LTCOMPILE = $(TCC) -Fo$@ LTRCOMPILE = $(RCC) -r LTLIB = lib.exe LTLINK = $(TCC) -Fe$@ # If a platform was set, force the linker to target that. # Note that the vcvars*.bat family of batch files typically # set this for you. Otherwise, the linker will attempt # to deduce the binary type based on the object files. |
︙ | ︙ | |||
729 730 731 732 733 734 735 | libsqlite3.lib: $(LIBOBJ) $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS) | | | | 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | libsqlite3.lib: $(LIBOBJ) $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS) sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib sqlite3res.lo sqlite3.h $(LTLINK) $(READLINE_FLAGS) \ $(TOP)\src\shell.c \ /link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib sqlite3res.lo $(LIBREADLINE) $(LTLIBS) $(TLIBS) # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to # build on the target system. Some of the C source code and header # files are automatically generated. This target takes care of # all that automatic generation. # |
︙ | ︙ | |||
780 781 782 783 784 785 786 787 788 789 790 791 792 793 | # parse.lo: parse.c $(HDR) $(LTCOMPILE) -c parse.c opcodes.lo: opcodes.c $(LTCOMPILE) -c opcodes.c # Rules to build individual *.lo files from files in the src directory. # alter.lo: $(TOP)\src\alter.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\alter.c analyze.lo: $(TOP)\src\analyze.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\analyze.c | > > > > > > > > > > > | 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 | # parse.lo: parse.c $(HDR) $(LTCOMPILE) -c parse.c opcodes.lo: opcodes.c $(LTCOMPILE) -c opcodes.c # Rule to build the Win32 resources object file. # sqlite3res.lo: $(TOP)\src\sqlite3.rc $(HDR) echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h for /F %%V in ('type "$(TOP)\VERSION"') do ( \ echo #define SQLITE_RESOURCE_VERSION %%V \ | $(NAWK) "/.*/ { gsub(/[.]/,\",\");print }" >> sqlite3rc.h \ ) echo #endif >> sqlite3rc.h $(LTRCOMPILE) -fo sqlite3res.lo $(TOP)\src\sqlite3.rc # Rules to build individual *.lo files from files in the src directory. # alter.lo: $(TOP)\src\alter.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\alter.c analyze.lo: $(TOP)\src\analyze.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\analyze.c |
︙ | ︙ | |||
995 996 997 998 999 1000 1001 | tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(LTCOMPILE) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c | | < | | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(LTCOMPILE) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite3.exe: tclsqlite-shell.lo libsqlite3.lib sqlite3res.lo $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ libsqlite3.lib tclsqlite-shell.lo sqlite3res.lo $(LTLIBS) $(TLIBS) # Rules to build opcodes.c and opcodes.h # opcodes.c: opcodes.h $(TOP)\mkopcodec.awk $(NAWK) -f $(TOP)\mkopcodec.awk opcodes.h > opcodes.c opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\mkopcodeh.awk |
︙ | ︙ | |||
1110 1111 1112 1113 1114 1115 1116 | TESTFIXTURE_SRC1 = sqlite3.c !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) !ELSE TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1) !ENDIF | | | > > > | | | > < | | | | 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | TESTFIXTURE_SRC1 = sqlite3.c !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) !ELSE TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1) !ENDIF testfixture.exe: $(TESTFIXTURE_SRC) sqlite3res.lo $(HDR) $(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \ -DBUILD_sqlite -I$(TCLINCDIR) \ $(TESTFIXTURE_SRC) \ /link $(LTLINKOPTS) $(LTLIBPATHS) sqlite3res.lo $(LTLIBS) $(TLIBS) fulltest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\all.test soaktest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\all.test -soak=1 fulltestonly: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\full.test test: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\veryquick.test sqlite3_analyzer.c: sqlite3.c $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl copy sqlite3.c + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@ echo static const char *tclsh_main_loop(void){ >> $@ echo static const char *zMainloop = >> $@ $(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@ echo ; return zMainloop; } >> $@ sqlite3_analyzer.exe: sqlite3_analyzer.c sqlite3res.lo $(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \ /link $(LTLINKOPTS) $(LTLIBPATHS) sqlite3res.lo $(LTLIBS) $(TLIBS) clean: del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib del /Q *.da *.bb *.bbg gmon.out del /Q sqlite3.h opcodes.c opcodes.h del /Q lemon.exe lempar.c parse.* del /Q mkkeywordhash.exe keywordhash.h -rmdir /Q/S .deps -rmdir /Q/S .libs -rmdir /Q/S quota2a -rmdir /Q/S quota2b -rmdir /Q/S quota2c -rmdir /Q/S tsrc del /Q .target_source del /Q tclsqlite3.exe tclsqlite3.exp del /Q testfixture.exe testfixture.exp test.db del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def del /Q sqlite3.c del /Q sqlite3rc.h del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c del /Q sqlite-output.vsix # Dynamic link library section. # dll: sqlite3.dll sqlite3.def: libsqlite3.lib echo EXPORTS > sqlite3.def dumpbin /all libsqlite3.lib \ | $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \ | sort >> sqlite3.def sqlite3.dll: $(LIBOBJ) sqlite3res.lo sqlite3.def $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) sqlite3res.lo $(LTLIBS) $(TLIBS) |
Changes to Makefile.vxworks.
︙ | ︙ | |||
620 621 622 623 624 625 626 627 628 629 630 631 632 633 | -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) fulltest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test soaktest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test -soak=1 test: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/veryquick.test sqlite3_analyzer$(EXE): $(TOP)/src/tclsqlite.c sqlite3.c $(TESTSRC) \ $(TOP)/tool/spaceanal.tcl sed \ | > > > | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) fulltest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test soaktest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test -soak=1 fulltestonly: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/full.test test: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/veryquick.test sqlite3_analyzer$(EXE): $(TOP)/src/tclsqlite.c sqlite3.c $(TESTSRC) \ $(TOP)/tool/spaceanal.tcl sed \ |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.7.15 |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.62 for sqlite 3.7.15. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## |
︙ | ︙ | |||
739 740 741 742 743 744 745 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.7.15' PACKAGE_STRING='sqlite 3.7.15' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> |
︙ | ︙ | |||
1481 1482 1483 1484 1485 1486 1487 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF | | | 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sqlite 3.7.15 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. |
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.7.15:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | | 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sqlite configure 3.7.15 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sqlite $as_me 3.7.15, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
14030 14031 14032 14033 14034 14035 14036 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" | | | 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 14043 14044 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sqlite $as_me 3.7.15, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ |
︙ | ︙ | |||
14083 14084 14085 14086 14087 14088 14089 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ | | | 14083 14084 14085 14086 14087 14088 14089 14090 14091 14092 14093 14094 14095 14096 14097 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ sqlite config.status 3.7.15 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
547 548 549 550 551 552 553 554 555 556 557 558 559 560 | -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) fulltest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test soaktest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test -soak=1 test: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/veryquick.test # The next two rules are used to support the "threadtest" target. Building # threadtest runs a few thread-safety tests that are implemented in C. This # target is invoked by the releasetest.tcl script. | > > > | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) fulltest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test soaktest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test -soak=1 fulltestonly: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/full.test test: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/veryquick.test # The next two rules are used to support the "threadtest" target. Building # threadtest runs a few thread-safety tests that are implemented in C. This # target is invoked by the releasetest.tcl script. |
︙ | ︙ |
Deleted publish.sh.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted publish_osx.sh.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to src/alter.c.
︙ | ︙ | |||
660 661 662 663 664 665 666 | pDflt = 0; } /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. ** If there is a NOT NULL constraint, then the default value for the ** column must not be NULL. */ | | | 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 | pDflt = 0; } /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. ** If there is a NOT NULL constraint, then the default value for the ** column must not be NULL. */ if( pCol->colFlags & COLFLAG_PRIMKEY ){ sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); return; } if( pNew->pIndex ){ sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); return; } |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1165 1166 1167 1168 1169 1170 1171 | sqlite3ErrorMsg(pParse, "table \"%s\" has more than one primary key", pTab->zName); goto primary_key_exit; } pTab->tabFlags |= TF_HasPrimaryKey; if( pList==0 ){ iCol = pTab->nCol - 1; | | | | 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 | sqlite3ErrorMsg(pParse, "table \"%s\" has more than one primary key", pTab->zName); goto primary_key_exit; } pTab->tabFlags |= TF_HasPrimaryKey; if( pList==0 ){ iCol = pTab->nCol - 1; pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; }else{ for(i=0; i<pList->nExpr; i++){ for(iCol=0; iCol<pTab->nCol; iCol++){ if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ break; } } if( iCol<pTab->nCol ){ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; } } if( pList->nExpr>1 ) iCol = -1; } if( iCol>=0 && iCol<pTab->nCol ){ zType = pTab->aCol[iCol].zType; } |
︙ | ︙ |
Changes to src/ctime.c.
︙ | ︙ | |||
333 334 335 336 337 338 339 340 341 342 343 344 345 346 | "OMIT_XFER_OPT", #endif #ifdef SQLITE_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif #ifdef SQLITE_PROXY_DEBUG "PROXY_DEBUG", #endif #ifdef SQLITE_SECURE_DELETE "SECURE_DELETE", #endif #ifdef SQLITE_SMALL_STACK "SMALL_STACK", #endif | > > > | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | "OMIT_XFER_OPT", #endif #ifdef SQLITE_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif #ifdef SQLITE_PROXY_DEBUG "PROXY_DEBUG", #endif #ifdef SQLITE_RTREE_INT_ONLY "RTREE_INT_ONLY", #endif #ifdef SQLITE_SECURE_DELETE "SECURE_DELETE", #endif #ifdef SQLITE_SMALL_STACK "SMALL_STACK", #endif |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
634 635 636 637 638 639 640 | }else{ sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); sqlite3ColumnDefault(v, pTab, idx, -1); } } if( doMakeRec ){ const char *zAff; | | > > | 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | }else{ sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); sqlite3ColumnDefault(v, pTab, idx, -1); } } if( doMakeRec ){ const char *zAff; if( pTab->pSelect || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt) ){ zAff = 0; }else{ zAff = sqlite3IndexAffinityStr(v, pIdx); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT); } |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1416 1417 1418 1419 1420 1421 1422 | int sqlite3CodeOnce(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); } /* ** This function is used by the implementation of the IN (...) operator. | > > > | | | | | > | | > > > > > | 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 | int sqlite3CodeOnce(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); } /* ** This function is used by the implementation of the IN (...) operator. ** The pX parameter is the expression on the RHS of the IN operator, which ** might be either a list of expressions or a subquery. ** ** The job of this routine is to find or create a b-tree object that can ** be used either to test for membership in the RHS set or to iterate through ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that the RHS of the IN operator ** and pX->iTable is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: ** ** IN_INDEX_ROWID - The cursor was opened on a database table. ** IN_INDEX_INDEX - The cursor was opened on a database index. ** IN_INDEX_EPH - The cursor was opened on a specially created and ** populated epheremal table. ** ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: ** ** SELECT <column> FROM <table> ** ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then ** pX->iTable made to point to the ephermeral table instead of an ** existing table. ** ** If the prNotFound parameter is 0, then the b-tree will be used to iterate ** through the set members, skipping any duplicates. In this case an ** epheremal table must be used unless the selected <column> is guaranteed ** to be unique - either because it is an INTEGER PRIMARY KEY or it ** has a UNIQUE constraint or UNIQUE index. ** |
︙ | ︙ | |||
1529 1530 1531 1532 1533 1534 1535 | ** to this collation sequence. */ CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); /* Check that the affinity that will be used to perform the ** comparison is the same as the affinity of the column. If ** it is not, it is not possible to use any index. */ | < | | 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 | ** to this collation sequence. */ CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); /* Check that the affinity that will be used to perform the ** comparison is the same as the affinity of the column. If ** it is not, it is not possible to use any index. */ int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity); for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ if( (pIdx->aiColumn[0]==iCol) && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) ){ int iAddr; |
︙ | ︙ | |||
1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 | } #endif switch( pExpr->op ){ case TK_IN: { char affinity; /* Affinity of the LHS of the IN */ KeyInfo keyInfo; /* Keyinfo for the generated table */ int addr; /* Address of OP_OpenEphemeral instruction */ Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ if( rMayHaveNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); } | > | 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 | } #endif switch( pExpr->op ){ case TK_IN: { char affinity; /* Affinity of the LHS of the IN */ KeyInfo keyInfo; /* Keyinfo for the generated table */ static u8 sortOrder = 0; /* Fake aSortOrder for keyInfo */ int addr; /* Address of OP_OpenEphemeral instruction */ Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ if( rMayHaveNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); } |
︙ | ︙ | |||
1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 | ** is used. */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ | > | 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 | ** is used. */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; keyInfo.aSortOrder = &sortOrder; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ |
︙ | ︙ | |||
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 | struct ExprList_item *pItem; int r1, r2, r3; if( !affinity ){ affinity = SQLITE_AFF_NONE; } keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); /* Loop through each expression in <exprlist>. */ r1 = sqlite3GetTempReg(pParse); r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Null, 0, r2); for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ Expr *pE2 = pItem->pExpr; | > | 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 | struct ExprList_item *pItem; int r1, r2, r3; if( !affinity ){ affinity = SQLITE_AFF_NONE; } keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); keyInfo.aSortOrder = &sortOrder; /* Loop through each expression in <exprlist>. */ r1 = sqlite3GetTempReg(pParse); r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Null, 0, r2); for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ Expr *pE2 = pItem->pExpr; |
︙ | ︙ | |||
2051 2052 2053 2054 2055 2056 2057 | assert( iReg>0 ); /* Register numbers are always positive */ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* The SQLITE_ColumnCache flag disables the column cache. This is used ** for testing only - to verify that SQLite always gets the same answer ** with and without the column cache. */ | | | 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 | assert( iReg>0 ); /* Register numbers are always positive */ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* The SQLITE_ColumnCache flag disables the column cache. This is used ** for testing only - to verify that SQLite always gets the same answer ** with and without the column cache. */ if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return; /* First replace any existing entry. ** ** Actually, the way the column cache is currently used, we are guaranteed ** that the object will never already be in cache. Verify this guarantee. */ #ifndef NDEBUG |
︙ | ︙ | |||
2248 2249 2250 2251 2252 2253 2254 | /* ** Generate code to move content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. */ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ int i; struct yColCache *p; | | | < < < < < < < < < < < < | 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 | /* ** Generate code to move content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. */ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ int i; struct yColCache *p; assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1); for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ int x = p->iReg; if( x>=iFrom && x<iFrom+nReg ){ p->iReg += iTo-iFrom; } } } #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) /* ** Return true if any register in the range iFrom..iTo (inclusive) ** is used as part of the column cache. ** ** This routine is used within assert() and testcase() macros only ** and does not appear in a normal build. |
︙ | ︙ | |||
3379 3380 3381 3382 3383 3384 3385 | ** interface. This allows test logic to verify that the same answer is ** obtained for queries regardless of whether or not constants are ** precomputed into registers or if they are inserted in-line. */ void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ Walker w; if( pParse->cookieGoto ) return; | | | 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 | ** interface. This allows test logic to verify that the same answer is ** obtained for queries regardless of whether or not constants are ** precomputed into registers or if they are inserted in-line. */ void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ Walker w; if( pParse->cookieGoto ) return; if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return; w.xExprCallback = evalConstExpr; w.xSelectCallback = 0; w.pParse = pParse; sqlite3WalkExpr(&w, pExpr); } |
︙ | ︙ |
Changes to src/fkey.c.
︙ | ︙ | |||
921 922 923 924 925 926 927 | /* Check if any parent key columns are being modified. */ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ for(i=0; i<p->nCol; i++){ char *zKey = p->aCol[i].zCol; int iKey; for(iKey=0; iKey<pTab->nCol; iKey++){ Column *pCol = &pTab->aCol[iKey]; | | > | 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 | /* Check if any parent key columns are being modified. */ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ for(i=0; i<p->nCol; i++){ char *zKey = p->aCol[i].zCol; int iKey; for(iKey=0; iKey<pTab->nCol; iKey++){ Column *pCol = &pTab->aCol[iKey]; if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey) : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){ if( aChange[iKey]>=0 ) return 1; if( iKey==pTab->iPKey && chngRowid ) return 1; } } } } } |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
366 367 368 369 370 371 372 | z1[i] = sqlite3Tolower(z2[i]); } sqlite3_result_text(context, z1, n, sqlite3_free); } } } | < < | | | < < < | < > | < < < < < < < < < < < < < < | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | z1[i] = sqlite3Tolower(z2[i]); } sqlite3_result_text(context, z1, n, sqlite3_free); } } } /* ** The COALESCE() and IFNULL() functions are implemented as VDBE code so ** that unused argument values do not have to be computed. However, we ** still need some kind of function implementation for this routines in ** the function table. That function implementation will never be called ** so it doesn't matter what the implementation is. We might as well use ** the "version()" function as a substitute. */ #define ifnullFunc versionFunc /* Substitute function - never called */ /* ** Implementation of random(). Return a random integer. */ static void randomFunc( sqlite3_context *context, |
︙ | ︙ | |||
511 512 513 514 515 516 517 | /* ** For LIKE and GLOB matching on EBCDIC machines, assume that every ** character is exactly one byte in size. Also, all characters are ** able to participate in upper-case-to-lower-case mappings in EBCDIC ** whereas only characters less than 0x80 do in ASCII. */ #if defined(SQLITE_EBCDIC) | | | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | /* ** For LIKE and GLOB matching on EBCDIC machines, assume that every ** character is exactly one byte in size. Also, all characters are ** able to participate in upper-case-to-lower-case mappings in EBCDIC ** whereas only characters less than 0x80 do in ASCII. */ #if defined(SQLITE_EBCDIC) # define sqlite3Utf8Read(A) (*((*A)++)) # define GlogUpperToLower(A) A = sqlite3UpperToLower[A] #else # define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; } #endif static const struct compareInfo globInfo = { '*', '?', '[', 0 }; /* The correct SQL-92 behavior is for the LIKE operator to ignore |
︙ | ︙ | |||
568 569 570 571 572 573 574 | int seen; u8 matchOne = pInfo->matchOne; u8 matchAll = pInfo->matchAll; u8 matchSet = pInfo->matchSet; u8 noCase = pInfo->noCase; int prevEscape = 0; /* True if the previous character was 'escape' */ | | | | | | | | | | | | | | | | | | | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 | int seen; u8 matchOne = pInfo->matchOne; u8 matchAll = pInfo->matchAll; u8 matchSet = pInfo->matchSet; u8 noCase = pInfo->noCase; int prevEscape = 0; /* True if the previous character was 'escape' */ while( (c = sqlite3Utf8Read(&zPattern))!=0 ){ if( c==matchAll && !prevEscape ){ while( (c=sqlite3Utf8Read(&zPattern)) == matchAll || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ return 0; } } if( c==0 ){ return 1; }else if( c==esc ){ c = sqlite3Utf8Read(&zPattern); if( c==0 ){ return 0; } }else if( c==matchSet ){ assert( esc==0 ); /* This is GLOB, not LIKE */ assert( matchSet<0x80 ); /* '[' is a single-byte character */ while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ SQLITE_SKIP_UTF8(zString); } return *zString!=0; } while( (c2 = sqlite3Utf8Read(&zString))!=0 ){ if( noCase ){ GlogUpperToLower(c2); GlogUpperToLower(c); while( c2 != 0 && c2 != c ){ c2 = sqlite3Utf8Read(&zString); GlogUpperToLower(c2); } }else{ while( c2 != 0 && c2 != c ){ c2 = sqlite3Utf8Read(&zString); } } if( c2==0 ) return 0; if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; } return 0; }else if( c==matchOne && !prevEscape ){ if( sqlite3Utf8Read(&zString)==0 ){ return 0; } }else if( c==matchSet ){ u32 prior_c = 0; assert( esc==0 ); /* This only occurs for GLOB, not LIKE */ seen = 0; invert = 0; c = sqlite3Utf8Read(&zString); if( c==0 ) return 0; c2 = sqlite3Utf8Read(&zPattern); if( c2=='^' ){ invert = 1; c2 = sqlite3Utf8Read(&zPattern); } if( c2==']' ){ if( c==']' ) seen = 1; c2 = sqlite3Utf8Read(&zPattern); } while( c2 && c2!=']' ){ if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ c2 = sqlite3Utf8Read(&zPattern); if( c>=prior_c && c<=c2 ) seen = 1; prior_c = 0; }else{ if( c==c2 ){ seen = 1; } prior_c = c2; } c2 = sqlite3Utf8Read(&zPattern); } if( c2==0 || (seen ^ invert)==0 ){ return 0; } }else if( esc==c && !prevEscape ){ prevEscape = 1; }else{ c2 = sqlite3Utf8Read(&zString); if( noCase ){ GlogUpperToLower(c); GlogUpperToLower(c2); } if( c!=c2 ){ return 0; } |
︙ | ︙ | |||
719 720 721 722 723 724 725 | const unsigned char *zEsc = sqlite3_value_text(argv[2]); if( zEsc==0 ) return; if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } | | | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 | const unsigned char *zEsc = sqlite3_value_text(argv[2]); if( zEsc==0 ) return; if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } escape = sqlite3Utf8Read(&zEsc); } if( zA && zB ){ struct compareInfo *pInfo = sqlite3_user_data(context); #ifdef SQLITE_TEST sqlite3_like_count++; #endif |
︙ | ︙ |
Changes to src/global.c.
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | }; #endif #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 0 #endif /* ** The following singleton contains the global configuration for ** the SQLite library. */ SQLITE_WSD struct Sqlite3Config sqlite3Config = { SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */ 1, /* bCoreMutex */ SQLITE_THREADSAFE==1, /* bFullMutex */ SQLITE_USE_URI, /* bOpenUri */ 0x7ffffffe, /* mxStrlen */ 128, /* szLookaside */ 500, /* nLookaside */ {0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0,0}, /* mutex */ {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ (void*)0, /* pHeap */ | > > > > > | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | }; #endif #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 0 #endif #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 #endif /* ** The following singleton contains the global configuration for ** the SQLite library. */ SQLITE_WSD struct Sqlite3Config sqlite3Config = { SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */ 1, /* bCoreMutex */ SQLITE_THREADSAFE==1, /* bFullMutex */ SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0x7ffffffe, /* mxStrlen */ 128, /* szLookaside */ 500, /* nLookaside */ {0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0,0}, /* mutex */ {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ (void*)0, /* pHeap */ |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
315 316 317 318 319 320 321 322 323 324 325 326 327 328 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines ** above are all no-ops */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* Forward declaration */ static int xferOptimization( Parse *pParse, /* Parser context */ Table *pDest, /* The table we are inserting into */ Select *pSelect, /* A SELECT statement to use as the data source */ int onError, /* How to handle constraint errors */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines ** above are all no-ops */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* ** Generate code for a co-routine that will evaluate a subquery one ** row at a time. ** ** The pSelect parameter is the subquery that the co-routine will evaluation. ** Information about the location of co-routine and the registers it will use ** is returned by filling in the pDest object. ** ** Registers are allocated as follows: ** ** pDest->iSDParm The register holding the next entry-point of the ** co-routine. Run the co-routine to its next breakpoint ** by calling "OP_Yield $X" where $X is pDest->iSDParm. ** ** pDest->iSDParm+1 The register holding the "completed" flag for the ** co-routine. This register is 0 if the previous Yield ** generated a new result row, or 1 if the subquery ** has completed. If the Yield is called again ** after this register becomes 1, then the VDBE will ** halt with an SQLITE_INTERNAL error. ** ** pDest->iSdst First result register. ** ** pDest->nSdst Number of result registers. ** ** This routine handles all of the register allocation and fills in the ** pDest structure appropriately. ** ** Here is a schematic of the generated code assuming that X is the ** co-routine entry-point register reg[pDest->iSDParm], that EOF is the ** completed flag reg[pDest->iSDParm+1], and R and S are the range of ** registers that hold the result set, reg[pDest->iSdst] through ** reg[pDest->iSdst+pDest->nSdst-1]: ** ** X <- A ** EOF <- 0 ** goto B ** A: setup for the SELECT ** loop rows in the SELECT ** load results into registers R..S ** yield X ** end loop ** cleanup after the SELECT ** EOF <- 1 ** yield X ** halt-error ** B: ** ** To use this subroutine, the caller generates code as follows: ** ** [ Co-routine generated by this subroutine, shown above ] ** S: yield X ** if EOF goto E ** if skip this row, goto C ** if terminate loop, goto E ** deal with this row ** C: goto S ** E: */ int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){ int regYield; /* Register holding co-routine entry-point */ int regEof; /* Register holding co-routine completion flag */ int addrTop; /* Top of the co-routine */ int j1; /* Jump instruction */ int rc; /* Result code */ Vdbe *v; /* VDBE under construction */ regYield = ++pParse->nMem; regEof = ++pParse->nMem; v = sqlite3GetVdbe(pParse); addrTop = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */ VdbeComment((v, "Co-routine entry point")); sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ VdbeComment((v, "Co-routine completion flag")); sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield); j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); rc = sqlite3Select(pParse, pSelect, pDest); assert( pParse->nErr==0 || rc ); if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM; if( rc ) return rc; sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); VdbeComment((v, "End of coroutine")); sqlite3VdbeJumpHere(v, j1); /* label B: */ return rc; } /* Forward declaration */ static int xferOptimization( Parse *pParse, /* Parser context */ Table *pDest, /* The table we are inserting into */ Select *pSelect, /* A SELECT statement to use as the data source */ int onError, /* How to handle constraint errors */ |
︙ | ︙ | |||
564 565 566 567 568 569 570 | /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ | | < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < | < < | | < < < < < | | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 | /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ /* Data is coming from a SELECT. Generate a co-routine to run that ** SELECT. */ int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest); if( rc ) goto insert_cleanup; regEof = dest.iSDParm + 1; regFromSelect = dest.iSdst; assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; assert( dest.nSdst==nColumn ); /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
473 474 475 476 477 478 479 480 481 482 483 484 485 486 | break; } case SQLITE_CONFIG_URI: { sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); break; } default: { rc = SQLITE_ERROR; break; } } va_end(ap); | > > > > > | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | break; } case SQLITE_CONFIG_URI: { sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } default: { rc = SQLITE_ERROR; break; } } va_end(ap); |
︙ | ︙ | |||
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 | int (*xBusy)(void*,int), void *pArg ){ sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; db->busyHandler.nBusy = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* ** This routine sets the progress callback for an Sqlite database to the | > | 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 | int (*xBusy)(void*,int), void *pArg ){ sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; db->busyHandler.nBusy = 0; db->busyTimeout = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* ** This routine sets the progress callback for an Sqlite database to the |
︙ | ︙ | |||
1156 1157 1158 1159 1160 1161 1162 | /* ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( ms>0 ){ | < > | 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 | /* ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( ms>0 ){ sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); db->busyTimeout = ms; }else{ sqlite3_busy_handler(db, 0, 0); } return SQLITE_OK; } /* |
︙ | ︙ | |||
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 | return SQLITE_MISUSE_BKPT; } if( !db || db->mallocFailed ){ return SQLITE_NOMEM; } return db->errCode; } /* ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. */ static int createCollation( sqlite3* db, | > > > > > > > > > | 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 | return SQLITE_MISUSE_BKPT; } if( !db || db->mallocFailed ){ return SQLITE_NOMEM; } return db->errCode; } /* ** Return a string that describes the kind of error specified in the ** argument. For now, this simply calls the internal sqlite3ErrStr() ** function. */ const char *sqlite3_errstr(int rc){ return sqlite3ErrStr(rc); } /* ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. */ static int createCollation( sqlite3* db, |
︙ | ︙ | |||
2859 2860 2861 2862 2863 2864 2865 | ** 2. The table is not a view and the column name identified an ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ zDataType = pCol->zType; zCollSeq = pCol->zColl; notnull = pCol->notNull!=0; | | | 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 | ** 2. The table is not a view and the column name identified an ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ zDataType = pCol->zType; zCollSeq = pCol->zColl; notnull = pCol->notNull!=0; primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0; }else{ zDataType = "INTEGER"; primarykey = 1; } if( !zCollSeq ){ zCollSeq = "BINARY"; |
︙ | ︙ | |||
3131 3132 3133 3134 3135 3136 3137 | ** operation N should be 0. The idea is that a test program (like the ** SQL Logic Test or SLT test module) can run the same SQL multiple times ** with various optimizations disabled to verify that the same answer ** is obtained in every case. */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); | | < | 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 | ** operation N should be 0. The idea is that a test program (like the ** SQL Logic Test or SLT test module) can run the same SQL multiple times ** with various optimizations disabled to verify that the same answer ** is obtained in every case. */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff); break; } #ifdef SQLITE_N_KEYWORD /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) ** ** If zWord is a keyword recognized by the parser, then return the |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #endif /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* ** Macro to find the minimum of two numeric values. */ #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif | > > > > > > > > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #endif /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* ** Compiling and using WAL mode requires several APIs that are only ** available in Windows platforms based on the NT kernel. */ #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) # error "WAL mode requires support from the Windows NT kernel, compile\ with SQLITE_OMIT_WAL." #endif /* ** Macro to find the minimum of two numeric values. */ #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif |
︙ | ︙ | |||
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | { "CreateFileW", (SYSCALL)CreateFileW, 0 }, #else { "CreateFileW", (SYSCALL)0, 0 }, #endif #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ !defined(SQLITE_OMIT_WAL)) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ | > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | { "CreateFileW", (SYSCALL)CreateFileW, 0 }, #else { "CreateFileW", (SYSCALL)0, 0 }, #endif #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) #if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ !defined(SQLITE_OMIT_WAL)) { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, #else { "CreateFileMappingA", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ !defined(SQLITE_OMIT_WAL)) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateMutexW", (SYSCALL)CreateMutexW, 0 }, #else { "CreateMutexW", (SYSCALL)0, 0 }, #endif #define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \ LPCWSTR))aSyscall[8].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "DeleteFileA", (SYSCALL)DeleteFileA, 0 }, #else { "DeleteFileA", (SYSCALL)0, 0 }, #endif #define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "DeleteFileW", (SYSCALL)DeleteFileW, 0 }, #else { "DeleteFileW", (SYSCALL)0, 0 }, #endif #define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent) #if SQLITE_OS_WINCE { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 }, #else { "FileTimeToLocalFileTime", (SYSCALL)0, 0 }, #endif #define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \ LPFILETIME))aSyscall[11].pCurrent) #if SQLITE_OS_WINCE { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 }, #else { "FileTimeToSystemTime", (SYSCALL)0, 0 }, #endif #define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \ LPSYSTEMTIME))aSyscall[12].pCurrent) { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 }, #define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "FormatMessageA", (SYSCALL)FormatMessageA, 0 }, #else { "FormatMessageA", (SYSCALL)0, 0 }, #endif #define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \ DWORD,va_list*))aSyscall[14].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "FormatMessageW", (SYSCALL)FormatMessageW, 0 }, #else { "FormatMessageW", (SYSCALL)0, 0 }, #endif #define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \ DWORD,va_list*))aSyscall[15].pCurrent) { "FreeLibrary", (SYSCALL)FreeLibrary, 0 }, #define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent) { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 }, #define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent) #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 }, #else { "GetDiskFreeSpaceA", (SYSCALL)0, 0 }, #endif #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \ LPDWORD))aSyscall[18].pCurrent) #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 }, #else { "GetDiskFreeSpaceW", (SYSCALL)0, 0 }, #endif #define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \ LPDWORD))aSyscall[19].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 }, #else { "GetFileAttributesA", (SYSCALL)0, 0 }, #endif #define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent) #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 }, #else { "GetFileAttributesW", (SYSCALL)0, 0 }, #endif #define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 }, #else { "GetFileAttributesExW", (SYSCALL)0, 0 }, #endif #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \ LPVOID))aSyscall[22].pCurrent) #if !SQLITE_OS_WINRT { "GetFileSize", (SYSCALL)GetFileSize, 0 }, #else { "GetFileSize", (SYSCALL)0, 0 }, #endif #define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent) #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 }, #else { "GetFullPathNameA", (SYSCALL)0, 0 }, #endif #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \ LPSTR*))aSyscall[24].pCurrent) #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 }, #else { "GetFullPathNameW", (SYSCALL)0, 0 }, #endif #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \ LPWSTR*))aSyscall[25].pCurrent) { "GetLastError", (SYSCALL)GetLastError, 0 }, #define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent) #if SQLITE_OS_WINCE /* The GetProcAddressA() routine is only available on Windows CE. */ { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 }, #else /* All other Windows platforms expect GetProcAddress() to take ** an ANSI string regardless of the _UNICODE setting */ { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 }, #endif #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \ LPCSTR))aSyscall[27].pCurrent) #if !SQLITE_OS_WINRT { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 }, #else { "GetSystemInfo", (SYSCALL)0, 0 }, #endif #define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent) { "GetSystemTime", (SYSCALL)GetSystemTime, 0 }, #define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent) #if !SQLITE_OS_WINCE { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 }, #else { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 }, #endif #define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \ LPFILETIME))aSyscall[30].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "GetTempPathA", (SYSCALL)GetTempPathA, 0 }, #else { "GetTempPathA", (SYSCALL)0, 0 }, #endif #define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent) #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetTempPathW", (SYSCALL)GetTempPathW, 0 }, #else { "GetTempPathW", (SYSCALL)0, 0 }, #endif #define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent) #if !SQLITE_OS_WINRT { "GetTickCount", (SYSCALL)GetTickCount, 0 }, #else { "GetTickCount", (SYSCALL)0, 0 }, #endif #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, #else { "GetVersionExA", (SYSCALL)0, 0 }, #endif #define osGetVersionExA ((BOOL(WINAPI*)( \ LPOSVERSIONINFOA))aSyscall[34].pCurrent) { "HeapAlloc", (SYSCALL)HeapAlloc, 0 }, #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \ SIZE_T))aSyscall[35].pCurrent) #if !SQLITE_OS_WINRT { "HeapCreate", (SYSCALL)HeapCreate, 0 }, #else { "HeapCreate", (SYSCALL)0, 0 }, #endif #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \ SIZE_T))aSyscall[36].pCurrent) #if !SQLITE_OS_WINRT { "HeapDestroy", (SYSCALL)HeapDestroy, 0 }, #else { "HeapDestroy", (SYSCALL)0, 0 }, #endif #define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent) { "HeapFree", (SYSCALL)HeapFree, 0 }, #define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent) { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 }, #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \ SIZE_T))aSyscall[39].pCurrent) { "HeapSize", (SYSCALL)HeapSize, 0 }, #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \ LPCVOID))aSyscall[40].pCurrent) #if !SQLITE_OS_WINRT { "HeapValidate", (SYSCALL)HeapValidate, 0 }, #else { "HeapValidate", (SYSCALL)0, 0 }, #endif #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \ LPCVOID))aSyscall[41].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 }, #else { "LoadLibraryA", (SYSCALL)0, 0 }, #endif #define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent) #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 }, #else { "LoadLibraryW", (SYSCALL)0, 0 }, #endif #define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent) #if !SQLITE_OS_WINRT { "LocalFree", (SYSCALL)LocalFree, 0 }, #else { "LocalFree", (SYSCALL)0, 0 }, #endif #define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent) #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "LockFile", (SYSCALL)LockFile, 0 }, #else { "LockFile", (SYSCALL)0, 0 }, #endif #ifndef osLockFile #define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ DWORD))aSyscall[45].pCurrent) #endif #if !SQLITE_OS_WINCE { "LockFileEx", (SYSCALL)LockFileEx, 0 }, #else { "LockFileEx", (SYSCALL)0, 0 }, #endif #ifndef osLockFileEx #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[46].pCurrent) #endif #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)) { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, #else { "MapViewOfFile", (SYSCALL)0, 0 }, #endif #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ SIZE_T))aSyscall[47].pCurrent) { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 }, #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \ int))aSyscall[48].pCurrent) { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 }, #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \ LARGE_INTEGER*))aSyscall[49].pCurrent) { "ReadFile", (SYSCALL)ReadFile, 0 }, #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \ LPOVERLAPPED))aSyscall[50].pCurrent) { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 }, #define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent) #if !SQLITE_OS_WINRT { "SetFilePointer", (SYSCALL)SetFilePointer, 0 }, #else { "SetFilePointer", (SYSCALL)0, 0 }, #endif #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \ DWORD))aSyscall[52].pCurrent) #if !SQLITE_OS_WINRT { "Sleep", (SYSCALL)Sleep, 0 }, #else { "Sleep", (SYSCALL)0, 0 }, #endif #define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent) { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 }, #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \ LPFILETIME))aSyscall[54].pCurrent) #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "UnlockFile", (SYSCALL)UnlockFile, 0 }, #else { "UnlockFile", (SYSCALL)0, 0 }, #endif #ifndef osUnlockFile #define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ DWORD))aSyscall[55].pCurrent) #endif #if !SQLITE_OS_WINCE { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 }, #else { "UnlockFileEx", (SYSCALL)0, 0 }, #endif #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[56].pCurrent) #if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, #else { "UnmapViewOfFile", (SYSCALL)0, 0 }, #endif #define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent) { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 }, #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \ LPCSTR,LPBOOL))aSyscall[58].pCurrent) { "WriteFile", (SYSCALL)WriteFile, 0 }, #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ LPOVERLAPPED))aSyscall[59].pCurrent) #if SQLITE_OS_WINRT { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, #else { "CreateEventExW", (SYSCALL)0, 0 }, #endif #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ DWORD,DWORD))aSyscall[60].pCurrent) #if !SQLITE_OS_WINRT { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, #else { "WaitForSingleObject", (SYSCALL)0, 0 }, #endif #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ DWORD))aSyscall[61].pCurrent) #if SQLITE_OS_WINRT { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, #else { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, #endif #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ BOOL))aSyscall[62].pCurrent) #if SQLITE_OS_WINRT { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, #else { "SetFilePointerEx", (SYSCALL)0, 0 }, #endif #define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent) #if SQLITE_OS_WINRT { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, #else { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, #endif #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent) #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL) { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, #else { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, #endif #define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ SIZE_T))aSyscall[65].pCurrent) #if SQLITE_OS_WINRT { "CreateFile2", (SYSCALL)CreateFile2, 0 }, #else { "CreateFile2", (SYSCALL)0, 0 }, #endif #define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent) #if SQLITE_OS_WINRT { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 }, #else { "LoadPackagedLibrary", (SYSCALL)0, 0 }, #endif #define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \ DWORD))aSyscall[67].pCurrent) #if SQLITE_OS_WINRT { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, #else { "GetTickCount64", (SYSCALL)0, 0 }, #endif #define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent) #if SQLITE_OS_WINRT { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, #else { "GetNativeSystemInfo", (SYSCALL)0, 0 }, #endif #define osGetNativeSystemInfo ((VOID(WINAPI*)( \ LPSYSTEM_INFO))aSyscall[69].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, #else { "OutputDebugStringA", (SYSCALL)0, 0 }, #endif #define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, #else { "OutputDebugStringW", (SYSCALL)0, 0 }, #endif #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent) { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent) #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL) { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, #else { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent) }; /* End of the overrideable system calls */ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the ** "win32" VFSes. Return SQLITE_OK opon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable |
︙ | ︙ | |||
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 | ** API as long as we don't call it when running Win95/98/ME. A call to ** this routine is used to determine if the host is Win95/98/ME or ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. */ #if SQLITE_OS_WINCE || SQLITE_OS_WINRT # define isNT() (1) #else static int isNT(void){ if( sqlite3_os_type==0 ){ OSVERSIONINFOA sInfo; sInfo.dwOSVersionInfoSize = sizeof(sInfo); osGetVersionExA(&sInfo); sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return sqlite3_os_type==2; } | > > | | 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 | ** API as long as we don't call it when running Win95/98/ME. A call to ** this routine is used to determine if the host is Win95/98/ME or ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. */ #if SQLITE_OS_WINCE || SQLITE_OS_WINRT # define isNT() (1) #elif !defined(SQLITE_WIN32_HAS_WIDE) # define isNT() (0) #else static int isNT(void){ if( sqlite3_os_type==0 ){ OSVERSIONINFOA sInfo; sInfo.dwOSVersionInfoSize = sizeof(sInfo); osGetVersionExA(&sInfo); sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return sqlite3_os_type==2; } #endif #ifdef SQLITE_WIN32_MALLOC /* ** Allocate nBytes of memory. */ static void *winMemMalloc(int nBytes){ HANDLE hHeap; |
︙ | ︙ | |||
1199 1200 1201 1202 1203 1204 1205 | int nChar; LPWSTR zWideFilename; nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); if( nChar==0 ){ return 0; } | | | 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 | int nChar; LPWSTR zWideFilename; nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); if( nChar==0 ){ return 0; } zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) ); if( zWideFilename==0 ){ return 0; } nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); if( nChar==0 ){ sqlite3_free(zWideFilename); |
︙ | ︙ | |||
1224 1225 1226 1227 1228 1229 1230 | int nByte; char *zFilename; nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } | | | 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 | int nByte; char *zFilename; nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } zFilename = sqlite3MallocZero( nByte ); if( zFilename==0 ){ return 0; } nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, 0, 0); if( nByte == 0 ){ sqlite3_free(zFilename); |
︙ | ︙ | |||
1254 1255 1256 1257 1258 1259 1260 | int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR); if( nByte==0 ){ return 0; } | | | 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR); if( nByte==0 ){ return 0; } zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) ); if( zMbcsFilename==0 ){ return 0; } nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); if( nByte==0 ){ sqlite3_free(zMbcsFilename); |
︙ | ︙ | |||
1283 1284 1285 1286 1287 1288 1289 | char *zFilename; int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } | | | 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | char *zFilename; int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } zFilename = sqlite3MallocZero( nByte ); if( zFilename==0 ){ return 0; } nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, 0, 0); if( nByte == 0 ){ sqlite3_free(zFilename); |
︙ | ︙ | |||
2939 2940 2941 2942 2943 2944 2945 | int nName; /* Size of zName in bytes */ assert( pDbFd->pShm==0 ); /* Not previously opened */ /* Allocate space for the new sqlite3_shm object. Also speculatively ** allocate space for a new winShmNode and filename. */ | | < | < | 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 | int nName; /* Size of zName in bytes */ assert( pDbFd->pShm==0 ); /* Not previously opened */ /* Allocate space for the new sqlite3_shm object. Also speculatively ** allocate space for a new winShmNode and filename. */ p = sqlite3MallocZero( sizeof(*p) ); if( p==0 ) return SQLITE_IOERR_NOMEM; nName = sqlite3Strlen30(pDbFd->zPath); pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 ); if( pNew==0 ){ sqlite3_free(p); return SQLITE_IOERR_NOMEM; } pNew->zFilename = (char*)&pNew[1]; sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); /* Look to see if there is an existing winShmNode that can be used. ** If no matching winShmNode currently exists, create a new one. */ |
︙ | ︙ | |||
3285 3286 3287 3288 3289 3290 3291 | if( !apNew ){ rc = SQLITE_IOERR_NOMEM; goto shmpage_out; } pShmNode->aRegion = apNew; while( pShmNode->nRegion<=iRegion ){ | | | > > > > | 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 | if( !apNew ){ rc = SQLITE_IOERR_NOMEM; goto shmpage_out; } pShmNode->aRegion = apNew; while( pShmNode->nRegion<=iRegion ){ HANDLE hMap = NULL; /* file-mapping handle */ void *pMap = 0; /* Mapped memory region */ #if SQLITE_OS_WINRT hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, NULL, PAGE_READWRITE, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_WIDE) hMap = osCreateFileMappingW(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_ANSI) hMap = osCreateFileMappingA(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); #endif OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n", (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte, hMap ? "ok" : "failed")); if( hMap ){ int iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; |
︙ | ︙ | |||
4044 4045 4046 4047 4048 4049 4050 | }else{ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); } return SQLITE_OK; #endif #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) | | | 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 | }else{ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); } return SQLITE_OK; #endif #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) DWORD nByte; void *zConverted; char *zOut; /* If this path name begins with "/X:", where "X" is any alphabetic ** character, discard the initial "/" from the pathname. */ if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){ |
︙ | ︙ | |||
4078 4079 4080 4081 4082 4083 4084 | } zConverted = convertUtf8Filename(zRelative); if( zConverted==0 ){ return SQLITE_IOERR_NOMEM; } if( isNT() ){ LPWSTR zTemp; | | > > > > > > > | | > > > > > > > | > > > > > > > | | > > > > > > > | 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 | } zConverted = convertUtf8Filename(zRelative); if( zConverted==0 ){ return SQLITE_IOERR_NOMEM; } if( isNT() ){ LPWSTR zTemp; nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0); if( nByte==0 ){ winLogError(SQLITE_ERROR, osGetLastError(), "GetFullPathNameW1", zConverted); sqlite3_free(zConverted); return SQLITE_CANTOPEN_FULLPATH; } nByte += 3; zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqlite3_free(zConverted); return SQLITE_IOERR_NOMEM; } nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); if( nByte==0 ){ winLogError(SQLITE_ERROR, osGetLastError(), "GetFullPathNameW2", zConverted); sqlite3_free(zConverted); sqlite3_free(zTemp); return SQLITE_CANTOPEN_FULLPATH; } sqlite3_free(zConverted); zOut = unicodeToUtf8(zTemp); sqlite3_free(zTemp); } #ifdef SQLITE_WIN32_HAS_ANSI else{ char *zTemp; nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0); if( nByte==0 ){ winLogError(SQLITE_ERROR, osGetLastError(), "GetFullPathNameA1", zConverted); sqlite3_free(zConverted); return SQLITE_CANTOPEN_FULLPATH; } nByte += 3; zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqlite3_free(zConverted); return SQLITE_IOERR_NOMEM; } nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0); if( nByte==0 ){ winLogError(SQLITE_ERROR, osGetLastError(), "GetFullPathNameA2", zConverted); sqlite3_free(zConverted); sqlite3_free(zTemp); return SQLITE_CANTOPEN_FULLPATH; } sqlite3_free(zConverted); zOut = sqlite3_win32_mbcs_to_utf8(zTemp); sqlite3_free(zTemp); } #endif if( zOut ){ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); |
︙ | ︙ | |||
4356 4357 4358 4359 4360 4361 4362 | winSetSystemCall, /* xSetSystemCall */ winGetSystemCall, /* xGetSystemCall */ winNextSystemCall, /* xNextSystemCall */ }; /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ | | | | 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 | winSetSystemCall, /* xSetSystemCall */ winGetSystemCall, /* xGetSystemCall */ winNextSystemCall, /* xNextSystemCall */ }; /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ assert( ArraySize(aSyscall)==74 ); #ifndef SQLITE_OMIT_WAL /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); #if SQLITE_OS_WINRT osGetNativeSystemInfo(&winSysInfo); #else osGetSystemInfo(&winSysInfo); #endif assert(winSysInfo.dwAllocationGranularity > 0); #endif sqlite3_vfs_register(&winVfs, 1); return SQLITE_OK; } int sqlite3_os_end(void){ #if SQLITE_OS_WINRT if( sleepObj!=NULL ){ osCloseHandle(sleepObj); sleepObj = NULL; } #endif return SQLITE_OK; } #endif /* SQLITE_OS_WIN */ |
Changes to src/pager.c.
︙ | ︙ | |||
4456 4457 4458 4459 4460 4461 4462 | /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */ if( zPathname ){ assert( nPathname>0 ); pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri); memcpy(pPager->zFilename, zPathname, nPathname); if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); memcpy(pPager->zJournal, zPathname, nPathname); | | | 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 | /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */ if( zPathname ){ assert( nPathname>0 ); pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri); memcpy(pPager->zFilename, zPathname, nPathname); if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); memcpy(pPager->zJournal, zPathname, nPathname); memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2); sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal); #ifndef SQLITE_OMIT_WAL pPager->zWal = &pPager->zJournal[nPathname+8+1]; memcpy(pPager->zWal, zPathname, nPathname); memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1); sqlite3FileSuffix3(pPager->zFilename, pPager->zWal); #endif |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
990 991 992 993 994 995 996 | pCol->zType ? pCol->zType : "", 0); sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); if( pCol->zDflt ){ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, 5); } | | > | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 | pCol->zType ? pCol->zType : "", 0); sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); if( pCol->zDflt ){ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, 5); } sqlite3VdbeAddOp2(v, OP_Integer, (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } }else if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ Index *pIdx; |
︙ | ︙ | |||
1249 1250 1251 1252 1253 1254 1255 | /* Do the b-tree integrity checks */ sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), P4_DYNAMIC); | | | 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 | /* Do the b-tree integrity checks */ sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), P4_DYNAMIC); sqlite3VdbeAddOp2(v, OP_Move, 2, 4); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); sqlite3VdbeJumpHere(v, addr); /* Make sure all the indices are constructed correctly. */ for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ |
︙ | ︙ | |||
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 | ** This pragma attempts to free as much memory as possible from the ** current database connection. */ if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){ sqlite3_db_release_memory(db); }else #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Report the current state of file logs for all databases */ if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ static const char *const azLockName[] = { "unlocked", "shared", "reserved", "pending", "exclusive" | > > > > > > > > > > > > > > > > | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | ** This pragma attempts to free as much memory as possible from the ** current database connection. */ if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){ sqlite3_db_release_memory(db); }else /* ** PRAGMA busy_timeout ** PRAGMA busy_timeout = N ** ** Call sqlite3_busy_timeout(db, N). Return the current timeout value ** if one is set. If no busy handler or a different busy handler is set ** then 0 is returned. Setting the busy_timeout to 0 or negative ** disables the timeout. */ if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){ if( zRight ){ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); } returnSingleInt(pParse, "timeout", &db->busyTimeout); }else #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Report the current state of file logs for all databases */ if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ static const char *const azLockName[] = { "unlocked", "shared", "reserved", "pending", "exclusive" |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; int i; int size; Table *pTab; Db *pDb; char const *azArg[4]; int meta[5]; InitData initData; char const *zMasterSchema; char const *zMasterName; | > > | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; int i; #ifndef SQLITE_OMIT_DEPRECATED int size; #endif Table *pTab; Db *pDb; char const *azArg[4]; int meta[5]; InitData initData; char const *zMasterSchema; char const *zMasterName; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | return 1; }else{ return 0; } } #endif /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** If srcTab and nColumn are both zero, then the pEList expressions ** are evaluated in order to get the data for this row. If nColumn>0 ** then data is pulled from srcTab and pEList is used only to get the ** datatypes for each column. */ static void selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ int srcTab, /* Pull data from this table */ int nColumn, /* Number of columns in the source table */ ExprList *pOrderBy, /* If not NULL, sort results using this key */ | > > > > > > > > > > > > > | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | return 1; }else{ return 0; } } #endif /* ** An instance of the following object is used to record information about ** how to process the DISTINCT keyword, to simplify passing that information ** into the selectInnerLoop() routine. */ typedef struct DistinctCtx DistinctCtx; struct DistinctCtx { u8 isTnct; /* True if the DISTINCT keyword is present */ u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */ int tabTnct; /* Ephemeral table used for DISTINCT processing */ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ }; /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** If srcTab and nColumn are both zero, then the pEList expressions ** are evaluated in order to get the data for this row. If nColumn>0 ** then data is pulled from srcTab and pEList is used only to get the ** datatypes for each column. */ static void selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ int srcTab, /* Pull data from this table */ int nColumn, /* Number of columns in the source table */ ExprList *pOrderBy, /* If not NULL, sort results using this key */ DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */ SelectDest *pDest, /* How to dispose of the results */ int iContinue, /* Jump here to continue with next row */ int iBreak /* Jump here to break out of the inner loop */ ){ Vdbe *v = pParse->pVdbe; int i; int hasDistinct; /* True if the DISTINCT keyword is present */ int regResult; /* Start of memory holding result set */ int eDest = pDest->eDest; /* How to dispose of results */ int iParm = pDest->iSDParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ assert( v ); if( NEVER(v==0) ) return; assert( pEList!=0 ); hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; if( pOrderBy==0 && !hasDistinct ){ codeOffset(v, p, iContinue); } /* Pull the requested columns. */ if( nColumn>0 ){ |
︙ | ︙ | |||
593 594 595 596 597 598 599 | /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ assert( pEList!=0 ); assert( pEList->nExpr==nColumn ); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ assert( pEList!=0 ); assert( pEList->nExpr==nColumn ); switch( pDistinct->eTnctType ){ case WHERE_DISTINCT_ORDERED: { VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ int iJump; /* Jump destination */ int regPrev; /* Previous row content */ /* Allocate space for the previous row */ regPrev = pParse->nMem+1; pParse->nMem += nColumn; /* Change the OP_OpenEphemeral coded earlier to an OP_Null ** sets the MEM_Cleared bit on the first register of the ** previous value. This will cause the OP_Ne below to always ** fail on the first iteration of the loop even if the first ** row is all NULLs. */ sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct); pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct); pOp->opcode = OP_Null; pOp->p1 = 1; pOp->p2 = regPrev; iJump = sqlite3VdbeCurrentAddr(v) + nColumn; for(i=0; i<nColumn; i++){ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr); if( i<nColumn-1 ){ sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i); }else{ sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i); } sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); } assert( sqlite3VdbeCurrentAddr(v)==iJump ); sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nColumn-1); break; } case WHERE_DISTINCT_UNIQUE: { sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct); break; } default: { assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED ); codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult); break; } } if( pOrderBy==0 ){ codeOffset(v, p, iContinue); } } switch( eDest ){ /* In this mode, write each query result to the key of the temporary |
︙ | ︙ | |||
651 652 653 654 655 656 657 | #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { assert( nColumn==1 ); | > | | | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { assert( nColumn==1 ); pDest->affSdst = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst); if( pOrderBy ){ /* At first glance you would think we could optimize out the ** 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 ** case the order does matter */ pushOntoSorter(pParse, pOrderBy, p, regResult); }else{ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); sqlite3ExprCacheAffinityChange(pParse, regResult, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); } break; } |
︙ | ︙ | |||
927 928 929 930 931 932 933 | sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==1 ); | | > | 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 | sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==1 ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &pDest->affSdst, 1); sqlite3ExprCacheAffinityChange(pParse, regRow, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); break; } case SRT_Mem: { assert( nColumn==1 ); sqlite3ExprCodeMove(pParse, regRow, iParm, 1); |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | ** ** Return SQLITE_OK on success. If a memory allocation error occurs, ** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. */ static int selectColumnsFromExprList( Parse *pParse, /* Parsing context */ ExprList *pEList, /* Expr list from which to derive column names */ | | | 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 | ** ** Return SQLITE_OK on success. If a memory allocation error occurs, ** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. */ static int selectColumnsFromExprList( Parse *pParse, /* Parsing context */ ExprList *pEList, /* Expr list from which to derive column names */ i16 *pnCol, /* Write the number of columns here */ Column **paCol /* Write the new column list here */ ){ sqlite3 *db = pParse->db; /* Database connection */ int i, j; /* Loop counters */ int cnt; /* Index added to make the name unique */ Column *aCol, *pCol; /* For looping over result columns */ int nCol; /* Number of columns in the result set */ |
︙ | ︙ | |||
1764 1765 1766 1767 1768 1769 1770 | } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); iStart = sqlite3VdbeCurrentAddr(v); selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, | | | 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 | } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); iStart = sqlite3VdbeCurrentAddr(v); selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); } break; } |
︙ | ︙ | |||
1842 1843 1844 1845 1846 1847 1848 | computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); sqlite3ReleaseTempReg(pParse, r1); selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, | | | 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 | computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); sqlite3ReleaseTempReg(pParse, r1); selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); break; } |
︙ | ︙ | |||
1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 | for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ *apColl = multiSelectCollSeq(pParse, p, i); if( 0==*apColl ){ *apColl = db->pDfltColl; } } for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ for(i=0; i<2; i++){ int addr = pLoop->addrOpenEphm[i]; if( addr<0 ){ /* If [0] is unused then [1] is also unused. So we can ** always safely abort as soon as the first unused slot is found */ | > | 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 | for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ *apColl = multiSelectCollSeq(pParse, p, i); if( 0==*apColl ){ *apColl = db->pDfltColl; } } pKeyInfo->aSortOrder = (u8*)apColl; for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ for(i=0; i<2; i++){ int addr = pLoop->addrOpenEphm[i]; if( addr<0 ){ /* If [0] is unused then [1] is also unused. So we can ** always safely abort as soon as the first unused slot is found */ |
︙ | ︙ | |||
1961 1962 1963 1964 1965 1966 1967 | if( regPrev ){ int j1, j2; j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, (char*)pKeyInfo, p4type); sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); sqlite3VdbeJumpHere(v, j1); | | | 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 | if( regPrev ){ int j1, j2; j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, (char*)pKeyInfo, p4type); sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); } if( pParse->db->mallocFailed ) return 0; /* Suppress the first OFFSET entries if there is an OFFSET clause */ codeOffset(v, p, iContinue); |
︙ | ︙ | |||
1996 1997 1998 1999 2000 2001 2002 | /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { int r1; assert( pIn->nSdst==1 ); | | | | 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 | /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { int r1; assert( pIn->nSdst==1 ); pDest->affSdst = sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1); sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; } #if 0 /* Never occurs on an ORDER BY query */ |
︙ | ︙ | |||
2741 2742 2743 2744 2745 2746 2747 | struct SrcList_item *pSubitem; /* The subquery */ sqlite3 *db = pParse->db; /* Check to see if flattening is permitted. Return 0 if not. */ assert( p!=0 ); assert( p->pPrior==0 ); /* Unable to flatten compound queries */ | | | 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 | struct SrcList_item *pSubitem; /* The subquery */ sqlite3 *db = pParse->db; /* Check to see if flattening is permitted. Return 0 if not. */ assert( p!=0 ); assert( p->pPrior==0 ); /* Unable to flatten compound queries */ if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; pSrc = p->pSrc; assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc ); pSubitem = &pSrc->a[iFrom]; iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ |
︙ | ︙ | |||
3781 3782 3783 3784 3785 3786 3787 | int isAgg; /* True for select lists like "count(*)" */ ExprList *pEList; /* List of columns to extract. */ SrcList *pTabList; /* List of tables to select from */ Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ Expr *pHaving; /* The HAVING clause. May be NULL */ | < < | | 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 | int isAgg; /* True for select lists like "count(*)" */ ExprList *pEList; /* List of columns to extract. */ SrcList *pTabList; /* List of tables to select from */ Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ Expr *pHaving; /* The HAVING clause. May be NULL */ int rc = 1; /* Value to return from this function */ int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */ DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */ AggInfo sAggInfo; /* Information used by aggregate queries */ int iEnd; /* Address of the end of the query */ sqlite3 *db; /* The database connection */ #ifndef SQLITE_OMIT_EXPLAIN int iRestoreSelectId = pParse->iSelectId; pParse->iSelectId = pParse->iNextSelectId++; |
︙ | ︙ | |||
3911 3912 3913 3914 3915 3916 3917 | } } pEList = p->pEList; #endif pWhere = p->pWhere; pGroupBy = p->pGroupBy; pHaving = p->pHaving; | | | 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 | } } pEList = p->pEList; #endif pWhere = p->pWhere; pGroupBy = p->pGroupBy; pHaving = p->pHaving; sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; #ifndef SQLITE_OMIT_COMPOUND_SELECT /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ if( p->pRightmost==0 ){ Select *pLoop, *pRight = 0; |
︙ | ︙ | |||
3946 3947 3948 3949 3950 3951 3952 | ** identical, then disable the ORDER BY clause since the GROUP BY ** will cause elements to come out in the correct order. This is ** an optimization - the correct answer should result regardless. ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER ** to disable this optimization for testing purposes. */ if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0 | | | 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 | ** identical, then disable the ORDER BY clause since the GROUP BY ** will cause elements to come out in the correct order. This is ** an optimization - the correct answer should result regardless. ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER ** to disable this optimization for testing purposes. */ if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0 && OptimizationEnabled(db, SQLITE_GroupByOrder) ){ pOrderBy = 0; } /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and ** if the select-list is the same as the ORDER BY list, then this query ** can be rewritten as a GROUP BY. In other words, this: ** |
︙ | ︙ | |||
3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 | if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && sqlite3ExprListCompare(pOrderBy, p->pEList)==0 ){ p->selFlags &= ~SF_Distinct; p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); pGroupBy = p->pGroupBy; pOrderBy = 0; } /* If there is an ORDER BY clause, then this sorting ** index might end up being unused if the data can be ** extracted in pre-sorted order. If that is the case, then the ** OP_OpenEphemeral instruction will be changed to an OP_Noop once ** we figure out that the sorting index is not needed. The addrSortIndex | > > > > | 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 | if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && sqlite3ExprListCompare(pOrderBy, p->pEList)==0 ){ p->selFlags &= ~SF_Distinct; p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); pGroupBy = p->pGroupBy; pOrderBy = 0; /* Notice that even thought SF_Distinct has been cleared from p->selFlags, ** the sDistinct.isTnct is still set. Hence, isTnct represents the ** original setting of the SF_Distinct flag, not the current setting */ assert( sDistinct.isTnct ); } /* If there is an ORDER BY clause, then this sorting ** index might end up being unused if the data can be ** extracted in pre-sorted order. If that is the case, then the ** OP_OpenEphemeral instruction will be changed to an OP_Noop once ** we figure out that the sorting index is not needed. The addrSortIndex |
︙ | ︙ | |||
4012 4013 4014 4015 4016 4017 4018 | sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen; p->selFlags |= SF_UseSorter; } /* Open a virtual index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ | < | > > | < | > | < > | | > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 | sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen; p->selFlags |= SF_UseSorter; } /* Open a virtual index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ sDistinct.tabTnct = pParse->nTab++; sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sDistinct.tabTnct, 0, 0, (char*)keyInfoFromExprList(pParse, p->pEList), P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; }else{ sDistinct.eTnctType = WHERE_DISTINCT_NOOP; } if( !isAgg && pGroupBy==0 ){ /* No aggregate functions and no GROUP BY clause */ ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0); /* Begin the database scan. */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0); if( pWInfo==0 ) goto select_end; if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut; if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct; if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0; /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( addrSortIndex>=0 && pOrderBy==0 ){ sqlite3VdbeChangeToNoop(v, addrSortIndex); p->addrOpenEphm[2] = -1; } /* Use the standard inner loop. */ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest, pWInfo->iContinue, pWInfo->iBreak); /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); }else{ /* This case when there exist aggregate functions or a GROUP BY clause ** or both */ NameContext sNC; /* Name context for processing aggregate information */ int iAMem; /* First Mem address for storing current GROUP BY */ int iBMem; /* First Mem address for previous GROUP BY */ int iUseFlag; /* Mem address holding flag indicating that at least ** one row of the input to the aggregator has been ** processed */ int iAbortFlag; /* Mem address which causes query abort if positive */ |
︙ | ︙ | |||
4200 4201 4202 4203 4204 4205 4206 | /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); | | | < | > | 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 | /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0); if( pWInfo==0 ) goto select_end; if( pWInfo->nOBSat==pGroupBy->nExpr ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo */ groupBySort = 0; }else{ /* Rows are coming out in undetermined order. We have to push ** each row into a sorting index, terminate the first loop, ** then loop over the sorting index in order to get the output ** in sorted order */ int regBase; int regRecord; int nCol; int nGroupBy; explainTempTable(pParse, (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ? "DISTINCT" : "GROUP BY"); groupBySort = 1; nGroupBy = pGroupBy->nExpr; nCol = nGroupBy + 1; j = nGroupBy+1; for(i=0; i<sAggInfo.nColumn; i++){ if( sAggInfo.aCol[i].iSorterColumn>=j ){ |
︙ | ︙ | |||
4353 4354 4355 4356 4357 4358 4359 | addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, &sAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, | | | 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 | addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, &sAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, &sDistinct, pDest, addrOutputRow+1, addrSetAbort); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); VdbeComment((v, "end groupby result generator")); /* Generate a subroutine that will reset the group-by accumulator */ sqlite3VdbeResolveLabel(v, addrReset); |
︙ | ︙ | |||
4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 | ** satisfying the 'ORDER BY' clause than it does in other cases. ** Refer to code and comments in where.c for details. */ ExprList *pMinMax = 0; u8 flag = minMaxQuery(p); if( flag ){ assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); pDel = pMinMax; if( pMinMax && !db->mallocFailed ){ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; pMinMax->a[0].pExpr->op = TK_COLUMN; } } /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); | > | | > | | | 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 | ** satisfying the 'ORDER BY' clause than it does in other cases. ** Refer to code and comments in where.c for details. */ ExprList *pMinMax = 0; u8 flag = minMaxQuery(p); if( flag ){ assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 ); pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); pDel = pMinMax; if( pMinMax && !db->mallocFailed ){ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; pMinMax->a[0].pExpr->op = TK_COLUMN; } } /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0); if( pWInfo==0 ){ sqlite3ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); assert( pMinMax==0 || pMinMax->nExpr==1 ); if( pWInfo->nOBSat>0 ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max"))); } sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); } pOrderBy = 0; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0, pDest, addrEnd, addrEnd); sqlite3ExprListDelete(db, pDel); } sqlite3VdbeResolveLabel(v, addrEnd); } /* endif aggregate query */ if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){ explainTempTable(pParse, "DISTINCT"); } /* If there is an ORDER BY clause, then we need to sort the results ** and send them to the callback one by one. */ if( pOrderBy ){ |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
692 693 694 695 696 697 698 | for(i=0; i<nArg; i++){ int w, n; if( i<ArraySize(p->colWidth) ){ w = p->colWidth[i]; }else{ w = 0; } | | > > > | > > | 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | for(i=0; i<nArg; i++){ int w, n; if( i<ArraySize(p->colWidth) ){ w = p->colWidth[i]; }else{ w = 0; } if( w==0 ){ w = strlen30(azCol[i] ? azCol[i] : ""); if( w<10 ) w = 10; n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue); if( w<n ) w = n; } if( i<ArraySize(p->actualWidth) ){ p->actualWidth[i] = w; } if( p->showHeader ){ if( w<0 ){ fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], i==nArg-1 ? "\n": " "); }else{ fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); } } } if( p->showHeader ){ for(i=0; i<nArg; i++){ int w; if( i<ArraySize(p->actualWidth) ){ w = p->actualWidth[i]; if( w<0 ) w = -w; }else{ w = 10; } fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" "----------------------------------------------------------", i==nArg-1 ? "\n": " "); } |
︙ | ︙ | |||
731 732 733 734 735 736 737 | }else{ w = 10; } if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ w = strlen30(azArg[i]); } | > > > > | | > | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 | }else{ w = 10; } if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ w = strlen30(azArg[i]); } if( w<0 ){ fprintf(p->out,"%*.*s%s",-w,-w, azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); }else{ fprintf(p->out,"%-*.*s%s",w,w, azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); } } break; } case MODE_Semi: case MODE_List: { if( p->cnt++==0 && p->showHeader ){ for(i=0; i<nArg; i++){ |
︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 | " column Left-aligned columns. (See .width)\n" " html HTML <table> code\n" " insert SQL insert statements for TABLE\n" " line One value per line\n" " list Values delimited by .separator string\n" " tabs Tab-separated values\n" " tcl TCL list elements\n" | | > | 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 | " column Left-aligned columns. (See .width)\n" " html HTML <table> code\n" " insert SQL insert statements for TABLE\n" " line One value per line\n" " list Values delimited by .separator string\n" " tabs Tab-separated values\n" " tcl TCL list elements\n" ".nullvalue STRING Use STRING in place of NULL values\n" ".output FILENAME Send output to FILENAME\n" ".output stdout Send output to the screen\n" ".print STRING... Print literal STRING\n" ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" ".schema ?TABLE? Show the CREATE statements\n" " If TABLE specified, only show tables matching\n" " LIKE pattern TABLE.\n" |
︙ | ︙ | |||
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 | p->out = stdout; rc = 1; } else { sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); } } }else if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ if( nArg >= 2) { strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); } if( nArg >= 3) { strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); | > > > > > > > > > | 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 | p->out = stdout; rc = 1; } else { sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); } } }else if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){ int i; for(i=1; i<nArg; i++){ if( i>1 ) fprintf(p->out, " "); fprintf(p->out, "%s", azArg[i]); } fprintf(p->out, "\n"); }else if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ if( nArg >= 2) { strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); } if( nArg >= 3) { strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); |
︙ | ︙ | |||
2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 | sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); if( zVfsName ){ printf("%s\n", zVfsName); sqlite3_free(zVfsName); } } }else if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){ int j; assert( nArg<=ArraySize(azArg) ); for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ p->colWidth[j-1] = atoi(azArg[j]); } | > > > > > > > | 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 | sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); if( zVfsName ){ printf("%s\n", zVfsName); sqlite3_free(zVfsName); } } }else #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ extern int sqlite3WhereTrace; sqlite3WhereTrace = atoi(azArg[1]); }else #endif if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){ int j; assert( nArg<=ArraySize(azArg) ); for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ p->colWidth[j-1] = atoi(azArg[j]); } |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
469 470 471 472 473 474 475 476 477 478 479 480 481 482 | #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations | > | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations |
︙ | ︙ | |||
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ | > > > > > > > > > > > > | 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN ** <dd> This option taks a single integer argument which is interpreted as ** a boolean in order to enable or disable the use of covering indices for ** full table scans in the query optimizer. The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ |
︙ | ︙ | |||
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** | > | 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
︙ | ︙ | |||
2596 2597 2598 2599 2600 2601 2602 | ** the value passed as the fourth parameter to sqlite3_open_v2(). ** ** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw", ** "rwc", or "memory". Attempting to set it to any other value is ** an error)^. ** ^If "ro" is specified, then the database is opened for read-only ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the | | | 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 | ** the value passed as the fourth parameter to sqlite3_open_v2(). ** ** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw", ** "rwc", or "memory". Attempting to set it to any other value is ** an error)^. ** ^If "ro" is specified, then the database is opened for read-only ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the ** third argument to sqlite3_open_v2(). ^If the mode option is set to ** "rw", then the database is opened for read-write (but not create) ** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had ** been set. ^Value "rwc" is equivalent to setting both ** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is ** set to "memory" then a pure [in-memory database] that never reads ** or writes from disk is used. ^It is an error to specify a value for ** the mode parameter that is less restrictive than that specified by |
︙ | ︙ | |||
2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 | ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. ** When that happens, the second error will be reported since these ** interfaces always report the most recent result. To avoid ** this, each thread can obtain exclusive use of the [database connection] D ** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning ** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after ** all calls to the interfaces listed here are completed. ** ** If an interface fails with SQLITE_MISUSE, that means the interface ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ int sqlite3_errcode(sqlite3 *db); int sqlite3_extended_errcode(sqlite3 *db); const char *sqlite3_errmsg(sqlite3*); const void *sqlite3_errmsg16(sqlite3*); /* ** CAPI3REF: SQL Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** ** An instance of this object represents a single SQL statement. ** This object is variously known as a "prepared statement" or a | > > > > > > | 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 | ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** ** ^The sqlite3_errstr() interface returns the English-language text ** that describes the [result code], as UTF-8. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. ** When that happens, the second error will be reported since these ** interfaces always report the most recent result. To avoid ** this, each thread can obtain exclusive use of the [database connection] D ** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning ** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after ** all calls to the interfaces listed here are completed. ** ** If an interface fails with SQLITE_MISUSE, that means the interface ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ int sqlite3_errcode(sqlite3 *db); int sqlite3_extended_errcode(sqlite3 *db); const char *sqlite3_errmsg(sqlite3*); const void *sqlite3_errmsg16(sqlite3*); const char *sqlite3_errstr(int); /* ** CAPI3REF: SQL Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** ** An instance of this object represents a single SQL statement. ** This object is variously known as a "prepared statement" or a |
︙ | ︙ | |||
4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 | ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** ** ^Note: This method is deprecated on MacOS X 10.7 and iOS version 5.0 ** and will always return SQLITE_MISUSE, instead of calling this function ** shared cache mode should be enabled per-database connection via ** sqlite3_open_v2 with SQLITE_OPEN_SHAREDCACHE instead. ** ** See Also: [SQLite Shared-Cache Mode] */ int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory | > > > | 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 | ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** ** ^Note: This method is deprecated on MacOS X 10.7 and iOS version 5.0 ** and will always return SQLITE_MISUSE, instead of calling this function ** shared cache mode should be enabled per-database connection via ** sqlite3_open_v2 with SQLITE_OPEN_SHAREDCACHE instead. ** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** ** See Also: [SQLite Shared-Cache Mode] */ int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory |
︙ | ︙ |
Added src/sqlite3.rc.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | /* ** 2012 September 2 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code and resources that are specific to Windows. */ #if !defined(_WIN32_WCE) #include "winresrc.h" #else #include "windows.h" #endif #include "sqlite3.h" #include "sqlite3rc.h" /* * English (U.S.) resources */ #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif /* _WIN32 */ /* * Version */ VS_VERSION_INFO VERSIONINFO FILEVERSION SQLITE_RESOURCE_VERSION PRODUCTVERSION SQLITE_RESOURCE_VERSION FILEFLAGSMASK 0x3F #if defined(_DEBUG) FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "SQLite Development Team" VALUE "FileDescription", "SQLite is a software library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine." VALUE "FileVersion", SQLITE_VERSION VALUE "InternalName", "sqlite3" VALUE "LegalCopyright", "http://www.sqlite.org/copyright.html" VALUE "ProductName", "SQLite" VALUE "ProductVersion", SQLITE_VERSION VALUE "SourceId", SQLITE_SOURCE_ID END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
657 658 659 660 661 662 663 664 665 666 667 668 669 670 | typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; | > | 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 | typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; typedef struct SelectDest SelectDest; typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; |
︙ | ︙ | |||
832 833 834 835 836 837 838 839 840 841 842 843 844 845 | Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ | > | 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ u8 dbOptFlags; /* Flags to enable/disable optimizations */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
︙ | ︙ | |||
936 937 938 939 940 941 942 | ** A macro to discover the encoding of a database. */ #define ENC(db) ((db)->aDb[0].pSchema->enc) /* ** Possible values for the sqlite3.flags. */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < | | | | > > > | > > > > > > > > > > | 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 | ** A macro to discover the encoding of a database. */ #define ENC(db) ((db)->aDb[0].pSchema->enc) /* ** Possible values for the sqlite3.flags. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ #define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ #define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ #define SQLITE_ShortColNames 0x00000008 /* Show short columns names */ #define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */ #define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */ #define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */ /* 0x00000200 Unused */ #define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */ #define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */ #define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */ #define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */ #define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */ #define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */ #define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */ #define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ #define SQLITE_ColumnCache 0x0002 /* Column cache */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_AllOpts 0x00ff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) #else #define OptimizationDisabled(db, mask) 0 #define OptimizationEnabled(db, mask) 1 #endif /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ #define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ |
︙ | ︙ | |||
1128 1129 1130 1131 1132 1133 1134 | */ struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ | | < < < < > > > > > > | 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 | */ struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; /* Allowed values for Column.colFlags: */ #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** ** There may two separate implementations of the collation function, one ** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that |
︙ | ︙ | |||
1291 1292 1293 1294 1295 1296 1297 | ** refers VDBE cursor number that holds the table open, not to the root ** page number. Transient tables are used to hold the results of a ** sub-query that appears instead of a real table name in the FROM clause ** of a SELECT statement. */ struct Table { char *zName; /* Name of the table or view */ | < < < < < < < > > > > > > > < > | 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 | ** refers VDBE cursor number that holds the table open, not to the root ** page number. Transient tables are used to hold the results of a ** sub-query that appears instead of a real table name in the FROM clause ** of a SELECT statement. */ struct Table { char *zName; /* Name of the table or view */ Column *aCol; /* Information about each column */ Index *pIndex; /* List of SQL indexes on this table. */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ #ifndef SQLITE_OMIT_CHECK ExprList *pCheck; /* All CHECK constraints */ #endif tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ int tnum; /* Root BTree node for this table (see note above) */ i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE int nModuleArg; /* Number of arguments to the module */ char **azModuleArg; /* Text of all module args. [0] is module name */ VTable *pVTable; /* List of VTable objects. */ #endif Trigger *pTrigger; /* List of triggers stored in pSchema */ Schema *pSchema; /* Schema that contains this table */ Table *pNextZombie; /* Next on the Parse.pZombieTab list */ }; /* |
︙ | ︙ | |||
1336 1337 1338 1339 1340 1341 1342 | /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) | | | 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 | /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) # define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) #else # define IsVirtual(X) 0 # define IsHiddenColumn(X) 0 #endif /* ** Each foreign key constraint is an instance of the following structure. |
︙ | ︙ | |||
1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 | CollSeq *pColl; /* The collation type of the column or 0 */ /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 flags2; /* Second set of flags. EP2_... */ u8 op2; /* TK_REGISTER: original value of Expr.op ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. */ | > > > < < < | 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 | CollSeq *pColl; /* The collation type of the column or 0 */ /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ #if SQLITE_MAX_EXPR_DEPTH>0 int nHeight; /* Height of the tree headed by this node */ #endif int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 flags2; /* Second set of flags. EP2_... */ u8 op2; /* TK_REGISTER: original value of Expr.op ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. */ }; /* ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */ #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ |
︙ | ︙ | |||
1911 1912 1913 1914 1915 1916 1917 | ** Within the union, pIdx is only used when wsFlags&WHERE_INDEXED is true. ** pTerm is only used when wsFlags&WHERE_MULTI_OR is true. And pVtabIdx ** is only used when wsFlags&WHERE_VIRTUALTABLE is true. It is never the ** case that more than one of these conditions is true. */ struct WherePlan { u32 wsFlags; /* WHERE_* flags that describe the strategy */ | | > | 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 | ** Within the union, pIdx is only used when wsFlags&WHERE_INDEXED is true. ** pTerm is only used when wsFlags&WHERE_MULTI_OR is true. And pVtabIdx ** is only used when wsFlags&WHERE_VIRTUALTABLE is true. It is never the ** case that more than one of these conditions is true. */ struct WherePlan { u32 wsFlags; /* WHERE_* flags that describe the strategy */ u16 nEq; /* Number of == constraints */ u16 nOBSat; /* Number of ORDER BY terms satisfied */ double nRow; /* Estimated number of rows (for EQP) */ union { Index *pIdx; /* Index when WHERE_INDEXED is true */ struct WhereTerm *pTerm; /* WHERE clause term for OR-search */ sqlite3_index_info *pVtabIdx; /* Virtual table index to use */ } u; }; |
︙ | ︙ | |||
1987 1988 1989 1990 1991 1992 1993 | ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. */ struct WhereInfo { | | > > | | | | < | | | | | | | | > > | | > | 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 | ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. */ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int nLevel; /* Number of nested loop */ struct WhereClause *pWC; /* Decomposition of the WHERE clause */ double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ double nRowOut; /* Estimated number of output rows */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; /* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */ #define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */ #define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */ #define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */ #define WHERE_DISTINCT_UNORDERED 3 /* Duplicates are scattered */ /* ** A NameContext defines a context in which to resolve table and column ** names. The context consists of a list of tables (the pSrcList) field and ** a list of named expression (pEList). The named expression list may ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or ** to the table being operated on by INSERT, UPDATE, or DELETE. The |
︙ | ︙ | |||
2063 2064 2065 2066 2067 2068 2069 | ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. ** These addresses must be stored so that we can go back and fill in ** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor ** the number of columns in P2 can be computed at the same time ** as the OP_OpenEphm instruction is coded because not ** enough information about the compound query is known at that point. ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences | | < | 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 | ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. ** These addresses must be stored so that we can go back and fill in ** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor ** the number of columns in P2 can be computed at the same time ** as the OP_OpenEphm instruction is coded because not ** enough information about the compound query is known at that point. ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences ** for the result set. The KeyInfo for addrOpenEphm[2] contains collating ** sequences for the ORDER BY clause. */ struct Select { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ u16 selFlags; /* Various SF_* values */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */ double nSelectRow; /* Estimated number of result rows */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ |
︙ | ︙ | |||
2120 2121 2122 2123 2124 2125 2126 | #define SRT_Mem 6 /* Store result in a memory cell */ #define SRT_Set 7 /* Store results as keys in an index */ #define SRT_Table 8 /* Store result as data with an automatic rowid */ #define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */ #define SRT_Coroutine 10 /* Generate a single row of result */ /* | | | < | | | 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 | #define SRT_Mem 6 /* Store result in a memory cell */ #define SRT_Set 7 /* Store results as keys in an index */ #define SRT_Table 8 /* Store result as data with an automatic rowid */ #define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */ #define SRT_Coroutine 10 /* Generate a single row of result */ /* ** An instance of this object describes where to put of the results of ** a SELECT statement. */ struct SelectDest { u8 eDest; /* How to dispose of the results. On of SRT_* above. */ char affSdst; /* Affinity used when eDest==SRT_Set */ int iSDParm; /* A parameter used by the eDest disposal method */ int iSdst; /* Base register where results are written */ int nSdst; /* Number of registers allocated */ }; /* ** During code generation of statements that do inserts into AUTOINCREMENT |
︙ | ︙ | |||
2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 | ** This structure also contains some state information. */ struct Sqlite3Config { int bMemstat; /* True to enable memory status */ int bCoreMutex; /* True to enable core mutexing */ int bFullMutex; /* True to enable full mutexing */ int bOpenUri; /* True to interpret filenames as URIs */ int mxStrlen; /* Maximum string length */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ void *pHeap; /* Heap storage space */ | > | 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 | ** This structure also contains some state information. */ struct Sqlite3Config { int bMemstat; /* True to enable memory status */ int bCoreMutex; /* True to enable core mutexing */ int bFullMutex; /* True to enable full mutexing */ int bOpenUri; /* True to interpret filenames as URIs */ int bUseCis; /* Use covering indices for full-scans */ int mxStrlen; /* Maximum string length */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ void *pHeap; /* Heap storage space */ |
︙ | ︙ | |||
2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 | #ifndef SQLITE_OMIT_AUTOINCREMENT void sqlite3AutoincrementBegin(Parse *pParse); void sqlite3AutoincrementEnd(Parse *pParse); #else # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) #endif void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, | > | 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 | #ifndef SQLITE_OMIT_AUTOINCREMENT void sqlite3AutoincrementBegin(Parse *pParse); void sqlite3AutoincrementEnd(Parse *pParse); #else # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) #endif int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, |
︙ | ︙ | |||
2813 2814 2815 2816 2817 2818 2819 | int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *); #endif void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); | | < < | 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 | int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *); #endif void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCacheStore(Parse*, int, int, int); void sqlite3ExprCachePush(Parse*); void sqlite3ExprCachePop(Parse*, int); void sqlite3ExprCacheRemove(Parse*, int, int); void sqlite3ExprCacheClear(Parse*); void sqlite3ExprCacheAffinityChange(Parse*, int, int); int sqlite3ExprCode(Parse*, Expr*, int); |
︙ | ︙ | |||
2959 2960 2961 2962 2963 2964 2965 | int sqlite3FixExprList(DbFixer*, ExprList*); int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); int sqlite3AtoF(const char *z, double*, int, u8); int sqlite3GetInt32(const char *, int*); int sqlite3Atoi(const char*); int sqlite3Utf16ByteLen(const void *pData, int nChar); int sqlite3Utf8CharLen(const char *pData, int nByte); | | | 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 | int sqlite3FixExprList(DbFixer*, ExprList*); int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); int sqlite3AtoF(const char *z, double*, int, u8); int sqlite3GetInt32(const char *, int*); int sqlite3Atoi(const char*); int sqlite3Utf16ByteLen(const void *pData, int nChar); int sqlite3Utf8CharLen(const char *pData, int nByte); u32 sqlite3Utf8Read(const u8**); /* ** Routines to read and write variable-length integers. These used to ** be defined locally, but now we use the varint routines in the util.c ** file. Code should use the MACRO forms below, as the Varint32 versions ** are coded to assume the single byte case is already handled (which ** the MACRO form does). |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
2554 2555 2556 2557 2558 2559 2560 | Tcl_WrongNumArgs(interp, 2, objv, "KEY"); return TCL_ERROR; } #ifdef SQLITE_HAS_CODEC pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); rc = sqlite3_rekey(pDb->db, pKey, nKey); if( rc ){ | | | 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 | Tcl_WrongNumArgs(interp, 2, objv, "KEY"); return TCL_ERROR; } #ifdef SQLITE_HAS_CODEC pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); rc = sqlite3_rekey(pDb->db, pKey, nKey); if( rc ){ Tcl_AppendResult(interp, sqlite3_errstr(rc), 0); rc = TCL_ERROR; } #endif break; } /* $db restore ?DATABASE? FILENAME |
︙ | ︙ | |||
2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 | const char *zVfs = 0; int flags; Tcl_DString translatedFilename; #ifdef SQLITE_HAS_CODEC void *pKey = 0; int nKey = 0; #endif /* In normal use, each TCL interpreter runs in a single thread. So ** by default, we can turn of mutexing on SQLite database connections. ** However, for testing purposes it is useful to have mutexes turned ** on. So, by default, mutexes default off. But if compiled with ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on. */ | > | 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 | const char *zVfs = 0; int flags; Tcl_DString translatedFilename; #ifdef SQLITE_HAS_CODEC void *pKey = 0; int nKey = 0; #endif int rc; /* In normal use, each TCL interpreter runs in a single thread. So ** by default, we can turn of mutexing on SQLite database connections. ** However, for testing purposes it is useful to have mutexes turned ** on. So, by default, mutexes default off. But if compiled with ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on. */ |
︙ | ︙ | |||
3029 3030 3031 3032 3033 3034 3035 | if( p==0 ){ Tcl_SetResult(interp, "malloc failed", TCL_STATIC); return TCL_ERROR; } memset(p, 0, sizeof(*p)); zFile = Tcl_GetStringFromObj(objv[2], 0); zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); | | > | | | | > > > | 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 | if( p==0 ){ Tcl_SetResult(interp, "malloc failed", TCL_STATIC); return TCL_ERROR; } memset(p, 0, sizeof(*p)); zFile = Tcl_GetStringFromObj(objv[2], 0); zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs); Tcl_DStringFree(&translatedFilename); if( p->db ){ if( SQLITE_OK!=sqlite3_errcode(p->db) ){ zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); sqlite3_close(p->db); p->db = 0; } }else{ zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc)); } #ifdef SQLITE_HAS_CODEC if( p->db ){ sqlite3_key(p->db, pKey, nKey); } #endif if( p->db==0 ){ |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
6127 6128 6129 6130 6131 6132 6133 | const char *zOpt; int onoff; int mask = 0; static const struct { const char *zOptName; int mask; } aOpt[] = { | | < < < > > > | 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 | const char *zOpt; int onoff; int mask = 0; static const struct { const char *zOptName; int mask; } aOpt[] = { { "all", SQLITE_AllOpts }, { "query-flattener", SQLITE_QueryFlattener }, { "column-cache", SQLITE_ColumnCache }, { "groupby-order", SQLITE_GroupByOrder }, { "factor-constants", SQLITE_FactorOutConst }, { "real-as-int", SQLITE_IdxRealAsInt }, { "distinct-opt", SQLITE_DistinctOpt }, { "cover-idx-scan", SQLITE_CoverIdxScan }, { "order-by-idx-join",SQLITE_OrderByIdxJoin }, }; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |
︙ | ︙ |
Changes to src/test_malloc.c.
︙ | ︙ | |||
1090 1091 1092 1093 1094 1095 1096 | return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } /* | < < | | 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } /* ** Usage: sqlite3_config_heap NBYTE NMINALLOC */ static int test_config_heap( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ |
︙ | ︙ | |||
1129 1130 1131 1132 1133 1134 1135 | } Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); return TCL_OK; } /* | | | 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 | } Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); return TCL_OK; } /* ** Usage: sqlite3_config_error [DB] ** ** Invoke sqlite3_config() or sqlite3_db_config() with invalid ** opcodes and verify that they return errors. */ static int test_config_error( void * clientData, Tcl_Interp *interp, |
︙ | ︙ | |||
1167 1168 1169 1170 1171 1172 1173 | return TCL_ERROR; } } return TCL_OK; } /* | | | | | 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 | return TCL_ERROR; } } return TCL_OK; } /* ** Usage: sqlite3_config_uri BOOLEAN ** ** Enables or disables interpretation of URI parameters by default using ** SQLITE_CONFIG_URI. */ static int test_config_uri( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ |
︙ | ︙ | |||
1196 1197 1198 1199 1200 1201 1202 | rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); return TCL_OK; } /* | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 | rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); return TCL_OK; } /* ** Usage: sqlite3_config_cis BOOLEAN ** ** Enables or disables the use of the covering-index scan optimization. ** SQLITE_CONFIG_COVERING_INDEX_SCAN. */ static int test_config_cis( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int rc; int bUseCis; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); return TCL_ERROR; } if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){ return TCL_ERROR; } rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); return TCL_OK; } /* ** Usage: sqlite3_dump_memsys3 FILENAME ** sqlite3_dump_memsys5 FILENAME ** ** Write a summary of unfreed memsys3 allocations to FILENAME. */ static int test_dump_memsys3( void * clientData, Tcl_Interp *interp, int objc, |
︙ | ︙ | |||
1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | { "sqlite3_db_status", test_db_status ,0 }, { "install_malloc_faultsim", test_install_malloc_faultsim ,0 }, { "sqlite3_config_heap", test_config_heap ,0 }, { "sqlite3_config_memstatus", test_config_memstatus ,0 }, { "sqlite3_config_lookaside", test_config_lookaside ,0 }, { "sqlite3_config_error", test_config_error ,0 }, { "sqlite3_config_uri", test_config_uri ,0 }, { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 }, { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 }, { "sqlite3_install_memsys3", test_install_memsys3 ,0 }, { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 }, }; int i; | > | 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | { "sqlite3_db_status", test_db_status ,0 }, { "install_malloc_faultsim", test_install_malloc_faultsim ,0 }, { "sqlite3_config_heap", test_config_heap ,0 }, { "sqlite3_config_memstatus", test_config_memstatus ,0 }, { "sqlite3_config_lookaside", test_config_lookaside ,0 }, { "sqlite3_config_error", test_config_error ,0 }, { "sqlite3_config_uri", test_config_uri ,0 }, { "sqlite3_config_cis", test_config_cis ,0 }, { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 }, { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 }, { "sqlite3_install_memsys3", test_install_memsys3 ,0 }, { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 }, }; int i; |
︙ | ︙ |
Changes to src/test_spellfix.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | #include <ctype.h> /* ** Character classes for ASCII characters: ** ** 0 '' Silent letters: H W ** 1 'A' Any vowel: A E I O U (Y) | | < | | | | < | | | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <ctype.h> /* ** Character classes for ASCII characters: ** ** 0 '' Silent letters: H W ** 1 'A' Any vowel: A E I O U (Y) ** 2 'B' A bilabeal stop or fricative: B F P V W ** 3 'C' Other fricatives or back stops: C G J K Q S X Z ** 4 'D' Alveolar stops: D T ** 5 'H' Letter H at the beginning of a word ** 6 'L' Glide: L ** 7 'R' Semivowel: R ** 8 'M' Nasals: M N ** 9 'Y' Letter Y at the beginning of a word. ** 10 '9' Digits: 0 1 2 3 4 5 6 7 8 9 ** 11 ' ' White space ** 12 '?' Other. */ #define CCLASS_SILENT 0 #define CCLASS_VOWEL 1 #define CCLASS_B 2 #define CCLASS_C 3 #define CCLASS_D 4 #define CCLASS_H 5 #define CCLASS_L 6 #define CCLASS_R 7 #define CCLASS_M 8 #define CCLASS_Y 9 #define CCLASS_DIGIT 10 #define CCLASS_SPACE 11 #define CCLASS_OTHER 12 /* ** The following table gives the character class for non-initial ASCII ** characters. */ static const unsigned char midClass[] = { /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, |
︙ | ︙ | |||
88 89 90 91 92 93 94 | /* B */ CCLASS_B, /* C */ CCLASS_C, /* D */ CCLASS_D, /* E */ CCLASS_VOWEL, /* F */ CCLASS_B, /* G */ CCLASS_C, /* H */ CCLASS_SILENT, /* I */ CCLASS_VOWEL, /* J */ CCLASS_C, /* K */ CCLASS_C, /* L */ CCLASS_L, /* M */ CCLASS_M, /* N */ CCLASS_M, /* O */ CCLASS_VOWEL, /* P */ CCLASS_B, /* Q */ CCLASS_C, /* R */ CCLASS_R, /* S */ CCLASS_C, /* T */ CCLASS_D, /* U */ CCLASS_VOWEL, /* V */ CCLASS_B, | | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | /* B */ CCLASS_B, /* C */ CCLASS_C, /* D */ CCLASS_D, /* E */ CCLASS_VOWEL, /* F */ CCLASS_B, /* G */ CCLASS_C, /* H */ CCLASS_SILENT, /* I */ CCLASS_VOWEL, /* J */ CCLASS_C, /* K */ CCLASS_C, /* L */ CCLASS_L, /* M */ CCLASS_M, /* N */ CCLASS_M, /* O */ CCLASS_VOWEL, /* P */ CCLASS_B, /* Q */ CCLASS_C, /* R */ CCLASS_R, /* S */ CCLASS_C, /* T */ CCLASS_D, /* U */ CCLASS_VOWEL, /* V */ CCLASS_B, /* W */ CCLASS_B, /* X */ CCLASS_C, /* Y */ CCLASS_VOWEL, /* Z */ CCLASS_C, /* [ */ CCLASS_OTHER, /* \ */ CCLASS_OTHER, /* ] */ CCLASS_OTHER, /* ^ */ CCLASS_OTHER, /* _ */ CCLASS_OTHER, /* ` */ CCLASS_OTHER, /* a */ CCLASS_VOWEL, /* b */ CCLASS_B, /* c */ CCLASS_C, /* d */ CCLASS_D, /* e */ CCLASS_VOWEL, /* f */ CCLASS_B, /* g */ CCLASS_C, /* h */ CCLASS_SILENT, /* i */ CCLASS_VOWEL, /* j */ CCLASS_C, /* k */ CCLASS_C, /* l */ CCLASS_L, /* m */ CCLASS_M, /* n */ CCLASS_M, /* o */ CCLASS_VOWEL, /* p */ CCLASS_B, /* q */ CCLASS_C, /* r */ CCLASS_R, /* s */ CCLASS_C, /* t */ CCLASS_D, /* u */ CCLASS_VOWEL, /* v */ CCLASS_B, /* w */ CCLASS_B, /* x */ CCLASS_C, /* y */ CCLASS_VOWEL, /* z */ CCLASS_C, /* { */ CCLASS_OTHER, /* | */ CCLASS_OTHER, /* } */ CCLASS_OTHER, /* ~ */ CCLASS_OTHER, /* */ CCLASS_OTHER, }; /* ** This tables gives the character class for ASCII characters that form the ** initial character of a word. The only difference from midClass is with |
︙ | ︙ | |||
138 139 140 141 142 143 144 | /* B */ CCLASS_B, /* C */ CCLASS_C, /* D */ CCLASS_D, /* E */ CCLASS_VOWEL, /* F */ CCLASS_B, /* G */ CCLASS_C, /* H */ CCLASS_SILENT, /* I */ CCLASS_VOWEL, /* J */ CCLASS_C, /* K */ CCLASS_C, /* L */ CCLASS_L, /* M */ CCLASS_M, /* N */ CCLASS_M, /* O */ CCLASS_VOWEL, /* P */ CCLASS_B, /* Q */ CCLASS_C, /* R */ CCLASS_R, /* S */ CCLASS_C, /* T */ CCLASS_D, /* U */ CCLASS_VOWEL, /* V */ CCLASS_B, | | | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /* B */ CCLASS_B, /* C */ CCLASS_C, /* D */ CCLASS_D, /* E */ CCLASS_VOWEL, /* F */ CCLASS_B, /* G */ CCLASS_C, /* H */ CCLASS_SILENT, /* I */ CCLASS_VOWEL, /* J */ CCLASS_C, /* K */ CCLASS_C, /* L */ CCLASS_L, /* M */ CCLASS_M, /* N */ CCLASS_M, /* O */ CCLASS_VOWEL, /* P */ CCLASS_B, /* Q */ CCLASS_C, /* R */ CCLASS_R, /* S */ CCLASS_C, /* T */ CCLASS_D, /* U */ CCLASS_VOWEL, /* V */ CCLASS_B, /* W */ CCLASS_B, /* X */ CCLASS_C, /* Y */ CCLASS_Y, /* Z */ CCLASS_C, /* [ */ CCLASS_OTHER, /* \ */ CCLASS_OTHER, /* ] */ CCLASS_OTHER, /* ^ */ CCLASS_OTHER, /* _ */ CCLASS_OTHER, /* ` */ CCLASS_OTHER, /* a */ CCLASS_VOWEL, /* b */ CCLASS_B, /* c */ CCLASS_C, /* d */ CCLASS_D, /* e */ CCLASS_VOWEL, /* f */ CCLASS_B, /* g */ CCLASS_C, /* h */ CCLASS_SILENT, /* i */ CCLASS_VOWEL, /* j */ CCLASS_C, /* k */ CCLASS_C, /* l */ CCLASS_L, /* m */ CCLASS_M, /* n */ CCLASS_M, /* o */ CCLASS_VOWEL, /* p */ CCLASS_B, /* q */ CCLASS_C, /* r */ CCLASS_R, /* s */ CCLASS_C, /* t */ CCLASS_D, /* u */ CCLASS_VOWEL, /* v */ CCLASS_B, /* w */ CCLASS_B, /* x */ CCLASS_C, /* y */ CCLASS_Y, /* z */ CCLASS_C, /* { */ CCLASS_OTHER, /* | */ CCLASS_OTHER, /* } */ CCLASS_OTHER, /* ~ */ CCLASS_OTHER, /* */ CCLASS_OTHER, }; /* ** Mapping from the character class number (0-13) to a symbol for each ** character class. Note that initClass[] can be used to map the class ** symbol back into the class number. */ static const unsigned char className[] = ".ABCDHLRMY9 ?"; /* ** Generate a "phonetic hash" from a string of ASCII characters ** in zIn[0..nIn-1]. ** ** * Map characters by character class as defined above. ** * Omit double-letters |
︙ | ︙ | |||
1892 1893 1894 1895 1896 1897 1898 | const char *zModule = argv[0]; const char *zDbName = argv[1]; const char *zTableName = argv[2]; int nDbName; int rc = SQLITE_OK; int i; | | | 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 | const char *zModule = argv[0]; const char *zDbName = argv[1]; const char *zTableName = argv[2]; int nDbName; int rc = SQLITE_OK; int i; nDbName = (int)strlen(zDbName); pNew = sqlite3_malloc( sizeof(*pNew) + nDbName + 1); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ memset(pNew, 0, sizeof(*pNew)); pNew->zDbName = (char*)&pNew[1]; memcpy(pNew->zDbName, zDbName, nDbName+1); |
︙ | ︙ | |||
2232 2233 2234 2235 2236 2237 2238 | if( pCur->a==0 || p->rc ) return; /* Prior memory allocation failure */ zClass = (char*)phoneticHash((unsigned char*)zQuery, nQuery); if( zClass==0 ){ p->rc = SQLITE_NOMEM; return; } | | | 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 | if( pCur->a==0 || p->rc ) return; /* Prior memory allocation failure */ zClass = (char*)phoneticHash((unsigned char*)zQuery, nQuery); if( zClass==0 ){ p->rc = SQLITE_NOMEM; return; } nClass = (int)strlen(zClass); if( nClass>SPELLFIX_MX_HASH-2 ){ nClass = SPELLFIX_MX_HASH-2; zClass[nClass] = 0; } if( nClass<=iScope ){ if( nClass>2 ){ iScope = nClass-1; |
︙ | ︙ | |||
2406 2407 2408 2409 2410 2411 2412 | zPattern = (char*)transliterate(zMatchThis, sqlite3_value_bytes(argv[0])); sqlite3_free(pCur->zPattern); pCur->zPattern = zPattern; if( zPattern==0 ){ x.rc = SQLITE_NOMEM; goto filter_exit; } | | | 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 | zPattern = (char*)transliterate(zMatchThis, sqlite3_value_bytes(argv[0])); sqlite3_free(pCur->zPattern); pCur->zPattern = zPattern; if( zPattern==0 ){ x.rc = SQLITE_NOMEM; goto filter_exit; } nPattern = (int)strlen(zPattern); if( zPattern[nPattern-1]=='*' ) nPattern--; zSql = sqlite3_mprintf( "SELECT id, word, rank, k1" " FROM \"%w\".\"%w_vocab\"" " WHERE langid=%d AND k2>=?1 AND k2<?2", p->zDbName, p->zTableName, iLang ); |
︙ | ︙ | |||
2567 2568 2569 2570 2571 2572 2573 | case SPELLFIX_COL_SCORE: { sqlite3_result_int(ctx, pCur->a[pCur->iRow].iScore); break; } case SPELLFIX_COL_MATCHLEN: { int iMatchlen = pCur->a[pCur->iRow].iMatchlen; if( iMatchlen<0 ){ | | | | 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 | case SPELLFIX_COL_SCORE: { sqlite3_result_int(ctx, pCur->a[pCur->iRow].iScore); break; } case SPELLFIX_COL_MATCHLEN: { int iMatchlen = pCur->a[pCur->iRow].iMatchlen; if( iMatchlen<0 ){ int nPattern = (int)strlen(pCur->zPattern); char *zWord = pCur->a[pCur->iRow].zWord; int nWord = (int)strlen(zWord); if( nPattern>0 && pCur->zPattern[nPattern-1]=='*' ){ char *zTranslit; int res; zTranslit = (char *)transliterate((unsigned char *)zWord, nWord); if( !zTranslit ) return SQLITE_NOMEM; res = editdist1(pCur->zPattern, zTranslit, &iMatchlen); |
︙ | ︙ |
Changes to src/utf.c.
︙ | ︙ | |||
160 161 162 163 164 165 166 | c = (c<<6) + (0x3f & *(zIn++)); \ } \ if( c<0x80 \ || (c&0xFFFFF800)==0xD800 \ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ } u32 sqlite3Utf8Read( | < | | | | < | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | c = (c<<6) + (0x3f & *(zIn++)); \ } \ if( c<0x80 \ || (c&0xFFFFF800)==0xD800 \ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ } u32 sqlite3Utf8Read( const unsigned char **pz /* Pointer to string from which to read char */ ){ unsigned int c; /* Same as READ_UTF8() above but without the zTerm parameter. ** For this routine, we assume the UTF8 string is always zero-terminated. */ c = *((*pz)++); if( c>=0xc0 ){ c = sqlite3Utf8Trans1[c-0xc0]; while( (*(*pz) & 0xc0)==0x80 ){ c = (c<<6) + (0x3f & *((*pz)++)); } if( c<0x80 || (c&0xFFFFF800)==0xD800 || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } } return c; } /* |
︙ | ︙ | |||
279 280 281 282 283 284 285 | } z = zOut; if( pMem->enc==SQLITE_UTF8 ){ if( desiredEnc==SQLITE_UTF16LE ){ /* UTF-8 -> UTF-16 Little-endian */ while( zIn<zTerm ){ | < < | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | } z = zOut; if( pMem->enc==SQLITE_UTF8 ){ if( desiredEnc==SQLITE_UTF16LE ){ /* UTF-8 -> UTF-16 Little-endian */ while( zIn<zTerm ){ READ_UTF8(zIn, zTerm, c); WRITE_UTF16LE(z, c); } }else{ assert( desiredEnc==SQLITE_UTF16BE ); /* UTF-8 -> UTF-16 Big-endian */ while( zIn<zTerm ){ READ_UTF8(zIn, zTerm, c); WRITE_UTF16BE(z, c); } } pMem->n = (int)(z - zOut); *z++ = 0; }else{ |
︙ | ︙ | |||
415 416 417 418 419 420 421 | */ int sqlite3Utf8To8(unsigned char *zIn){ unsigned char *zOut = zIn; unsigned char *zStart = zIn; u32 c; while( zIn[0] && zOut<=zIn ){ | | | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | */ int sqlite3Utf8To8(unsigned char *zIn){ unsigned char *zOut = zIn; unsigned char *zStart = zIn; u32 c; while( zIn[0] && zOut<=zIn ){ c = sqlite3Utf8Read((const u8**)&zIn); if( c!=0xfffd ){ WRITE_UTF8(zOut, c); } } *zOut = 0; return (int)(zOut - zStart); } |
︙ | ︙ | |||
520 521 522 523 524 525 526 | for(i=0; i<0x00110000; i++){ z = zBuf; WRITE_UTF8(z, i); n = (int)(z-zBuf); assert( n>0 && n<=4 ); z[0] = 0; z = zBuf; | | | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | for(i=0; i<0x00110000; i++){ z = zBuf; WRITE_UTF8(z, i); n = (int)(z-zBuf); assert( n>0 && n<=4 ); z[0] = 0; z = zBuf; c = sqlite3Utf8Read((const u8**)&z); t = i; if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD; if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD; assert( c==t ); assert( (z-zBuf)==n ); } for(i=0; i<0x00110000; i++){ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
952 953 954 955 956 957 958 | pOut->z = pOp->p4.z; pOut->n = pOp->p1; pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; } | | | | > > > > > | | | 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 | pOut->z = pOp->p4.z; pOut->n = pOp->p1; pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; } /* Opcode: Null P1 P2 P3 * * ** ** Write a NULL into registers P2. If P3 greater than P2, then also write ** NULL into register P3 and every register in between P2 and P3. If P3 ** is less than P2 (typically P3 is zero) then only register P2 is ** set to NULL. ** ** If the P1 value is non-zero, then also set the MEM_Cleared flag so that ** NULL values will not compare equal even if SQLITE_NULLEQ is set on ** OP_Ne or OP_Eq. */ case OP_Null: { /* out2-prerelease */ int cnt; u16 nullFlag; cnt = pOp->p3-pOp->p2; assert( pOp->p3<=p->nMem ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); VdbeMemRelease(pOut); pOut->flags = nullFlag; cnt--; } break; } /* Opcode: Blob P1 P2 * P4 |
︙ | ︙ | |||
1011 1012 1013 1014 1015 1016 1017 | sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; } /* Opcode: Move P1 P2 P3 * * ** | | | | | | 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 | sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; } /* Opcode: Move P1 P2 P3 * * ** ** Move the values in register P1..P1+P3 over into ** registers P2..P2+P3. Registers P1..P1+P3 are ** left holding a NULL. It is an error for register ranges ** P1..P1+P3 and P2..P2+P3 to overlap. */ case OP_Move: { char *zMalloc; /* Holding variable for allocated memory */ int n; /* Number of registers left to copy */ int p1; /* Register to copy from */ int p2; /* Register to copy to */ n = pOp->p3 + 1; p1 = pOp->p1; p2 = pOp->p2; assert( n>0 && p1>0 && p2>0 ); assert( p1+n<=p2 || p2+n<=p1 ); pIn1 = &aMem[p1]; pOut = &aMem[p2]; |
︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 | REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; } break; } | | | | > > > > | | | > > > > | 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 | REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; } break; } /* Opcode: Copy P1 P2 P3 * * ** ** Make a copy of registers P1..P1+P3 into registers P2..P2+P3. ** ** This instruction makes a deep copy of the value. A duplicate ** is made of any string or blob constant. See also OP_SCopy. */ case OP_Copy: { int n; n = pOp->p3; pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); while( 1 ){ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); if( (n--)==0 ) break; pOut++; pIn1++; } break; } /* Opcode: SCopy P1 P2 * * * ** ** Make a shallow copy of register P1 into register P2. ** |
︙ | ︙ | |||
1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 | ** memcmp() is used to compare text string. If both values are ** numeric, then a numeric comparison is used. If the two values ** are of different types, then numbers are considered less than ** strings and strings are considered less than blobs. ** ** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead, ** store a boolean result (either 0, or 1, or NULL) in register P2. */ /* Opcode: Ne P1 P2 P3 P4 P5 ** ** This works just like the Lt opcode except that the jump is taken if ** the operands in registers P1 and P3 are not equal. See the Lt opcode for ** additional information. ** | > > > > | 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 | ** memcmp() is used to compare text string. If both values are ** numeric, then a numeric comparison is used. If the two values ** are of different types, then numbers are considered less than ** strings and strings are considered less than blobs. ** ** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead, ** store a boolean result (either 0, or 1, or NULL) in register P2. ** ** If the SQLITE_NULLEQ bit is set in P5, then NULL values are considered ** equal to one another, provided that they do not have their MEM_Cleared ** bit set. */ /* Opcode: Ne P1 P2 P3 P4 P5 ** ** This works just like the Lt opcode except that the jump is taken if ** the operands in registers P1 and P3 are not equal. See the Lt opcode for ** additional information. ** |
︙ | ︙ | |||
1799 1800 1801 1802 1803 1804 1805 | /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ /* If SQLITE_NULLEQ is set (which will only happen if the operator is ** OP_Eq or OP_Ne) then take the jump or not depending on whether ** or not both operands are null. */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); | | > > > > > > > > | 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 | /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ /* If SQLITE_NULLEQ is set (which will only happen if the operator is ** OP_Eq or OP_Ne) then take the jump or not depending on whether ** or not both operands are null. */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); if( (flags1&MEM_Null)!=0 && (flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 ){ res = 0; /* Results are equal */ }else{ res = 1; /* Results are not equal */ } }else{ /* SQLITE_NULLEQ is clear and at least one operand is NULL, ** then the result is always NULL. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. */ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; |
︙ | ︙ | |||
3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 | ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. */ case OP_SorterOpen: { VdbeCursor *pCx; #ifndef SQLITE_OMIT_MERGE_SORT pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; pCx->pKeyInfo->enc = ENC(p->db); pCx->isSorter = 1; rc = sqlite3VdbeSorterInit(db, pCx); | > | 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 | ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. */ case OP_SorterOpen: { VdbeCursor *pCx; #ifndef SQLITE_OMIT_MERGE_SORT pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; pCx->pKeyInfo->enc = ENC(p->db); pCx->isSorter = 1; rc = sqlite3VdbeSorterInit(db, pCx); |
︙ | ︙ | |||
4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 | /* Opcode: SorterData P1 P2 * * * ** ** Write into register P2 the current sorter data for sorter cursor P1. */ case OP_SorterData: { VdbeCursor *pC; #ifndef SQLITE_OMIT_MERGE_SORT pOut = &aMem[pOp->p2]; pC = p->apCsr[pOp->p1]; assert( pC->isSorter ); rc = sqlite3VdbeSorterRowkey(pC, pOut); #else pOp->opcode = OP_RowKey; | > | 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 | /* Opcode: SorterData P1 P2 * * * ** ** Write into register P2 the current sorter data for sorter cursor P1. */ case OP_SorterData: { VdbeCursor *pC; #ifndef SQLITE_OMIT_MERGE_SORT pOut = &aMem[pOp->p2]; pC = p->apCsr[pOp->p1]; assert( pC->isSorter ); rc = sqlite3VdbeSorterRowkey(pC, pOut); #else pOp->opcode = OP_RowKey; |
︙ | ︙ | |||
4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 | ** See also: Clear */ case OP_Destroy: { /* out2-prerelease */ int iMoved; int iCnt; Vdbe *pVdbe; int iDb; #ifndef SQLITE_OMIT_VIRTUALTABLE iCnt = 0; for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ iCnt++; } } | > | 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 | ** See also: Clear */ case OP_Destroy: { /* out2-prerelease */ int iMoved; int iCnt; Vdbe *pVdbe; int iDb; #ifndef SQLITE_OMIT_VIRTUALTABLE iCnt = 0; for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ iCnt++; } } |
︙ | ︙ | |||
5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 | ** Write a string containing the final journal-mode to register P2. */ case OP_JournalMode: { /* out2-prerelease */ Btree *pBt; /* Btree to change journal mode of */ Pager *pPager; /* Pager associated with pBt */ int eNew; /* New journal mode */ int eOld; /* The old journal mode */ const char *zFilename; /* Name of database file for pPager */ eNew = pOp->p3; assert( eNew==PAGER_JOURNALMODE_DELETE || eNew==PAGER_JOURNALMODE_TRUNCATE || eNew==PAGER_JOURNALMODE_PERSIST || eNew==PAGER_JOURNALMODE_OFF || eNew==PAGER_JOURNALMODE_MEMORY | > > | 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 | ** Write a string containing the final journal-mode to register P2. */ case OP_JournalMode: { /* out2-prerelease */ Btree *pBt; /* Btree to change journal mode of */ Pager *pPager; /* Pager associated with pBt */ int eNew; /* New journal mode */ int eOld; /* The old journal mode */ #ifndef SQLITE_OMIT_WAL const char *zFilename; /* Name of database file for pPager */ #endif eNew = pOp->p3; assert( eNew==PAGER_JOURNALMODE_DELETE || eNew==PAGER_JOURNALMODE_TRUNCATE || eNew==PAGER_JOURNALMODE_PERSIST || eNew==PAGER_JOURNALMODE_OFF || eNew==PAGER_JOURNALMODE_MEMORY |
︙ | ︙ | |||
6071 6072 6073 6074 6075 6076 6077 | ** If tracing is enabled (by the sqlite3_trace()) interface, then ** the UTF-8 string contained in P4 is emitted on the trace callback. */ case OP_Trace: { char *zTrace; char *z; | > > | > | 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 | ** If tracing is enabled (by the sqlite3_trace()) interface, then ** the UTF-8 string contained in P4 is emitted on the trace callback. */ case OP_Trace: { char *zTrace; char *z; if( db->xTrace && !p->doingRerun && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){ z = sqlite3VdbeExpandSql(p, zTrace); db->xTrace(db->pTraceArg, z); sqlite3DbFree(db, z); } #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
183 184 185 186 187 188 189 | #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ #define MEM_Invalid 0x0080 /* Value is undefined */ | > | > | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ #define MEM_Invalid 0x0080 /* Value is undefined */ #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ #define MEM_TypeMask 0x01ff /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of ** the following flags must be set to determine the memory management ** policy for Mem.z. The MEM_Term flag tells us whether or not the ** string is \000 or \u0000 terminated */ #define MEM_Term 0x0200 /* String rep is nul terminated */ |
︙ | ︙ | |||
269 270 271 272 273 274 275 276 277 278 279 280 281 282 | Vdbe *pVdbe; /* Attach the explanation to this Vdbe */ StrAccum str; /* The string being accumulated */ int nIndent; /* Number of elements in aIndent */ u16 aIndent[100]; /* Levels of indentation */ char zBase[100]; /* Initial space */ }; /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. ** | > > > > > | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | Vdbe *pVdbe; /* Attach the explanation to this Vdbe */ StrAccum str; /* The string being accumulated */ int nIndent; /* Number of elements in aIndent */ u16 aIndent[100]; /* Levels of indentation */ char zBase[100]; /* Initial space */ }; /* A bitfield type for use inside of structures. Always follow with :N where ** N is the number of bits. */ typedef unsigned bft; /* Bit Field Type */ /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. ** |
︙ | ︙ | |||
310 311 312 313 314 315 316 | char **azVar; /* Name of variables */ ynVar nVar; /* Number of entries in aVar[] */ ynVar nzVar; /* Number of entries in azVar[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ u8 errorAction; /* Recovery action to do in case of an error */ | > | > | | | < < | | | > | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | char **azVar; /* Name of variables */ ynVar nVar; /* Number of entries in aVar[] */ ynVar nzVar; /* Number of entries in azVar[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft inVtabMethod:2; /* See comments above */ bft changeCntOn:1; /* True to update the change-counter */ bft expired:1; /* True if the VM needs to be recompiled */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for read-only statements */ bft isPrepareV2:1; /* True if prepared with prepare_v2() */ bft doingRerun:1; /* True if rerunning after an auto-reprepare */ int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[3]; /* Counters used by sqlite3_stmt_status() */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | sqlite3 *db; /* The database connection */ if( vdbeSafetyNotNull(v) ){ return SQLITE_MISUSE_BKPT; } db = v->db; sqlite3_mutex_enter(db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < SQLITE_MAX_SCHEMA_RETRY && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ sqlite3_reset(pStmt); assert( v->expired==0 ); } if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ /* This case occurs after failing to recompile an sql statement. ** The error message from the SQL compiler has already been loaded ** into the database handle. This block copies the error message ** from the database handle into the statement and sets the statement | > > | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | sqlite3 *db; /* The database connection */ if( vdbeSafetyNotNull(v) ){ return SQLITE_MISUSE_BKPT; } db = v->db; sqlite3_mutex_enter(db->mutex); v->doingRerun = 0; while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < SQLITE_MAX_SCHEMA_RETRY && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ sqlite3_reset(pStmt); v->doingRerun = 1; assert( v->expired==0 ); } if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ /* This case occurs after failing to recompile an sql statement. ** The error message from the SQL compiler has already been loaded ** into the database handle. This block copies the error message ** from the database handle into the statement and sets the statement |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
741 742 743 744 745 746 747 | nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField; pKeyInfo = sqlite3DbMallocRaw(0, nByte); pOp->p4.pKeyInfo = pKeyInfo; if( pKeyInfo ){ u8 *aSortOrder; memcpy((char*)pKeyInfo, zP4, nByte - nField); aSortOrder = pKeyInfo->aSortOrder; | | | | < | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 | nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField; pKeyInfo = sqlite3DbMallocRaw(0, nByte); pOp->p4.pKeyInfo = pKeyInfo; if( pKeyInfo ){ u8 *aSortOrder; memcpy((char*)pKeyInfo, zP4, nByte - nField); aSortOrder = pKeyInfo->aSortOrder; assert( aSortOrder!=0 ); pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField]; memcpy(pKeyInfo->aSortOrder, aSortOrder, nField); pOp->p4type = P4_KEYINFO; }else{ p->db->mallocFailed = 1; pOp->p4type = P4_NOTUSED; } }else if( n==P4_KEYINFO_HANDOFF ){ pOp->p4.p = (void*)zP4; |
︙ | ︙ | |||
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 | char *zP4 = zTemp; assert( nTemp>=20 ); switch( pOp->p4type ){ case P4_KEYINFO_STATIC: case P4_KEYINFO: { int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); i = sqlite3Strlen30(zTemp); for(j=0; j<pKeyInfo->nField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; if( pColl ){ int n = sqlite3Strlen30(pColl->zName); if( i+n>nTemp-6 ){ memcpy(&zTemp[i],",...",4); break; } zTemp[i++] = ','; | > | | 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | char *zP4 = zTemp; assert( nTemp>=20 ); switch( pOp->p4type ){ case P4_KEYINFO_STATIC: case P4_KEYINFO: { int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); i = sqlite3Strlen30(zTemp); for(j=0; j<pKeyInfo->nField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; if( pColl ){ int n = sqlite3Strlen30(pColl->zName); if( i+n>nTemp-6 ){ memcpy(&zTemp[i],",...",4); break; } zTemp[i++] = ','; if( pKeyInfo->aSortOrder[j] ){ zTemp[i++] = '-'; } memcpy(&zTemp[i], pColl->zName,n+1); i += n; }else if( i+4<nTemp-6 ){ memcpy(&zTemp[i],",nil",4); i += 4; |
︙ | ︙ | |||
2581 2582 2583 2584 2585 2586 2587 | return 0; } if( flags&MEM_Int ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ # define MAX_6BYTE ((((i64)0x00008000)<<32)-1) i64 i = pMem->u.i; u64 u; | < < < | > > | 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 | return 0; } if( flags&MEM_Int ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ # define MAX_6BYTE ((((i64)0x00008000)<<32)-1) i64 i = pMem->u.i; u64 u; if( i<0 ){ if( i<(-MAX_6BYTE) ) return 6; /* Previous test prevents: u = -(-9223372036854775808) */ u = -i; }else{ u = i; } if( u<=127 ){ return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1; } if( u<=32767 ) return 2; if( u<=8388607 ) return 3; if( u<=2147483647 ) return 4; if( u<=MAX_6BYTE ) return 5; return 6; } if( flags&MEM_Real ){ |
︙ | ︙ | |||
2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 | if( !p ) return 0; }else{ p = (UnpackedRecord*)&pSpace[nOff]; *ppFree = 0; } p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nField + 1; return p; } /* ** Given the nKey-byte encoding of a record in pKey[], populate the | > | 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 | if( !p ) return 0; }else{ p = (UnpackedRecord*)&pSpace[nOff]; *ppFree = 0; } p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; assert( pKeyInfo->aSortOrder!=0 ); p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nField + 1; return p; } /* ** Given the nKey-byte encoding of a record in pKey[], populate the |
︙ | ︙ | |||
2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 | ** to ignore the compiler warnings and leave this variable uninitialized. */ /* mem1.u.i = 0; // not needed, here to silence compiler warning */ idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; nField = pKeyInfo->nField; while( idx1<szHdr1 && i<pPKey2->nField ){ u32 serial_type1; /* Read the serial types for the next element in each key. */ idx1 += getVarint32( aKey1+idx1, serial_type1 ); if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; /* Extract the values to be compared. */ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); /* Do the comparison */ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], i<nField ? pKeyInfo->aColl[i] : 0); if( rc!=0 ){ assert( mem1.zMalloc==0 ); /* See comment below */ /* Invert the result if we are using DESC sort order. */ | > | | 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 | ** to ignore the compiler warnings and leave this variable uninitialized. */ /* mem1.u.i = 0; // not needed, here to silence compiler warning */ idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; nField = pKeyInfo->nField; assert( pKeyInfo->aSortOrder!=0 ); while( idx1<szHdr1 && i<pPKey2->nField ){ u32 serial_type1; /* Read the serial types for the next element in each key. */ idx1 += getVarint32( aKey1+idx1, serial_type1 ); if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; /* Extract the values to be compared. */ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); /* Do the comparison */ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], i<nField ? pKeyInfo->aColl[i] : 0); if( rc!=0 ){ assert( mem1.zMalloc==0 ); /* See comment below */ /* Invert the result if we are using DESC sort order. */ if( i<nField && pKeyInfo->aSortOrder[i] ){ rc = -rc; } /* If the PREFIX_SEARCH flag is set and all fields except the final ** rowid field were equal, then clear the PREFIX_SEARCH flag and set ** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1). ** This is used by the OP_IsUnique opcode. |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
524 525 526 527 528 529 530 | sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; /* If everything went according to plan, link the new VTable structure ** into the linked list headed by pTab->pVTable. Then loop through the ** columns of the table to see if any of them contain the token "hidden". | | | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 | sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; /* If everything went according to plan, link the new VTable structure ** into the linked list headed by pTab->pVTable. Then loop through the ** columns of the table to see if any of them contain the token "hidden". ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from ** the type string. */ pVTable->pNext = pTab->pVTable; pTab->pVTable = pVTable; for(iCol=0; iCol<pTab->nCol; iCol++){ char *zType = pTab->aCol[iCol].zType; int nType; |
︙ | ︙ | |||
555 556 557 558 559 560 561 | for(j=i; (j+nDel)<=nType; j++){ zType[j] = zType[j+nDel]; } if( zType[i]=='\0' && i>0 ){ assert(zType[i-1]==' '); zType[i-1] = '\0'; } | | | 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 | for(j=i; (j+nDel)<=nType; j++){ zType[j] = zType[j+nDel]; } if( zType[i]=='\0' && i>0 ){ assert(zType[i-1]==' '); zType[i-1] = '\0'; } pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN; } } } } sqlite3DbFree(db, zModuleName); return rc; |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | #include "sqliteInt.h" /* ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) | | | > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include "sqliteInt.h" /* ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) /***/ int sqlite3WhereTrace = 0; #endif #if defined(SQLITE_DEBUG) \ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) # define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X #else # define WHERETRACE(X) #endif /* Forward reference */ |
︙ | ︙ | |||
260 261 262 263 264 265 266 267 268 269 270 271 272 273 | #define WHERE_ORDERBY 0x01000000 /* Output will appear in correct order */ #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */ #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */ #define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */ #define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */ #define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */ #define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */ /* ** Initialize a preallocated WhereClause structure. */ static void whereClauseInit( WhereClause *pWC, /* The WhereClause to be initialized */ Parse *pParse, /* The parsing context */ | > > > > > > > > > > > > > > > > > > > > > > > | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | #define WHERE_ORDERBY 0x01000000 /* Output will appear in correct order */ #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */ #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */ #define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */ #define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */ #define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */ #define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */ #define WHERE_COVER_SCAN 0x80000000 /* Full scan of a covering index */ /* ** This module contains many separate subroutines that work together to ** find the best indices to use for accessing a particular table in a query. ** An instance of the following structure holds context information about the ** index search so that it can be more easily passed between the various ** routines. */ typedef struct WhereBestIdx WhereBestIdx; struct WhereBestIdx { Parse *pParse; /* Parser context */ WhereClause *pWC; /* The WHERE clause */ struct SrcList_item *pSrc; /* The FROM clause term to search */ Bitmask notReady; /* Mask of cursors not available */ Bitmask notValid; /* Cursors not available for any purpose */ ExprList *pOrderBy; /* The ORDER BY clause */ ExprList *pDistinct; /* The select-list if query is DISTINCT */ sqlite3_index_info **ppIdxInfo; /* Index information passed to xBestIndex */ int i, n; /* Which loop is being coded; # of loops */ WhereLevel *aLevel; /* Info about outer loops */ WhereCost cost; /* Lowest cost query plan */ }; /* ** Initialize a preallocated WhereClause structure. */ static void whereClauseInit( WhereClause *pWC, /* The WhereClause to be initialized */ Parse *pParse, /* The parsing context */ |
︙ | ︙ | |||
1403 1404 1405 1406 1407 1408 1409 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } /* | | | | | < < | > | < < < > | | < | | 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } /* ** Return TRUE if the given index is UNIQUE and all columns past the ** first nSkip columns are NOT NULL. */ static int indexIsUniqueNotNull(Index *pIdx, int nSkip){ Table *pTab = pIdx->pTable; int i; if( pIdx->onError==OE_None ) return 0; for(i=nSkip; i<pIdx->nColumn; i++){ int j = pIdx->aiColumn[i]; if( j>=0 && pTab->aCol[j].notNull==0 ) return 0; } return 1; } /* ** This function searches the expression list passed as the second argument ** for an expression of type TK_COLUMN that refers to the same column and ** uses the same collation sequence as the iCol'th column of index pIdx. ** Argument iBase is the cursor number used for the table that pIdx refers |
︙ | ︙ | |||
1584 1585 1586 1587 1588 1589 1590 | } return 0; } /* ** This routine decides if pIdx can be used to satisfy the ORDER BY | | | > < < | > | > > > > | < < | < < > | < | | < | | > | > | | | | > > | > > > > > > > > > > > > > > | | | < | | 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 | } return 0; } /* ** This routine decides if pIdx can be used to satisfy the ORDER BY ** clause, either in whole or in part. The return value is the ** cumulative number of terms in the ORDER BY clause that are satisfied ** by the index pIdx and other indices in outer loops. ** ** The table being queried has a cursor number of "base". pIdx is the ** index that is postulated for use to access the table. ** ** nEqCol is the number of columns of pIdx that are used as equality ** constraints and where the other side of the == is an ordered column ** or constant. An "order column" in the previous sentence means a column ** in table from an outer loop whose values will always appear in the ** correct order due to othre index, or because the outer loop generates ** a unique result. Any of the first nEqCol columns of pIdx may be missing ** from the ORDER BY clause and the match can still be a success. ** ** The *pbRev value is set to 0 order 1 depending on whether or not ** pIdx should be run in the forward order or in reverse order. */ static int isSortingIndex( WhereBestIdx *p, /* Best index search context */ Index *pIdx, /* The index we are testing */ int base, /* Cursor number for the table to be sorted */ int nEqCol, /* Number of index columns with ordered == constraints */ int wsFlags, /* Index usages flags */ int bOuterRev, /* True if outer loops scan in reverse order */ int *pbRev /* Set to 1 for reverse-order scan of pIdx */ ){ int i; /* Number of pIdx terms used */ int j; /* Number of ORDER BY terms satisfied */ int sortOrder = 0; /* XOR of index and ORDER BY sort direction */ int nTerm; /* Number of ORDER BY terms */ struct ExprList_item *pTerm; /* A term of the ORDER BY clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Parse *pParse = p->pParse; /* Parser context */ sqlite3 *db = pParse->db; /* Database connection */ int nPriorSat; /* ORDER BY terms satisfied by outer loops */ int seenRowid = 0; /* True if an ORDER BY rowid term is seen */ int nEqOneRow; /* Idx columns that ref unique values */ if( p->i==0 ){ nPriorSat = 0; nEqOneRow = nEqCol; }else{ if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0; nPriorSat = p->aLevel[p->i-1].plan.nOBSat; sortOrder = bOuterRev; nEqOneRow = 0; } if( p->i>0 && nEqCol==0 /*&& !allOuterLoopsUnique(p)*/ ) return nPriorSat; pOrderBy = p->pOrderBy; if( !pOrderBy ) return nPriorSat; if( wsFlags & WHERE_COLUMN_IN ) return nPriorSat; if( pIdx->bUnordered ) return nPriorSat; nTerm = pOrderBy->nExpr; assert( nTerm>0 ); /* Argument pIdx must either point to a 'real' named index structure, ** or an index structure allocated on the stack by bestBtreeIndex() to ** represent the rowid index that is part of every table. */ assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) ); /* Match terms of the ORDER BY clause against columns of ** the index. ** ** Note that indices have pIdx->nColumn regular columns plus ** one additional column containing the rowid. The rowid column ** of the index is also allowed to match against the ORDER BY ** clause. */ for(i=0,j=nPriorSat,pTerm=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){ Expr *pExpr; /* The expression of the ORDER BY pTerm */ CollSeq *pColl; /* The collating sequence of pExpr */ int termSortOrder; /* Sort order for this term */ int iColumn; /* The i-th column of the index. -1 for rowid */ int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */ const char *zColl; /* Name of the collating sequence for i-th index term */ |
︙ | ︙ | |||
1681 1682 1683 1684 1685 1686 1687 | }else if( i==pIdx->nColumn ){ /* Index column i is the rowid. All other terms match. */ break; }else{ /* If an index column fails to match and is not constrained by == ** then the index cannot satisfy the ORDER BY constraint. */ | | | | | < < < < < < | > < | < < < < | > > > > | | < < | > | > | < < < < < < < < < < > > > | < < | | 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 | }else if( i==pIdx->nColumn ){ /* Index column i is the rowid. All other terms match. */ break; }else{ /* If an index column fails to match and is not constrained by == ** then the index cannot satisfy the ORDER BY constraint. */ return nPriorSat; } } assert( pIdx->aSortOrder!=0 || iColumn==-1 ); assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 ); assert( iSortOrder==0 || iSortOrder==1 ); termSortOrder = iSortOrder ^ pTerm->sortOrder; if( i>nEqOneRow ){ if( termSortOrder!=sortOrder ){ /* Indices can only be used if all ORDER BY terms past the ** equality constraints are all either DESC or ASC. */ break; } }else{ sortOrder = termSortOrder; } j++; pTerm++; if( iColumn<0 ){ seenRowid = 1; break; } } *pbRev = sortOrder; /* If there was an "ORDER BY rowid" term that matched, or it is only ** possible for a single row from this table to match, then skip over ** any additional ORDER BY terms dealing with this table. */ if( seenRowid || ( (wsFlags & WHERE_COLUMN_NULL)==0 && i>=pIdx->nColumn && indexIsUniqueNotNull(pIdx, nEqCol) ) ){ /* Advance j over additional ORDER BY terms associated with base */ WhereMaskSet *pMS = p->pWC->pMaskSet; Bitmask m = ~getMask(pMS, base); while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){ j++; } } return j; } /* ** Prepare a crude estimate of the logarithm of the input value. ** The results need not be exact. This is only used for estimating ** the total cost of performing operations with O(logN) or O(NlogN) ** complexity. Because N is just a guess, it is no great tragedy if |
︙ | ︙ | |||
1805 1806 1807 1808 1809 1810 1811 | #define TRACE_IDX_INPUTS(A) #define TRACE_IDX_OUTPUTS(A) #endif /* ** Required because bestIndex() is called by bestOrClauseIndex() */ | | < < | < < < < < < < < > > | | | > > > > > < | | > | | | | | | | | | | | | | 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 | #define TRACE_IDX_INPUTS(A) #define TRACE_IDX_OUTPUTS(A) #endif /* ** Required because bestIndex() is called by bestOrClauseIndex() */ static void bestIndex(WhereBestIdx*); /* ** This routine attempts to find an scanning strategy that can be used ** to optimize an 'OR' expression that is part of a WHERE clause. ** ** The table associated with FROM clause term pSrc may be either a ** regular B-Tree table or a virtual table. */ static void bestOrClauseIndex(WhereBestIdx *p){ #ifndef SQLITE_OMIT_OR_OPTIMIZATION WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ const int iCur = pSrc->iCursor; /* The cursor of the table */ const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */ WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */ WhereTerm *pTerm; /* A single term of the WHERE clause */ /* The OR-clause optimization is disallowed if the INDEXED BY or ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */ if( pSrc->notIndexed || pSrc->pIndex!=0 ){ return; } if( pWC->wctrlFlags & WHERE_AND_ONLY ){ return; } /* Search the WHERE clause terms for a usable WO_OR term. */ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( pTerm->eOperator==WO_OR && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0 && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 ){ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int flags = WHERE_MULTI_OR; double rTotal = 0; double nRow = 0; Bitmask used = 0; WhereBestIdx sBOI; sBOI = *p; sBOI.pOrderBy = 0; sBOI.pDistinct = 0; sBOI.ppIdxInfo = 0; for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", (pOrTerm - pOrWC->a), (pTerm - pWC->a) )); if( pOrTerm->eOperator==WO_AND ){ sBOI.pWC = &pOrTerm->u.pAndInfo->wc; bestIndex(&sBOI); }else if( pOrTerm->leftCursor==iCur ){ WhereClause tempWC; tempWC.pParse = pWC->pParse; tempWC.pMaskSet = pWC->pMaskSet; tempWC.pOuter = pWC; tempWC.op = TK_AND; tempWC.a = pOrTerm; tempWC.wctrlFlags = 0; tempWC.nTerm = 1; sBOI.pWC = &tempWC; bestIndex(&sBOI); }else{ continue; } rTotal += sBOI.cost.rCost; nRow += sBOI.cost.plan.nRow; used |= sBOI.cost.used; if( rTotal>=p->cost.rCost ) break; } /* If there is an ORDER BY clause, increase the scan cost to account ** for the cost of the sort. */ if( p->pOrderBy!=0 ){ WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n", rTotal, rTotal+nRow*estLog(nRow))); rTotal += nRow*estLog(nRow); } /* If the cost of scanning using this OR term for optimization is ** less than the current cost stored in pCost, replace the contents ** of pCost. */ WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow)); if( rTotal<p->cost.rCost ){ p->cost.rCost = rTotal; p->cost.used = used; p->cost.plan.nRow = nRow; p->cost.plan.wsFlags = flags; p->cost.plan.u.pTerm = pTerm; } } } #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ } #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
︙ | ︙ | |||
1935 1936 1937 1938 1939 1940 1941 | ** If the query plan for pSrc specified in pCost is a full table scan ** and indexing is allows (if there is no NOT INDEXED clause) and it ** possible to construct a transient index that would perform better ** than a full table scan even when the cost of constructing the index ** is taken into account, then alter the query plan to use the ** transient index. */ | | | | | < < < | | | | | | | | | | | | 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 | ** If the query plan for pSrc specified in pCost is a full table scan ** and indexing is allows (if there is no NOT INDEXED clause) and it ** possible to construct a transient index that would perform better ** than a full table scan even when the cost of constructing the index ** is taken into account, then alter the query plan to use the ** transient index. */ static void bestAutomaticIndex(WhereBestIdx *p){ Parse *pParse = p->pParse; /* The parsing context */ WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ double nTableRow; /* Rows in the input table */ double logN; /* log(nTableRow) */ double costTempIdx; /* per-query cost of the transient index */ WhereTerm *pTerm; /* A single term of the WHERE clause */ WhereTerm *pWCEnd; /* End of pWC->a[] */ Table *pTable; /* Table tht might be indexed */ if( pParse->nQueryLoop<=(double)1 ){ /* There is no point in building an automatic index for a single scan */ return; } if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){ /* Automatic indices are disabled at run-time */ return; } if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){ /* We already have some kind of index in use for this query. */ return; } if( pSrc->notIndexed ){ /* The NOT INDEXED clause appears in the SQL. */ return; } if( pSrc->isCorrelated ){ /* The source is a correlated sub-query. No point in indexing it. */ return; } assert( pParse->nQueryLoop >= (double)1 ); pTable = pSrc->pTab; nTableRow = pTable->nRowEst; logN = estLog(nTableRow); costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1); if( costTempIdx>=p->cost.rCost ){ /* The cost of creating the transient table would be greater than ** doing the full table scan */ return; } /* Search for any equality comparison term */ pWCEnd = &pWC->a[pWC->nTerm]; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){ WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n", p->cost.rCost, costTempIdx)); p->cost.rCost = costTempIdx; p->cost.plan.nRow = logN + 1; p->cost.plan.wsFlags = WHERE_TEMP_INDEX; p->cost.used = pTerm->prereqRight; break; } } } #else # define bestAutomaticIndex(A) /* no-op */ #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* ** Generate code to construct the Index object for an automatic index ** and to set up the WhereLevel object pLevel so that the code generator |
︙ | ︙ | |||
2157 2158 2159 2160 2161 2162 2163 | #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure ** by passing the pointer returned by this function to sqlite3_free(). */ | | | | | | < | 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 | #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure ** by passing the pointer returned by this function to sqlite3_free(). */ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){ Parse *pParse = p->pParse; WhereClause *pWC = p->pWC; struct SrcList_item *pSrc = p->pSrc; ExprList *pOrderBy = p->pOrderBy; int i, j; int nTerm; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_orderby *pIdxOrderBy; struct sqlite3_index_constraint_usage *pUsage; WhereTerm *pTerm; int nOrderBy; |
︙ | ︙ | |||
2192 2193 2194 2195 2196 2197 2198 | /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite3_index_info structure. */ nOrderBy = 0; if( pOrderBy ){ | > | | | | 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 | /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite3_index_info structure. */ nOrderBy = 0; if( pOrderBy ){ int n = pOrderBy->nExpr; for(i=0; i<n; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; } if( i==n){ nOrderBy = n; } } /* Allocate the sqlite3_index_info structure */ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm |
︙ | ︙ | |||
2321 2322 2323 2324 2325 2326 2327 | ** same virtual table. The sqlite3_index_info structure is created ** and initialized on the first invocation and reused on all subsequent ** invocations. The sqlite3_index_info structure is also used when ** code is generated to access the virtual table. The whereInfoDelete() ** routine takes care of freeing the sqlite3_index_info structure after ** everybody has finished with it. */ | | | | | < < < < < < | | | | | 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 | ** same virtual table. The sqlite3_index_info structure is created ** and initialized on the first invocation and reused on all subsequent ** invocations. The sqlite3_index_info structure is also used when ** code is generated to access the virtual table. The whereInfoDelete() ** routine takes care of freeing the sqlite3_index_info structure after ** everybody has finished with it. */ static void bestVirtualIndex(WhereBestIdx *p){ Parse *pParse = p->pParse; /* The parsing context */ WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ Table *pTab = pSrc->pTab; sqlite3_index_info *pIdxInfo; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage; WhereTerm *pTerm; int i, j; int nOrderBy; double rCost; /* Make sure wsFlags is initialized to some sane value. Otherwise, if the ** malloc in allocateIndexInfo() fails and this function returns leaving ** wsFlags in an uninitialized state, the caller may behave unpredictably. */ memset(&p->cost, 0, sizeof(p->cost)); p->cost.plan.wsFlags = WHERE_VIRTUALTABLE; /* If the sqlite3_index_info structure has not been previously ** allocated and initialized, then allocate and initialize it now. */ pIdxInfo = *p->ppIdxInfo; if( pIdxInfo==0 ){ *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p); } if( pIdxInfo==0 ){ return; } /* At this point, the sqlite3_index_info structure that pIdxInfo points ** to will have been initialized, either during the current invocation or |
︙ | ︙ | |||
2397 2398 2399 2400 2401 2402 2403 | ** each time. */ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; pUsage = pIdxInfo->aConstraintUsage; for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ j = pIdxCons->iTermOffset; pTerm = &pWC->a[j]; | | | | | | | | | | | | 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 | ** each time. */ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; pUsage = pIdxInfo->aConstraintUsage; for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ j = pIdxCons->iTermOffset; pTerm = &pWC->a[j]; pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1; } memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); nOrderBy = pIdxInfo->nOrderBy; if( !p->pOrderBy ){ pIdxInfo->nOrderBy = 0; } if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ return; } pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++){ if( pUsage[i].argvIndex>0 ){ p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight; } } /* If there is an ORDER BY clause, and the selected virtual table index ** does not satisfy it, increase the cost of the scan accordingly. This ** matches the processing for non-virtual tables in bestBtreeIndex(). */ rCost = pIdxInfo->estimatedCost; if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){ rCost += estLog(rCost)*rCost; } /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the ** inital value of lowestCost in this loop. If it is, then the ** (cost<lowestCost) test below will never be true. ** ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT ** is defined. */ if( (SQLITE_BIG_DBL/((double)2))<rCost ){ p->cost.rCost = (SQLITE_BIG_DBL/((double)2)); }else{ p->cost.rCost = rCost; } p->cost.plan.u.pVtabIdx = pIdxInfo; if( pIdxInfo->orderByConsumed ){ p->cost.plan.wsFlags |= WHERE_ORDERBY; } p->cost.plan.nEq = 0; pIdxInfo->nOrderBy = nOrderBy; /* Try to find a more efficient access pattern by using multiple indexes ** to optimize an OR expression within the WHERE clause. */ bestOrClauseIndex(p); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifdef SQLITE_ENABLE_STAT3 /* ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: |
︙ | ︙ | |||
2855 2856 2857 2858 2859 2860 2861 | *pnRow = nRowEst; WHERETRACE(("IN row estimate: est=%g\n", nRowEst)); } return rc; } #endif /* defined(SQLITE_ENABLE_STAT3) */ | > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 | *pnRow = nRowEst; WHERETRACE(("IN row estimate: est=%g\n", nRowEst)); } return rc; } #endif /* defined(SQLITE_ENABLE_STAT3) */ /* ** Check to see if column iCol of the table with cursor iTab will appear ** in sorted order according to the current query plan. Return true if ** it will and false if not. ** ** If *pbRev is initially 2 (meaning "unknown") then set *pbRev to the ** sort order of iTab.iCol. If *pbRev is 0 or 1 but does not match ** the sort order of iTab.iCol, then consider the column to be unordered. */ static int isOrderedColumn(WhereBestIdx *p, int iTab, int iCol, int *pbRev){ int i, j; WhereLevel *pLevel = &p->aLevel[p->i-1]; Index *pIdx; u8 sortOrder; for(i=p->i-1; i>=0; i--, pLevel--){ if( pLevel->iTabCur!=iTab ) continue; if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){ pIdx = pLevel->plan.u.pIdx; if( iCol<0 ){ sortOrder = 0; testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); }else{ for(j=0; j<pIdx->nColumn; j++){ if( iCol==pIdx->aiColumn[j] ) break; } if( j>=pIdx->nColumn ) return 0; sortOrder = pIdx->aSortOrder[j]; testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); } }else{ if( iCol!=(-1) ) return 0; sortOrder = 0; testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); } if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){ assert( sortOrder==0 || sortOrder==1 ); testcase( sortOrder==1 ); sortOrder = 1 - sortOrder; } if( *pbRev==2 ){ *pbRev = sortOrder; return 1; } return (*pbRev==sortOrder); } return 0; } /* ** pTerm is an == constraint. Check to see if the other side of ** the == is a constant or a value that is guaranteed to be ordered ** by outer loops. Return 1 if pTerm is ordered, and 0 if not. */ static int isOrderedTerm(WhereBestIdx *p, WhereTerm *pTerm, int *pbRev){ Expr *pExpr = pTerm->pExpr; assert( pExpr->op==TK_EQ ); assert( pExpr->pLeft!=0 && pExpr->pLeft->op==TK_COLUMN ); assert( pExpr->pRight!=0 ); if( p->i==0 ){ return 1; /* All == are ordered in the outer loop */ } if( pTerm->prereqRight==0 ){ return 1; /* RHS of the == is a constant */ } if( pExpr->pRight->op==TK_COLUMN && isOrderedColumn(p, pExpr->pRight->iTable, pExpr->pRight->iColumn, pbRev) ){ return 1; } /* If we cannot prove that the constraint is ordered, assume it is not */ return 0; } /* ** Find the best query plan for accessing a particular table. Write the ** best query plan and its cost into the p->cost. ** ** The lowest cost plan wins. The cost is an estimate of the amount of ** CPU and disk I/O needed to process the requested result. ** Factors that influence cost include: ** ** * The estimated number of rows that will be retrieved. (The ** fewer the better.) |
︙ | ︙ | |||
2884 2885 2886 2887 2888 2889 2890 | ** then the cost is calculated in the usual way. ** ** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table ** in the SELECT statement, then no indexes are considered. However, the ** selected plan may still take advantage of the built-in rowid primary key ** index. */ | | | | | < < < < < < | | | | 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 | ** then the cost is calculated in the usual way. ** ** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table ** in the SELECT statement, then no indexes are considered. However, the ** selected plan may still take advantage of the built-in rowid primary key ** index. */ static void bestBtreeIndex(WhereBestIdx *p){ Parse *pParse = p->pParse; /* The parsing context */ WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ Index *pProbe; /* An index we are evaluating */ Index *pIdx; /* Copy of pProbe, or zero for IPK index */ int eqTermMask; /* Current mask of valid equality operators */ int idxEqTermMask; /* Index mask of valid equality operators */ Index sPk; /* A fake index object for the primary key */ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ /* Initialize the cost to a worst-case value */ memset(&p->cost, 0, sizeof(p->cost)); p->cost.rCost = SQLITE_BIG_DBL; /* If the pSrc table is the right table of a LEFT JOIN then we may not ** use an index to satisfy IS NULL constraints on that table. This is ** because columns might end up being NULL if the table does not match - ** a circumstance which the index cannot help us discover. Ticket #2177. */ if( pSrc->jointype & JT_LEFT ){ |
︙ | ︙ | |||
2959 2960 2961 2962 2963 2964 2965 | /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const tRowcnt * const aiRowEst = pProbe->aiRowEst; double cost; /* Cost of using pProbe */ double nRow; /* Estimated number of rows in result set */ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ | | | 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 | /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const tRowcnt * const aiRowEst = pProbe->aiRowEst; double cost; /* Cost of using pProbe */ double nRow; /* Estimated number of rows in result set */ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ int bRev = 2; /* 0=forward scan. 1=reverse. 2=undecided */ int wsFlags = 0; Bitmask used = 0; /* The following variables are populated based on the properties of ** index being evaluated. They are then used to determine the expected ** cost and number of rows returned. ** |
︙ | ︙ | |||
2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 | ** ** nInMul is set to 1. ** ** If there exists a WHERE term of the form "x IN (SELECT ...)", then ** the sub-select is assumed to return 25 rows for the purposes of ** determining nInMul. ** ** bInEst: ** Set to true if there was at least one "x IN (SELECT ...)" term used ** in determining the value of nInMul. Note that the RHS of the ** IN operator must be a SELECT, not a value list, for this variable ** to be true. ** ** rangeDiv: ** An estimate of a divisor by which to reduce the search space due ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE ** data, a single inequality reduces the search space to 1/4rd its ** original size (rangeDiv==4). Two inequalities reduce the search ** space to 1/16th of its original size (rangeDiv==16). ** ** bSort: ** Boolean. True if there is an ORDER BY clause that will require an ** external sort (i.e. scanning the index being evaluated will not ** correctly order records). ** ** bLookup: ** Boolean. True if a table lookup is required for each index entry ** visited. In other words, true if this is not a covering index. ** This is always false for the rowid primary key index of a table. ** For other indexes, it is true unless all the columns of the table ** used by the SELECT statement are present in the index (such an ** index is sometimes described as a covering index). ** For example, given the index on (a, b), the second of the following ** two queries requires table b-tree lookups in order to find the value ** of column c, but the first does not because columns a and b are ** both available in the index. ** ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int nEq; /* Number of == or IN terms matching index */ int bInEst = 0; /* True if "x IN (SELECT...)" seen */ int nInMul = 1; /* Number of distinct equalities to lookup */ double rangeDiv = (double)1; /* Estimated reduction in search space */ int nBound = 0; /* Number of range constraints seen */ | > > > > > > > > > | | > > > > > > | | > > > | 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 | ** ** nInMul is set to 1. ** ** If there exists a WHERE term of the form "x IN (SELECT ...)", then ** the sub-select is assumed to return 25 rows for the purposes of ** determining nInMul. ** ** nOrdered: ** The number of equality terms that are constrainted by outer loop ** variables that are well-ordered. ** ** bInEst: ** Set to true if there was at least one "x IN (SELECT ...)" term used ** in determining the value of nInMul. Note that the RHS of the ** IN operator must be a SELECT, not a value list, for this variable ** to be true. ** ** rangeDiv: ** An estimate of a divisor by which to reduce the search space due ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE ** data, a single inequality reduces the search space to 1/4rd its ** original size (rangeDiv==4). Two inequalities reduce the search ** space to 1/16th of its original size (rangeDiv==16). ** ** bSort: ** Boolean. True if there is an ORDER BY clause that will require an ** external sort (i.e. scanning the index being evaluated will not ** correctly order records). ** ** bDistinct: ** Boolean. True if there is a DISTINCT clause that will require an ** external btree. ** ** bLookup: ** Boolean. True if a table lookup is required for each index entry ** visited. In other words, true if this is not a covering index. ** This is always false for the rowid primary key index of a table. ** For other indexes, it is true unless all the columns of the table ** used by the SELECT statement are present in the index (such an ** index is sometimes described as a covering index). ** For example, given the index on (a, b), the second of the following ** two queries requires table b-tree lookups in order to find the value ** of column c, but the first does not because columns a and b are ** both available in the index. ** ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int nEq; /* Number of == or IN terms matching index */ int nOrdered; /* Number of ordered terms matching index */ int bInEst = 0; /* True if "x IN (SELECT...)" seen */ int nInMul = 1; /* Number of distinct equalities to lookup */ double rangeDiv = (double)1; /* Estimated reduction in search space */ int nBound = 0; /* Number of range constraints seen */ int bSort; /* True if external sort required */ int bDist; /* True if index cannot help with DISTINCT */ int bLookup = 0; /* True if not a covering index */ int nOBSat = 0; /* Number of ORDER BY terms satisfied */ int nOrderBy; /* Number of ORDER BY terms */ WhereTerm *pTerm; /* A single term of the WHERE clause */ #ifdef SQLITE_ENABLE_STAT3 WhereTerm *pFirstTerm = 0; /* First term matching the index */ #endif nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; bSort = nOrderBy>0 && (p->i==0 || p->aLevel[p->i-1].plan.nOBSat<nOrderBy); bDist = p->i==0 && p->pDistinct!=0; /* Determine the values of nEq and nInMul */ for(nEq=nOrdered=0; nEq<pProbe->nColumn; nEq++){ int j = pProbe->aiColumn[nEq]; pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); if( pTerm==0 ) break; wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ); testcase( pTerm->pWC!=pWC ); if( pTerm->eOperator & WO_IN ){ Expr *pExpr = pTerm->pExpr; wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */ nInMul *= 25; bInEst = 1; }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nInMul *= pExpr->x.pList->nExpr; } }else if( pTerm->eOperator & WO_ISNULL ){ wsFlags |= WHERE_COLUMN_NULL; if( nEq==nOrdered ) nOrdered++; }else if( bSort && nEq==nOrdered && isOrderedTerm(p, pTerm, &bRev) ){ nOrdered++; } #ifdef SQLITE_ENABLE_STAT3 if( nEq==0 && pProbe->aSample ) pFirstTerm = pTerm; #endif used |= pTerm->prereqRight; } |
︙ | ︙ | |||
3082 3083 3084 3085 3086 3087 3088 | testcase( wsFlags & WHERE_COLUMN_IN ); testcase( wsFlags & WHERE_COLUMN_NULL ); if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ wsFlags |= WHERE_UNIQUE; } }else if( pProbe->bUnordered==0 ){ int j = (nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[nEq]); | | | > | | 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 | testcase( wsFlags & WHERE_COLUMN_IN ); testcase( wsFlags & WHERE_COLUMN_NULL ); if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ wsFlags |= WHERE_UNIQUE; } }else if( pProbe->bUnordered==0 ){ int j = (nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[nEq]); if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){ WhereTerm *pTop, *pBtm; pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx); pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx); whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv); if( pTop ){ nBound = 1; wsFlags |= WHERE_TOP_LIMIT; used |= pTop->prereqRight; testcase( pTop->pWC!=pWC ); } |
︙ | ︙ | |||
3106 3107 3108 3109 3110 3111 3112 | } } /* If there is an ORDER BY clause and the index being considered will ** naturally scan rows in the required order, set the appropriate flags ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index ** will scan rows in a different order, set the bSort variable. */ | > > > > > | | | | | > | > | | | 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 | } } /* If there is an ORDER BY clause and the index being considered will ** naturally scan rows in the required order, set the appropriate flags ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index ** will scan rows in a different order, set the bSort variable. */ assert( bRev>=0 && bRev<=2 ); if( bSort ){ testcase( bRev==0 ); testcase( bRev==1 ); testcase( bRev==2 ); nOBSat = isSortingIndex(p, pProbe, iCur, nOrdered, wsFlags, bRev&1, &bRev); if( nOrderBy==nOBSat ){ bSort = 0; wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY; } if( bRev & 1 ) wsFlags |= WHERE_REVERSE; } /* If there is a DISTINCT qualifier and this index will scan rows in ** order of the DISTINCT expressions, clear bDist and set the appropriate ** flags in wsFlags. */ if( bDist && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, nEq) && (wsFlags & WHERE_COLUMN_IN)==0 ){ bDist = 0; wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT; } /* If currently calculating the cost of using an index (not the IPK ** index), determine if all required column data may be obtained without ** using the main table (i.e. if the index is a covering ** index for this query). If it is, set the WHERE_IDX_ONLY flag in ** wsFlags. Otherwise, set the bLookup variable to true. */ if( pIdx ){ Bitmask m = pSrc->colUsed; int j; for(j=0; j<pIdx->nColumn; j++){ int x = pIdx->aiColumn[j]; if( x<BMS-1 ){ m &= ~(((Bitmask)1)<<x); } |
︙ | ︙ | |||
3194 3195 3196 3197 3198 3199 3200 | ** on one page and hence more pages have to be fetched. ** ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do ** not give us data on the relative sizes of table and index records. ** So this computation assumes table records are about twice as big ** as index records */ | > > > > > > > > > > > | > | 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 | ** on one page and hence more pages have to be fetched. ** ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do ** not give us data on the relative sizes of table and index records. ** So this computation assumes table records are about twice as big ** as index records */ if( (wsFlags&~WHERE_REVERSE)==WHERE_IDX_ONLY && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 && sqlite3GlobalConfig.bUseCis && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan) ){ /* This index is not useful for indexing, but it is a covering index. ** A full-scan of the index might be a little faster than a full-scan ** of the table, so give this case a cost slightly less than a table ** scan. */ cost = aiRowEst[0]*3 + pProbe->nColumn; wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE; }else if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){ /* The cost of a full table scan is a number of move operations equal ** to the number of rows in the table. ** ** We add an additional 4x penalty to full table scans. This causes ** the cost function to err on the side of choosing an index over ** choosing a full scan. This 4x full-scan penalty is an arguable ** decision and one which we expect to revisit in the future. But ** it seems to be working well enough at the moment. */ cost = aiRowEst[0]*4; wsFlags &= ~WHERE_IDX_ONLY; }else{ log10N = estLog(aiRowEst[0]); cost = nRow; if( pIdx ){ if( bLookup ){ /* For an index lookup followed by a table lookup: ** nInMul index searches to find the start of each index range |
︙ | ︙ | |||
3239 3240 3241 3242 3243 3244 3245 | /* Add in the estimated cost of sorting the result. Actual experimental ** measurements of sorting performance in SQLite show that sorting time ** adds C*N*log10(N) to the cost, where N is the number of rows to be ** sorted and C is a factor between 1.95 and 4.3. We will split the ** difference and select C of 3.0. */ if( bSort ){ | | | 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 | /* Add in the estimated cost of sorting the result. Actual experimental ** measurements of sorting performance in SQLite show that sorting time ** adds C*N*log10(N) to the cost, where N is the number of rows to be ** sorted and C is a factor between 1.95 and 4.3. We will split the ** difference and select C of 3.0. */ if( bSort ){ cost += nRow*estLog(nRow*(nOrderBy - nOBSat)/nOrderBy)*3; } if( bDist ){ cost += nRow*estLog(nRow)*3; } /**** Cost of using this index has now been computed ****/ |
︙ | ︙ | |||
3263 3264 3265 3266 3267 3268 3269 | ** mask will only have one bit set - the bit for the current table. ** The notValid mask, on the other hand, always has all bits set for ** tables that are not in outer loops. If notReady is used here instead ** of notValid, then a optimal index that depends on inner joins loops ** might be selected even when there exists an optimal index that has ** no such dependency. */ | | | | 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 | ** mask will only have one bit set - the bit for the current table. ** The notValid mask, on the other hand, always has all bits set for ** tables that are not in outer loops. If notReady is used here instead ** of notValid, then a optimal index that depends on inner joins loops ** might be selected even when there exists an optimal index that has ** no such dependency. */ if( nRow>2 && cost<=p->cost.rCost ){ int k; /* Loop counter */ int nSkipEq = nEq; /* Number of == constraints to skip */ int nSkipRange = nBound; /* Number of < constraints to skip */ Bitmask thisTab; /* Bitmap for pSrc */ thisTab = getMask(pWC->pMaskSet, iCur); for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){ if( pTerm->wtFlags & TERM_VIRTUAL ) continue; if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue; if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){ if( nSkipEq ){ /* Ignore the first nEq equality matches since the index ** has already accounted for these */ nSkipEq--; }else{ /* Assume each additional equality match reduces the result |
︙ | ︙ | |||
3307 3308 3309 3310 3311 3312 3313 | } } if( nRow<2 ) nRow = 2; } WHERETRACE(( | > | | > | | | | | | | > | | | | | | | | | | | | > > > > > > | < < < < < < < < | | > | | | | | | 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 | } } if( nRow<2 ) nRow = 2; } WHERETRACE(( "%s(%s):\n" " nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n" " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n" " used=0x%llx nOrdered=%d nOBSat=%d\n", pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"), nEq, nInMul, (int)rangeDiv, bSort, bLookup, wsFlags, p->notReady, log10N, nRow, cost, used, nOrdered, nOBSat )); /* If this index is the best we have seen so far, then record this ** index and its cost in the pCost structure. */ if( (!pIdx || wsFlags) && (cost<p->cost.rCost || (cost<=p->cost.rCost && nRow<p->cost.plan.nRow)) ){ p->cost.rCost = cost; p->cost.used = used; p->cost.plan.nRow = nRow; p->cost.plan.wsFlags = (wsFlags&wsFlagMask); p->cost.plan.nEq = nEq; p->cost.plan.nOBSat = nOBSat; p->cost.plan.u.pIdx = pIdx; } /* If there was an INDEXED BY clause, then only that one index is ** considered. */ if( pSrc->pIndex ) break; /* Reset masks for the next index in the loop */ wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); eqTermMask = idxEqTermMask; } /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag ** is set, then reverse the order that the index will be scanned ** in. This is used for application testing, to help find cases ** where application behaviour depends on the (undefined) order that ** SQLite outputs rows in in the absence of an ORDER BY clause. */ if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){ p->cost.plan.wsFlags |= WHERE_REVERSE; } assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERBY)==0 ); assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 ); assert( pSrc->pIndex==0 || p->cost.plan.u.pIdx==0 || p->cost.plan.u.pIdx==pSrc->pIndex ); WHERETRACE(("best index is: %s\n", ((p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" : p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk") )); bestOrClauseIndex(p); bestAutomaticIndex(p); p->cost.plan.wsFlags |= eqTermMask; } /* ** Find the query plan for accessing table pSrc->pTab. Write the ** best query plan and its cost into the WhereCost object supplied ** as the last parameter. This function may calculate the cost of ** both real and virtual table scans. ** ** This function does not take ORDER BY or DISTINCT into account. Nor ** does it remember the virtual table query plan. All it does is compute ** the cost while determining if an OR optimization is applicable. The ** details will be reconsidered later if the optimization is found to be ** applicable. */ static void bestIndex(WhereBestIdx *p){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(p->pSrc->pTab) ){ sqlite3_index_info *pIdxInfo = 0; p->ppIdxInfo = &pIdxInfo; bestVirtualIndex(p); if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } sqlite3DbFree(p->pParse->db, pIdxInfo); }else #endif { bestBtreeIndex(p); } } /* ** Disable a term in the WHERE clause. Except, do not disable the term ** if it controls a LEFT OUTER JOIN and it did not originate in the ON ** or USING clause of that join. |
︙ | ︙ | |||
4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 | pLevel->op = OP_Noop; }else if( bRev ){ pLevel->op = OP_Prev; }else{ pLevel->op = OP_Next; } pLevel->p1 = iIdxCur; }else #ifndef SQLITE_OMIT_OR_OPTIMIZATION if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){ /* Case 4: Two or more separately indexed terms connected by OR ** ** Example: | > > > > > | 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 | pLevel->op = OP_Noop; }else if( bRev ){ pLevel->op = OP_Prev; }else{ pLevel->op = OP_Next; } pLevel->p1 = iIdxCur; if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){ pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; }else{ assert( pLevel->p5==0 ); } }else #ifndef SQLITE_OMIT_OR_OPTIMIZATION if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){ /* Case 4: Two or more separately indexed terms connected by OR ** ** Example: |
︙ | ︙ | |||
4642 4643 4644 4645 4646 4647 4648 | ** move the row2 cursor to a null row ** goto start ** fi ** end ** ** ORDER BY CLAUSE PROCESSING ** | | | | | | | | < > < < | | > > > > > > | 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 | ** move the row2 cursor to a null row ** goto start ** fi ** end ** ** ORDER BY CLAUSE PROCESSING ** ** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement, ** if there is one. If there is no ORDER BY clause or if this routine ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. ** ** If an index can be used so that the natural output order of the table ** scan is correct for the ORDER BY clause, then that index is used and ** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr. This ** is an optimization that prevents an unnecessary sort of the result set ** if an index appropriate for the ORDER BY clause already exists. ** ** If the where clause loops cannot be arranged to provide the correct ** output order, then WhereInfo.nOBSat is 0. */ WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList *pOrderBy, /* An ORDER BY clause, or NULL */ ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */ ){ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ int nTabList; /* Number of elements in pTabList */ WhereInfo *pWInfo; /* Will become the return value of this function */ Vdbe *v = pParse->pVdbe; /* The virtual database engine */ Bitmask notReady; /* Cursors that are not yet positioned */ WhereBestIdx sWBI; /* Best index search context */ WhereMaskSet *pMaskSet; /* The expression mask set */ WhereLevel *pLevel; /* A single level in pWInfo->a[] */ int iFrom; /* First unused FROM clause element */ int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */ int ii; /* Loop counter */ sqlite3 *db; /* Database connection */ /* Variable initialization */ memset(&sWBI, 0, sizeof(sWBI)); sWBI.pParse = pParse; /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ testcase( pTabList->nSrc==BMS ); if( pTabList->nSrc>BMS ){ sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); return 0; |
︙ | ︙ | |||
4717 4718 4719 4720 4721 4722 4723 | pWInfo = 0; goto whereBeginError; } pWInfo->nLevel = nTabList; pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); | | | > | | | | 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 | pWInfo = 0; goto whereBeginError; } pWInfo->nLevel = nTabList; pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo]; pWInfo->wctrlFlags = wctrlFlags; pWInfo->savedNQueryLoop = pParse->nQueryLoop; pMaskSet = (WhereMaskSet*)&sWBI.pWC[1]; sWBI.aLevel = pWInfo->a; /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0; /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ initMaskSet(pMaskSet); whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags); sqlite3ExprCodeConstants(pParse, pWhere); whereSplit(sWBI.pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */ /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); pWhere = 0; |
︙ | ︙ | |||
4763 4764 4765 4766 4767 4768 4769 | ** with virtual tables. ** ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the ** WHERE_ONETABLE_ONLY flag is set. */ | | | | | | | | | | | > > > | | | | | 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 | ** with virtual tables. ** ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the ** WHERE_ONETABLE_ONLY flag is set. */ assert( sWBI.pWC->vmask==0 && pMaskSet->n==0 ); for(ii=0; ii<pTabList->nSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); #ifndef SQLITE_OMIT_VIRTUALTABLE if( ALWAYS(pTabList->a[ii].pTab) && IsVirtual(pTabList->a[ii].pTab) ){ sWBI.pWC->vmask |= ((Bitmask)1 << ii); } #endif } #ifndef NDEBUG { Bitmask toTheLeft = 0; for(ii=0; ii<pTabList->nSrc; ii++){ Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); assert( (m-1)==toTheLeft ); toTheLeft |= m; } } #endif /* Analyze all of the subexpressions. Note that exprAnalyze() might ** add new virtual terms onto the end of the WHERE clause. We do not ** want to analyze these virtual terms, so start analyzing at the end ** and work forward so that the added virtual terms are never processed. */ exprAnalyzeAll(pTabList, sWBI.pWC); if( db->mallocFailed ){ goto whereBeginError; } /* Check if the DISTINCT qualifier, if there is one, is redundant. ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT. */ if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){ pDistinct = 0; pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } /* Chose the best index to use for each table in the FROM clause. ** ** This loop fills in the following fields: ** ** pWInfo->a[].pIdx The index to use for this level of the loop. ** pWInfo->a[].wsFlags WHERE_xxx flags associated with pIdx ** pWInfo->a[].nEq The number of == and IN constraints ** pWInfo->a[].iFrom Which term of the FROM clause is being coded ** pWInfo->a[].iTabCur The VDBE cursor for the database table ** pWInfo->a[].iIdxCur The VDBE cursor for the index ** pWInfo->a[].pTerm When wsFlags==WO_OR, the OR-clause term ** ** This loop also figures out the nesting order of tables in the FROM ** clause. */ sWBI.notValid = ~(Bitmask)0; sWBI.pOrderBy = pOrderBy; sWBI.n = nTabList; sWBI.pDistinct = pDistinct; andFlags = ~0; WHERETRACE(("*** Optimizer Start ***\n")); for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){ WhereCost bestPlan; /* Most efficient plan seen so far */ Index *pIdx; /* Index for FROM table at pTabItem */ int j; /* For looping over FROM tables */ int bestJ = -1; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ int isOptimal; /* Iterator for optimal/non-optimal search */ int nUnconstrained; /* Number tables without INDEXED BY */ Bitmask notIndexed; /* Mask of tables that cannot use an index */ memset(&bestPlan, 0, sizeof(bestPlan)); bestPlan.rCost = SQLITE_BIG_DBL; WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i)); /* Loop through the remaining entries in the FROM clause to find the ** next nested loop. The loop tests all FROM clause entries ** either once or twice. ** ** The first test is always performed if there are two or more entries ** remaining and never performed if there is only one FROM clause entry ** to choose from. The first test looks for an "optimal" scan. In ** this context an optimal scan is one that uses the same strategy ** for the given FROM clause entry as would be selected if the entry ** were used as the innermost nested loop. In other words, a table ** is chosen such that the cost of running that table cannot be reduced ** by waiting for other tables to run first. This "optimal" test works ** by first assuming that the FROM clause is on the inner loop and finding ** its query plan, then checking to see if that query plan uses any ** other FROM clause terms that are sWBI.notValid. If no notValid terms ** are used then the "optimal" query plan works. ** ** Note that the WhereCost.nRow parameter for an optimal scan might ** not be as small as it would be if the table really were the innermost ** join. The nRow value can be reduced by WHERE clause constraints ** that do not use indices. But this nRow reduction only happens if the ** table really is the innermost join. ** |
︙ | ︙ | |||
4880 4881 4882 4883 4884 4885 4886 | ** as the cost of a linear scan through table t1, a simple greedy ** algorithm may choose to use t2 for the outer loop, which is a much ** costlier approach. */ nUnconstrained = 0; notIndexed = 0; for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){ | < | < < < | | | | < < | | | | | < | < | | | | | | > | | | | | | | | | > | | | | | | | | | | | 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 | ** as the cost of a linear scan through table t1, a simple greedy ** algorithm may choose to use t2 for the outer loop, which is a much ** costlier approach. */ nUnconstrained = 0; notIndexed = 0; for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){ int doNotReorder; /* True if this table should not be reordered */ doNotReorder = (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0; if( j!=iFrom && doNotReorder ) break; m = getMask(pMaskSet, sWBI.pSrc->iCursor); if( (m & sWBI.notValid)==0 ){ if( j==iFrom ) iFrom++; continue; } sWBI.notReady = (isOptimal ? m : sWBI.notValid); if( sWBI.pSrc->pIndex==0 ) nUnconstrained++; WHERETRACE(("=== trying table %d with isOptimal=%d ===\n", j, isOptimal)); assert( sWBI.pSrc->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(sWBI.pSrc->pTab) ){ sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo; bestVirtualIndex(&sWBI); }else #endif { bestBtreeIndex(&sWBI); } assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 ); /* If an INDEXED BY clause is present, then the plan must use that ** index if it uses any index at all */ assert( sWBI.pSrc->pIndex==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ notIndexed |= m; } /* Conditions under which this table becomes the best so far: ** ** (1) The table must not depend on other tables that have not ** yet run. (In other words, it must not depend on tables ** in inner loops.) ** ** (2) A full-table-scan plan cannot supercede indexed plan unless ** the full-table-scan is an "optimal" plan as defined above. ** ** (3) All tables have an INDEXED BY clause or this table lacks an ** INDEXED BY clause or this table uses the specific ** index specified by its INDEXED BY clause. This rule ensures ** that a best-so-far is always selected even if an impossible ** combination of INDEXED BY clauses are given. The error ** will be detected and relayed back to the application later. ** The NEVER() comes about because rule (2) above prevents ** An indexable full-table-scan from reaching rule (3). ** ** (4) The plan cost must be lower than prior plans or else the ** cost must be the same and the number of rows must be lower. */ if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */ && (bestJ<0 || (notIndexed&m)!=0 /* (2) */ || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */ || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) && (bestJ<0 || sWBI.cost.rCost<bestPlan.rCost /* (4) */ || (sWBI.cost.rCost<=bestPlan.rCost && sWBI.cost.plan.nRow<bestPlan.plan.nRow)) ){ WHERETRACE(("=== table %d is best so far" " with cost=%.1f, nRow=%.1f, nOBSat=%d\n", j, sWBI.cost.rCost, sWBI.cost.plan.nRow, sWBI.cost.plan.nOBSat)); bestPlan = sWBI.cost; bestJ = j; } if( doNotReorder ) break; } } assert( bestJ>=0 ); assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) ); WHERETRACE(("*** Optimizer selects table %d for loop %d with:\n" " cost=%.1f, nRow=%.1f, nOBSat=%d wsFlags=0x%08x\n", bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow, bestPlan.plan.nOBSat, bestPlan.plan.wsFlags)); if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){ pWInfo->nOBSat = pOrderBy->nExpr; } if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){ assert( pWInfo->eDistinct==0 ); pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } andFlags &= bestPlan.plan.wsFlags; pLevel->plan = bestPlan.plan; testcase( bestPlan.plan.wsFlags & WHERE_INDEXED ); testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX ); if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){ if( (wctrlFlags & WHERE_ONETABLE_ONLY) && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0 ){ pLevel->iIdxCur = iIdxCur; }else{ pLevel->iIdxCur = pParse->nTab++; } }else{ pLevel->iIdxCur = -1; } sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor); pLevel->iFrom = (u8)bestJ; if( bestPlan.plan.nRow>=(double)1 ){ pParse->nQueryLoop *= bestPlan.plan.nRow; } /* Check that if the table scanned by this loop iteration had an ** INDEXED BY clause attached to it, that the named index is being |
︙ | ︙ | |||
5024 5025 5026 5027 5028 5029 5030 | if( pParse->nErr || db->mallocFailed ){ goto whereBeginError; } /* If the total query only selects a single row, then the ORDER BY ** clause is irrelevant. */ | | | | > | 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 | if( pParse->nErr || db->mallocFailed ){ goto whereBeginError; } /* If the total query only selects a single row, then the ORDER BY ** clause is irrelevant. */ if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){ pWInfo->nOBSat = pOrderBy->nExpr; } /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. ** The one-pass algorithm only works if the WHERE clause constraints ** the statement to update a single row. */ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){ pWInfo->okOnePass = 1; pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY; } /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ notReady = ~(Bitmask)0; pWInfo->nRowOut = (double)1; for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){ Table *pTab; /* Table to open */ int iDb; /* Index of database containing table/index */ struct SrcList_item *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; pLevel->iTabCur = pTabItem->iCursor; pWInfo->nRowOut *= pLevel->plan.nRow; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ |
︙ | ︙ | |||
5083 5084 5085 5086 5087 5088 5089 | assert( n<=pTab->nCol ); } }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } #ifndef SQLITE_OMIT_AUTOMATIC_INDEX if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){ | | | | | | | | > > > | > | | | | | | 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 | assert( n<=pTab->nCol ); } }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } #ifndef SQLITE_OMIT_AUTOMATIC_INDEX if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){ constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel); }else #endif if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){ Index *pIx = pLevel->plan.u.pIdx; KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); int iIndexCur = pLevel->iIdxCur; assert( pIx->pSchema==pTab->pSchema ); assert( iIndexCur>=0 ); sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIx->zName)); } sqlite3CodeVerifySchema(pParse, iDb); notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor); } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); if( db->mallocFailed ) goto whereBeginError; /* Generate the code to do the search. Each iteration of the for ** loop below generates code for a single nested loop of the VM ** program. */ notReady = ~(Bitmask)0; for(ii=0; ii<nTabList; ii++){ pLevel = &pWInfo->a[ii]; explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags); notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady); pWInfo->iContinue = pLevel->addrCont; } #ifdef SQLITE_TEST /* For testing and debugging use only */ /* Record in the query plan information about the current table ** and the index used to access it (if any). If the table itself ** is not used, its name is just '{}'. If no index is used ** the index is listed as "{}". If the primary key is used the ** index name is '*'. */ for(ii=0; ii<nTabList; ii++){ char *z; int n; int w; struct SrcList_item *pTabItem; pLevel = &pWInfo->a[ii]; w = pLevel->plan.wsFlags; pTabItem = &pTabList->a[pLevel->iFrom]; z = pTabItem->zAlias; if( z==0 ) z = pTabItem->pTab->zName; n = sqlite3Strlen30(z); if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){ if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){ memcpy(&sqlite3_query_plan[nQPlan], "{}", 2); nQPlan += 2; }else{ memcpy(&sqlite3_query_plan[nQPlan], z, n); nQPlan += n; } sqlite3_query_plan[nQPlan++] = ' '; } testcase( w & WHERE_ROWID_EQ ); testcase( w & WHERE_ROWID_RANGE ); if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){ memcpy(&sqlite3_query_plan[nQPlan], "* ", 2); nQPlan += 2; }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){ n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName); if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){ memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n); nQPlan += n; sqlite3_query_plan[nQPlan++] = ' '; } }else{ |
︙ | ︙ |
Changes to test/analyze6.test.
︙ | ︙ | |||
57 58 59 60 61 62 63 | # The lowest cost plan is to scan CAT and for each integer there, do a single # lookup of the first corresponding entry in EV then read off the equal values # in EV. (Prior to the 2011-03-04 enhancement to where.c, this query would # have used EV for the outer loop instead of CAT - which was about 3x slower.) # do_test analyze6-1.1 { eqp {SELECT count(*) FROM ev, cat WHERE x=y} | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | # The lowest cost plan is to scan CAT and for each integer there, do a single # lookup of the first corresponding entry in EV then read off the equal values # in EV. (Prior to the 2011-03-04 enhancement to where.c, this query would # have used EV for the outer loop instead of CAT - which was about 3x slower.) # do_test analyze6-1.1 { eqp {SELECT count(*) FROM ev, cat WHERE x=y} } {0 0 1 {SCAN TABLE cat USING COVERING INDEX catx (~16 rows)} 0 1 0 {SEARCH TABLE ev USING COVERING INDEX evy (y=?) (~32 rows)}} # The same plan is chosen regardless of the order of the tables in the # FROM clause. # do_test analyze6-1.2 { eqp {SELECT count(*) FROM cat, ev WHERE x=y} } {0 0 0 {SCAN TABLE cat USING COVERING INDEX catx (~16 rows)} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?) (~32 rows)}} # Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30 # If ANALYZE is run on an empty table, make sure indices are used # on the table. # do_test analyze6-2.1 { |
︙ | ︙ |
Changes to test/autovacuum.test.
︙ | ︙ | |||
110 111 112 113 114 115 116 | # Ensure the data remaining in the table is what was expected. foreach d $delete { set idx [lsearch $::tbl_data [make_str $d $ENTRY_LEN]] set ::tbl_data [lreplace $::tbl_data $idx $idx] } do_test autovacuum-1.$tn.($delete).3 { execsql { | | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | # Ensure the data remaining in the table is what was expected. foreach d $delete { set idx [lsearch $::tbl_data [make_str $d $ENTRY_LEN]] set ::tbl_data [lreplace $::tbl_data $idx $idx] } do_test autovacuum-1.$tn.($delete).3 { execsql { select a from av1 order by rowid } } $::tbl_data } # All rows have been deleted. Ensure the file has shrunk to 4 pages. do_test autovacuum-1.$tn.3 { file_pages |
︙ | ︙ |
Changes to test/backcompat.test.
︙ | ︙ | |||
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | #------------------------------------------------------------------------- # Test that WAL and wal-index files may be shared between different # SQLite versions. # do_allbackcompat_test { if {[code1 {sqlite3 -version}] >= "3.7.0" && [code2 {sqlite3 -version}] >= "3.7.0" } { do_test backcompat-2.1.1 { sql1 { PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES('I', 1); INSERT INTO t1 VALUES('II', 2); | > > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | #------------------------------------------------------------------------- # Test that WAL and wal-index files may be shared between different # SQLite versions. # do_allbackcompat_test { if {[code1 {sqlite3 -version}] >= "3.7.0" && [code1 {set ::sqlite_options(wal)}] && [code2 {sqlite3 -version}] >= "3.7.0" && [code2 {set ::sqlite_options(wal)}] } { do_test backcompat-2.1.1 { sql1 { PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES('I', 1); INSERT INTO t1 VALUES('II', 2); |
︙ | ︙ |
Changes to test/collate4.test.
︙ | ︙ | |||
90 91 92 93 94 95 96 | do_test collate4-1.1.4 { cksort {SELECT b FROM collate4t1 ORDER BY b} } {{} A B a b nosort} do_test collate4-1.1.5 { cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE TEXT} } {{} A B a b nosort} do_test collate4-1.1.6 { | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | do_test collate4-1.1.4 { cksort {SELECT b FROM collate4t1 ORDER BY b} } {{} A B a b nosort} do_test collate4-1.1.5 { cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE TEXT} } {{} A B a b nosort} do_test collate4-1.1.6 { cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE NOCASE, rowid} } {{} a A b B sort} do_test collate4-1.1.7 { execsql { CREATE TABLE collate4t2( a PRIMARY KEY COLLATE NOCASE, b UNIQUE COLLATE TEXT |
︙ | ︙ | |||
167 168 169 170 171 172 173 | INSERT INTO collate4t4 VALUES( 'B', 'B' ); INSERT INTO collate4t4 VALUES( 'A', 'A' ); CREATE INDEX collate4i3 ON collate4t4(a COLLATE TEXT); CREATE INDEX collate4i4 ON collate4t4(b COLLATE NOCASE); } } {} do_test collate4-1.1.22 { | | | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | INSERT INTO collate4t4 VALUES( 'B', 'B' ); INSERT INTO collate4t4 VALUES( 'A', 'A' ); CREATE INDEX collate4i3 ON collate4t4(a COLLATE TEXT); CREATE INDEX collate4i4 ON collate4t4(b COLLATE NOCASE); } } {} do_test collate4-1.1.22 { cksort {SELECT a FROM collate4t4 ORDER BY a, rowid} } {{} a A b B sort} do_test collate4-1.1.23 { cksort {SELECT a FROM collate4t4 ORDER BY a COLLATE NOCASE, rowid} } {{} a A b B sort} do_test collate4-1.1.24 { cksort {SELECT a FROM collate4t4 ORDER BY a COLLATE TEXT, rowid} } {{} A B a b nosort} do_test collate4-1.1.25 { cksort {SELECT b FROM collate4t4 ORDER BY b} } {{} A B a b sort} do_test collate4-1.1.26 { cksort {SELECT b FROM collate4t4 ORDER BY b COLLATE TEXT} } {{} A B a b sort} |
︙ | ︙ | |||
218 219 220 221 222 223 224 | do_test collate4-1.2.3 { cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE text} } {{} A B a b sort} do_test collate4-1.2.4 { cksort {SELECT a FROM collate4t1 ORDER BY a, b} } {{} A a B b nosort} do_test collate4-1.2.5 { | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | do_test collate4-1.2.3 { cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE text} } {{} A B a b sort} do_test collate4-1.2.4 { cksort {SELECT a FROM collate4t1 ORDER BY a, b} } {{} A a B b nosort} do_test collate4-1.2.5 { cksort {SELECT a FROM collate4t1 ORDER BY a, b COLLATE nocase, rowid} } {{} a A b B sort} do_test collate4-1.2.6 { cksort {SELECT a FROM collate4t1 ORDER BY a, b COLLATE text} } {{} A a B b nosort} do_test collate4-1.2.7 { execsql { |
︙ | ︙ | |||
267 268 269 270 271 272 273 | INSERT INTO collate4t3 VALUES( NULL, NULL ); INSERT INTO collate4t3 VALUES( 'B', 'B' ); INSERT INTO collate4t3 VALUES( 'A', 'A' ); CREATE INDEX collate4i2 ON collate4t3(a COLLATE TEXT, b COLLATE NOCASE); } } {} do_test collate4-1.2.15 { | | | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | INSERT INTO collate4t3 VALUES( NULL, NULL ); INSERT INTO collate4t3 VALUES( 'B', 'B' ); INSERT INTO collate4t3 VALUES( 'A', 'A' ); CREATE INDEX collate4i2 ON collate4t3(a COLLATE TEXT, b COLLATE NOCASE); } } {} do_test collate4-1.2.15 { cksort {SELECT a FROM collate4t3 ORDER BY a, rowid} } {{} a A b B sort} do_test collate4-1.2.16 { cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE nocase, rowid} } {{} a A b B sort} do_test collate4-1.2.17 { cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text} } {{} A B a b nosort} do_test collate4-1.2.18 { cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text, b} } {{} A B a b sort} |
︙ | ︙ | |||
360 361 362 363 364 365 366 | } {A A 19} do_test collate4-2.1.4 { execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a COLLATE TEXT); } count { | | > | > | > | | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | } {A A 19} do_test collate4-2.1.4 { execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a COLLATE TEXT); } count { SELECT * FROM collate4t2, collate4t1 WHERE a = b ORDER BY collate4t2.rowid, collate4t1.rowid } } {A a A A 19} do_test collate4-2.1.5 { count { SELECT * FROM collate4t2, collate4t1 WHERE b = a; } } {A A 4} ifcapable subquery { do_test collate4-2.1.6 { count { SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2) ORDER BY rowid } } {a A 10} do_test collate4-2.1.7 { execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a); } count { SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2) ORDER BY rowid } } {a A 6} do_test collate4-2.1.8 { count { SELECT a FROM collate4t1 WHERE a IN ('z', 'a'); } } {a A 5} do_test collate4-2.1.9 { execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a COLLATE TEXT); } count { SELECT a FROM collate4t1 WHERE a IN ('z', 'a') ORDER BY rowid; } } {a A 9} } do_test collate4-2.1.10 { execsql { DROP TABLE collate4t1; DROP TABLE collate4t2; |
︙ | ︙ |
Changes to test/collate5.test.
︙ | ︙ | |||
217 218 219 220 221 222 223 | # These tests - collate5-3.* - focus on compound SELECT queries that # feature ORDER BY clauses. # do_test collate5-3.0 { execsql { SELECT a FROM collate5t1 UNION ALL SELECT a FROM collate5t2 ORDER BY 1; } | | | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | # These tests - collate5-3.* - focus on compound SELECT queries that # feature ORDER BY clauses. # do_test collate5-3.0 { execsql { SELECT a FROM collate5t1 UNION ALL SELECT a FROM collate5t2 ORDER BY 1; } } {/[aA] [aA] [aA] [aA] [bB] [bB] [bB] [bB] [nN] [nN]/} do_test collate5-3.1 { execsql { SELECT a FROM collate5t2 UNION ALL SELECT a FROM collate5t1 ORDER BY 1; } } {A A B B N a a b b n} do_test collate5-3.2 { execsql { |
︙ | ︙ | |||
278 279 280 281 282 283 284 | SELECT a, count(*) FROM collate5t1 GROUP BY a; }] } {a 2 b 2} do_test collate5-4.2 { execsql { SELECT a, b, count(*) FROM collate5t1 GROUP BY a, b ORDER BY a, b; } | | | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | SELECT a, count(*) FROM collate5t1 GROUP BY a; }] } {a 2 b 2} do_test collate5-4.2 { execsql { SELECT a, b, count(*) FROM collate5t1 GROUP BY a, b ORDER BY a, b; } } {/[aA] 1(.0)? 2 [bB] 2 1 [bB] 3 1/} do_test collate5-4.3 { execsql { DROP TABLE collate5t1; } } {} finish_test |
Changes to test/corruptD.test.
︙ | ︙ | |||
103 104 105 106 107 108 109 | #------------------------------------------------------------------------- # The following tests, corruptD-1.1.*, focus on the page header field # containing the offset of the first free block in a page. # do_test corruptD-1.1.1 { incr_change_counter hexio_write test.db [expr 1024+1] FFFF | | | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | #------------------------------------------------------------------------- # The following tests, corruptD-1.1.*, focus on the page header field # containing the offset of the first free block in a page. # do_test corruptD-1.1.1 { incr_change_counter hexio_write test.db [expr 1024+1] FFFF catchsql { SELECT * FROM t1 ORDER BY rowid } } {1 {database disk image is malformed}} do_test corruptD-1.1.2 { incr_change_counter hexio_write test.db [expr 1024+1] [hexio_render_int32 1021] catchsql { SELECT * FROM t1 ORDER BY rowid } } {1 {database disk image is malformed}} #------------------------------------------------------------------------- # The following tests, corruptD-1.2.*, focus on the offsets contained # in the first 2 byte of each free-block on the free-list. # do_test corruptD-1.2.1 { |
︙ | ︙ |
Changes to test/corruptE.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 | INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*11,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*13,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*17,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*19,y FROM t1; CREATE INDEX t1i1 ON t1(x); | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*11,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*13,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*17,y FROM t1; INSERT OR IGNORE INTO t1 SELECT x*19,y FROM t1; CREATE INDEX t1i1 ON t1(x); CREATE TABLE t2 AS SELECT x,2 as y FROM t1 WHERE rowid%5!=0 ORDER BY rowid; COMMIT; } } {} ifcapable {integrityck} { integrity_check corruptE-1.2 } |
︙ | ︙ |
Added test/coveridxscan.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | # 2012 September 17 # # 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. # #*********************************************************************** # # Tests for the optimization which attempts to use a covering index # for a full-table scan (under the theory that the index will be smaller # and require less I/O and hence will run faster.) # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix coveridxscan do_test 1.1 { db eval { CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(5,4,3), (4,8,2), (3,2,1); CREATE INDEX t1ab ON t1(a,b); CREATE INDEX t1b ON t1(b); SELECT a FROM t1; } # covering index used for the scan, hence values are increasing } {3 4 5} do_test 1.2 { db eval { SELECT a, c FROM t1; } # There is no covering index, hence the values are in rowid order } {5 3 4 2 3 1} do_test 1.3 { db eval { SELECT b FROM t1; } # Choice of two indices: use the one with fewest columns } {2 4 8} do_test 2.1 { optimization_control db cover-idx-scan 0 db eval {SELECT a FROM t1} # With the optimization turned off, output in rowid order } {5 4 3} do_test 2.2 { db eval {SELECT a, c FROM t1} } {5 3 4 2 3 1} do_test 2.3 { db eval {SELECT b FROM t1} } {4 8 2} db close sqlite3_shutdown sqlite3_config_cis 0 sqlite3 db test.db do_test 3.1 { db eval {SELECT a FROM t1} # With the optimization configured off, output in rowid order } {5 4 3} do_test 3.2 { db eval {SELECT a, c FROM t1} } {5 3 4 2 3 1} do_test 3.3 { db eval {SELECT b FROM t1} } {4 8 2} db close sqlite3_shutdown sqlite3_config_cis 1 sqlite3 db test.db # The CIS optimization is enabled again. Covering indices are once again # used for all table scans. do_test 4.1 { db eval {SELECT a FROM t1} } {3 4 5} do_test 4.2 { db eval {SELECT a, c FROM t1} } {5 3 4 2 3 1} do_test 4.3 { db eval {SELECT b FROM t1} } {2 4 8} finish_test |
Changes to test/dbstatus2.test.
︙ | ︙ | |||
84 85 86 87 88 89 90 | execsql { INSERT INTO t1 VALUES(4, randomblob(600)) } db_write db } {0 4 0} do_test 2.3 { db_write db 1 } {0 4 0} do_test 2.4 { db_write db 0 } {0 0 0} do_test 2.5 { db_write db 1 } {0 0 0} | > | | | | > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | execsql { INSERT INTO t1 VALUES(4, randomblob(600)) } db_write db } {0 4 0} do_test 2.3 { db_write db 1 } {0 4 0} do_test 2.4 { db_write db 0 } {0 0 0} do_test 2.5 { db_write db 1 } {0 0 0} ifcapable wal { do_test 2.6 { execsql { PRAGMA journal_mode = WAL } db_write db 1 } {0 1 0} } do_test 2.7 { execsql { INSERT INTO t1 VALUES(5, randomblob(600)) } db_write db } {0 4 0} do_test 2.8 { db_write db 1 } {0 4 0} do_test 2.9 { db_write db 0 } {0 0 0} |
︙ | ︙ |
Changes to test/distinct.test.
︙ | ︙ | |||
171 172 173 174 175 176 177 | 9 "b COLLATE nocase FROM t1 ORDER BY b COLLATE nocase" {} {B} } { do_execsql_test 2.$tn.1 "SELECT DISTINCT $sql" $res do_temptables_test 2.$tn.2 "SELECT DISTINCT $sql" $temptables } do_execsql_test 2.A { | | | > > > > > > > > > > | > > > > > > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | 9 "b COLLATE nocase FROM t1 ORDER BY b COLLATE nocase" {} {B} } { do_execsql_test 2.$tn.1 "SELECT DISTINCT $sql" $res do_temptables_test 2.$tn.2 "SELECT DISTINCT $sql" $temptables } do_execsql_test 2.A { SELECT (SELECT DISTINCT o.a FROM t1 AS i) FROM t1 AS o ORDER BY rowid; } {a A a A} do_test 3.0 { db eval { CREATE TABLE t3(a INTEGER, b INTEGER, c, UNIQUE(a,b)); INSERT INTO t3 VALUES (null, null, 1), (null, null, 2), (null, 3, 4), (null, 3, 5), (6, null, 7), (6, null, 8); SELECT DISTINCT a, b FROM t3 ORDER BY +a, +b; } } {{} {} {} 3 6 {}} do_test 3.1 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT DISTINCT a, b FROM t3 ORDER BY +a, +b; }] } {0} finish_test |
Changes to test/e_createtable.test.
︙ | ︙ | |||
1587 1588 1589 1590 1591 1592 1593 | do_execsql_test 4.17.$tn.1 "BEGIN; INSERT INTO $tbl VALUES(3, 'three')" do_catchsql_test 4.17.$tn.2 " INSERT INTO $tbl SELECT ((a%2)*a+3), 'three' FROM $tbl " $res do_test e_createtable-4.17.$tn.3 { sqlite3_get_autocommit db } $ac | | | 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 | do_execsql_test 4.17.$tn.1 "BEGIN; INSERT INTO $tbl VALUES(3, 'three')" do_catchsql_test 4.17.$tn.2 " INSERT INTO $tbl SELECT ((a%2)*a+3), 'three' FROM $tbl " $res do_test e_createtable-4.17.$tn.3 { sqlite3_get_autocommit db } $ac do_execsql_test 4.17.$tn.4 "SELECT * FROM $tbl ORDER BY rowid" $data } catchsql COMMIT # EVIDENCE-OF: R-12645-39772 Or, if a constraint definition does not # include a conflict-clause or it is a CHECK constraint, the default # conflict resolution algorithm is ABORT. # |
︙ | ︙ |
Changes to test/e_fkey.test.
︙ | ︙ | |||
2056 2057 2058 2059 2060 2061 2062 | INSERT INTO cA VALUES(X'ABCD'); INSERT INTO cB VALUES(X'1234'); } } {} do_test e_fkey-45.2 { execsql { DELETE FROM pA WHERE rowid = 3; | | | | 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 | INSERT INTO cA VALUES(X'ABCD'); INSERT INTO cB VALUES(X'1234'); } } {} do_test e_fkey-45.2 { execsql { DELETE FROM pA WHERE rowid = 3; SELECT quote(x) FROM pA ORDER BY rowid; } } {X'0000' X'9999' X'1234'} do_test e_fkey-45.3 { execsql { SELECT quote(c) FROM cA } } {X'0000'} do_test e_fkey-45.4 { execsql { UPDATE pA SET x = X'8765' WHERE rowid = 4; SELECT quote(x) FROM pA ORDER BY rowid; } } {X'0000' X'9999' X'8765'} do_test e_fkey-45.5 { execsql { SELECT quote(c) FROM cB } } {X'9999'} #------------------------------------------------------------------------- |
︙ | ︙ | |||
2321 2322 2323 2324 2325 2326 2327 | INSERT INTO parent VALUES(1); INSERT INTO child VALUES(1); } } {} do_test e_fkey-51.2 { execsql { UPDATE parent SET x = 22; | | | | 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 | INSERT INTO parent VALUES(1); INSERT INTO child VALUES(1); } } {} do_test e_fkey-51.2 { execsql { UPDATE parent SET x = 22; SELECT * FROM parent ORDER BY rowid; SELECT 'xxx' ; SELECT a FROM child; } } {22 21 23 xxx 22} do_test e_fkey-51.3 { execsql { DELETE FROM child; DELETE FROM parent; INSERT INTO parent VALUES(-1); INSERT INTO child VALUES(-1); UPDATE parent SET x = 22; SELECT * FROM parent ORDER BY rowid; SELECT 'xxx' ; SELECT a FROM child; } } {22 23 21 xxx 23} #------------------------------------------------------------------------- # Verify that ON UPDATE actions only actually take place if the parent key # is set to a new value that is distinct from the old value. The default |
︙ | ︙ |
Changes to test/e_select.test.
︙ | ︙ | |||
1019 1020 1021 1022 1023 1024 1025 | # These tests also show that the following is not untrue: # # EVIDENCE-OF: R-25883-55063 The expressions in the GROUP BY clause do # not have to be expressions that appear in the result. # do_select_tests e_select-4.9 { 1 "SELECT group_concat(one), two FROM b1 GROUP BY two" { | | | | | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 | # These tests also show that the following is not untrue: # # EVIDENCE-OF: R-25883-55063 The expressions in the GROUP BY clause do # not have to be expressions that appear in the result. # do_select_tests e_select-4.9 { 1 "SELECT group_concat(one), two FROM b1 GROUP BY two" { /#,# f 1 o #,# s #,# t/ } 2 "SELECT group_concat(one), sum(one) FROM b1 GROUP BY (one>4)" { 1,2,3,4 10 5,6,7 18 } 3 "SELECT group_concat(one) FROM b1 GROUP BY (two>'o'), one%2" { 4 1,5 2,6 3,7 } 4 "SELECT group_concat(one) FROM b1 GROUP BY (one==2 OR two=='o')" { 4,3,5,7,6 1,2 } } # EVIDENCE-OF: R-14926-50129 For the purposes of grouping rows, NULL # values are considered equal. # do_select_tests e_select-4.10 { 1 "SELECT group_concat(y) FROM b2 GROUP BY x" {/#,# 3 #,#/} 2 "SELECT count(*) FROM b2 GROUP BY CASE WHEN y<4 THEN NULL ELSE 0 END" {4 1} } # EVIDENCE-OF: R-10470-30318 The usual rules for selecting a collation # sequence with which to compare text values apply when evaluating # expressions in a GROUP BY clause. # |
︙ | ︙ | |||
1741 1742 1743 1744 1745 1746 1747 | 1 2 3 1 2 -20 1 4 93 1 5 -1 } 7 "SELECT * FROM d1 ORDER BY 1 DESC, 2, 3" { 2 4 93 2 5 -1 1 2 -20 1 2 3 1 2 7 1 2 8 1 4 93 1 5 -1 } 8 "SELECT z, x FROM d1 ORDER BY 2" { | | | | | | | | 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 | 1 2 3 1 2 -20 1 4 93 1 5 -1 } 7 "SELECT * FROM d1 ORDER BY 1 DESC, 2, 3" { 2 4 93 2 5 -1 1 2 -20 1 2 3 1 2 7 1 2 8 1 4 93 1 5 -1 } 8 "SELECT z, x FROM d1 ORDER BY 2" { /# 1 # 1 # 1 # 1 # 1 # 1 # 2 # 2/ } 9 "SELECT z, x FROM d1 ORDER BY 1" { /-20 1 -1 # -1 # 3 1 7 1 8 1 93 # 93 #/ } } # EVIDENCE-OF: R-63286-51977 If the ORDER BY expression is an identifier # that corresponds to the alias of one of the output columns, then the # expression is considered an alias for that column. # do_select_tests e_select-8.5 { 1 "SELECT z+1 AS abc FROM d1 ORDER BY abc" { -19 0 0 4 8 9 94 94 } 2 "SELECT z+1 AS abc FROM d1 ORDER BY abc DESC" { 94 94 9 8 4 0 0 -19 } 3 "SELECT z AS x, x AS z FROM d1 ORDER BY z" { /# 1 # 1 # 1 # 1 # 1 # 1 # 2 # 2/ } 4 "SELECT z AS x, x AS z FROM d1 ORDER BY x" { /-20 1 -1 # -1 # 3 1 7 1 8 1 93 # 93 #/ } } # EVIDENCE-OF: R-65068-27207 Otherwise, if the ORDER BY expression is # any other expression, it is evaluated and the returned value used to # order the output rows. # |
︙ | ︙ |
Changes to test/eqp.test.
︙ | ︙ | |||
58 59 60 61 62 63 64 | SELECT a FROM t1 ORDER BY a } { 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1 (~1000000 rows)} } do_eqp_test 1.4 { SELECT a FROM t1 ORDER BY +a } { | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | SELECT a FROM t1 ORDER BY a } { 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1 (~1000000 rows)} } do_eqp_test 1.4 { SELECT a FROM t1 ORDER BY +a } { 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1 (~1000000 rows)} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } do_eqp_test 1.5 { SELECT a FROM t1 WHERE a=4 } { 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)} } |
︙ | ︙ | |||
162 163 164 165 166 167 168 | det 2.3.1 "SELECT max(x) FROM t2" { 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)} } det 2.3.2 "SELECT min(x) FROM t2" { 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)} } det 2.3.3 "SELECT min(x), max(x) FROM t2" { | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | det 2.3.1 "SELECT max(x) FROM t2" { 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)} } det 2.3.2 "SELECT min(x) FROM t2" { 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)} } det 2.3.3 "SELECT min(x), max(x) FROM t2" { 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1 (~1000000 rows)} } det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" { 0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)} } |
︙ | ︙ | |||
335 336 337 338 339 340 341 | 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)} } do_eqp_test 4.3.1 { SELECT x FROM t1 UNION SELECT x FROM t2 } { 1 0 0 {SCAN TABLE t1 (~1000000 rows)} | | | | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)} } do_eqp_test 4.3.1 { SELECT x FROM t1 UNION SELECT x FROM t2 } { 1 0 0 {SCAN TABLE t1 (~1000000 rows)} 2 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1 (~1000000 rows)} 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)} } do_eqp_test 4.3.2 { SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 } { 2 0 0 {SCAN TABLE t1 (~1000000 rows)} 3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1 (~1000000 rows)} 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)} 4 0 0 {SCAN TABLE t1 (~1000000 rows)} 0 0 0 {COMPOUND SUBQUERIES 1 AND 4 USING TEMP B-TREE (UNION)} } do_eqp_test 4.3.3 { SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1 } { |
︙ | ︙ | |||
443 444 445 446 447 448 449 | # 0|0|0|SCAN TABLE t2 (~1000000 rows) 0|0|0|EXECUTE SCALAR SUBQUERY 1 # 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows) # 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2 2|0|0|SEARCH TABLE t1 USING # INDEX i3 (b=?) (~10 rows) det 5.9 { SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2 } { | | | 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 | # 0|0|0|SCAN TABLE t2 (~1000000 rows) 0|0|0|EXECUTE SCALAR SUBQUERY 1 # 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows) # 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2 2|0|0|SEARCH TABLE t1 USING # INDEX i3 (b=?) (~10 rows) det 5.9 { SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2 } { 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i4 (~1000000 rows)} 0 0 0 {EXECUTE SCALAR SUBQUERY 1} 1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows)} 0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2} 2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?) (~10 rows)} } # EVIDENCE-OF: R-17911-16445 sqlite> EXPLAIN QUERY PLAN SELECT |
︙ | ︙ | |||
467 468 469 470 471 472 473 | } # EVIDENCE-OF: R-18544-33103 sqlite> EXPLAIN QUERY PLAN SELECT * FROM # (SELECT * FROM t2 WHERE c=1), t1; 0|0|0|SEARCH TABLE t2 USING INDEX i4 # (c=?) (~10 rows) 0|1|1|SCAN TABLE t1 (~1000000 rows) det 5.11 "SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1" { 0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?) (~10 rows)} | | | | | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | } # EVIDENCE-OF: R-18544-33103 sqlite> EXPLAIN QUERY PLAN SELECT * FROM # (SELECT * FROM t2 WHERE c=1), t1; 0|0|0|SEARCH TABLE t2 USING INDEX i4 # (c=?) (~10 rows) 0|1|1|SCAN TABLE t1 (~1000000 rows) det 5.11 "SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1" { 0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?) (~10 rows)} 0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2 (~1000000 rows)} } # EVIDENCE-OF: R-40701-42164 sqlite> EXPLAIN QUERY PLAN SELECT a FROM # t1 UNION SELECT c FROM t2; 1|0|0|SCAN TABLE t1 (~1000000 rows) # 2|0|0|SCAN TABLE t2 (~1000000 rows) 0|0|0|COMPOUND SUBQUERIES 1 AND 2 # USING TEMP B-TREE (UNION) det 5.12 "SELECT a FROM t1 UNION SELECT c FROM t2" { 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1 (~1000000 rows)} 2 0 0 {SCAN TABLE t2 USING COVERING INDEX i4 (~1000000 rows)} 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)} } # EVIDENCE-OF: R-61538-24748 sqlite> EXPLAIN QUERY PLAN SELECT a FROM # t1 EXCEPT SELECT d FROM t2 ORDER BY 1; 1|0|0|SCAN TABLE t1 USING # COVERING INDEX i2 (~1000000 rows) 2|0|0|SCAN TABLE t2 (~1000000 rows) # 2|0|0|USE TEMP B-TREE FOR ORDER BY 0|0|0|COMPOUND SUBQUERIES 1 AND 2 |
︙ | ︙ |
Added test/full.test.
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 2012 September 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 runs the "full" test suite. It is a peer of the quick.test # and all.test scripts. # set testdir [file dirname $argv0] source $testdir/permutations.test run_test_suite full finish_test |
Added test/in5.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | # 2012 September 18 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl do_test in5-1.1 { execsql { CREATE TABLE t1x(x INTEGER PRIMARY KEY); INSERT INTO t1x VALUES(1),(3),(5),(7),(9); CREATE TABLE t1y(y INTEGER UNIQUE); INSERT INTO t1y VALUES(2),(4),(6),(8); CREATE TABLE t1z(z TEXT UNIQUE); INSERT INTO t1z VALUES('a'),('c'),('e'),('g'); CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT, d TEXT); INSERT INTO t2 VALUES(1,2,'a','12a'),(1,2,'b','12b'), (2,3,'g','23g'),(3,5,'c','35c'), (4,6,'h','46h'),(5,6,'e','56e'); CREATE TABLE t3x AS SELECT x FROM t1x; CREATE TABLE t3y AS SELECT y FROM t1y; CREATE TABLE t3z AS SELECT z FROM t1z; SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY c; } } {12a 56e} do_test in5-1.2 { execsql { SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d; } } {23g} do_test in5-1.3 { execsql { SELECT d FROM t2 WHERE a IN t3x AND b IN t3y AND c IN t3z ORDER BY d; } } {12a 56e} do_test in5-2.1 { execsql { CREATE INDEX t2abc ON t2(a,b,c); SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d; } } {12a 56e} do_test in5-2.2 { execsql { SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d; } } {23g} do_test in5-2.3 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z }] } {0} do_test in5-2.4 { execsql { SELECT d FROM t2 WHERE a IN t3x AND b IN t3y AND c IN t3z ORDER BY d; } } {12a 56e} do_test in5-2.5.1 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t3x AND b IN t1y AND c IN t1z }] } {1} do_test in5-2.5.2 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t3y AND c IN t1z }] } {1} do_test in5-2.5.3 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t3z }] } {1} do_test in5-3.1 { execsql { DROP INDEX t2abc; CREATE INDEX t2ab ON t2(a,b); SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d; } } {12a 56e} do_test in5-3.2 { execsql { SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d; } } {23g} do_test in5-3.3 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z }] } {0} do_test in5-4.1 { execsql { DROP INDEX t2ab; CREATE INDEX t2abcd ON t2(a,b,c,d); SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d; } } {12a 56e} do_test in5-4.2 { execsql { SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d; } } {23g} do_test in5-4.3 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z }] } {0} do_test in5-5.1 { execsql { DROP INDEX t2abcd; CREATE INDEX t2cbad ON t2(c,b,a,d); SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d; } } {12a 56e} do_test in5-5.2 { execsql { SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d; } } {23g} do_test in5-5.3 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z }] } {0} finish_test |
Changes to test/incrblob.test.
︙ | ︙ | |||
433 434 435 436 437 438 439 | execsql { BEGIN; INSERT INTO blobs(k, v, i) VALUES('a', 'different', 'connection'); } db2 } {} do_test incrblob-6.2 { execsql { | | | 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | execsql { BEGIN; INSERT INTO blobs(k, v, i) VALUES('a', 'different', 'connection'); } db2 } {} do_test incrblob-6.2 { execsql { SELECT rowid FROM blobs ORDER BY rowid } } {1 2 3} do_test incrblob-6.3 { set rc [catch { db incrblob blobs v 1 } msg] list $rc $msg |
︙ | ︙ |
Changes to test/intpkey.test.
︙ | ︙ | |||
372 373 374 375 376 377 378 | } count { SELECT * FROM t1 WHERE a=0; } } {0 zero entry 0} do_test intpkey-5.2 { execsql { | | | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 | } count { SELECT * FROM t1 WHERE a=0; } } {0 zero entry 0} do_test intpkey-5.2 { execsql { SELECT rowid, a FROM t1 ORDER BY rowid } } {-4 -4 0 0 5 5 6 6 11 11} # Test the ability of the COPY command to put data into a # table that contains an integer primary key. # # COPY command has been removed. But we retain these tests so |
︙ | ︙ |
Changes to test/like.test.
︙ | ︙ | |||
402 403 404 405 406 407 408 | } {ABC {ABC abc xyz} abc abcd nosort {} i1} do_test like-5.2 { set sqlite_like_count } 12 do_test like-5.3 { execsql { CREATE TABLE t2(x TEXT COLLATE NOCASE); | | | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 | } {ABC {ABC abc xyz} abc abcd nosort {} i1} do_test like-5.2 { set sqlite_like_count } 12 do_test like-5.3 { execsql { CREATE TABLE t2(x TEXT COLLATE NOCASE); INSERT INTO t2 SELECT * FROM t1 ORDER BY rowid; CREATE INDEX i2 ON t2(x COLLATE NOCASE); } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1 } } {abc ABC {ABC abc xyz} abcd nosort {} i2} |
︙ | ︙ | |||
658 659 660 661 662 663 664 | }] } {0 {x hello}} ifcapable explain { do_test like-9.4.3 { set res [sqlite3_exec_hex db { EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25' }] | | | | 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | }] } {0 {x hello}} ifcapable explain { do_test like-9.4.3 { set res [sqlite3_exec_hex db { EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25' }] regexp {SCAN TABLE t2} $res } {1} } do_test like-9.5.1 { set res [sqlite3_exec_hex db { SELECT x FROM t2 WHERE x LIKE '%fe%25' }] } {0 {}} ifcapable explain { |
︙ | ︙ |
Changes to test/lock.test.
︙ | ︙ | |||
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | # do_test lock-2.8 { db2 timeout 400 execsql BEGIN execsql {UPDATE t1 SET a = 0 WHERE 0} catchsql {BEGIN EXCLUSIVE;} db2 } {1 {database is locked}} do_test lock-2.9 { db2 timeout 0 execsql COMMIT } {} integrity_check lock-2.10 # Try to start two transactions in a row # do_test lock-3.1 { execsql {BEGIN TRANSACTION} set r [catch {execsql {BEGIN TRANSACTION}} msg] execsql {ROLLBACK} | > > > > > > > > > > > > > > > > > > > > > > > | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | # do_test lock-2.8 { db2 timeout 400 execsql BEGIN execsql {UPDATE t1 SET a = 0 WHERE 0} catchsql {BEGIN EXCLUSIVE;} db2 } {1 {database is locked}} do_test lock-2.8b { db2 eval {PRAGMA busy_timeout} } {400} do_test lock-2.9 { db2 timeout 0 execsql COMMIT } {} do_test lock-2.9b { db2 eval {PRAGMA busy_timeout} } {0} integrity_check lock-2.10 do_test lock-2.11 { db2 eval {PRAGMA busy_timeout(400)} execsql BEGIN execsql {UPDATE t1 SET a = 0 WHERE 0} catchsql {BEGIN EXCLUSIVE;} db2 } {1 {database is locked}} do_test lock-2.11b { db2 eval {PRAGMA busy_timeout} } {400} do_test lock-2.12 { db2 eval {PRAGMA busy_timeout(0)} execsql COMMIT } {} do_test lock-2.12b { db2 eval {PRAGMA busy_timeout} } {0} integrity_check lock-2.13 # Try to start two transactions in a row # do_test lock-3.1 { execsql {BEGIN TRANSACTION} set r [catch {execsql {BEGIN TRANSACTION}} msg] execsql {ROLLBACK} |
︙ | ︙ |
Added test/orderby1.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 | # 2012 Sept 27 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing that the optimizations that disable # ORDER BY clauses when the natural order of a query is correct. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix orderby1 # Generate test data for a join. Verify that the join gets the # correct answer. # do_test 1.0 { db eval { BEGIN; CREATE TABLE album( aid INTEGER PRIMARY KEY, title TEXT UNIQUE NOT NULL ); CREATE TABLE track( tid INTEGER PRIMARY KEY, aid INTEGER NOT NULL REFERENCES album, tn INTEGER NOT NULL, name TEXT, UNIQUE(aid, tn) ); INSERT INTO album VALUES(1, '1-one'), (2, '2-two'), (3, '3-three'); INSERT INTO track VALUES (NULL, 1, 1, 'one-a'), (NULL, 2, 2, 'two-b'), (NULL, 3, 3, 'three-c'), (NULL, 1, 3, 'one-c'), (NULL, 2, 1, 'two-a'), (NULL, 3, 1, 'three-a'); COMMIT; } } {} do_test 1.1a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} # Verify that the ORDER BY clause is optimized out # do_test 1.1b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {~/ORDER BY/} ;# ORDER BY optimized out # The same query with ORDER BY clause optimization disabled via + operators # should give exactly the same answer. # do_test 1.2a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn } } {one-a one-c two-a two-b three-a three-c} # The output is sorted manually in this case. # do_test 1.2b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn } } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms # The same query with ORDER BY optimizations turned off via built-in test. # do_test 1.3a { optimization_control db order-by-idx-join 0 db cache flush db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} do_test 1.3b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {/ORDER BY/} ;# separate sorting pass due to disabled optimization optimization_control db all 1 db cache flush # Reverse order sorts # do_test 1.4a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {three-a three-c two-a two-b one-a one-c} do_test 1.4b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 1.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {/ORDER BY/} ;# separate sorting pass due to mixed DESC/ASC do_test 1.5a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 1.5b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting do_test 1.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {/ORDER BY/} ;# separate sorting pass due to mixed DESC/ASC do_test 1.6a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 1.6b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC } } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting do_test 1.6c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {~/ORDER BY/} ;# ORDER BY optimized-out # Reconstruct the test data to use indices rather than integer primary keys. # do_test 2.0 { db eval { BEGIN; DROP TABLE album; DROP TABLE track; CREATE TABLE album( aid INT PRIMARY KEY, title TEXT NOT NULL ); CREATE INDEX album_i1 ON album(title, aid); CREATE TABLE track( aid INTEGER NOT NULL REFERENCES album, tn INTEGER NOT NULL, name TEXT, UNIQUE(aid, tn) ); INSERT INTO album VALUES(1, '1-one'), (2, '2-two'), (3, '3-three'); INSERT INTO track VALUES (1, 1, 'one-a'), (2, 2, 'two-b'), (3, 3, 'three-c'), (1, 3, 'one-c'), (2, 1, 'two-a'), (3, 1, 'three-a'); COMMIT; } } {} do_test 2.1a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} # Verify that the ORDER BY clause is optimized out # do_test 2.1b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {~/ORDER BY/} ;# ORDER BY optimized out # The same query with ORDER BY clause optimization disabled via + operators # should give exactly the same answer. # do_test 2.2a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn } } {one-a one-c two-a two-b three-a three-c} # The output is sorted manually in this case. # do_test 2.2b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn } } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms # The same query with ORDER BY optimizations turned off via built-in test. # do_test 2.3a { optimization_control db order-by-idx-join 0 db cache flush db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} do_test 2.3b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {/ORDER BY/} ;# separate sorting pass due to disabled optimization optimization_control db all 1 db cache flush # Reverse order sorts # do_test 2.4a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {three-a three-c two-a two-b one-a one-c} do_test 2.4b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 2.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {/ORDER BY/} ;# separate sorting pass due to mixed DESC/ASC do_test 2.5a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 2.5b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting do_test 2.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {/ORDER BY/} ;# separate sorting pass due to mixed ASC/DESC do_test 2.6a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 2.6b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC } } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting do_test 2.6c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {~/ORDER BY/} ;# ORDER BY optimized-out # Generate another test dataset, but this time using mixed ASC/DESC indices. # do_test 3.0 { db eval { BEGIN; DROP TABLE album; DROP TABLE track; CREATE TABLE album( aid INTEGER PRIMARY KEY, title TEXT UNIQUE NOT NULL ); CREATE TABLE track( tid INTEGER PRIMARY KEY, aid INTEGER NOT NULL REFERENCES album, tn INTEGER NOT NULL, name TEXT, UNIQUE(aid ASC, tn DESC) ); INSERT INTO album VALUES(1, '1-one'), (2, '2-two'), (3, '3-three'); INSERT INTO track VALUES (NULL, 1, 1, 'one-a'), (NULL, 2, 2, 'two-b'), (NULL, 3, 3, 'three-c'), (NULL, 1, 3, 'one-c'), (NULL, 2, 1, 'two-a'), (NULL, 3, 1, 'three-a'); COMMIT; } } {} do_test 3.1a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} # Verify that the ORDER BY clause is optimized out # do_test 3.1b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {~/ORDER BY/} ;# ORDER BY optimized out # The same query with ORDER BY clause optimization disabled via + operators # should give exactly the same answer. # do_test 3.2a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} # The output is sorted manually in this case. # do_test 3.2b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC } } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms # The same query with ORDER BY optimizations turned off via built-in test. # do_test 3.3a { optimization_control db order-by-idx-join 0 db cache flush db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 3.3b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {/ORDER BY/} ;# separate sorting pass due to disabled optimization optimization_control db all 1 db cache flush # Without the mixed ASC/DESC on ORDER BY # do_test 3.4a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} do_test 3.4b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn } } {one-a one-c two-a two-b three-a three-c} ;# verify same order after sorting do_test 3.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {/ORDER BY/} ;# separate sorting pass due to mismatched DESC/ASC do_test 3.5a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 3.5b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC } } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting do_test 3.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {/ORDER BY/} ;# separate sorting pass due to mismatched ASC/DESC do_test 3.6a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {three-a three-c two-a two-b one-a one-c} do_test 3.6b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 3.6c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {~/ORDER BY/} ;# inverted ASC/DESC is optimized out finish_test |
Changes to test/permutations.test.
︙ | ︙ | |||
92 93 94 95 96 97 98 | if {$::tcl_platform(platform)!="unix"} { set alltests [test_set $alltests -exclude crash.test crash2.test] } set alltests [test_set $alltests -exclude { all.test async.test quick.test veryquick.test memleak.test permutations.test soak.test fts3.test | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | if {$::tcl_platform(platform)!="unix"} { set alltests [test_set $alltests -exclude crash.test crash2.test] } set alltests [test_set $alltests -exclude { all.test async.test quick.test veryquick.test memleak.test permutations.test soak.test fts3.test mallocAll.test rtree.test full.test }] set allquicktests [test_set $alltests -exclude { async2.test async3.test backup_ioerr.test corrupt.test corruptC.test crash.test crash2.test crash3.test crash4.test crash5.test crash6.test crash7.test delete3.test e_fts3.test fts3rnd.test fkey_malloc.test fuzz.test fuzz3.test fuzz_malloc.test in2.test loadext.test |
︙ | ︙ |
Changes to test/shell1.test.
︙ | ︙ | |||
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | catchcmd "test.db" ".width xxx yyy" # this should be treated the same as a '0' width for col 1 and 2 } {0 {}} do_test shell1-3.26.4 { catchcmd "test.db" ".width 1 1" # this should be treated the same as a '1' width for col 1 and 2 } {0 {}} # .timer ON|OFF Turn the CPU timer measurement on or off do_test shell1-3.27.1 { catchcmd "test.db" ".timer" } {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}} do_test shell1-3.27.2 { catchcmd "test.db" ".timer ON" } {0 {}} do_test shell1-3.27.3 { catchcmd "test.db" ".timer OFF" } {0 {}} do_test shell1-3.27.4 { # too many arguments catchcmd "test.db" ".timer OFF BAD" } {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}} do_test shell1-3-28.1 { catchcmd test.db \ ".log stdout\nSELECT coalesce(sqlite_log(123,'hello'),'456');" } "0 {(123) hello\n456}" # Test the output of the ".dump" command # do_test shell1-4.1 { db eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(null), (1), (2.25), ('hello'), (x'807f'); | > > > > > > > > > > > > > | 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 | catchcmd "test.db" ".width xxx yyy" # this should be treated the same as a '0' width for col 1 and 2 } {0 {}} do_test shell1-3.26.4 { catchcmd "test.db" ".width 1 1" # this should be treated the same as a '1' width for col 1 and 2 } {0 {}} do_test shell1-3.26.5 { catchcmd "test.db" ".mode column\n.width 10 -10\nSELECT 'abcdefg', 123456;" # this should be treated the same as a '1' width for col 1 and 2 } {0 {abcdefg 123456}} do_test shell1-3.26.6 { catchcmd "test.db" ".mode column\n.width -10 10\nSELECT 'abcdefg', 123456;" # this should be treated the same as a '1' width for col 1 and 2 } {0 { abcdefg 123456 }} # .timer ON|OFF Turn the CPU timer measurement on or off do_test shell1-3.27.1 { catchcmd "test.db" ".timer" } {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}} do_test shell1-3.27.2 { catchcmd "test.db" ".timer ON" } {0 {}} do_test shell1-3.27.3 { catchcmd "test.db" ".timer OFF" } {0 {}} do_test shell1-3.27.4 { # too many arguments catchcmd "test.db" ".timer OFF BAD" } {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}} do_test shell1-3-28.1 { catchcmd test.db \ ".log stdout\nSELECT coalesce(sqlite_log(123,'hello'),'456');" } "0 {(123) hello\n456}" do_test shell1-3-29.1 { catchcmd "test.db" ".print this is a test" } {0 {this is a test}} # Test the output of the ".dump" command # do_test shell1-4.1 { db eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(null), (1), (2.25), ('hello'), (x'807f'); |
︙ | ︙ |
Changes to test/spellfix.test.
︙ | ︙ | |||
64 65 66 67 68 69 70 | execsql { CREATE VIRTUAL TABLE t1 USING spellfix1 } foreach word $vocab { execsql { INSERT INTO t1(word) VALUES($word) } } } {} foreach {tn word res} { | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | execsql { CREATE VIRTUAL TABLE t1 USING spellfix1 } foreach word $vocab { execsql { INSERT INTO t1(word) VALUES($word) } } } {} foreach {tn word res} { 1 raxpi* {rasping 5 rasped 5 ragweed 5 raspberry 6 rasp 4} 2 ril* {rail 4 railed 4 railer 4 railers 4 railing 4} 3 rilis* {realism 6 realist 6 realistic 6 realistically 6 realists 6} 4 reail* {real 3 realest 3 realign 3 realigned 3 realigning 3} 5 ras* {rascal 3 rascally 3 rascals 3 rash 3 rasher 3} 6 realistss* {realists 8 realigns 8 realistic 9 realistically 9 realest 7} 7 realistss {realists 8 realist 7 realigns 8 realistic 9 realest 7} 8 rllation* {realities 9 reality 7 rallied 7 railed 4} |
︙ | ︙ |
Changes to test/stat.test.
︙ | ︙ | |||
72 73 74 75 76 77 78 | DROP TABLE t1; } } {} do_execsql_test stat-2.1 { CREATE TABLE t3(a PRIMARY KEY, b); INSERT INTO t3(rowid, a, b) VALUES(2, a_string(111), a_string(222)); | | > | > | > | > | > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | DROP TABLE t1; } } {} do_execsql_test stat-2.1 { CREATE TABLE t3(a PRIMARY KEY, b); INSERT INTO t3(rowid, a, b) VALUES(2, a_string(111), a_string(222)); INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3 ORDER BY rowid; INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3 ORDER BY rowid; INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3 ORDER BY rowid; INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3 ORDER BY rowid; INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3 ORDER BY rowid; SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload FROM stat WHERE name != 'sqlite_master'; } [list \ sqlite_autoindex_t3_1 / 3 internal 3 368 623 125 \ sqlite_autoindex_t3_1 /000/ 8 leaf 8 946 46 123 \ sqlite_autoindex_t3_1 /001/ 9 leaf 8 988 2 131 \ sqlite_autoindex_t3_1 /002/ 15 leaf 7 857 137 132 \ |
︙ | ︙ |
Changes to test/tclsqlite.test.
︙ | ︙ | |||
139 140 141 142 143 144 145 | set v [catch {db collation_needed} msg] lappend v $msg } {1 {wrong # args: should be "db collation_needed SCRIPT"}} do_test tcl-1.21 { set v [catch {db total_changes xyz} msg] lappend v $msg } {1 {wrong # args: should be "db total_changes "}} | | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | set v [catch {db collation_needed} msg] lappend v $msg } {1 {wrong # args: should be "db collation_needed SCRIPT"}} do_test tcl-1.21 { set v [catch {db total_changes xyz} msg] lappend v $msg } {1 {wrong # args: should be "db total_changes "}} do_test tcl-1.22 { set v [catch {db copy} msg] lappend v $msg } {1 {wrong # args: should be "db copy CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"}} do_test tcl-1.23 { set v [catch {sqlite3 db2 test.db -vfs nosuchvfs} msg] lappend v $msg } {1 {no such vfs: nosuchvfs}} catch {unset ::result} do_test tcl-2.1 { execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)" |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # drop_all_tables ?DB? # forcecopy FROM TO # forcedelete FILENAME # # Test the capability of the SQLite version built into the interpreter to # determine if a specific test can be run: # # ifcapable EXPR # # Calulate checksums based on database contents: # # dbcksum DB DBNAME # allcksum ?DB? # cksum ?DB? | > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | # drop_all_tables ?DB? # forcecopy FROM TO # forcedelete FILENAME # # Test the capability of the SQLite version built into the interpreter to # determine if a specific test can be run: # # capable EXPR # ifcapable EXPR # # Calulate checksums based on database contents: # # dbcksum DB DBNAME # allcksum ?DB? # cksum ?DB? |
︙ | ︙ | |||
130 131 132 133 134 135 136 | proc getFileRetries {} { if {![info exists ::G(file-retries)]} { # # NOTE: Return the default number of retries for [file] operations. A # value of zero or less here means "disabled". # | | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | proc getFileRetries {} { if {![info exists ::G(file-retries)]} { # # NOTE: Return the default number of retries for [file] operations. A # value of zero or less here means "disabled". # return [expr {$::tcl_platform(platform) eq "windows" ? 50 : 0}] } return $::G(file-retries) } proc getFileRetryDelay {} { if {![info exists ::G(file-retry-delay)]} { # |
︙ | ︙ | |||
558 559 560 561 562 563 564 | if {![info exists ::G(match)] || [string match $::G(match) $name]} { if {[catch {uplevel #0 "$cmd;\n"} result]} { puts "\nError: $result" fail_test $name } else { if {[regexp {^~?/.*/$} $expected]} { if {[string index $expected 0]=="~"} { | | | > > > | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | if {![info exists ::G(match)] || [string match $::G(match) $name]} { if {[catch {uplevel #0 "$cmd;\n"} result]} { puts "\nError: $result" fail_test $name } else { if {[regexp {^~?/.*/$} $expected]} { if {[string index $expected 0]=="~"} { set re [string map {# {[-0-9.]+}} [string range $expected 2 end-1]] set ok [expr {![regexp $re $result]}] } else { set re [string map {# {[-0-9.]+}} [string range $expected 1 end-1]] set ok [regexp $re $result] } } else { set ok [expr {[string compare $result $expected]==0}] } if {!$ok} { # if {![info exists ::testprefix] || $::testprefix eq ""} { # error "no test prefix" # } puts "\nExpected: \[$expected\]\n Got: \[$result\]" fail_test $name } else { puts " Ok" } } } else { |
︙ | ︙ | |||
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 | } append ret $char set state $newstate } if {$state} {append ret )} return $ret } # Evaluate a boolean expression of capabilities. If true, execute the # code. Omit the code if false. # proc ifcapable {expr code {else ""} {elsecode ""}} { #regsub -all {[a-z_0-9]+} $expr {$::sqlite_options(&)} e2 set e2 [fix_ifcapable_expr $expr] | > > > > > > | 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 | } append ret $char set state $newstate } if {$state} {append ret )} return $ret } # Returns non-zero if the capabilities are present; zero otherwise. # proc capable {expr} { set e [fix_ifcapable_expr $expr]; return [expr ($e)] } # Evaluate a boolean expression of capabilities. If true, execute the # code. Omit the code if false. # proc ifcapable {expr code {else ""} {elsecode ""}} { #regsub -all {[a-z_0-9]+} $expr {$::sqlite_options(&)} e2 set e2 [fix_ifcapable_expr $expr] |
︙ | ︙ |
Changes to test/tkt-385a5b56b9.test.
︙ | ︙ | |||
35 36 37 38 39 40 41 | } do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } { 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2x (~1000000 rows)} } do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } { | | < | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | } do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } { 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2x (~1000000 rows)} } do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } { 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2y (~1000000 rows)} } do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } { 0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?) (~1 rows)} } do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } { 0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x=?) (~1 rows)} } finish_test |
Changes to test/tkt-5d863f876e.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 | # This file implements tests to verify that ticket [5d863f876e] has been # fixed. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl | | | < < | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # This file implements tests to verify that ticket [5d863f876e] has been # fixed. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl set ::testprefix tkt-5d863f876e ifcapable !wal {finish_test ; return } do_multiclient_test tn { do_test $tn.1 { sql1 { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); INSERT INTO t1 VALUES(1, 2); |
︙ | ︙ |
Changes to test/tkt-78e04e52ea.test.
︙ | ︙ | |||
40 41 42 43 44 45 46 | CREATE INDEX i1 ON ""("" COLLATE nocase); } } {} do_test tkt-78e04-1.4 { execsql { EXPLAIN QUERY PLAN SELECT * FROM "" WHERE "" LIKE 'abc%'; } | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | CREATE INDEX i1 ON ""("" COLLATE nocase); } } {} do_test tkt-78e04-1.4 { execsql { EXPLAIN QUERY PLAN SELECT * FROM "" WHERE "" LIKE 'abc%'; } } {0 0 0 {SCAN TABLE USING COVERING INDEX i1 (~500000 rows)}} do_test tkt-78e04-1.5 { execsql { DROP TABLE ""; SELECT name FROM sqlite_master; } } {t2} |
︙ | ︙ |
Changes to test/tkt-80ba201079.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 | # resolved. That ticket is about an incorrect result that appears when # an index is added. The root cause is that a constant is being used # without initialization when the OR optimization applies in the WHERE clause. # set testdir [file dirname $argv0] source $testdir/tester.tcl | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # resolved. That ticket is about an incorrect result that appears when # an index is added. The root cause is that a constant is being used # without initialization when the OR optimization applies in the WHERE clause. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix tkt-80ba201079 do_test tkt-80ba2-100 { db eval { CREATE TABLE t1(a); INSERT INTO t1 VALUES('A'); CREATE TABLE t2(b); INSERT INTO t2 VALUES('B'); |
︙ | ︙ |
Changes to test/tkt-cbd054fa6b.test.
︙ | ︙ | |||
46 47 48 49 50 51 52 | do_test tkt-cbd05-1.3 { execsql { SELECT tbl,idx,group_concat(sample,' ') FROM sqlite_stat3 WHERE idx = 't1_x' GROUP BY tbl,idx } | | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | do_test tkt-cbd05-1.3 { execsql { SELECT tbl,idx,group_concat(sample,' ') FROM sqlite_stat3 WHERE idx = 't1_x' GROUP BY tbl,idx } } {/t1 t1_x .[ ABCDEFGHI]{10}./} do_test tkt-cbd05-2.1 { db eval { DROP TABLE t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB UNIQUE NOT NULL); CREATE INDEX t1_x ON t1(b); INSERT INTO t1 VALUES(NULL, X''); |
︙ | ︙ | |||
78 79 80 81 82 83 84 | do_test tkt-cbd05-2.3 { execsql { SELECT tbl,idx,group_concat(sample,' ') FROM sqlite_stat3 WHERE idx = 't1_x' GROUP BY tbl,idx } | | | 78 79 80 81 82 83 84 85 86 87 | do_test tkt-cbd05-2.3 { execsql { SELECT tbl,idx,group_concat(sample,' ') FROM sqlite_stat3 WHERE idx = 't1_x' GROUP BY tbl,idx } } {/t1 t1_x .[ ABCDEFGHI]{10}./} finish_test |
Changes to test/triggerC.test.
︙ | ︙ | |||
218 219 220 221 222 223 224 | } { do_test triggerC-2.1.$n { catchsql { DROP TRIGGER t2_trig } execsql { DELETE FROM t2 } execsql $tdefn catchsql { INSERT INTO t2 VALUES(10); | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | } { do_test triggerC-2.1.$n { catchsql { DROP TRIGGER t2_trig } execsql { DELETE FROM t2 } execsql $tdefn catchsql { INSERT INTO t2 VALUES(10); SELECT * FROM t2 ORDER BY rowid; } } $rc } do_test triggerC-2.2 { execsql " CREATE TABLE t22(x); |
︙ | ︙ | |||
543 544 545 546 547 548 549 | 2 integer 9.1 text 9.1 real 9.1 real } } { do_test triggerC-4.1.$n { eval concat [execsql " DELETE FROM log; $insert ; | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | 2 integer 9.1 text 9.1 real 9.1 real } } { do_test triggerC-4.1.$n { eval concat [execsql " DELETE FROM log; $insert ; SELECT * FROM log ORDER BY rowid; "] } [join $log " "] } #------------------------------------------------------------------------- # This block of tests, triggerC-5.*, test that DELETE triggers are fired # if a row is deleted as a result of OR REPLACE conflict resolution. |
︙ | ︙ | |||
580 581 582 583 584 585 586 | 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 3 3 c 2} {1 a 2 c} 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 3 2 b 2} {1 b} } { do_test triggerC-5.1.$n { execsql " BEGIN; $dml ; | | | | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 | 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 3 3 c 2} {1 a 2 c} 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 3 2 b 2} {1 b} } { do_test triggerC-5.1.$n { execsql " BEGIN; $dml ; SELECT * FROM t5g ORDER BY rowid; SELECT * FROM t5 ORDER BY rowid; ROLLBACK; " } [concat $t5g $t5] } do_test triggerC-5.2.0 { execsql { DROP TRIGGER t5t; |
︙ | ︙ | |||
607 608 609 610 611 612 613 | 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 2 3 c 1} {1 a 2 c} 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 2 2 b 1} {1 b} } { do_test triggerC-5.2.$n { execsql " BEGIN; $dml ; | | | | | | 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 2 3 c 1} {1 a 2 c} 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 2 2 b 1} {1 b} } { do_test triggerC-5.2.$n { execsql " BEGIN; $dml ; SELECT * FROM t5g ORDER BY rowid; SELECT * FROM t5 ORDER BY rowid; ROLLBACK; " } [concat $t5g $t5] } do_test triggerC-5.3.0 { execsql { PRAGMA recursive_triggers = off } } {} foreach {n dml t5g t5} { 1 "DELETE FROM t5 WHERE a=2" {2 b 2} {1 a 3 c} 2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')" {} {1 a 2 d 3 c} 3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3" {} {1 a 2 c} 4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')" {} {1 a 3 c 4 b} 5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'" {} {1 a 3 b} 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {} {1 a 2 c} 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {} {1 b} } { do_test triggerC-5.3.$n { execsql " BEGIN; $dml ; SELECT * FROM t5g ORDER BY rowid; SELECT * FROM t5 ORDER BY rowid; ROLLBACK; " } [concat $t5g $t5] } do_test triggerC-5.3.8 { execsql { PRAGMA recursive_triggers = on } } {} |
︙ | ︙ |
Changes to test/unordered.test.
︙ | ︙ | |||
47 48 49 50 51 52 53 | {0 0 0 {SCAN TABLE t1 (~42 rows)}} 3 "SELECT * FROM t1 WHERE a = ? ORDER BY rowid" {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~1 rows)}} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~1 rows)} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}} 4 "SELECT max(a) FROM t1" {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (~1 rows)}} | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | {0 0 0 {SCAN TABLE t1 (~42 rows)}} 3 "SELECT * FROM t1 WHERE a = ? ORDER BY rowid" {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~1 rows)}} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~1 rows)} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}} 4 "SELECT max(a) FROM t1" {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (~1 rows)}} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (~1 rows)}} 5 "SELECT group_concat(b) FROM t1 GROUP BY a" {0 0 0 {SCAN TABLE t1 USING INDEX i1 (~128 rows)}} {0 0 0 {SCAN TABLE t1 (~128 rows)} 0 0 0 {USE TEMP B-TREE FOR GROUP BY}} 6 "SELECT * FROM t1 WHERE a = ?" {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~1 rows)}} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~1 rows)}} |
︙ | ︙ |
Changes to test/wal8.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | # size from the database file as soon as it is opened (even before the # first read transaction is executed), and the "PRAGMA page_size = XXX" # is a no-op. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix wal8 ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } db close forcedelete test.db test.db-wal sqlite3 db test.db | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # size from the database file as soon as it is opened (even before the # first read transaction is executed), and the "PRAGMA page_size = XXX" # is a no-op. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix wal8 ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } db close forcedelete test.db test.db-wal sqlite3 db test.db |
︙ | ︙ | |||
85 86 87 88 89 90 91 | do_execsql_test 3.1 { PRAGMA page_size = 4096; SELECT name FROM sqlite_master; } {t1} finish_test | < | 86 87 88 89 90 91 92 | do_execsql_test 3.1 { PRAGMA page_size = 4096; SELECT name FROM sqlite_master; } {t1} finish_test |
Changes to test/where.test.
︙ | ︙ | |||
1094 1095 1096 1097 1098 1099 1100 | SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b DESC } } {1/1 1/4 4/1 4/4 sort} do_test where-14.3 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, x.b } | | | | | | | 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 | SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b DESC } } {1/1 1/4 4/1 4/4 sort} do_test where-14.3 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, x.b } } {1/4 1/1 4/4 4/1 nosort} do_test where-14.4 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, x.b DESC } } {1/4 1/1 4/4 4/1 nosort} do_test where-14.5 { # This test case changed from "nosort" to "sort". See ticket 2a5629202f. cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, x.a||x.b } } {/4/[14] 4/[14] 1/[14] 1/[14] sort/} do_test where-14.6 { # This test case changed from "nosort" to "sort". See ticket 2a5629202f. cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, x.a||x.b DESC } } {/4/[14] 4/[14] 1/[14] 1/[14] sort/} do_test where-14.7 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, y.a||y.b } } {4/1 4/4 1/1 1/4 sort} do_test where-14.7.1 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, x.a, y.a||y.b } } {4/1 4/4 1/1 1/4 sort} do_test where-14.7.2 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, x.a, x.a||x.b } } {4/4 4/1 1/4 1/1 nosort} do_test where-14.8 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, y.a||y.b DESC } } {4/4 4/1 1/4 1/1 sort} do_test where-14.9 { cksort { |
︙ | ︙ |
Changes to test/where9.test.
︙ | ︙ | |||
688 689 690 691 692 693 694 | OR f='fghijklmn' OR g='hgfedcb' } } {scan 0 sort 0} ;# Add 100 to rowids 5 31 57 82 83 84 85 86 87 do_test where9-6.5.4 { db eval { SELECT count(*) FROM t1 UNION ALL | | | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 | OR f='fghijklmn' OR g='hgfedcb' } } {scan 0 sort 0} ;# Add 100 to rowids 5 31 57 82 83 84 85 86 87 do_test where9-6.5.4 { db eval { SELECT count(*) FROM t1 UNION ALL SELECT a FROM t1 WHERE a%100 IN (5,31,57,82,83,84,85,86,87) ORDER BY rowid; ROLLBACK; } } {99 105 131 157 182 183 184 185 186 187} do_test where9-6.6.1 { count_steps { BEGIN; |
︙ | ︙ |
Changes to test/zerodamage.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 | # # The name of this file comes from the fact that we used to call the # POWERSAFE_OVERWRITE property ZERO_DAMAGE. # set testdir [file dirname $argv0] source $testdir/tester.tcl | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # # The name of this file comes from the fact that we used to call the # POWERSAFE_OVERWRITE property ZERO_DAMAGE. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zerodamage ifcapable !vtab { finish_test return } # POWERSAFE_OVERWRITE defaults to true |
︙ | ︙ | |||
85 86 87 88 89 90 91 | sqlite3 db file:test.db?psow=FALSE -uri 1 db eval { UPDATE t1 SET y=randomblob(50) WHERE x=124; } concat [file_control_powersafe_overwrite db -1] [set ::max_journal_size] } {0 0 24704} | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | sqlite3 db file:test.db?psow=FALSE -uri 1 db eval { UPDATE t1 SET y=randomblob(50) WHERE x=124; } concat [file_control_powersafe_overwrite db -1] [set ::max_journal_size] } {0 0 24704} ifcapable wal { # Run a WAL-mode transaction with POWERSAFE_OVERWRITE on to verify that the # WAL file does not get too big. # do_test zerodamage-3.0 { db eval { PRAGMA journal_mode=WAL; } db close sqlite3 db file:test.db?psow=TRUE -uri 1 db eval { UPDATE t1 SET y=randomblob(50) WHERE x=124; } file size test.db-wal } {1080} # Repeat the previous with POWERSAFE_OVERWRITE off. Verify that the WAL file # is padded. # do_test zerodamage-3.1 { db close sqlite3 db file:test.db?psow=FALSE -uri 1 db eval { UPDATE t1 SET y=randomblob(50) WHERE x=124; } file size test.db-wal } {8416} } finish_test |
Added tool/stack_usage.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #!/usr/bin/tclsh # # Parse the output of # # objdump -d sqlite3.o # # for x64 and generate a report showing: # # (1) Stack used by each function # (2) Recursion paths and their aggregate stack depth # set getStack 0 while {![eof stdin]} { set line [gets stdin] if {[regexp {^[0-9a-f]+ <([^>]+)>:\s*$} $line all procname]} { set curfunc $procname set root($curfunc) 1 set calls($curfunc) {} set calledby($curfunc) {} set recursive($curfunc) {} set stkdepth($curfunc) 0 set getStack 1 continue } if {[regexp {callq? +[0-9a-z]+ <([^>]+)>} $line all other]} { set key [list $curfunc $other] set callpair($key) 1 unset -nocomplain root($curfunc) continue } if {[regexp {sub +\$(0x[0-9a-z]+),%[er]sp} $line all xdepth]} { if {$getStack} { scan $xdepth %x depth set stkdepth($curfunc) $depth set getStack 0 } continue } } puts "****************** Stack Usage By Function ********************" set sdlist {} foreach f [array names stkdepth] { lappend sdlist [list $stkdepth($f) $f] } foreach sd [lsort -integer -decr -index 0 $sdlist] { foreach {depth fname} $sd break puts [format {%6d %s} $depth $fname] } puts "****************** Stack Usage By Recursion *******************" foreach key [array names callpair] { foreach {from to} $key break lappend calls($from) $to # lappend calledby($to) $from } proc all_descendents {root} { global calls recursive set todo($root) $root set go 1 while {$go} { set go 0 foreach f [array names todo] { set path $todo($f) unset todo($f) if {![info exists calls($f)]} continue foreach x $calls($f) { if {$x==$root} { lappend recursive($root) [concat $path $root] } elseif {![info exists d($x)]} { set go 1 set todo($x) [concat $path $x] set d($x) 1 } } } } return [array names d] } set pathlist {} foreach f [array names recursive] { all_descendents $f foreach m $recursive($f) { set depth 0 foreach b [lrange $m 0 end-1] { set depth [expr {$depth+$stkdepth($b)}] } lappend pathlist [list $depth $m] } } foreach path [lsort -integer -decr -index 0 $pathlist] { foreach {depth m} $path break set first [lindex $m 0] puts [format {%6d %s %d} $depth $first $stkdepth($first)] foreach b [lrange $m 1 end] { puts " $b $stkdepth($b)" } } |
Changes to tool/vdbe-compress.tcl.
︙ | ︙ | |||
75 76 77 78 79 80 81 82 83 84 85 86 87 88 | append afterUnion \ "#if 0 /* local variables moved into u.$sname */\n" set seenDecl 1 } append unionDef " $line\n" append afterUnion $line\n lappend vlist $vname } else { break } } if {$seenDecl} { append unionDef " \175 $sname;\n" append afterUnion "#endif /* local variables moved into u.$sname */\n" | > > > | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | append afterUnion \ "#if 0 /* local variables moved into u.$sname */\n" set seenDecl 1 } append unionDef " $line\n" append afterUnion $line\n lappend vlist $vname } elseif {[regexp {^#(if|endif)} $line] && [llength $vlist]>0} { append unionDef "$line\n" append afterUnion $line\n } else { break } } if {$seenDecl} { append unionDef " \175 $sname;\n" append afterUnion "#endif /* local variables moved into u.$sname */\n" |
︙ | ︙ |