Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge all the latest trunk changes into the sessions branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sessions |
Files: | files | file ages | folders |
SHA1: |
fc07a4795e027108674d1d41eb4350df |
User & Date: | drh 2012-08-15 16:21:55.837 |
Context
2012-08-25
| ||
01:21 | Merge the latest trunk changes into the sessions branch. (check-in: aa62d6881b user: drh tags: sessions) | |
2012-08-15
| ||
16:21 | Merge all the latest trunk changes into the sessions branch. (check-in: fc07a4795e user: drh tags: sessions) | |
16:06 | Change autoconf so that the --with-tcl=DIR option will override the TCL configuration that is found using tclsh. (check-in: 772d0de3f3 user: drh tags: trunk) | |
2012-06-09
| ||
19:15 | Merge latest trunk changes with sessions branch. (check-in: 47f8f0711d user: dan tags: sessions) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
168 169 170 171 172 173 174 | fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo journal.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ | | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo journal.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \ table.lo tokenize.lo trigger.lo \ update.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo |
︙ | ︙ | |||
228 229 230 231 232 233 234 | $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ $(TOP)/src/mutex_noop.c \ | < < | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ $(TOP)/src/mutex_noop.c \ $(TOP)/src/mutex_unix.c \ $(TOP)/src/mutex_w32.c \ $(TOP)/src/notify.c \ $(TOP)/src/os.c \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ $(TOP)/src/pager.h \ $(TOP)/src/parse.y \ $(TOP)/src/pcache.c \ $(TOP)/src/pcache.h \ |
︙ | ︙ | |||
398 399 400 401 402 403 404 | $(TOP)/src/date.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ | < | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | $(TOP)/src/date.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ $(TOP)/src/pragma.c \ $(TOP)/src/prepare.c \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ |
︙ | ︙ | |||
653 654 655 656 657 658 659 | mutex.lo: $(TOP)/src/mutex.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c mutex_noop.lo: $(TOP)/src/mutex_noop.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_noop.c | < < < | 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | mutex.lo: $(TOP)/src/mutex.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c mutex_noop.lo: $(TOP)/src/mutex_noop.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_noop.c mutex_unix.lo: $(TOP)/src/mutex_unix.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_unix.c mutex_w32.lo: $(TOP)/src/mutex_w32.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_w32.c notify.lo: $(TOP)/src/notify.c $(HDR) |
︙ | ︙ | |||
683 684 685 686 687 688 689 | os_unix.lo: $(TOP)/src/os_unix.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_unix.c os_win.lo: $(TOP)/src/os_win.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_win.c | < < < | 677 678 679 680 681 682 683 684 685 686 687 688 689 690 | os_unix.lo: $(TOP)/src/os_unix.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_unix.c os_win.lo: $(TOP)/src/os_win.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_win.c pragma.lo: $(TOP)/src/pragma.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pragma.c prepare.lo: $(TOP)/src/prepare.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/prepare.c printf.lo: $(TOP)/src/printf.c $(HDR) |
︙ | ︙ | |||
946 947 948 949 950 951 952 953 954 955 956 957 958 959 | rm -rf quota2a quota2b quota2c rm -rf tsrc .target_source rm -f tclsqlite3$(TEXE) rm -f testfixture$(TEXE) test.db rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def rm -f sqlite3.c rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c distclean: clean rm -f config.log config.status libtool Makefile sqlite3.pc # # Windows section # | > | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 | rm -rf quota2a quota2b quota2c rm -rf tsrc .target_source rm -f tclsqlite3$(TEXE) rm -f testfixture$(TEXE) test.db rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def rm -f sqlite3.c rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c rm -f sqlite-output.vsix distclean: clean rm -f config.log config.status libtool Makefile sqlite3.pc # # Windows section # |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
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 | # Set this non-0 to create and use the SQLite amalgamation file. # USE_AMALGAMATION = 1 # Set this non-0 to use the International Components for Unicode (ICU). # USE_ICU = 0 # Set this non-0 to compile binaries suitable for the WinRT environment. # This setting does not apply to any binaries that require Tcl to operate # properly (i.e. the text fixture, etc). # FOR_WINRT = 0 # Set this to non-0 to create and use PDBs. # SYMBOLS = 1 # Set this to one of the following values to enable various debugging # features. Each level includes the debugging options from the previous # levels. Currently, the recognized values for DEBUG are: # # 0 == NDEBUG: Disables assert() and other runtime diagnostics. # 1 == Disables NDEBUG and all optimizations and then enables PDBs. # 2 == SQLITE_DEBUG: Enables various diagnostics messages and code. # 3 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call. # 4 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros. # 5 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros. # DEBUG = 0 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > | | > > > > > > | | > > | > | > > > > > > > > > | 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 | # Set this non-0 to create and use the SQLite amalgamation file. # USE_AMALGAMATION = 1 # Set this non-0 to use the International Components for Unicode (ICU). # USE_ICU = 0 # Set this non-0 to dynamically link to the MSVC runtime library. # USE_CRT_DLL = 0 # Set this non-0 to use the native libraries paths for cross-compiling # the command line tools needed during the compilation process. # USE_NATIVE_LIBPATHS = 0 # Set this non-0 to compile binaries suitable for the WinRT environment. # This setting does not apply to any binaries that require Tcl to operate # properly (i.e. the text fixture, etc). # FOR_WINRT = 0 # Set this non-0 to skip attempting to look for and/or link with the Tcl # runtime library. # NO_TCL = 0 # Set this to non-0 to create and use PDBs. # SYMBOLS = 1 # Set this to one of the following values to enable various debugging # features. Each level includes the debugging options from the previous # levels. Currently, the recognized values for DEBUG are: # # 0 == NDEBUG: Disables assert() and other runtime diagnostics. # 1 == Disables NDEBUG and all optimizations and then enables PDBs. # 2 == SQLITE_DEBUG: Enables various diagnostics messages and code. # 3 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call. # 4 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros. # 5 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros. # DEBUG = 0 # Check for the predefined command macro CC. This should point to the compiler # binary for the target platform. If it is not defined, simply define it to # the legacy default value 'cl.exe'. # !IFNDEF CC CC = cl.exe !ENDIF # 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 # line similar to the following could be used (all on one line): # # nmake /f Makefile.msc # "NCC=""%VCINSTALLDIR%\bin\cl.exe""" # USE_NATIVE_LIBPATHS=1 # !IFDEF NCC NCC = $(NCC:\\=\) !ELSE NCC = $(CC) !ENDIF # Check for the MSVC runtime library path macro. Othertise, this # value will default to the 'lib' directory underneath the MSVC # installation directory. # !IFNDEF NCRTLIBPATH NCRTLIBPATH = $(VCINSTALLDIR)\lib !ENDIF NCRTLIBPATH = $(NCRTLIBPATH:\\=\) # Check for the Platform SDK library path macro. Othertise, this # value will default to the 'lib' directory underneath the Windows # SDK installation directory (the environment variable used appears # to be available when using Visual C++ 2008 or later via the # command line). # !IFNDEF NSDKLIBPATH NSDKLIBPATH = $(WINDOWSSDKDIR)\lib !ENDIF NSDKLIBPATH = $(NSDKLIBPATH:\\=\) # C compiler and options for use in building executables that # will run on the platform that is doing the build. # BCC = $(NCC) -W3 # Check if the native library paths should be used when compiling # the command line tools used during the compilation process. If # so, set the necessary macro now. # !IF $(USE_NATIVE_LIBPATHS)!=0 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. -I$(TOP)\src -fp:precise # 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 TCC = $(TCC) -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. # !IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0 !IF $(DEBUG)>0 TCC = $(TCC) -MDd !ELSE TCC = $(TCC) -MD !ENDIF !ELSE !IF $(DEBUG)>0 TCC = $(TCC) -MTd !ELSE TCC = $(TCC) -MT !ENDIF !ENDIF # 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 |
︙ | ︙ | |||
87 88 89 90 91 92 93 | !ENDIF !IF $(DEBUG)>4 TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE !ENDIF # | | > > > > > > > | | | | | | | | | | | | | | | | | 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 | !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 native Win32 heap instead of malloc/free? # # 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 # 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 # version on this machine. # !IFNDEF TCLINCDIR TCLINCDIR = c:\tcl\include !ENDIF !IFNDEF TCLLIBDIR TCLLIBDIR = c:\tcl\lib !ENDIF !IFNDEF LIBTCL LIBTCL = tcl85.lib !ENDIF # The locations of the ICU header and library files. These variables # (ICUINCDIR, ICULIBDIR, and LIBICU) may be overridden via the environment # prior to running nmake in order to match the actual installed location on # this machine. # !IFNDEF ICUINCDIR ICUINCDIR = c:\icu\include !ENDIF !IFNDEF ICULIBDIR ICULIBDIR = c:\icu\lib !ENDIF !IFNDEF LIBICU LIBICU = icuuc.lib icuin.lib !ENDIF # This is the command to use for tclsh - normally just "tclsh", but we may # know the specific version we want to use. This variable (TCLSH_CMD) may be # overridden via the environment prior to running nmake in order to select a # specific Tcl shell to use. # !IFNDEF TCLSH_CMD TCLSH_CMD = tclsh85 !ENDIF # Compiler options needed for programs that use the readline() library. # READLINE_FLAGS = -DHAVE_READLINE=0 # 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. # |
︙ | ︙ | |||
232 233 234 235 236 237 238 | 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. | | < | > > | 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 | 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. !IFDEF PLATFORM LTLINKOPTS = /MACHINE:$(PLATFORM) LTLIBOPTS = /MACHINE:$(PLATFORM) !ENDIF # When compiling for use in the WinRT environment, the following # linker option must be used to mark the executable as runnable # only in the context of an application container. # !IF $(FOR_WINRT)!=0 LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER !ENDIF # If either debugging or symbols are enabled, enable PDBs. !IF $(DEBUG)>0 || $(SYMBOLS)!=0 LDFLAGS = /DEBUG !ENDIF # Start with the Tcl related linker options. !IF $(NO_TCL)==0 LTLIBPATHS = /LIBPATH:$(TCLLIBDIR) LTLIBS = $(LIBTCL) !ENDIF # If ICU support is enabled, add the linker options for it. !IF $(USE_ICU)!=0 LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR) LTLIBS = $(LTLIBS) $(LIBICU) !ENDIF |
︙ | ︙ | |||
280 281 282 283 284 285 286 | fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo journal.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ | | | | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo journal.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \ table.lo tokenize.lo trigger.lo \ update.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo |
︙ | ︙ | |||
343 344 345 346 347 348 349 | $(TOP)\src\mem2.c \ $(TOP)\src\mem3.c \ $(TOP)\src\mem5.c \ $(TOP)\src\memjournal.c \ $(TOP)\src\mutex.c \ $(TOP)\src\mutex.h \ $(TOP)\src\mutex_noop.c \ | < < | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | $(TOP)\src\mem2.c \ $(TOP)\src\mem3.c \ $(TOP)\src\mem5.c \ $(TOP)\src\memjournal.c \ $(TOP)\src\mutex.c \ $(TOP)\src\mutex.h \ $(TOP)\src\mutex_noop.c \ $(TOP)\src\mutex_unix.c \ $(TOP)\src\mutex_w32.c \ $(TOP)\src\notify.c \ $(TOP)\src\os.c \ $(TOP)\src\os.h \ $(TOP)\src\os_common.h \ $(TOP)\src\os_unix.c \ $(TOP)\src\os_win.c \ $(TOP)\src\pager.c \ $(TOP)\src\pager.h \ $(TOP)\src\parse.y \ $(TOP)\src\pcache.c \ $(TOP)\src\pcache.h \ |
︙ | ︙ | |||
517 518 519 520 521 522 523 | $(TOP)\src\date.c \ $(TOP)\src\expr.c \ $(TOP)\src\func.c \ $(TOP)\src\insert.c \ $(TOP)\src\wal.c \ $(TOP)\src\mem5.c \ $(TOP)\src\os.c \ | < | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | $(TOP)\src\date.c \ $(TOP)\src\expr.c \ $(TOP)\src\func.c \ $(TOP)\src\insert.c \ $(TOP)\src\wal.c \ $(TOP)\src\mem5.c \ $(TOP)\src\os.c \ $(TOP)\src\os_unix.c \ $(TOP)\src\os_win.c \ $(TOP)\src\pager.c \ $(TOP)\src\pragma.c \ $(TOP)\src\prepare.c \ $(TOP)\src\printf.c \ $(TOP)\src\random.c \ |
︙ | ︙ | |||
649 650 651 652 653 654 655 | # Rules to build the LEMON compiler generator # lempar.c: $(TOP)\src\lempar.c copy $(TOP)\src\lempar.c . lemon.exe: $(TOP)\tool\lemon.c lempar.c | | | 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | # Rules to build the LEMON compiler generator # lempar.c: $(TOP)\src\lempar.c copy $(TOP)\src\lempar.c . lemon.exe: $(TOP)\tool\lemon.c lempar.c $(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLIBPATHS) # Rules to build individual *.lo files from generated *.c files. This # applies to: # # parse.lo # opcodes.lo # |
︙ | ︙ | |||
767 768 769 770 771 772 773 | mutex.lo: $(TOP)\src\mutex.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\mutex.c mutex_noop.lo: $(TOP)\src\mutex_noop.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\mutex_noop.c | < < < | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 | mutex.lo: $(TOP)\src\mutex.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\mutex.c mutex_noop.lo: $(TOP)\src\mutex_noop.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\mutex_noop.c mutex_unix.lo: $(TOP)\src\mutex_unix.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\mutex_unix.c mutex_w32.lo: $(TOP)\src\mutex_w32.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\mutex_w32.c notify.lo: $(TOP)\src\notify.c $(HDR) |
︙ | ︙ | |||
797 798 799 800 801 802 803 | os_unix.lo: $(TOP)\src\os_unix.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\os_unix.c os_win.lo: $(TOP)\src\os_win.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\os_win.c | < < < | 895 896 897 898 899 900 901 902 903 904 905 906 907 908 | os_unix.lo: $(TOP)\src\os_unix.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\os_unix.c os_win.lo: $(TOP)\src\os_win.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\os_win.c pragma.lo: $(TOP)\src\pragma.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\pragma.c prepare.lo: $(TOP)\src\prepare.c $(HDR) $(LTCOMPILE) -c $(TOP)\src\prepare.c printf.lo: $(TOP)\src\printf.c $(HDR) |
︙ | ︙ | |||
911 912 913 914 915 916 917 | move parse.h parse.h.temp $(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP) > sqlite3.h mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c | | | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 | move parse.h parse.h.temp $(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP) > sqlite3.h mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c $(BCC) -Fe$@ $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLIBPATHS) keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe .\mkkeywordhash.exe > keywordhash.h # Rules to build the extension objects. |
︙ | ︙ | |||
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | -rmdir /Q/S tsrc del /Q .target_source del /Q tclsqlite3.exe del /Q testfixture.exe testfixture.exp test.db del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def del /Q sqlite3.c del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c # # Windows 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) sqlite3.def | > | | 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 | -rmdir /Q/S tsrc del /Q .target_source del /Q tclsqlite3.exe del /Q testfixture.exe testfixture.exp test.db del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def del /Q sqlite3.c del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c del /Q sqlite-output.vsix # # Windows 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) sqlite3.def $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LTLIBS) $(TLIBS) |
Changes to Makefile.vxworks.
︙ | ︙ | |||
200 201 202 203 204 205 206 | callback.o complete.o date.o delete.o expr.o fault.o \ fts3.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \ fts3_tokenizer.o fts3_tokenizer1.o \ func.o global.o hash.o \ icu.o insert.o journal.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memjournal.o \ | | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | callback.o complete.o date.o delete.o expr.o fault.o \ fts3.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \ fts3_tokenizer.o fts3_tokenizer1.o \ func.o global.o hash.o \ icu.o insert.o journal.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_unix.o os_win.o \ pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o select.o status.o \ table.o tokenize.o trigger.o \ update.o util.o vacuum.o \ vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o \ walker.o where.o utf.o vtab.o |
︙ | ︙ | |||
252 253 254 255 256 257 258 | $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ $(TOP)/src/mutex_noop.c \ | < < | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ $(TOP)/src/mutex_noop.c \ $(TOP)/src/mutex_unix.c \ $(TOP)/src/mutex_w32.c \ $(TOP)/src/notify.c \ $(TOP)/src/os.c \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ $(TOP)/src/pager.h \ $(TOP)/src/parse.y \ $(TOP)/src/pcache.c \ $(TOP)/src/pcache.h \ |
︙ | ︙ | |||
392 393 394 395 396 397 398 | #TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c #TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c TESTSRC2 = \ $(TOP)/src/attach.c $(TOP)/src/backup.c $(TOP)/src/btree.c \ $(TOP)/src/build.c $(TOP)/src/ctime.c $(TOP)/src/date.c \ $(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \ | | | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | #TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c #TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c TESTSRC2 = \ $(TOP)/src/attach.c $(TOP)/src/backup.c $(TOP)/src/btree.c \ $(TOP)/src/build.c $(TOP)/src/ctime.c $(TOP)/src/date.c \ $(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \ $(TOP)/src/os_unix.c $(TOP)/src/os_win.c \ $(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c \ $(TOP)/src/printf.c $(TOP)/src/random.c $(TOP)/src/pcache.c \ $(TOP)/src/pcache1.c $(TOP)/src/select.c $(TOP)/src/tokenize.c \ $(TOP)/src/utf.c $(TOP)/src/util.c $(TOP)/src/vdbeapi.c $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbe.c $(TOP)/src/vdbemem.c $(TOP)/src/where.c parse.c \ $(TOP)/ext/fts3/fts3.c $(TOP)/ext/fts3/fts3_expr.c \ $(TOP)/ext/fts3/fts3_tokenizer.c \ |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.7.14 |
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.14. # # 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.14' PACKAGE_STRING='sqlite 3.7.14' 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.14 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.14:";; 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.14 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.14, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
12774 12775 12776 12777 12778 12779 12780 | { { $as_echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 $as_echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} { (exit 1); exit 1; }; } fi fi # Start autosearch by asking tclsh | > | | | | | | | | > | 12774 12775 12776 12777 12778 12779 12780 12781 12782 12783 12784 12785 12786 12787 12788 12789 12790 12791 12792 12793 12794 12795 12796 12797 | { { $as_echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 $as_echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} { (exit 1); exit 1; }; } fi fi # Start autosearch by asking tclsh if test x"${ac_cv_c_tclconfig}" = x ; then if test x"$cross_compiling" = xno; then for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="$i" break fi done fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ |
︙ | ︙ | |||
14028 14029 14030 14031 14032 14033 14034 | 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.14, 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 $@ |
︙ | ︙ | |||
14081 14082 14083 14084 14085 14086 14087 | $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.14 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." |
︙ | ︙ | |||
14514 14515 14516 14517 14518 14519 14520 | # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then | | > | 14516 14517 14518 14519 14520 14521 14522 14523 14524 14525 14526 14527 14528 14529 14530 14531 | # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=' ' ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi |
︙ | ︙ | |||
15749 15750 15751 15752 15753 15754 15755 | # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:$LINENO: WARNING: Unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2;} fi | < | 15752 15753 15754 15755 15756 15757 15758 | # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:$LINENO: WARNING: Unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2;} fi |
Changes to configure.ac.
︙ | ︙ | |||
384 385 386 387 388 389 390 | ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # Start autosearch by asking tclsh | > | | | | | | | | > | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # Start autosearch by asking tclsh if test x"${ac_cv_c_tclconfig}" = x ; then if test x"$cross_compiling" = xno; then for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="$i" break fi done fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ |
︙ | ︙ |
Changes to ext/fts3/fts3_icu.c.
︙ | ︙ | |||
195 196 197 198 199 200 201 | iEnd = ubrk_next(pCsr->pIter); if( iEnd==UBRK_DONE ){ return SQLITE_DONE; } while( iStart<iEnd ){ int iWhite = iStart; | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | iEnd = ubrk_next(pCsr->pIter); if( iEnd==UBRK_DONE ){ return SQLITE_DONE; } while( iStart<iEnd ){ int iWhite = iStart; U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c); if( u_isspace(c) ){ iStart = iWhite; }else{ break; } } assert(iStart<=iEnd); |
︙ | ︙ |
Changes to ext/fts3/fts3_unicode2.c.
︙ | ︙ | |||
142 143 144 145 146 147 148 | iLo = iTest+1; }else{ iHi = iTest-1; } } assert( aEntry[0]<key ); assert( key>=aEntry[iRes] ); | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | iLo = iTest+1; }else{ iHi = iTest-1; } } assert( aEntry[0]<key ); assert( key>=aEntry[iRes] ); return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); } return 1; } /* ** If the argument is a codepoint corresponding to a lowercase letter |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
57 58 59 60 61 62 63 | fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \ fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \ fts3_unicode.o fts3_unicode2.o \ fts3_write.o func.o global.o hash.o \ icu.o insert.o journal.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memjournal.o \ | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \ fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \ fts3_unicode.o fts3_unicode2.o \ fts3_write.o func.o global.o hash.o \ icu.o insert.o journal.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_unix.o os_win.o \ pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o select.o status.o \ table.o tokenize.o trigger.o \ update.o util.o vacuum.o \ vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ vdbetrace.o wal.o walker.o where.o utf.o vtab.o |
︙ | ︙ | |||
110 111 112 113 114 115 116 | $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ $(TOP)/src/mutex_noop.c \ | < < | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ $(TOP)/src/mutex_noop.c \ $(TOP)/src/mutex_unix.c \ $(TOP)/src/mutex_w32.c \ $(TOP)/src/notify.c \ $(TOP)/src/os.c \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ $(TOP)/src/pager.h \ $(TOP)/src/parse.y \ $(TOP)/src/pcache.c \ $(TOP)/src/pcache.h \ |
︙ | ︙ | |||
279 280 281 282 283 284 285 | $(TOP)/src/date.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ | < | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | $(TOP)/src/date.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ $(TOP)/src/pragma.c \ $(TOP)/src/prepare.c \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ |
︙ | ︙ | |||
618 619 620 621 622 623 624 | rm -f testloadext.dll libtestloadext.so rm -f amalgamation-testfixture amalgamation-testfixture.exe rm -f fts3-testfixture fts3-testfixture.exe rm -f testfixture testfixture.exe rm -f threadtest3 threadtest3.exe rm -f sqlite3.c fts?amal.c tclsqlite3.c rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c | > | 615 616 617 618 619 620 621 622 | rm -f testloadext.dll libtestloadext.so rm -f amalgamation-testfixture amalgamation-testfixture.exe rm -f fts3-testfixture fts3-testfixture.exe rm -f testfixture testfixture.exe rm -f threadtest3 threadtest3.exe rm -f sqlite3.c fts?amal.c tclsqlite3.c rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c rm -f sqlite-output.vsix |
Changes to src/analyze.c.
︙ | ︙ | |||
172 173 174 175 176 177 178 | ** side-effect of the CREATE TABLE statement is to leave the rootpage ** of the new table in register pParse->regRoot. This is important ** because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols ); aRoot[i] = pParse->regRoot; | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | ** side-effect of the CREATE TABLE statement is to leave the rootpage ** of the new table in register pParse->regRoot. This is important ** because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols ); aRoot[i] = pParse->regRoot; aCreateTbl[i] = OPFLAG_P2ISREG; }else{ /* The table already exists. If zWhere is not NULL, delete all entries ** associated with the table zWhere. If zWhere is NULL, delete the ** entire contents of the table. */ aRoot[i] = pStat->tnum; sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab); if( zWhere ){ |
︙ | ︙ | |||
252 253 254 255 256 257 258 | int mxSample; int n; UNUSED_PARAMETER(argc); nRow = (tRowcnt)sqlite3_value_int64(argv[0]); mxSample = sqlite3_value_int(argv[1]); n = sizeof(*p) + sizeof(p->a[0])*mxSample; | | < | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | int mxSample; int n; UNUSED_PARAMETER(argc); nRow = (tRowcnt)sqlite3_value_int64(argv[0]); mxSample = sqlite3_value_int(argv[1]); n = sizeof(*p) + sizeof(p->a[0])*mxSample; p = sqlite3MallocZero( n ); if( p==0 ){ sqlite3_result_error_nomem(context); return; } p->a = (struct Stat3Sample*)&p[1]; p->nRow = nRow; p->mxSample = mxSample; p->nPSample = p->nRow/(mxSample/3+1) + 1; sqlite3_randomness(sizeof(p->iPrn), &p->iPrn); sqlite3_result_blob(context, p, sizeof(p), sqlite3_free); } |
︙ | ︙ |
Changes to src/backup.c.
︙ | ︙ | |||
160 161 162 163 164 165 166 | ); p = 0; }else { /* Allocate space for a new sqlite3_backup object... ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a ** call to sqlite3_backup_init() and is destroyed by a call to ** sqlite3_backup_finish(). */ | | < | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | ); p = 0; }else { /* Allocate space for a new sqlite3_backup object... ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a ** call to sqlite3_backup_init() and is destroyed by a call to ** sqlite3_backup_finish(). */ p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); if( !p ){ sqlite3Error(pDestDb, SQLITE_NOMEM, 0); } } /* If the allocation succeeded, populate the new object. */ if( p ){ p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); p->pDest = findBtree(pDestDb, pDestDb, zDestDb); p->pDestDb = pDestDb; p->pSrcDb = pSrcDb; p->iNext = 1; p->isAttached = 0; |
︙ | ︙ | |||
539 540 541 542 543 544 545 | } /* ** Release all resources associated with an sqlite3_backup* handle. */ int sqlite3_backup_finish(sqlite3_backup *p){ sqlite3_backup **pp; /* Ptr to head of pagers backup list */ | | > | < | 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 | } /* ** Release all resources associated with an sqlite3_backup* handle. */ int sqlite3_backup_finish(sqlite3_backup *p){ sqlite3_backup **pp; /* Ptr to head of pagers backup list */ sqlite3 *pSrcDb; /* Source database connection */ int rc; /* Value to return */ /* Enter the mutexes */ if( p==0 ) return SQLITE_OK; pSrcDb = p->pSrcDb; sqlite3_mutex_enter(pSrcDb->mutex); sqlite3BtreeEnter(p->pSrc); if( p->pDestDb ){ sqlite3_mutex_enter(p->pDestDb->mutex); } /* Detach this backup from the source pager. */ if( p->pDestDb ){ p->pSrc->nBackup--; |
︙ | ︙ | |||
572 573 574 575 576 577 578 | /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; sqlite3Error(p->pDestDb, rc, 0); /* Exit the mutexes and free the backup context structure. */ if( p->pDestDb ){ | | | | 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; sqlite3Error(p->pDestDb, rc, 0); /* Exit the mutexes and free the backup context structure. */ if( p->pDestDb ){ sqlite3LeaveMutexAndCloseZombie(p->pDestDb); } sqlite3BtreeLeave(p->pSrc); if( p->pDestDb ){ /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a ** call to sqlite3_backup_init() and is destroyed by a call to ** sqlite3_backup_finish(). */ sqlite3_free(p); } sqlite3LeaveMutexAndCloseZombie(pSrcDb); return rc; } /* ** Return the number of pages still to be backed up as of the most recent ** call to sqlite3_backup_step(). */ |
︙ | ︙ |
Changes to src/bitvec.c.
︙ | ︙ | |||
336 337 338 339 340 341 342 | int rc = -1; int i, nx, pc, op; void *pTmpSpace; /* Allocate the Bitvec to be tested and a linear array of ** bits to act as the reference */ pBitvec = sqlite3BitvecCreate( sz ); | | < | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | int rc = -1; int i, nx, pc, op; void *pTmpSpace; /* Allocate the Bitvec to be tested and a linear array of ** bits to act as the reference */ pBitvec = sqlite3BitvecCreate( sz ); pV = sqlite3MallocZero( (sz+7)/8 + 1 ); pTmpSpace = sqlite3_malloc(BITVEC_SZ); if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; /* NULL pBitvec tests */ sqlite3BitvecSet(0, 1); sqlite3BitvecClear(0, 1, pTmpSpace); /* Run the program */ pc = 0; |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
5922 5923 5924 5925 5926 5927 5928 | ** If aOvflSpace is set to a null pointer, this function returns ** SQLITE_NOMEM. */ static int balance_nonroot( MemPage *pParent, /* Parent page of siblings being balanced */ int iParentIdx, /* Index of "the page" in pParent */ u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */ | | > | 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 | ** If aOvflSpace is set to a null pointer, this function returns ** SQLITE_NOMEM. */ static int balance_nonroot( MemPage *pParent, /* Parent page of siblings being balanced */ int iParentIdx, /* Index of "the page" in pParent */ u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */ int isRoot, /* True if pParent is a root-page */ int bBulk /* True if this call is part of a bulk load */ ){ BtShared *pBt; /* The whole database */ int nCell = 0; /* Number of cells in apCell[] */ int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ int nNew = 0; /* Number of pages in apNew[] */ int nOld; /* Number of pages in apOld[] */ int i, j, k; /* Loop counters */ |
︙ | ︙ | |||
5986 5987 5988 5989 5990 5991 5992 | ** way, the remainder of the function does not have to deal with any ** overflow cells in the parent page, since if any existed they will ** have already been removed. */ i = pParent->nOverflow + pParent->nCell; if( i<2 ){ nxDiv = 0; | < < > | > | > | 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 | ** way, the remainder of the function does not have to deal with any ** overflow cells in the parent page, since if any existed they will ** have already been removed. */ i = pParent->nOverflow + pParent->nCell; if( i<2 ){ nxDiv = 0; }else{ assert( bBulk==0 || bBulk==1 ); if( iParentIdx==0 ){ nxDiv = 0; }else if( iParentIdx==i ){ nxDiv = i-2+bBulk; }else{ assert( bBulk==0 ); nxDiv = iParentIdx-1; } i = 2-bBulk; } nOld = i+1; if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){ pRight = &pParent->aData[pParent->hdrOffset+8]; }else{ pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); } pgno = get4byte(pRight); while( 1 ){ |
︙ | ︙ | |||
6206 6207 6208 6209 6210 6211 6212 | int r; /* Index of right-most cell in left sibling */ int d; /* Index of first cell to the left of right sibling */ r = cntNew[i-1] - 1; d = r + 1 - leafData; assert( d<nMaxCells ); assert( r<nMaxCells ); | > | > | 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 | int r; /* Index of right-most cell in left sibling */ int d; /* Index of first cell to the left of right sibling */ r = cntNew[i-1] - 1; d = r + 1 - leafData; assert( d<nMaxCells ); assert( r<nMaxCells ); while( szRight==0 || (!bBulk && szRight+szCell[d]+2<=szLeft-(szCell[r]+2)) ){ szRight += szCell[d] + 2; szLeft -= szCell[r] + 2; cntNew[i-1]--; r = cntNew[i-1] - 1; d = r + 1 - leafData; } szNew[i] = szRight; |
︙ | ︙ | |||
6253 6254 6255 6256 6257 6258 6259 | pNew = apNew[i] = apOld[i]; apOld[i] = 0; rc = sqlite3PagerWrite(pNew->pDbPage); nNew++; if( rc ) goto balance_cleanup; }else{ assert( i>0 ); | | | 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 | pNew = apNew[i] = apOld[i]; apOld[i] = 0; rc = sqlite3PagerWrite(pNew->pDbPage); nNew++; if( rc ) goto balance_cleanup; }else{ assert( i>0 ); rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0); if( rc ) goto balance_cleanup; apNew[i] = pNew; nNew++; /* Set the pointer-map entry for the new sibling page. */ if( ISAUTOVACUUM ){ ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); |
︙ | ︙ | |||
6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 | for(i=0; i<nCell; i++){ int isDivider = 0; while( i==iNextOld ){ /* Cell i is the cell immediately following the last cell on old ** sibling page j. If the siblings are not leaf pages of an ** intkey b-tree, then cell i was a divider cell. */ assert( j+1 < ArraySize(apCopy) ); pOld = apCopy[++j]; iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow; if( pOld->nOverflow ){ nOverflow = pOld->nOverflow; iOverflow = i + !leafData + pOld->aiOvfl[0]; } isDivider = !leafData; | > | 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 | for(i=0; i<nCell; i++){ int isDivider = 0; while( i==iNextOld ){ /* Cell i is the cell immediately following the last cell on old ** sibling page j. If the siblings are not leaf pages of an ** intkey b-tree, then cell i was a divider cell. */ assert( j+1 < ArraySize(apCopy) ); assert( j+1 < nOld ); pOld = apCopy[++j]; iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow; if( pOld->nOverflow ){ nOverflow = pOld->nOverflow; iOverflow = i + !leafData + pOld->aiOvfl[0]; } isDivider = !leafData; |
︙ | ︙ | |||
6703 6704 6705 6706 6707 6708 6709 | ** different page). Once this subsequent call to balance_nonroot() ** has completed, it is safe to release the pSpace buffer used by ** the previous call, as the overflow cell data will have been ** copied either into the body of a database page or into the new ** pSpace buffer passed to the latter call to balance_nonroot(). */ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); | | | 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 | ** different page). Once this subsequent call to balance_nonroot() ** has completed, it is safe to release the pSpace buffer used by ** the previous call, as the overflow cell data will have been ** copied either into the body of a database page or into the new ** pSpace buffer passed to the latter call to balance_nonroot(). */ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints); if( pFree ){ /* If pFree is not NULL, it points to the pSpace buffer used ** by a previous call to balance_nonroot(). Its contents are ** now stored either on real database pages or within the ** new pSpace buffer, so it may be safely freed here. */ sqlite3PageFree(pFree); } |
︙ | ︙ | |||
8290 8291 8292 8293 8294 8295 8296 | } } } pBt->btsFlags &= ~BTS_NO_WAL; return rc; } | > > > > > > > > > | 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 | } } } pBt->btsFlags &= ~BTS_NO_WAL; return rc; } /* ** set the mask of hint flags for cursor pCsr. Currently the only valid ** values are 0 and BTREE_BULKLOAD. */ void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ assert( mask==BTREE_BULKLOAD || mask==0 ); pCsr->hints = mask; } |
Changes to src/btree.h.
︙ | ︙ | |||
131 132 133 134 135 136 137 138 139 140 141 142 143 144 | #define BTREE_FILE_FORMAT 2 #define BTREE_DEFAULT_CACHE_SIZE 3 #define BTREE_LARGEST_ROOT_PAGE 4 #define BTREE_TEXT_ENCODING 5 #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ struct KeyInfo*, /* First argument to compare function */ BtCursor *pCursor /* Space to write cursor structure */ ); | > > > > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #define BTREE_FILE_FORMAT 2 #define BTREE_DEFAULT_CACHE_SIZE 3 #define BTREE_LARGEST_ROOT_PAGE 4 #define BTREE_TEXT_ENCODING 5 #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 /* ** Values that may be OR'd together to form the second argument of an ** sqlite3BtreeCursorHints() call. */ #define BTREE_BULKLOAD 0x00000001 int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ struct KeyInfo*, /* First argument to compare function */ BtCursor *pCursor /* Space to write cursor structure */ ); |
︙ | ︙ | |||
174 175 176 177 178 179 180 | char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeCacheOverflow(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); | < > | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeCacheOverflow(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); #ifndef NDEBUG int sqlite3BtreeCursorIsValid(BtCursor*); #endif #ifndef SQLITE_OMIT_BTREECOUNT int sqlite3BtreeCount(BtCursor *, i64 *); |
︙ | ︙ |
Changes to src/btreeInt.h.
︙ | ︙ | |||
506 507 508 509 510 511 512 513 514 515 516 517 518 519 | u8 wrFlag; /* True if writable */ u8 atLast; /* Cursor pointing to the last entry */ u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ #ifndef SQLITE_OMIT_INCRBLOB u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ #endif i16 iPage; /* Index of current page in apPage */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ }; /* ** Potential values for BtCursor.eState. | > | 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | u8 wrFlag; /* True if writable */ u8 atLast; /* Cursor pointing to the last entry */ u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ #ifndef SQLITE_OMIT_INCRBLOB u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ #endif u8 hints; /* As configured by CursorSetHints() */ i16 iPage; /* Index of current page in apPage */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ }; /* ** Potential values for BtCursor.eState. |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1577 1578 1579 1580 1581 1582 1583 | */ if( pSelect ){ SelectDest dest; Table *pSelTab; assert(pParse->nTab==1); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); | | | 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 | */ if( pSelect ){ SelectDest dest; Table *pSelTab; assert(pParse->nTab==1); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); pParse->nTab = 2; sqlite3SelectDestInit(&dest, SRT_Table, 1); sqlite3Select(pParse, pSelect, &dest); sqlite3VdbeAddOp1(v, OP_Close, 1); if( pParse->nErr==0 ){ pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); if( pSelTab==0 ) return; |
︙ | ︙ | |||
2393 2394 2395 2396 2397 2398 2399 | }else{ tnum = pIndex->tnum; sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); } pKey = sqlite3IndexKeyinfo(pParse, pIndex); sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); | < | < | 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 | }else{ tnum = pIndex->tnum; sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); } pKey = sqlite3IndexKeyinfo(pParse, pIndex); sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); #ifndef SQLITE_OMIT_MERGE_SORT /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO); #else iSorter = iTab; |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1697 1698 1699 1700 1701 1702 1703 | ** table allocated and opened above. */ SelectDest dest; ExprList *pEList; assert( !isRowid ); sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); | | | 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 | ** table allocated and opened above. */ SelectDest dest; ExprList *pEList; assert( !isRowid ); sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.affSdst = (u8)affinity; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); pExpr->x.pSelect->iLimit = 0; if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){ return 0; } pEList = pExpr->x.pSelect->pEList; if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){ |
︙ | ︙ | |||
1790 1791 1792 1793 1794 1795 1796 | assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); assert( ExprHasProperty(pExpr, EP_xIsSelect) ); pSel = pExpr->x.pSelect; sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; | | | | | 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 | assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); assert( ExprHasProperty(pExpr, EP_xIsSelect) ); pSel = pExpr->x.pSelect; sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm); VdbeComment((v, "Init subquery result")); }else{ dest.eDest = SRT_Exists; sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); VdbeComment((v, "Init EXISTS result")); } sqlite3ExprDelete(pParse->db, pSel->pLimit); pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[1]); pSel->iLimit = 0; if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } rReg = dest.iSDParm; ExprSetIrreducible(pExpr); break; } } if( testAddr>=0 ){ sqlite3VdbeJumpHere(v, testAddr); |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
859 860 861 862 863 864 865 | ** "NULL". Otherwise, the argument is enclosed in single quotes with ** single-quote escapes. */ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ assert( argc==1 ); UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ | | > > > > > > > > > > > | | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 | ** "NULL". Otherwise, the argument is enclosed in single quotes with ** single-quote escapes. */ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ assert( argc==1 ); UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ case SQLITE_FLOAT: { double r1, r2; char zBuf[50]; r1 = sqlite3_value_double(argv[0]); sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1); sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8); if( r1!=r2 ){ sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1); } sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); break; } case SQLITE_INTEGER: { sqlite3_result_value(context, argv[0]); break; } case SQLITE_BLOB: { char *zText = 0; char const *zBlob = sqlite3_value_blob(argv[0]); int nBlob = sqlite3_value_bytes(argv[0]); |
︙ | ︙ |
Changes to src/hash.c.
︙ | ︙ | |||
109 110 111 112 113 114 115 | new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht); } if( new_size==pH->htsize ) return 0; #endif /* The inability to allocates space for a larger hash table is ** a performance hit but it is not a fatal error. So mark the | | > > > > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht); } if( new_size==pH->htsize ) return 0; #endif /* The inability to allocates space for a larger hash table is ** a performance hit but it is not a fatal error. So mark the ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero() ** only zeroes the requested number of bytes whereas this module will ** use the actual amount of space allocated for the hash table (which ** may be larger than the requested amount). */ sqlite3BeginBenignMalloc(); new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) ); sqlite3EndBenignMalloc(); if( new_ht==0 ) return 0; sqlite3_free(pH->ht); |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
593 594 595 596 597 598 599 | int rc, j1; regEof = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ VdbeComment((v, "SELECT eof flag")); sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem); addrSelect = sqlite3VdbeCurrentAddr(v)+2; | | | | | | 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 | int rc, j1; regEof = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ VdbeComment((v, "SELECT eof flag")); sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem); addrSelect = sqlite3VdbeCurrentAddr(v)+2; sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iSDParm); j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); VdbeComment((v, "Jump over SELECT coroutine")); /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, &dest); assert( pParse->nErr==0 || rc ); if( rc || NEVER(pParse->nErr) || db->mallocFailed ){ goto insert_cleanup; } sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); /* yield X */ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); VdbeComment((v, "End of SELECT coroutine")); sqlite3VdbeJumpHere(v, j1); /* label B: */ 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 ** FALSE if each* row of the SELECT can be written directly into ** the destination table (template 3). ** ** A temp table must be used if the table being updated is also one |
︙ | ︙ | |||
648 649 650 651 652 653 654 | int addrTop; /* Label "L" */ int addrIf; /* Address of jump to M */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regTempRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); | | | 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 | int addrTop; /* Label "L" */ int addrIf; /* Address of jump to M */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regTempRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); sqlite3VdbeJumpHere(v, addrIf); sqlite3ReleaseTempReg(pParse, regRec); |
︙ | ︙ | |||
785 786 787 788 789 790 791 | ** ** C: yield X ** if EOF goto D ** insert the select result into <table> from R..R+n ** goto C ** D: ... */ | | | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 | ** ** C: yield X ** if EOF goto D ** insert the select result into <table> from R..R+n ** goto C ** D: ... */ addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof); } /* Allocate registers for holding the rowid of the new row, ** the content of the new row, and the assemblied row record. */ regRowid = regIns = pParse->nMem+1; |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
760 761 762 763 764 765 766 767 768 769 770 | } } sqlite3BtreeLeaveAll(db); #else UNUSED_PARAMETER(db); #endif } /* ** Close an existing SQLite database */ | > > > > > > > > > > > > > > > | < < < > | > | | | | > > > > > | | > > > > > > > > > > > | | > > > > > > > > | > > | > > > > > | | | | > > > > > | 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 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | } } sqlite3BtreeLeaveAll(db); #else UNUSED_PARAMETER(db); #endif } /* ** Return TRUE if database connection db has unfinalized prepared ** statements or unfinished sqlite3_backup objects. */ static int connectionIsBusy(sqlite3 *db){ int j; assert( sqlite3_mutex_held(db->mutex) ); if( db->pVdbe ) return 1; for(j=0; j<db->nDb; j++){ Btree *pBt = db->aDb[j].pBt; if( pBt && sqlite3BtreeIsInBackup(pBt) ) return 1; } return 0; } /* ** Close an existing SQLite database */ static int sqlite3Close(sqlite3 *db, int forceZombie){ if( !db ){ return SQLITE_OK; } if( !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); /* Force xDisconnect calls on all virtual tables */ disconnectAllVtab(db); /* If a transaction is open, the disconnectAllVtab() call above ** will not have called the xDisconnect() method on any virtual ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() ** call will do so. We need to do this before the check for active ** SQL statements below, as the v-table implementation may be storing ** some prepared statements internally. */ sqlite3VtabRollback(db); /* Legacy behavior (sqlite3_close() behavior) is to return ** SQLITE_BUSY if the connection can not be closed immediately. */ if( !forceZombie && connectionIsBusy(db) ){ sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; } /* Convert the connection into a zombie and then close it. */ db->magic = SQLITE_MAGIC_ZOMBIE; sqlite3LeaveMutexAndCloseZombie(db); return SQLITE_OK; } /* ** Two variations on the public interface for closing a database ** connection. The sqlite3_close() version returns SQLITE_BUSY and ** leaves the connection option if there are unfinalized prepared ** statements or unfinished sqlite3_backups. The sqlite3_close_v2() ** version forces the connection to become a zombie if there are ** unclosed resources, and arranges for deallocation when the last ** prepare statement or sqlite3_backup closes. */ int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } /* ** Close the mutex on database connection db. ** ** Furthermore, if database connection db is a zombie (meaning that there ** has been a prior call to sqlite3_close(db) or sqlite3_close_v2(db)) and ** every sqlite3_stmt has now been finalized and every sqlite3_backup has ** finished, then free all resources. */ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ HashElem *i; /* Hash table iterator */ int j; /* If there are outstanding sqlite3_stmt or sqlite3_backup objects ** or if the connection has not yet been closed by sqlite3_close_v2(), ** then just leave the mutex and return. */ if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){ sqlite3_mutex_leave(db->mutex); return; } /* If we reach this point, it means that the database connection has ** closed all sqlite3_stmt and sqlite3_backup objects and has been ** pased to sqlite3_close (meaning that it is a zombie). Therefore, ** go ahead and free all resources. */ /* Free any outstanding Savepoint structures. */ sqlite3CloseSavepoints(db); /* Close all database connections */ for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; |
︙ | ︙ | |||
894 895 896 897 898 899 900 | db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */ if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } sqlite3_free(db); | < | 944 945 946 947 948 949 950 951 952 953 954 955 956 957 | db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */ if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } sqlite3_free(db); } /* ** Rollback all database files. If tripCode is not SQLITE_OK, then ** any open cursors are invalidated ("tripped" - as in "tripping a circuit ** breaker") and made to return tripCode if there are any further ** attempts to use that cursor. |
︙ | ︙ |
Changes to src/mutex.h.
︙ | ︙ | |||
32 33 34 35 36 37 38 | ** mutual exclusion is provided. But this ** implementation can be overridden at ** start-time. ** ** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. ** ** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. | < < < < | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | ** mutual exclusion is provided. But this ** implementation can be overridden at ** start-time. ** ** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. ** ** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. */ #if !SQLITE_THREADSAFE # define SQLITE_MUTEX_OMIT #endif #if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP) # if SQLITE_OS_UNIX # define SQLITE_MUTEX_PTHREADS # elif SQLITE_OS_WIN # define SQLITE_MUTEX_W32 # else # define SQLITE_MUTEX_NOOP # endif #endif #ifdef SQLITE_MUTEX_OMIT /* |
︙ | ︙ |
Deleted src/mutex_os2.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to src/mutex_w32.c.
︙ | ︙ | |||
105 106 107 108 109 110 111 | /* As winMutexInit() and winMutexEnd() are called as part ** of the sqlite3_initialize and sqlite3_shutdown() ** processing, the "interlocked" magic is probably not ** strictly necessary. */ static long winMutex_lock = 0; | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | /* As winMutexInit() and winMutexEnd() are called as part ** of the sqlite3_initialize and sqlite3_shutdown() ** processing, the "interlocked" magic is probably not ** strictly necessary. */ static long winMutex_lock = 0; void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ static int winMutexInit(void){ /* The first to increment to 1 does actual initialization */ if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ int i; for(i=0; i<ArraySize(winMutex_staticMutexes); i++){ #if SQLITE_OS_WINRT |
︙ | ︙ |
Changes to src/os.h.
︙ | ︙ | |||
19 20 21 22 23 24 25 | */ #ifndef _SQLITE_OS_H_ #define _SQLITE_OS_H_ /* ** Figure out if we are dealing with Unix, Windows, or some other ** operating system. After the following block of preprocess macros, | | < < < < < < < < < < < < < < < < < < < < < < < < | 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 | */ #ifndef _SQLITE_OS_H_ #define _SQLITE_OS_H_ /* ** Figure out if we are dealing with Unix, Windows, or some other ** operating system. After the following block of preprocess macros, ** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER ** will defined to either 1 or 0. One of the four will be 1. The other ** three will be 0. */ #if defined(SQLITE_OS_OTHER) # if SQLITE_OS_OTHER==1 # undef SQLITE_OS_UNIX # define SQLITE_OS_UNIX 0 # undef SQLITE_OS_WIN # define SQLITE_OS_WIN 0 # else # undef SQLITE_OS_OTHER # endif #endif #if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) # define SQLITE_OS_OTHER 0 # ifndef SQLITE_OS_WIN # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) # define SQLITE_OS_WIN 1 # define SQLITE_OS_UNIX 0 # else # define SQLITE_OS_WIN 0 # define SQLITE_OS_UNIX 1 # endif # else # define SQLITE_OS_UNIX 0 # endif #else # ifndef SQLITE_OS_WIN # define SQLITE_OS_WIN 0 # endif #endif #if SQLITE_OS_WIN # include <windows.h> #endif /* ** Determine if we are dealing with Windows NT. ** ** We ought to be able to determine if we are compiling for win98 or winNT ** using the _WIN32_WINNT macro as follows: ** ** #if defined(_WIN32_WINNT) |
︙ | ︙ | |||
112 113 114 115 116 117 118 | #if defined(_WIN32_WCE) # define SQLITE_OS_WINCE 1 #else # define SQLITE_OS_WINCE 0 #endif /* | | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | #if defined(_WIN32_WCE) # define SQLITE_OS_WINCE 1 #else # define SQLITE_OS_WINCE 0 #endif /* ** Determine if we are dealing with WinRT, which provides only a subset of ** the full Win32 API. */ #if !defined(SQLITE_OS_WINRT) # define SQLITE_OS_WINRT 0 #endif /* ** When compiled for WinCE or WinRT, there is no concept of the current |
︙ | ︙ |
Deleted src/os_os2.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to src/os_win.c.
︙ | ︙ | |||
284 285 286 287 288 289 290 | #else { "CreateFileW", (SYSCALL)0, 0 }, #endif #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) | | > | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | #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, \ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[6].pCurrent) |
︙ | ︙ | |||
596 597 598 599 600 601 602 | #endif #ifndef osLockFileEx #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[45].pCurrent) #endif | | | 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | #endif #ifndef osLockFileEx #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[45].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[46].pCurrent) |
︙ | ︙ | |||
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | #else { "UnlockFileEx", (SYSCALL)0, 0 }, #endif #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[55].pCurrent) { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, #define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[56].pCurrent) { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 }, #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \ LPCSTR,LPBOOL))aSyscall[57].pCurrent) | > > > > | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | #else { "UnlockFileEx", (SYSCALL)0, 0 }, #endif #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[55].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[56].pCurrent) { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 }, #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \ LPCSTR,LPBOOL))aSyscall[57].pCurrent) |
︙ | ︙ | |||
698 699 700 701 702 703 704 | #else { "WaitForSingleObject", (SYSCALL)0, 0 }, #endif #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ DWORD))aSyscall[60].pCurrent) | | | | | 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 | #else { "WaitForSingleObject", (SYSCALL)0, 0 }, #endif #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ DWORD))aSyscall[60].pCurrent) #if SQLITE_OS_WINRT { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, #else { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, #endif #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ BOOL))aSyscall[61].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[62].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[63].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[64].pCurrent) |
︙ | ︙ | |||
789 790 791 792 793 794 795 | #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[70].pCurrent) { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].pCurrent) | | | 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 | #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[70].pCurrent) { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].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[72].pCurrent) |
︙ | ︙ |
Changes to src/pcache1.c.
︙ | ︙ | |||
392 393 394 395 396 397 398 | nNew = p->nHash*2; if( nNew<256 ){ nNew = 256; } pcache1LeaveMutex(p->pGroup); if( p->nHash ){ sqlite3BeginBenignMalloc(); } | | < | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | nNew = p->nHash*2; if( nNew<256 ){ nNew = 256; } pcache1LeaveMutex(p->pGroup); if( p->nHash ){ sqlite3BeginBenignMalloc(); } apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew); if( p->nHash ){ sqlite3EndBenignMalloc(); } pcache1EnterMutex(p->pGroup); if( apNew ){ for(i=0; i<p->nHash; i++){ PgHdr1 *pPage; PgHdr1 *pNext = p->apHash[i]; while( (pPage = pNext)!=0 ){ unsigned int h = pPage->iKey % nNew; pNext = pPage->pNext; pPage->pNext = apNew[h]; |
︙ | ︙ | |||
580 581 582 583 584 585 586 | int separateCache = sqlite3GlobalConfig.bCoreMutex>0; #endif assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); assert( szExtra < 300 ); sz = sizeof(PCache1) + sizeof(PGroup)*separateCache; | | < | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | int separateCache = sqlite3GlobalConfig.bCoreMutex>0; #endif assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); assert( szExtra < 300 ); sz = sizeof(PCache1) + sizeof(PGroup)*separateCache; pCache = (PCache1 *)sqlite3MallocZero(sz); if( pCache ){ if( separateCache ){ pGroup = (PGroup*)&pCache[1]; pGroup->mxPinned = 10; }else{ pGroup = &pcache1.grp; } pCache->pGroup = pGroup; |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 | { OP_AddImm, 1, 0, 0}, /* 0 */ { OP_IfNeg, 1, 0, 0}, /* 1 */ { OP_String8, 0, 3, 0}, /* 2 */ { OP_ResultRow, 3, 1, 0}, }; int isQuick = (sqlite3Tolower(zLeft[0])=='q'); /* Initialize the VDBE program */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; pParse->nMem = 6; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); | > > > > > > > > > > > > > | 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 | { OP_AddImm, 1, 0, 0}, /* 0 */ { OP_IfNeg, 1, 0, 0}, /* 1 */ { OP_String8, 0, 3, 0}, /* 2 */ { OP_ResultRow, 3, 1, 0}, }; int isQuick = (sqlite3Tolower(zLeft[0])=='q'); /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check", ** then iDb is set to the index of the database identified by <db>. ** In this case, the integrity of database iDb only is verified by ** the VDBE created below. ** ** Otherwise, if the command was simply "PRAGMA integrity_check" (or ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb ** to -1 here, to indicate that the VDBE should verify the integrity ** of all attached databases. */ assert( iDb>=0 ); assert( iDb==0 || pId2->z ); if( pId2->z==0 ) iDb = -1; /* Initialize the VDBE program */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; pParse->nMem = 6; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); |
︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 | /* Do an integrity check on each database file */ for(i=0; i<db->nDb; i++){ HashElem *x; Hash *pTbls; int cnt = 0; if( OMIT_TEMPDB && i==1 ) continue; sqlite3CodeVerifySchema(pParse, i); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); /* Do an integrity check of the B-Tree ** ** Begin by filling registers 2, 3, ... with the root pages numbers ** for all tables and indices in the database. */ | > | | 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 | /* Do an integrity check on each database file */ for(i=0; i<db->nDb; i++){ HashElem *x; Hash *pTbls; int cnt = 0; if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; sqlite3CodeVerifySchema(pParse, i); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); /* Do an integrity check of the B-Tree ** ** Begin by filling registers 2, 3, ... with the root pages numbers ** for all tables and indices in the database. */ assert( sqlite3SchemaMutexHeld(db, i, 0) ); pTbls = &db->aDb[i].pSchema->tblHash; for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt); cnt++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
120 121 122 123 124 125 126 | ** The counter *cnt is incremented each time. After counter exceeds ** 16 (the number of significant digits in a 64-bit float) '0' is ** always returned. */ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ int digit; LONGDOUBLE_TYPE d; | | > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** The counter *cnt is incremented each time. After counter exceeds ** 16 (the number of significant digits in a 64-bit float) '0' is ** always returned. */ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ int digit; LONGDOUBLE_TYPE d; if( (*cnt)<=0 ) return '0'; (*cnt)--; digit = (int)*val; d = digit; digit += '0'; *val = (*val - d)*10.0; return (char)digit; } #endif /* SQLITE_OMIT_FLOATING_POINT */ |
︙ | ︙ | |||
424 425 426 427 428 429 430 | exp = 0; if( sqlite3IsNaN((double)realvalue) ){ bufpt = "NaN"; length = 3; break; } if( realvalue>0.0 ){ | > | > | | > | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | exp = 0; if( sqlite3IsNaN((double)realvalue) ){ bufpt = "NaN"; length = 3; break; } if( realvalue>0.0 ){ LONGDOUBLE_TYPE scale = 1.0; while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;} while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; } while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; } while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } realvalue /= scale; while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } if( exp>350 ){ if( prefix=='-' ){ bufpt = "-Inf"; }else if( prefix=='+' ){ bufpt = "+Inf"; |
︙ | ︙ | |||
459 460 461 462 463 464 465 | if( exp<-4 || exp>precision ){ xtype = etEXP; }else{ precision = precision - exp; xtype = etFLOAT; } }else{ | | | | 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 | if( exp<-4 || exp>precision ){ xtype = etEXP; }else{ precision = precision - exp; xtype = etFLOAT; } }else{ flag_rtz = flag_altform2; } if( xtype==etEXP ){ e2 = 0; }else{ e2 = exp; } if( e2+precision+width > etBUFSIZE - 15 ){ bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 ); if( bufpt==0 ){ pAccum->mallocFailed = 1; return; } } zOut = bufpt; nsd = 16 + flag_altform2*10; flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; /* The sign in front of the number */ if( prefix ){ *(bufpt++) = prefix; } /* Digits prior to the decimal point */ if( e2<0 ){ |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | } /* ** Initialize a SelectDest structure. */ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; | | | | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | } /* ** Initialize a SelectDest structure. */ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; pDest->iSDParm = iParm; pDest->affSdst = 0; pDest->iSdst = 0; pDest->nSdst = 0; } /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
547 548 549 550 551 552 553 | 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 */ | | | | | | | | 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 | 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 = distinct>=0; if( pOrderBy==0 && !hasDistinct ){ codeOffset(v, p, iContinue); } /* Pull the requested columns. */ if( nColumn>0 ){ nResultCol = nColumn; }else{ nResultCol = pEList->nExpr; } if( pDest->iSdst==0 ){ pDest->iSdst = pParse->nMem+1; pDest->nSdst = nResultCol; pParse->nMem += nResultCol; }else{ assert( pDest->nSdst==nResultCol ); } regResult = pDest->iSdst; if( nColumn>0 ){ for(i=0; i<nColumn; i++){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. |
︙ | ︙ | |||
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 ); | | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 | #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 ); p->affinity = 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{ |
︙ | ︙ | |||
706 707 708 709 710 711 712 | testcase( eDest==SRT_Output ); if( pOrderBy ){ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Coroutine ){ | | | 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 | testcase( eDest==SRT_Output ); if( pOrderBy ){ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); } break; } |
︙ | ︙ | |||
886 887 888 889 890 891 892 | int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ int addr; int iTab; int pseudoTab = 0; ExprList *pOrderBy = p->pOrderBy; int eDest = pDest->eDest; | | | 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 | int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ int addr; int iTab; int pseudoTab = 0; ExprList *pOrderBy = p->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; iTab = pOrderBy->iECursor; regRow = sqlite3GetTempReg(pParse); if( eDest==SRT_Output || eDest==SRT_Coroutine ){ |
︙ | ︙ | |||
945 946 947 948 949 950 951 | #endif default: { int i; assert( eDest==SRT_Output || eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); testcase( eDest==SRT_Coroutine ); for(i=0; i<nColumn; i++){ | | | | | | | 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 | #endif default: { int i; assert( eDest==SRT_Output || eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); testcase( eDest==SRT_Coroutine ); for(i=0; i<nColumn; i++){ assert( regRow!=pDest->iSdst+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i); if( i==0 ){ sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); } } if( eDest==SRT_Output ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn); }else{ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); } break; } } sqlite3ReleaseTempReg(pParse, regRow); sqlite3ReleaseTempReg(pParse, regRowid); |
︙ | ︙ | |||
1606 1607 1608 1609 1610 1611 1612 | v = sqlite3GetVdbe(pParse); assert( v!=0 ); /* The VDBE already created by calling function */ /* Create the destination temporary table if necessary */ if( dest.eDest==SRT_EphemTab ){ assert( p->pEList ); | | | 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 | v = sqlite3GetVdbe(pParse); assert( v!=0 ); /* The VDBE already created by calling function */ /* Create the destination temporary table if necessary */ if( dest.eDest==SRT_EphemTab ){ assert( p->pEList ); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); dest.eDest = SRT_Table; } /* Make sure all SELECTs in the statement have the same number of elements ** in their result sets. */ |
︙ | ︙ | |||
1692 1693 1694 1695 1696 1697 1698 | /* We can reuse a temporary table generated by a SELECT to our ** right. */ assert( p->pRightmost!=p ); /* Can only happen for leftward elements ** of a 3-way or more compound */ assert( p->pLimit==0 ); /* Not allowed on leftward elements */ assert( p->pOffset==0 ); /* Not allowed on leftward elements */ | | | 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 | /* We can reuse a temporary table generated by a SELECT to our ** right. */ assert( p->pRightmost!=p ); /* Can only happen for leftward elements ** of a 3-way or more compound */ assert( p->pLimit==0 ); /* Not allowed on leftward elements */ assert( p->pOffset==0 ); /* Not allowed on leftward elements */ unionTab = dest.iSDParm; }else{ /* We will need to create our own temporary table to hold the ** intermediate results. */ unionTab = pParse->nTab++; assert( p->pOrderBy==0 ); addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); |
︙ | ︙ | |||
1749 1750 1751 1752 1753 1754 1755 | p->pOffset = pOffset; p->iLimit = 0; p->iOffset = 0; /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ | | | 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 | p->pOffset = pOffset; p->iLimit = 0; p->iOffset = 0; /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); if( dest.eDest!=priorOp ){ int iCont, iBreak, iStart; assert( p->pEList ); if( dest.eDest==SRT_Output ){ Select *pFirst = p; while( pFirst->pPrior ) pFirst = pFirst->pPrior; generateColumnNames(pParse, 0, pFirst->pEList); |
︙ | ︙ | |||
1813 1814 1815 1816 1817 1818 1819 | assert( p->addrOpenEphm[1] == -1 ); p->addrOpenEphm[1] = addr; p->pPrior = 0; pLimit = p->pLimit; p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; | | | 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 | assert( p->addrOpenEphm[1] == -1 ); p->addrOpenEphm[1] = addr; p->pPrior = 0; pLimit = p->pLimit; p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; intersectdest.iSDParm = tab2; explainSetInteger(iSub2, pParse->iNextSelectId); rc = sqlite3Select(pParse, p, &intersectdest); testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; p->pPrior = pPrior; if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; sqlite3ExprDelete(db, p->pLimit); |
︙ | ︙ | |||
1907 1908 1909 1910 1911 1912 1913 | pLoop->addrOpenEphm[i] = -1; } } sqlite3DbFree(db, pKeyInfo); } multi_select_end: | | | | | | 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 | pLoop->addrOpenEphm[i] = -1; } } sqlite3DbFree(db, pKeyInfo); } multi_select_end: pDest->iSdst = dest.iSdst; pDest->nSdst = dest.nSdst; sqlite3SelectDelete(db, pDelete); return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ /* ** Code an output subroutine for a coroutine implementation of a ** SELECT statment. ** ** The data to be output is contained in pIn->iSdst. There are ** pIn->nSdst columns to be output. pDest is where the output should ** be sent. ** ** regReturn is the number of the register holding the subroutine ** return address. ** ** If regPrev>0 then it is the first register in a vector that ** records the previous output. mem[regPrev] is a flag that is false |
︙ | ︙ | |||
1957 1958 1959 1960 1961 1962 1963 | iContinue = sqlite3VdbeMakeLabel(v); /* Suppress duplicates for UNION, EXCEPT, and INTERSECT */ if( regPrev ){ int j1, j2; j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); | | | | | | | | | | | | | | | | | | | | | | | 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 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 | iContinue = sqlite3VdbeMakeLabel(v); /* Suppress duplicates for UNION, EXCEPT, and INTERSECT */ 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); sqlite3ExprCodeCopy(pParse, pIn->iSdst, regPrev+1, pIn->nSdst); sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); } if( pParse->db->mallocFailed ) return 0; /* Suppress the the first OFFSET entries if there is an OFFSET clause */ codeOffset(v, p, iContinue); switch( pDest->eDest ){ /* Store the result as data using a unique key. */ case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); testcase( pDest->eDest==SRT_Table ); testcase( pDest->eDest==SRT_EphemTab ); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); sqlite3ReleaseTempReg(pParse, r1); break; } #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: { int r1; assert( pIn->nSdst==1 ); p->affinity = sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &p->affinity, 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 */ /* If any row exist in the result set, record that fact and abort. */ case SRT_Exists: { sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm); /* The LIMIT clause will terminate the loop for us */ break; } #endif /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ case SRT_Mem: { assert( pIn->nSdst==1 ); sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); /* The LIMIT clause will jump out of the loop for us */ break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ /* The results are stored in a sequence of registers ** starting at pDest->iSdst. Then the co-routine yields. */ case SRT_Coroutine: { if( pDest->iSdst==0 ){ pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); pDest->nSdst = pIn->nSdst; } sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); break; } /* If none of the above, then the result destination must be ** SRT_Output. This routine is never called with any other ** destination other than the ones handled above or SRT_Output. ** ** For SRT_Output, results are stored in a sequence of registers. ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to ** return the next row of result. */ default: { assert( pDest->eDest==SRT_Output ); sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); break; } } /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ |
︙ | ︙ | |||
2471 2472 2473 2474 2475 2476 2477 | sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); | | | 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 | sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Release temporary registers */ if( regPrev ){ sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1); |
︙ | ︙ | |||
3717 3718 3719 3720 3721 3722 3723 | ** pDest->eDest Result ** ------------ ------------------------------------------- ** SRT_Output Generate a row of output (using the OP_ResultRow ** opcode) for each row in the result set. ** ** SRT_Mem Only valid if the result is a single column. ** Store the first column of the first result row | | | | | > | | | | | | 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 | ** pDest->eDest Result ** ------------ ------------------------------------------- ** SRT_Output Generate a row of output (using the OP_ResultRow ** opcode) for each row in the result set. ** ** SRT_Mem Only valid if the result is a single column. ** Store the first column of the first result row ** in register pDest->iSDParm then abandon the rest ** of the query. This destination implies "LIMIT 1". ** ** SRT_Set The result must be a single column. Store each ** row of result as the key in table pDest->iSDParm. ** Apply the affinity pDest->affSdst before storing ** results. Used to implement "IN (SELECT ...)". ** ** SRT_Union Store results as a key in a temporary table ** identified by pDest->iSDParm. ** ** SRT_Except Remove results from the temporary table pDest->iSDParm. ** ** SRT_Table Store results in temporary table pDest->iSDParm. ** This is like SRT_EphemTab except that the table ** is assumed to already be open. ** ** SRT_EphemTab Create an temporary table pDest->iSDParm and store ** the result there. The cursor is left open after ** returning. This is like SRT_Table except that ** this destination uses OP_OpenEphemeral to create ** the table first. ** ** SRT_Coroutine Generate a co-routine that returns a new row of ** results each time it is invoked. The entry point ** of the co-routine is stored in register pDest->iSDParm. ** ** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result ** set is not empty. ** ** SRT_Discard Throw the results away. This is used by SELECT ** statements within triggers whose only purpose is ** the side-effects of functions. ** ** This routine returns the number of errors. If any errors are |
︙ | ︙ | |||
3987 3988 3989 3990 3991 3992 3993 | }else{ addrSortIndex = -1; } /* If the output is destined for a temporary table, open that table. */ if( pDest->eDest==SRT_EphemTab ){ | | | 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 | }else{ addrSortIndex = -1; } /* If the output is destined for a temporary table, open that table. */ if( pDest->eDest==SRT_EphemTab ){ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr); } /* Set the limiter. */ iEnd = sqlite3VdbeMakeLabel(v); p->nSelectRow = (double)LARGEST_INT64; computeLimitRegisters(pParse, p, iEnd); |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | #include <string.h> #include <stdio.h> #include <assert.h> #include "sqlite3.h" #include <ctype.h> #include <stdarg.h> | | < < < < | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include <string.h> #include <stdio.h> #include <assert.h> #include "sqlite3.h" #include <ctype.h> #include <stdarg.h> #if !defined(_WIN32) && !defined(WIN32) # include <signal.h> # if !defined(__RTP__) && !defined(_WRS_KERNEL) # include <pwd.h> # endif # include <unistd.h> # include <sys/types.h> #endif #ifdef HAVE_EDITLINE # include <editline/editline.h> #endif #if defined(HAVE_READLINE) && HAVE_READLINE==1 # include <readline/readline.h> # include <readline/history.h> #endif |
︙ | ︙ | |||
88 89 90 91 92 93 94 | static int enableTimer = 0; /* ctype macros that work with signed characters */ #define IsSpace(X) isspace((unsigned char)X) #define IsDigit(X) isdigit((unsigned char)X) #define ToLower(X) (char)tolower((unsigned char)X) | | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | static int enableTimer = 0; /* ctype macros that work with signed characters */ #define IsSpace(X) isspace((unsigned char)X) #define IsDigit(X) isdigit((unsigned char)X) #define ToLower(X) (char)tolower((unsigned char)X) #if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) #include <sys/time.h> #include <sys/resource.h> /* Saved resource information for the beginning of an operation */ static struct rusage sBegin; /* |
︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 | /* ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. */ static void open_db(struct callback_data *p){ if( p->db==0 ){ sqlite3_open(p->zDbFilename, &p->db); db = p->db; if( db && sqlite3_errcode(db)==SQLITE_OK ){ sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, shellstaticFunc, 0, 0); } if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ | > | 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 | /* ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. */ static void open_db(struct callback_data *p){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); db = p->db; if( db && sqlite3_errcode(db)==SQLITE_OK ){ sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, shellstaticFunc, 0, 0); } if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ |
︙ | ︙ | |||
2464 2465 2466 2467 2468 2469 2470 | enableTimer = booleanValue(azArg[1]); }else if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){ open_db(p); output_file_close(p->traceOut); p->traceOut = output_file_open(azArg[1]); | | | 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 | enableTimer = booleanValue(azArg[1]); }else if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){ open_db(p); output_file_close(p->traceOut); p->traceOut = output_file_open(azArg[1]); #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) if( p->traceOut==0 ){ sqlite3_trace(p->db, 0, 0); }else{ sqlite3_trace(p->db, sql_trace_callback, p->traceOut); } #endif }else |
︙ | ︙ | |||
2692 2693 2694 2695 2696 2697 2698 | ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ static char *find_home_dir(void){ static char *home_dir = NULL; if( home_dir ) return home_dir; | | > | | | | > | | | 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 | ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ static char *find_home_dir(void){ static char *home_dir = NULL; if( home_dir ) return home_dir; #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL) { struct passwd *pwent; uid_t uid = getuid(); if( (pwent=getpwuid(uid)) != NULL) { home_dir = pwent->pw_dir; } } #endif #if defined(_WIN32_WCE) /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() */ home_dir = "/"; #else #if defined(_WIN32) || defined(WIN32) if (!home_dir) { home_dir = getenv("USERPROFILE"); } #endif if (!home_dir) { home_dir = getenv("HOME"); } #if defined(_WIN32) || defined(WIN32) if (!home_dir) { char *zDrive, *zPath; int n; zDrive = getenv("HOMEDRIVE"); zPath = getenv("HOMEPATH"); if( zDrive && zPath ){ n = strlen30(zDrive) + strlen30(zPath) + 1; |
︙ | ︙ | |||
2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 | home_dir = find_home_dir(); if( home_dir==0 ){ #if !defined(__RTP__) && !defined(_WRS_KERNEL) fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0); #endif return 1; } zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); sqliterc = zBuf; } in = fopen(sqliterc,"rb"); if( in ){ if( stdin_is_interactive ){ fprintf(stderr,"-- Loading resources from %s\n",sqliterc); | > | 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 | home_dir = find_home_dir(); if( home_dir==0 ){ #if !defined(__RTP__) && !defined(_WRS_KERNEL) fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0); #endif return 1; } sqlite3_initialize(); zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); sqliterc = zBuf; } in = fopen(sqliterc,"rb"); if( in ){ if( stdin_is_interactive ){ fprintf(stderr,"-- Loading resources from %s\n",sqliterc); |
︙ | ︙ | |||
2932 2933 2934 2935 2936 2937 2938 | }else{ fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]); exit(1); } } } if( i<argc ){ | < < < < | 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 | }else{ fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]); exit(1); } } } if( i<argc ){ data.zDbFilename = argv[i++]; }else{ #ifndef SQLITE_OMIT_MEMORYDB data.zDbFilename = ":memory:"; #else data.zDbFilename = 0; #endif } |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
210 211 212 213 214 215 216 | ** CAPI3REF: Database Connection Handle ** KEYWORDS: {database connection} {database connections} ** ** Each open SQLite database is represented by a pointer to an instance of ** the opaque structure named "sqlite3". It is useful to think of an sqlite3 ** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and ** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] | > | | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | ** CAPI3REF: Database Connection Handle ** KEYWORDS: {database connection} {database connections} ** ** Each open SQLite database is represented by a pointer to an instance of ** the opaque structure named "sqlite3". It is useful to think of an sqlite3 ** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and ** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] ** and [sqlite3_close_v2()] are its destructors. There are many other ** interfaces (such as ** [sqlite3_prepare_v2()], [sqlite3_create_function()], and ** [sqlite3_busy_timeout()] to name but three) that are methods on an ** sqlite3 object. */ typedef struct sqlite3 sqlite3; /* |
︙ | ︙ | |||
257 258 259 260 261 262 263 | #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite3_int64 #endif /* ** CAPI3REF: Closing A Database Connection ** | > | | | > > > > > > > > > > > > | | > | | | > > | | > | | | > | 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 | #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite3_int64 #endif /* ** CAPI3REF: Closing A Database Connection ** ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors ** for the [sqlite3] object. ** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if ** the [sqlite3] object is successfully destroyed and all associated ** resources are deallocated. ** ** ^If the database connection is associated with unfinalized prepared ** statements or unfinished sqlite3_backup objects then sqlite3_close() ** will leave the database connection open and return [SQLITE_BUSY]. ** ^If sqlite3_close_v2() is called with unfinalized prepared statements ** and unfinished sqlite3_backups, then the database connection becomes ** an unusable "zombie" which will automatically be deallocated when the ** last prepared statement is finalized or the last sqlite3_backup is ** finished. The sqlite3_close_v2() interface is intended for use with ** host languages that are garbage collected, and where the order in which ** destructors are called is arbitrary. ** ** Applications should [sqlite3_finalize | finalize] all [prepared statements], ** [sqlite3_blob_close | close] all [BLOB handles], and ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated ** with the [sqlite3] object prior to attempting to close the object. ^If ** sqlite3_close() is called on a [database connection] that still has ** outstanding [prepared statements], [BLOB handles], and/or ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation ** of resources is deferred until all [prepared statements], [BLOB handles], ** and [sqlite3_backup] objects are also destroyed. ** ** ^If an [sqlite3] object is destroyed while a transaction is open, ** the transaction is automatically rolled back. ** ** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] ** must be either a NULL ** pointer or an [sqlite3] object pointer obtained ** from [sqlite3_open()], [sqlite3_open16()], or ** [sqlite3_open_v2()], and not previously closed. ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ int sqlite3_close(sqlite3*); int sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. ** This is legacy and deprecated. It is included for historical ** compatibility and is not documented. */ typedef int (*sqlite3_callback)(void*,int,char**, char**); |
︙ | ︙ | |||
4129 4130 4131 4132 4133 4134 4135 | ** they return. Hence, the calling function can deallocate or ** modify the text after they return without harm. ** ^The sqlite3_result_error_code() function changes the error code ** returned by SQLite as a result of an error in a function. ^By default, ** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. ** | | | | | | 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 | ** they return. Hence, the calling function can deallocate or ** modify the text after they return without harm. ** ^The sqlite3_result_error_code() function changes the error code ** returned by SQLite as a result of an error in a function. ^By default, ** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. ** ** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an ** error indicating that a string or BLOB is too long to represent. ** ** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an ** error indicating that a memory allocation failed. ** ** ^The sqlite3_result_int() interface sets the return value ** of the application-defined function to be the 32-bit signed integer ** value given in the 2nd argument. ** ^The sqlite3_result_int64() interface sets the return value ** of the application-defined function to be the 64-bit signed integer ** value given in the 2nd argument. |
︙ | ︙ | |||
5485 5486 5487 5488 5489 5490 5491 | ** ** The SQLite source code contains multiple implementations ** of these mutex routines. An appropriate implementation ** is selected automatically at compile-time. ^(The following ** implementations are available in the SQLite core: ** ** <ul> | < | | | | 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 | ** ** The SQLite source code contains multiple implementations ** of these mutex routines. An appropriate implementation ** is selected automatically at compile-time. ^(The following ** implementations are available in the SQLite core: ** ** <ul> ** <li> SQLITE_MUTEX_PTHREADS ** <li> SQLITE_MUTEX_W32 ** <li> SQLITE_MUTEX_NOOP ** </ul>)^ ** ** ^The SQLITE_MUTEX_NOOP implementation is a set of routines ** that does no real locking and is appropriate for use in ** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and ** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix ** and Windows. ** ** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor ** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex ** implementation is included with the library. In this case the ** application must supply a custom mutex implementation using the ** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function ** before calling sqlite3_initialize() or any other public sqlite3_ |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_WIN32_MALLOC // Use Win32 native heap API ** SQLITE_MEMDEBUG // Debugging version of system malloc() ** ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the ** assert() macro is enabled, each call into the Win32 native heap subsystem ** will cause HeapValidate to be called. If heap validation should fail, an ** assertion will be triggered. ** ** (Historical note: There used to be several other options, but we've ** pared it down to just these three.) ** ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as ** the default. */ | > | > > > | > | > | > > > | 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 | /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_WIN32_MALLOC // Use Win32 native heap API ** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails ** SQLITE_MEMDEBUG // Debugging version of system malloc() ** ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the ** assert() macro is enabled, each call into the Win32 native heap subsystem ** will cause HeapValidate to be called. If heap validation should fail, an ** assertion will be triggered. ** ** (Historical note: There used to be several other options, but we've ** pared it down to just these three.) ** ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as ** the default. */ #if defined(SQLITE_SYSTEM_MALLOC) \ + defined(SQLITE_WIN32_MALLOC) \ + defined(SQLITE_ZERO_MALLOC) \ + defined(SQLITE_MEMDEBUG)>1 # error "Two or more of the following compile-time configuration options\ are defined but at most one is allowed:\ SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\ SQLITE_ZERO_MALLOC" #endif #if defined(SQLITE_SYSTEM_MALLOC) \ + defined(SQLITE_WIN32_MALLOC) \ + defined(SQLITE_ZERO_MALLOC) \ + defined(SQLITE_MEMDEBUG)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ |
︙ | ︙ | |||
978 979 980 981 982 983 984 985 986 987 988 989 990 991 | ** than being distinct from one another. */ #define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ #define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ #define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ #define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ #define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ | > | 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | ** than being distinct from one another. */ #define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ #define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ #define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ #define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ #define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ #define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */ /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ |
︙ | ︙ | |||
2112 2113 2114 2115 2116 2117 2118 | /* ** A structure used to customize the behavior of sqlite3Select(). See ** comments above sqlite3Select() for details. */ typedef struct SelectDest SelectDest; struct SelectDest { u8 eDest; /* How to dispose of the results */ | | | | | | 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 | /* ** A structure used to customize the behavior of sqlite3Select(). See ** comments above sqlite3Select() for details. */ typedef struct SelectDest SelectDest; struct SelectDest { u8 eDest; /* How to dispose of the results */ u8 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 ** tables, the following information is attached to the Table.u.autoInc.p ** pointer of each autoincrement table to record some side information that ** the code generator needs. We have to keep per-table autoincrement |
︙ | ︙ | |||
2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 | #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ #define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the | > > | 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 | #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ #define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the |
︙ | ︙ | |||
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 | void sqlite3CodeVerifySchema(Parse*, int); void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); void sqlite3BeginTransaction(Parse*, int); void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); void sqlite3Savepoint(Parse*, int, Token*); void sqlite3CloseSavepoints(sqlite3 *); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3ExprCanBeNull(const Expr*); void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); | > | 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 | void sqlite3CodeVerifySchema(Parse*, int); void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); void sqlite3BeginTransaction(Parse*, int); void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); void sqlite3Savepoint(Parse*, int, Token*); void sqlite3CloseSavepoints(sqlite3 *); void sqlite3LeaveMutexAndCloseZombie(sqlite3*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3ExprCanBeNull(const Expr*); void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); |
︙ | ︙ |
Changes to src/test8.c.
︙ | ︙ | |||
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 | rc = sqlite3_declare_vtab(db, Tcl_GetString(objv[2])); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); return TCL_ERROR; } return TCL_OK; } #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ /* ** Register commands with the TCL interpreter. */ int Sqlitetest8_Init(Tcl_Interp *interp){ #ifndef SQLITE_OMIT_VIRTUALTABLE static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { | > > > > > > > > > > > > > > > > > > > > > > > | > | | 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 | rc = sqlite3_declare_vtab(db, Tcl_GetString(objv[2])); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); return TCL_ERROR; } return TCL_OK; } #include "test_spellfix.c" /* ** Register the spellfix virtual table module. */ static int register_spellfix_module( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3 *db; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; sqlite3Spellfix1Register(db); return TCL_OK; } #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ /* ** Register commands with the TCL interpreter. */ int Sqlitetest8_Init(Tcl_Interp *interp){ #ifndef SQLITE_OMIT_VIRTUALTABLE static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { { "register_echo_module", register_echo_module, 0 }, { "register_spellfix_module", register_spellfix_module, 0 }, { "sqlite3_declare_vtab", declare_vtab, 0 }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, aObjCmd[i].clientData, 0); } #endif |
︙ | ︙ |
Changes to src/test_config.c.
︙ | ︙ | |||
624 625 626 627 628 629 630 631 632 633 634 635 636 637 | LINKVAR( MAX_DEFAULT_PAGE_SIZE ); { static const int cv_TEMP_STORE = SQLITE_TEMP_STORE; Tcl_LinkVar(interp, "TEMP_STORE", (char *)&(cv_TEMP_STORE), TCL_LINK_INT | TCL_LINK_READ_ONLY); } } /* ** Register commands with the TCL interpreter. */ int Sqliteconfig_Init(Tcl_Interp *interp){ | > > > > > > > > > > > > > > > | 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 | LINKVAR( MAX_DEFAULT_PAGE_SIZE ); { static const int cv_TEMP_STORE = SQLITE_TEMP_STORE; Tcl_LinkVar(interp, "TEMP_STORE", (char *)&(cv_TEMP_STORE), TCL_LINK_INT | TCL_LINK_READ_ONLY); } #ifdef _MSC_VER { static const int cv__MSC_VER = 1; Tcl_LinkVar(interp, "_MSC_VER", (char *)&(cv__MSC_VER), TCL_LINK_INT | TCL_LINK_READ_ONLY); } #endif #ifdef __GNUC__ { static const int cv___GNUC__ = 1; Tcl_LinkVar(interp, "__GNUC__", (char *)&(cv___GNUC__), TCL_LINK_INT | TCL_LINK_READ_ONLY); } #endif } /* ** Register commands with the TCL interpreter. */ int Sqliteconfig_Init(Tcl_Interp *interp){ |
︙ | ︙ |
Changes to src/test_func.c.
︙ | ︙ | |||
417 418 419 420 421 422 423 424 425 426 427 428 429 430 | sqlite3_result_error_nomem(pCtx); }else{ testHexToBin(zIn, zOut); sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free); } } #endif static int registerTestFunctions(sqlite3 *db){ static const struct { char *zName; signed char nArg; unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ void (*xFunc)(sqlite3_context*,int,sqlite3_value **); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | sqlite3_result_error_nomem(pCtx); }else{ testHexToBin(zIn, zOut); sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free); } } #endif /* ** SQL function: real2hex(X) ** ** If argument X is a real number, then convert it into a string which is ** the big-endian hexadecimal representation of the ieee754 encoding of ** that number. If X is not a real number, return NULL. */ static void real2hex( sqlite3_context *context, int argc, sqlite3_value **argv ){ union { sqlite3_uint64 i; double r; unsigned char x[8]; } v; char zOut[20]; int i; int bigEndian; v.i = 1; bigEndian = v.x[0]==0; v.r = sqlite3_value_double(argv[0]); for(i=0; i<8; i++){ if( bigEndian ){ zOut[i*2] = "0123456789abcdef"[v.x[i]>>4]; zOut[i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; }else{ zOut[14-i*2] = "0123456789abcdef"[v.x[i]>>4]; zOut[14-i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; } } zOut[16] = 0; sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); } static int registerTestFunctions(sqlite3 *db){ static const struct { char *zName; signed char nArg; unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ void (*xFunc)(sqlite3_context*,int,sqlite3_value **); |
︙ | ︙ | |||
440 441 442 443 444 445 446 447 448 449 450 451 452 453 | { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count}, { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, { "test_error", 1, SQLITE_UTF8, test_error}, { "test_error", 2, SQLITE_UTF8, test_error}, { "test_eval", 1, SQLITE_UTF8, test_eval}, { "test_isolation", 2, SQLITE_UTF8, test_isolation}, { "test_counter", 1, SQLITE_UTF8, counterFunc}, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); } | > | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count}, { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, { "test_error", 1, SQLITE_UTF8, test_error}, { "test_error", 2, SQLITE_UTF8, test_error}, { "test_eval", 1, SQLITE_UTF8, test_eval}, { "test_isolation", 2, SQLITE_UTF8, test_isolation}, { "test_counter", 1, SQLITE_UTF8, counterFunc}, { "real2hex", 1, SQLITE_UTF8, real2hex}, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); } |
︙ | ︙ |
Changes to src/test_quota.c.
︙ | ︙ | |||
44 45 46 47 48 49 50 | #define sqlite3_mutex_notheld(X) ((void)(X),1) #endif /* SQLITE_THREADSAFE==0 */ /* ** Figure out if we are dealing with Unix, Windows, or some other ** operating system. After the following block of preprocess macros, | | < < < < < < < < < < | 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 | #define sqlite3_mutex_notheld(X) ((void)(X),1) #endif /* SQLITE_THREADSAFE==0 */ /* ** Figure out if we are dealing with Unix, Windows, or some other ** operating system. After the following block of preprocess macros, ** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER ** will defined to either 1 or 0. One of the four will be 1. The other ** three will be 0. */ #if defined(SQLITE_OS_OTHER) # if SQLITE_OS_OTHER==1 # undef SQLITE_OS_UNIX # define SQLITE_OS_UNIX 0 # undef SQLITE_OS_WIN # define SQLITE_OS_WIN 0 # else # undef SQLITE_OS_OTHER # endif #endif #if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) # define SQLITE_OS_OTHER 0 # ifndef SQLITE_OS_WIN # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) \ || defined(__MINGW32__) || defined(__BORLANDC__) # define SQLITE_OS_WIN 1 # define SQLITE_OS_UNIX 0 # else # define SQLITE_OS_WIN 0 # define SQLITE_OS_UNIX 1 # endif # else # define SQLITE_OS_UNIX 0 # endif #else # ifndef SQLITE_OS_WIN # define SQLITE_OS_WIN 0 # endif #endif |
︙ | ︙ |
Changes to src/test_spellfix.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* ** 2012 April 10 ** ** 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. ** ************************************************************************* ** | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | > | | | | | | > | | | | | | < | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < > | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > | > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > < | | | | | | > > > | 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 | /* ** 2012 April 10 ** ** 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 module implements the spellfix1 VIRTUAL TABLE that can be used ** to search a large vocabulary for close matches. See separate ** documentation files (spellfix1.wiki and editdist3.wiki) for details. */ #if SQLITE_CORE # include "sqliteInt.h" #else # include <string.h> # include <stdio.h> # include <stdlib.h> # include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #endif /* !SQLITE_CORE */ #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 ** 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 'W' Letter W at the beginning of a word ** 10 'Y' Letter Y at the beginning of a word. ** 11 '9' Digits: 0 1 2 3 4 5 6 7 8 9 ** 12 ' ' White space ** 13 '?' 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_W 9 #define CCLASS_Y 10 #define CCLASS_DIGIT 11 #define CCLASS_SPACE 12 #define CCLASS_OTHER 13 /* ** The following table gives the character class for non-initial ASCII ** characters. */ static const unsigned char midClass[] = { /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE, /* */ CCLASS_SPACE, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE, /* ! */ CCLASS_OTHER, /* " */ CCLASS_OTHER, /* # */ CCLASS_OTHER, /* $ */ CCLASS_OTHER, /* % */ CCLASS_OTHER, /* & */ CCLASS_OTHER, /* ' */ CCLASS_SILENT, /* ( */ CCLASS_OTHER, /* ) */ CCLASS_OTHER, /* * */ CCLASS_OTHER, /* + */ CCLASS_OTHER, /* , */ CCLASS_OTHER, /* - */ CCLASS_OTHER, /* . */ CCLASS_OTHER, /* / */ CCLASS_OTHER, /* 0 */ CCLASS_DIGIT, /* 1 */ CCLASS_DIGIT, /* 2 */ CCLASS_DIGIT, /* 3 */ CCLASS_DIGIT, /* 4 */ CCLASS_DIGIT, /* 5 */ CCLASS_DIGIT, /* 6 */ CCLASS_DIGIT, /* 7 */ CCLASS_DIGIT, /* 8 */ CCLASS_DIGIT, /* 9 */ CCLASS_DIGIT, /* : */ CCLASS_OTHER, /* ; */ 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_SILENT, /* 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_SILENT, /* 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 ** the letters H, W, and Y. */ static const unsigned char initClass[] = { /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE, /* */ CCLASS_SPACE, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_OTHER, /* */ CCLASS_SPACE, /* ! */ CCLASS_OTHER, /* " */ CCLASS_OTHER, /* # */ CCLASS_OTHER, /* $ */ CCLASS_OTHER, /* % */ CCLASS_OTHER, /* & */ CCLASS_OTHER, /* ' */ CCLASS_OTHER, /* ( */ CCLASS_OTHER, /* ) */ CCLASS_OTHER, /* * */ CCLASS_OTHER, /* + */ CCLASS_OTHER, /* , */ CCLASS_OTHER, /* - */ CCLASS_OTHER, /* . */ CCLASS_OTHER, /* / */ CCLASS_OTHER, /* 0 */ CCLASS_DIGIT, /* 1 */ CCLASS_DIGIT, /* 2 */ CCLASS_DIGIT, /* 3 */ CCLASS_DIGIT, /* 4 */ CCLASS_DIGIT, /* 5 */ CCLASS_DIGIT, /* 6 */ CCLASS_DIGIT, /* 7 */ CCLASS_DIGIT, /* 8 */ CCLASS_DIGIT, /* 9 */ CCLASS_DIGIT, /* : */ CCLASS_OTHER, /* ; */ 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_W, /* 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_W, /* 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[] = ".ABCDHLRMWY9 ?"; /* ** 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 ** * Omit vowels beside R and L ** * Omit T when followed by CH ** * Omit W when followed by R ** * Omit D when followed by J or G ** * Omit K in KN or G in GN at the beginning of a word ** ** Space to hold the result is obtained from sqlite3_malloc() ** ** Return NULL if memory allocation fails. */ static unsigned char *phoneticHash(const unsigned char *zIn, int nIn){ unsigned char *zOut = sqlite3_malloc( nIn + 1 ); int i; int nOut = 0; char cPrev = 0x77; char cPrevX = 0x77; const unsigned char *aClass = initClass; if( zOut==0 ) return 0; if( nIn>2 ){ switch( zIn[0] ){ case 'g': case 'k': { if( zIn[1]=='n' ){ zIn++; nIn--; } break; } } } for(i=0; i<nIn; i++){ unsigned char c = zIn[i]; if( i+1<nIn ){ if( c=='w' && zIn[i+1]=='r' ) continue; if( c=='d' && (zIn[i+1]=='j' || zIn[i+1]=='g') ) continue; if( i+2<nIn ){ if( c=='t' && zIn[i+1]=='c' && zIn[i+2]=='h' ) continue; } } c = aClass[c&0x7f]; if( c==CCLASS_SPACE ) continue; if( c==CCLASS_OTHER && cPrev!=CCLASS_DIGIT ) continue; aClass = midClass; if( c==CCLASS_VOWEL && (cPrevX==CCLASS_R || cPrevX==CCLASS_L) ){ continue; /* No vowels beside L or R */ } if( (c==CCLASS_R || c==CCLASS_L) && cPrevX==CCLASS_VOWEL ){ nOut--; /* No vowels beside L or R */ } cPrev = c; if( c==CCLASS_SILENT ) continue; cPrevX = c; c = className[c]; if( c!=zOut[nOut-1] ) zOut[nOut++] = c; } zOut[nOut] = 0; return zOut; } /* ** This is an SQL function wrapper around phoneticHash(). See ** the description of phoneticHash() for additional information. */ static void phoneticHashSqlFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zIn; unsigned char *zOut; zIn = sqlite3_value_text(argv[0]); if( zIn==0 ) return; zOut = phoneticHash(zIn, sqlite3_value_bytes(argv[0])); if( zOut==0 ){ sqlite3_result_error_nomem(context); }else{ sqlite3_result_text(context, (char*)zOut, -1, sqlite3_free); } } /* ** Return the character class number for a character given its ** context. */ static char characterClass(char cPrev, char c){ return cPrev==0 ? initClass[c&0x7f] : midClass[c&0x7f]; } /* ** Return the cost of inserting or deleting character c immediately ** following character cPrev. If cPrev==0, that means c is the first ** character of the word. */ static int insertOrDeleteCost(char cPrev, char c, char cNext){ char classC = characterClass(cPrev, c); char classCprev; if( classC==CCLASS_SILENT ){ /* Insert or delete "silent" characters such as H or W */ return 1; } if( cPrev==c ){ /* Repeated characters, or miss a repeat */ return 10; } if( classC==CCLASS_VOWEL && (cPrev=='r' || cNext=='r') ){ return 20; /* Insert a vowel before or after 'r' */ } classCprev = characterClass(cPrev, cPrev); if( classC==classCprev ){ if( classC==CCLASS_VOWEL ){ /* Remove or add a new vowel to a vowel cluster */ return 15; }else{ |
︙ | ︙ | |||
472 473 474 475 476 477 478 | /* differ only in case */ return 0; } classFrom = characterClass(cPrev, cFrom); classTo = characterClass(cPrev, cTo); if( classFrom==classTo ){ /* Same character class */ | | | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | /* differ only in case */ return 0; } classFrom = characterClass(cPrev, cFrom); classTo = characterClass(cPrev, cTo); if( classFrom==classTo ){ /* Same character class */ return 40; } if( classFrom>=CCLASS_B && classFrom<=CCLASS_Y && classTo>=CCLASS_B && classTo<=CCLASS_Y ){ /* Convert from one consonant to another, but in a different class */ return 75; } /* Any other subsitution */ |
︙ | ︙ | |||
495 496 497 498 499 500 501 502 | ** ** Smaller numbers mean a closer match. ** ** Negative values indicate an error: ** -1 One of the inputs is NULL ** -2 Non-ASCII characters on input ** -3 Unable to allocate memory */ | > > > > > > | > > | > | | | | | 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 | ** ** Smaller numbers mean a closer match. ** ** Negative values indicate an error: ** -1 One of the inputs is NULL ** -2 Non-ASCII characters on input ** -3 Unable to allocate memory ** ** If pnMatch is not NULL, then *pnMatch is set to the number of bytes ** of zB that matched the pattern in zA. If zA does not end with a '*', ** then this value is always the number of bytes in zB (i.e. strlen(zB)). ** If zA does end in a '*', then it is the number of bytes in the prefix ** of zB that was deemed to match zA. */ static int editdist1(const char *zA, const char *zB, int *pnMatch){ int nA, nB; /* Number of characters in zA[] and zB[] */ int xA, xB; /* Loop counters for zA[] and zB[] */ char cA, cB; /* Current character of zA and zB */ char cAprev, cBprev; /* Previous character of zA and zB */ char cAnext, cBnext; /* Next character in zA and zB */ int d; /* North-west cost value */ int dc = 0; /* North-west character value */ int res; /* Final result */ int *m; /* The cost matrix */ char *cx; /* Corresponding character values */ int *toFree = 0; /* Malloced space */ int mStack[60+15]; /* Stack space to use if not too much is needed */ int nMatch = 0; /* Early out if either input is NULL */ if( zA==0 || zB==0 ) return -1; /* Skip any common prefix */ while( zA[0] && zA[0]==zB[0] ){ dc = zA[0]; zA++; zB++; nMatch++; } if( pnMatch ) *pnMatch = nMatch; if( zA[0]==0 && zB[0]==0 ) return 0; #if 0 printf("A=\"%s\" B=\"%s\" dc=%c\n", zA, zB, dc?dc:' '); #endif /* Verify input strings and measure their lengths */ for(nA=0; zA[nA]; nA++){ if( zA[nA]&0x80 ) return -2; } for(nB=0; zB[nB]; nB++){ if( zB[nB]&0x80 ) return -2; } /* Special processing if either string is empty */ if( nA==0 ){ cBprev = dc; for(xB=res=0; (cB = zB[xB])!=0; xB++){ res += insertOrDeleteCost(cBprev, cB, zB[xB+1])/FINAL_INS_COST_DIV; cBprev = cB; } return res; } if( nB==0 ){ cAprev = dc; for(xA=res=0; (cA = zA[xA])!=0; xA++){ res += insertOrDeleteCost(cAprev, cA, zA[xA+1]); cAprev = cA; } return res; } /* A is a prefix of B */ if( zA[0]=='*' && zA[1]==0 ) return 0; |
︙ | ︙ | |||
563 564 565 566 567 568 569 570 571 | cx = (char*)&m[nB+1]; /* Compute the Wagner edit distance */ m[0] = 0; cx[0] = dc; cBprev = dc; for(xB=1; xB<=nB; xB++){ cB = zB[xB-1]; cx[xB] = cB; | > | > | > | | | 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 | cx = (char*)&m[nB+1]; /* Compute the Wagner edit distance */ m[0] = 0; cx[0] = dc; cBprev = dc; for(xB=1; xB<=nB; xB++){ cBnext = zB[xB]; cB = zB[xB-1]; cx[xB] = cB; m[xB] = m[xB-1] + insertOrDeleteCost(cBprev, cB, cBnext); cBprev = cB; } cAprev = dc; for(xA=1; xA<=nA; xA++){ int lastA = (xA==nA); cA = zA[xA-1]; cAnext = zA[xA]; if( cA=='*' && lastA ) break; d = m[0]; dc = cx[0]; m[0] = d + insertOrDeleteCost(cAprev, cA, cAnext); cBprev = 0; for(xB=1; xB<=nB; xB++){ int totalCost, insCost, delCost, subCost, ncx; cB = zB[xB-1]; cBnext = zB[xB]; /* Cost to insert cB */ insCost = insertOrDeleteCost(cx[xB-1], cB, cBnext); if( lastA ) insCost /= FINAL_INS_COST_DIV; /* Cost to delete cA */ delCost = insertOrDeleteCost(cx[xB], cA, cBnext); /* Cost to substitute cA->cB */ subCost = substituteCost(cx[xB-1], cA, cB); /* Best cost */ totalCost = insCost + m[xB-1]; ncx = cB; |
︙ | ︙ | |||
620 621 622 623 624 625 626 | cx[xB] = ncx; cBprev = cB; } cAprev = cA; } /* Free the wagner matrix and return the result */ | | | | | > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 855 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 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 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 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 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 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 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 1092 1093 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 | cx[xB] = ncx; cBprev = cB; } cAprev = cA; } /* Free the wagner matrix and return the result */ if( cA=='*' ){ res = m[1]; for(xB=1; xB<=nB; xB++){ if( m[xB]<res ){ res = m[xB]; if( pnMatch ) *pnMatch = xB+nMatch; } } }else{ res = m[nB]; /* In the current implementation, pnMatch is always NULL if zA does ** not end in "*" */ assert( pnMatch==0 ); } sqlite3_free(toFree); return res; } /* ** Function: editdist(A,B) ** ** Return the cost of transforming string A into string B. Both strings ** must be pure ASCII text. If A ends with '*' then it is assumed to be ** a prefix of B and extra characters on the end of B have minimal additional ** cost. */ static void editdistSqlFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int res = editdist1( (const char*)sqlite3_value_text(argv[0]), (const char*)sqlite3_value_text(argv[1]), 0); if( res<0 ){ if( res==(-3) ){ sqlite3_result_error_nomem(context); }else if( res==(-2) ){ sqlite3_result_error(context, "non-ASCII input to editdist()", -1); }else{ sqlite3_result_error(context, "NULL input to editdist()", -1); } }else{ sqlite3_result_int(context, res); } } /* End of the fixed-cost edit distance implementation ****************************************************************************** ***************************************************************************** ** Begin: Configurable cost unicode edit distance routines */ /* Forward declaration of structures */ typedef struct EditDist3Cost EditDist3Cost; typedef struct EditDist3Config EditDist3Config; typedef struct EditDist3Point EditDist3Point; typedef struct EditDist3From EditDist3From; typedef struct EditDist3FromString EditDist3FromString; typedef struct EditDist3To EditDist3To; typedef struct EditDist3ToString EditDist3ToString; typedef struct EditDist3Lang EditDist3Lang; /* ** An entry in the edit cost table */ struct EditDist3Cost { EditDist3Cost *pNext; /* Next cost element */ u8 nFrom; /* Number of bytes in aFrom */ u8 nTo; /* Number of bytes in aTo */ u16 iCost; /* Cost of this transformation */ char a[4] ; /* FROM string followed by TO string */ /* Additional TO and FROM string bytes appended as necessary */ }; /* ** Edit costs for a particular language ID */ struct EditDist3Lang { int iLang; /* Language ID */ int iInsCost; /* Default insertion cost */ int iDelCost; /* Default deletion cost */ int iSubCost; /* Default substitution cost */ EditDist3Cost *pCost; /* Costs */ }; /* ** The default EditDist3Lang object, with default costs. */ static const EditDist3Lang editDist3Lang = { 0, 100, 100, 150, 0 }; /* ** Complete configuration */ struct EditDist3Config { int nLang; /* Number of language IDs. Size of a[] */ EditDist3Lang *a; /* One for each distinct language ID */ }; /* ** Extra information about each character in the FROM string. */ struct EditDist3From { int nSubst; /* Number of substitution cost entries */ int nDel; /* Number of deletion cost entries */ int nByte; /* Number of bytes in this character */ EditDist3Cost **apSubst; /* Array of substitution costs for this element */ EditDist3Cost **apDel; /* Array of deletion cost entries */ }; /* ** A precompiled FROM string. * ** In the common case we expect the FROM string to be reused multiple times. ** In other words, the common case will be to measure the edit distance ** from a single origin string to multiple target strings. */ struct EditDist3FromString { char *z; /* The complete text of the FROM string */ int n; /* Number of characters in the FROM string */ int isPrefix; /* True if ends with '*' character */ EditDist3From *a; /* Extra info about each char of the FROM string */ }; /* ** Extra information about each character in the TO string. */ struct EditDist3To { int nIns; /* Number of insertion cost entries */ int nByte; /* Number of bytes in this character */ EditDist3Cost **apIns; /* Array of deletion cost entries */ }; /* ** A precompiled FROM string */ struct EditDist3ToString { char *z; /* The complete text of the TO string */ int n; /* Number of characters in the TO string */ EditDist3To *a; /* Extra info about each char of the TO string */ }; /* ** Clear or delete an instance of the object that records all edit-distance ** weights. */ static void editDist3ConfigClear(EditDist3Config *p){ int i; if( p==0 ) return; for(i=0; i<p->nLang; i++){ EditDist3Cost *pCost, *pNext; pCost = p->a[i].pCost; while( pCost ){ pNext = pCost->pNext; sqlite3_free(pCost); pCost = pNext; } } sqlite3_free(p->a); memset(p, 0, sizeof(*p)); } static void editDist3ConfigDelete(void *pIn){ EditDist3Config *p = (EditDist3Config*)pIn; editDist3ConfigClear(p); sqlite3_free(p); } /* ** Load all edit-distance weights from a table. */ static int editDist3ConfigLoad( EditDist3Config *p, /* The edit distance configuration to load */ sqlite3 *db, /* Load from this database */ const char *zTable /* Name of the table from which to load */ ){ sqlite3_stmt *pStmt; int rc, rc2; char *zSql; int iLangPrev = -9999; EditDist3Lang *pLang; zSql = sqlite3_mprintf("SELECT iLang, cFrom, cTo, iCost" " FROM \"%w\" WHERE iLang>=0 ORDER BY iLang", zTable); if( zSql==0 ) return SQLITE_NOMEM; rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ) return rc; editDist3ConfigClear(p); while( sqlite3_step(pStmt)==SQLITE_ROW ){ int iLang = sqlite3_column_int(pStmt, 0); const char *zFrom = (const char*)sqlite3_column_text(pStmt, 1); int nFrom = zFrom ? sqlite3_column_bytes(pStmt, 1) : 0; const char *zTo = (const char*)sqlite3_column_text(pStmt, 2); int nTo = zTo ? sqlite3_column_bytes(pStmt, 2) : 0; int iCost = sqlite3_column_int(pStmt, 3); assert( zFrom!=0 || nFrom==0 ); assert( zTo!=0 || nTo==0 ); if( nFrom>100 || nTo>100 ) continue; if( iCost<0 ) continue; if( iLang!=iLangPrev ){ EditDist3Lang *pNew; pNew = sqlite3_realloc(p->a, (p->nLang+1)*sizeof(p->a[0])); if( pNew==0 ){ rc = SQLITE_NOMEM; break; } p->a = pNew; pLang = &p->a[p->nLang]; p->nLang++; pLang->iLang = iLang; pLang->iInsCost = 100; pLang->iDelCost = 100; pLang->iSubCost = 150; pLang->pCost = 0; iLangPrev = iLang; } if( nFrom==1 && zFrom[0]=='?' && nTo==0 ){ pLang->iDelCost = iCost; }else if( nFrom==0 && nTo==1 && zTo[0]=='?' ){ pLang->iInsCost = iCost; }else if( nFrom==1 && nTo==1 && zFrom[0]=='?' && zTo[0]=='?' ){ pLang->iSubCost = iCost; }else{ EditDist3Cost *pCost; int nExtra = nFrom + nTo - 4; if( nExtra<0 ) nExtra = 0; pCost = sqlite3_malloc( sizeof(*pCost) + nExtra ); if( pCost==0 ){ rc = SQLITE_NOMEM; break; } pCost->nFrom = nFrom; pCost->nTo = nTo; pCost->iCost = iCost; memcpy(pCost->a, zFrom, nFrom); memcpy(pCost->a + nFrom, zTo, nTo); pCost->pNext = pLang->pCost; pLang->pCost = pCost; } } rc2 = sqlite3_finalize(pStmt); if( rc==SQLITE_OK ) rc = rc2; return rc; } /* ** Return the length (in bytes) of a utf-8 character. Or return a maximum ** of N. */ static int utf8Len(unsigned char c, int N){ int len = 1; if( c>0x7f ){ if( (c&0xe0)==0xc0 ){ len = 2; }else if( (c&0xf0)==0xe0 ){ len = 3; }else{ len = 4; } } if( len>N ) len = N; return len; } /* ** Return TRUE (non-zero) of the To side of the given cost matches ** the given string. */ static int matchTo(EditDist3Cost *p, const char *z, int n){ if( p->nTo>n ) return 0; if( memcmp(p->a+p->nFrom, z, p->nTo)!=0 ) return 0; return 1; } /* ** Return TRUE (non-zero) of the To side of the given cost matches ** the given string. */ static int matchFrom(EditDist3Cost *p, const char *z, int n){ assert( p->nFrom<=n ); if( memcmp(p->a, z, p->nFrom)!=0 ) return 0; return 1; } /* ** Return TRUE (non-zero) of the next FROM character and the next TO ** character are the same. */ static int matchFromTo( EditDist3FromString *pStr, /* Left hand string */ int n1, /* Index of comparison character on the left */ const char *z2, /* Right-handl comparison character */ int n2 /* Bytes remaining in z2[] */ ){ int b1 = pStr->a[n1].nByte; if( b1>n2 ) return 0; if( memcmp(pStr->z+n1, z2, b1)!=0 ) return 0; return 1; } /* ** Delete an EditDist3FromString objecct */ static void editDist3FromStringDelete(EditDist3FromString *p){ int i; if( p ){ for(i=0; i<p->n; i++){ sqlite3_free(p->a[i].apDel); sqlite3_free(p->a[i].apSubst); } sqlite3_free(p); } } /* ** Create a EditDist3FromString object. */ static EditDist3FromString *editDist3FromStringNew( const EditDist3Lang *pLang, const char *z, int n ){ EditDist3FromString *pStr; EditDist3Cost *p; int i; if( z==0 ) return 0; if( n<0 ) n = (int)strlen(z); pStr = sqlite3_malloc( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 ); if( pStr==0 ) return 0; pStr->a = (EditDist3From*)&pStr[1]; memset(pStr->a, 0, sizeof(pStr->a[0])*n); pStr->n = n; pStr->z = (char*)&pStr->a[n]; memcpy(pStr->z, z, n+1); if( n && z[n-1]=='*' ){ pStr->isPrefix = 1; n--; pStr->n--; pStr->z[n] = 0; }else{ pStr->isPrefix = 0; } for(i=0; i<n; i++){ EditDist3From *pFrom = &pStr->a[i]; memset(pFrom, 0, sizeof(*pFrom)); pFrom->nByte = utf8Len((unsigned char)z[i], n-i); for(p=pLang->pCost; p; p=p->pNext){ EditDist3Cost **apNew; if( i+p->nFrom>n ) continue; if( matchFrom(p, z+i, n-i)==0 ) continue; if( p->nTo==0 ){ apNew = sqlite3_realloc(pFrom->apDel, sizeof(*apNew)*(pFrom->nDel+1)); if( apNew==0 ) break; pFrom->apDel = apNew; apNew[pFrom->nDel++] = p; }else{ apNew = sqlite3_realloc(pFrom->apSubst, sizeof(*apNew)*(pFrom->nSubst+1)); if( apNew==0 ) break; pFrom->apSubst = apNew; apNew[pFrom->nSubst++] = p; } } if( p ){ editDist3FromStringDelete(pStr); pStr = 0; break; } } return pStr; } /* ** Update entry m[i] such that it is the minimum of its current value ** and m[j]+iCost. ** ** If the iCost is 1,000,000 or greater, then consider the cost to be ** infinite and skip the update. */ static void updateCost( unsigned int *m, int i, int j, int iCost ){ int b; if( iCost<10000 ){ b = m[j] + iCost; if( b<m[i] ) m[i] = b; } } /* Compute the edit distance between two strings. ** ** If an error occurs, return a negative number which is the error code. ** ** If pnMatch is not NULL, then *pnMatch is set to the number of characters ** (not bytes) in z2 that matched the search pattern in *pFrom. If pFrom does ** not contain the pattern for a prefix-search, then this is always the number ** of characters in z2. If pFrom does contain a prefix search pattern, then ** it is the number of characters in the prefix of z2 that was deemed to ** match pFrom. */ static int editDist3Core( EditDist3FromString *pFrom, /* The FROM string */ const char *z2, /* The TO string */ int n2, /* Length of the TO string */ const EditDist3Lang *pLang, /* Edit weights for a particular language ID */ int *pnMatch /* OUT: Characters in matched prefix */ ){ int k, n; int i1, b1; int i2, b2; EditDist3FromString f = *pFrom; EditDist3To *a2; unsigned int *m; int szRow; EditDist3Cost *p; int res; /* allocate the Wagner matrix and the aTo[] array for the TO string */ n = (f.n+1)*(n2+1); n = (n+1)&~1; m = sqlite3_malloc( n*sizeof(m[0]) + sizeof(a2[0])*n2 ); if( m==0 ) return -1; /* Out of memory */ a2 = (EditDist3To*)&m[n]; memset(a2, 0, sizeof(a2[0])*n2); /* Fill in the a1[] matrix for all characters of the TO string */ for(i2=0; i2<n2; i2++){ a2[i2].nByte = utf8Len((unsigned char)z2[i2], n2-i2); for(p=pLang->pCost; p; p=p->pNext){ EditDist3Cost **apNew; if( p->nFrom>0 ) continue; if( i2+p->nTo>n2 ) continue; if( matchTo(p, z2+i2, n2-i2)==0 ) continue; a2[i2].nIns++; apNew = sqlite3_realloc(a2[i2].apIns, sizeof(*apNew)*a2[i2].nIns); if( apNew==0 ){ res = -1; /* Out of memory */ goto editDist3Abort; } a2[i2].apIns = apNew; a2[i2].apIns[a2[i2].nIns-1] = p; } } /* Prepare to compute the minimum edit distance */ szRow = f.n+1; memset(m, 0x01, (n2+1)*szRow*sizeof(m[0])); m[0] = 0; /* First fill in the top-row of the matrix with FROM deletion costs */ for(i1=0; i1<f.n; i1 += b1){ b1 = f.a[i1].nByte; updateCost(m, i1+b1, i1, pLang->iDelCost); for(k=0; k<f.a[i1].nDel; k++){ p = f.a[i1].apDel[k]; updateCost(m, i1+p->nFrom, i1, p->iCost); } } /* Fill in all subsequent rows, top-to-bottom, left-to-right */ for(i2=0; i2<n2; i2 += b2){ int rx; /* Starting index for current row */ int rxp; /* Starting index for previous row */ b2 = a2[i2].nByte; rx = szRow*(i2+b2); rxp = szRow*i2; updateCost(m, rx, rxp, pLang->iInsCost); for(k=0; k<a2[i2].nIns; k++){ p = a2[i2].apIns[k]; updateCost(m, szRow*(i2+p->nTo), rxp, p->iCost); } for(i1=0; i1<f.n; i1+=b1){ int cx; /* Index of current cell */ int cxp; /* Index of cell immediately to the left */ int cxd; /* Index of cell to the left and one row above */ int cxu; /* Index of cell immediately above */ b1 = f.a[i1].nByte; cxp = rx + i1; cx = cxp + b1; cxd = rxp + i1; cxu = cxd + b1; updateCost(m, cx, cxp, pLang->iDelCost); for(k=0; k<f.a[i1].nDel; k++){ p = f.a[i1].apDel[k]; updateCost(m, cxp+p->nFrom, cxp, p->iCost); } updateCost(m, cx, cxu, pLang->iInsCost); if( matchFromTo(&f, i1, z2+i2, n2-i2) ){ updateCost(m, cx, cxd, 0); } updateCost(m, cx, cxd, pLang->iSubCost); for(k=0; k<f.a[i1].nSubst; k++){ p = f.a[i1].apSubst[k]; if( matchTo(p, z2+i2, n2-i2) ){ updateCost(m, cxd+p->nFrom+szRow*p->nTo, cxd, p->iCost); } } } } #if 0 /* Enable for debugging */ printf(" ^"); for(i1=0; i1<f.n; i1++) printf(" %c-%2x", f.z[i1], f.z[i1]&0xff); printf("\n ^:"); for(i1=0; i1<szRow; i1++){ int v = m[i1]; if( v>9999 ) printf(" ****"); else printf(" %4d", v); } printf("\n"); for(i2=0; i2<n2; i2++){ printf("%c-%02x:", z2[i2], z2[i2]&0xff); for(i1=0; i1<szRow; i1++){ int v = m[(i2+1)*szRow+i1]; if( v>9999 ) printf(" ****"); else printf(" %4d", v); } printf("\n"); } #endif /* Free memory allocations and return the result */ res = (int)m[szRow*(n2+1)-1]; n = n2; if( f.isPrefix ){ for(i2=1; i2<=n2; i2++){ int b = m[szRow*i2-1]; if( b<=res ){ res = b; n = i2 - 1; } } } if( pnMatch ){ int nExtra = 0; for(k=0; k<n; k++){ if( (z2[k] & 0xc0)==0x80 ) nExtra++; } *pnMatch = n - nExtra; } editDist3Abort: for(i2=0; i2<n2; i2++) sqlite3_free(a2[i2].apIns); sqlite3_free(m); return res; } /* ** Get an appropriate EditDist3Lang object. */ static const EditDist3Lang *editDist3FindLang( EditDist3Config *pConfig, int iLang ){ int i; for(i=0; i<pConfig->nLang; i++){ if( pConfig->a[i].iLang==iLang ) return &pConfig->a[i]; } return &editDist3Lang; } /* ** Function: editdist3(A,B,iLang) ** editdist3(tablename) ** ** Return the cost of transforming string A into string B using edit ** weights for iLang. ** ** The second form loads edit weights into memory from a table. */ static void editDist3SqlFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ EditDist3Config *pConfig = (EditDist3Config*)sqlite3_user_data(context); sqlite3 *db = sqlite3_context_db_handle(context); int rc; if( argc==1 ){ const char *zTable = (const char*)sqlite3_value_text(argv[0]); rc = editDist3ConfigLoad(pConfig, db, zTable); if( rc ) sqlite3_result_error_code(context, rc); }else{ const char *zA = (const char*)sqlite3_value_text(argv[0]); const char *zB = (const char*)sqlite3_value_text(argv[1]); int nA = sqlite3_value_bytes(argv[0]); int nB = sqlite3_value_bytes(argv[1]); int iLang = argc==3 ? sqlite3_value_int(argv[2]) : 0; const EditDist3Lang *pLang = editDist3FindLang(pConfig, iLang); EditDist3FromString *pFrom; int dist; pFrom = editDist3FromStringNew(pLang, zA, nA); if( pFrom==0 ){ sqlite3_result_error_nomem(context); return; } dist = editDist3Core(pFrom, zB, nB, pLang, 0); editDist3FromStringDelete(pFrom); if( dist==(-1) ){ sqlite3_result_error_nomem(context); }else{ sqlite3_result_int(context, dist); } } } /* ** Register the editDist3 function with SQLite */ static int editDist3Install(sqlite3 *db){ int rc; EditDist3Config *pConfig = sqlite3_malloc( sizeof(*pConfig) ); if( pConfig==0 ) return SQLITE_NOMEM; memset(pConfig, 0, sizeof(*pConfig)); rc = sqlite3_create_function_v2(db, "editdist3", 2, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function_v2(db, "editdist3", 3, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function_v2(db, "editdist3", 1, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0, editDist3ConfigDelete); }else{ sqlite3_free(pConfig); } return rc; } /* End configurable cost unicode edit distance routines ****************************************************************************** ****************************************************************************** ** Begin transliterate unicode-to-ascii implementation */ #if !SQLITE_AMALGAMATION /* ** This lookup table is used to help decode the first byte of ** a multi-byte UTF8 character. */ static const unsigned char sqlite3Utf8Trans1[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
︙ | ︙ | |||
683 684 685 686 687 688 689 | /* ** Return the value of the first UTF-8 character in the string. */ static int utf8Read(const unsigned char *z, int n, int *pSize){ int c, i; | > > | > > > > > > > > > > > > > > > | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 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 | /* ** Return the value of the first UTF-8 character in the string. */ static int utf8Read(const unsigned char *z, int n, int *pSize){ int c, i; /* All callers to this routine (in the current implementation) ** always have n>0. */ if( NEVER(n==0) ){ c = i = 0; }else{ c = z[0]; i = 1; if( c>=0xc0 ){ c = sqlite3Utf8Trans1[c-0xc0]; while( i<n && (z[i] & 0xc0)==0x80 ){ c = (c<<6) + (0x3f & z[i++]); } } } *pSize = i; return c; } /* ** Return the number of characters in the utf-8 string in the nIn byte ** buffer pointed to by zIn. */ static int utf8Charlen(const char *zIn, int nIn){ int i; int nChar = 0; for(i=0; i<nIn; nChar++){ int sz; utf8Read((const unsigned char *)&zIn[i], nIn-i, &sz); i += sz; } return nChar; } /* ** Table of translations from unicode characters into ASCII. */ static const struct { unsigned short int cFrom; unsigned char cTo0, cTo1; |
︙ | ︙ | |||
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 | { 0x0423, 0x55, 0x00 }, /* У to U */ { 0x0424, 0x46, 0x00 }, /* Ф to F */ { 0x0425, 0x4b, 0x68 }, /* Х to Kh */ { 0x0426, 0x54, 0x63 }, /* Ц to Tc */ { 0x0427, 0x43, 0x68 }, /* Ч to Ch */ { 0x0428, 0x53, 0x68 }, /* Ш to Sh */ { 0x0429, 0x53, 0x68 }, /* Щ to Shch */ { 0x042B, 0x59, 0x00 }, /* Ы to Y */ { 0x042D, 0x45, 0x00 }, /* Э to E */ { 0x042E, 0x49, 0x75 }, /* Ю to Iu */ { 0x042F, 0x49, 0x61 }, /* Я to Ia */ { 0x0430, 0x61, 0x00 }, /* а to a */ { 0x0431, 0x62, 0x00 }, /* б to b */ { 0x0432, 0x76, 0x00 }, /* в to v */ { 0x0433, 0x67, 0x00 }, /* г to g */ | > > | 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 | { 0x0423, 0x55, 0x00 }, /* У to U */ { 0x0424, 0x46, 0x00 }, /* Ф to F */ { 0x0425, 0x4b, 0x68 }, /* Х to Kh */ { 0x0426, 0x54, 0x63 }, /* Ц to Tc */ { 0x0427, 0x43, 0x68 }, /* Ч to Ch */ { 0x0428, 0x53, 0x68 }, /* Ш to Sh */ { 0x0429, 0x53, 0x68 }, /* Щ to Shch */ { 0x042A, 0x61, 0x00 }, /* to A */ { 0x042B, 0x59, 0x00 }, /* Ы to Y */ { 0x042C, 0x59, 0x00 }, /* to Y */ { 0x042D, 0x45, 0x00 }, /* Э to E */ { 0x042E, 0x49, 0x75 }, /* Ю to Iu */ { 0x042F, 0x49, 0x61 }, /* Я to Ia */ { 0x0430, 0x61, 0x00 }, /* а to a */ { 0x0431, 0x62, 0x00 }, /* б to b */ { 0x0432, 0x76, 0x00 }, /* в to v */ { 0x0433, 0x67, 0x00 }, /* г to g */ |
︙ | ︙ | |||
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 | { 0x0443, 0x75, 0x00 }, /* у to u */ { 0x0444, 0x66, 0x00 }, /* ф to f */ { 0x0445, 0x6b, 0x68 }, /* х to kh */ { 0x0446, 0x74, 0x63 }, /* ц to tc */ { 0x0447, 0x63, 0x68 }, /* ч to ch */ { 0x0448, 0x73, 0x68 }, /* ш to sh */ { 0x0449, 0x73, 0x68 }, /* щ to shch */ { 0x044B, 0x79, 0x00 }, /* ы to y */ { 0x044D, 0x65, 0x00 }, /* э to e */ { 0x044E, 0x69, 0x75 }, /* ю to iu */ { 0x044F, 0x69, 0x61 }, /* я to ia */ { 0x0450, 0x65, 0x00 }, /* ѐ to e */ { 0x0451, 0x65, 0x00 }, /* ё to e */ { 0x0452, 0x64, 0x00 }, /* ђ to d */ { 0x0453, 0x67, 0x00 }, /* ѓ to g */ | > > | 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 | { 0x0443, 0x75, 0x00 }, /* у to u */ { 0x0444, 0x66, 0x00 }, /* ф to f */ { 0x0445, 0x6b, 0x68 }, /* х to kh */ { 0x0446, 0x74, 0x63 }, /* ц to tc */ { 0x0447, 0x63, 0x68 }, /* ч to ch */ { 0x0448, 0x73, 0x68 }, /* ш to sh */ { 0x0449, 0x73, 0x68 }, /* щ to shch */ { 0x044A, 0x61, 0x00 }, /* to a */ { 0x044B, 0x79, 0x00 }, /* ы to y */ { 0x044C, 0x79, 0x00 }, /* to y */ { 0x044D, 0x65, 0x00 }, /* э to e */ { 0x044E, 0x69, 0x75 }, /* ю to iu */ { 0x044F, 0x69, 0x61 }, /* я to ia */ { 0x0450, 0x65, 0x00 }, /* ѐ to e */ { 0x0451, 0x65, 0x00 }, /* ё to e */ { 0x0452, 0x64, 0x00 }, /* ђ to d */ { 0x0453, 0x67, 0x00 }, /* ѓ to g */ |
︙ | ︙ | |||
1105 1106 1107 1108 1109 1110 1111 | ** The returned string might contain more characters than the input. ** ** Space to hold the returned string comes from sqlite3_malloc() and ** should be freed by the caller. */ static unsigned char *transliterate(const unsigned char *zIn, int nIn){ unsigned char *zOut = sqlite3_malloc( nIn*4 + 1 ); | | | | | 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 | ** The returned string might contain more characters than the input. ** ** Space to hold the returned string comes from sqlite3_malloc() and ** should be freed by the caller. */ static unsigned char *transliterate(const unsigned char *zIn, int nIn){ unsigned char *zOut = sqlite3_malloc( nIn*4 + 1 ); int c, sz, nOut; if( zOut==0 ) return 0; nOut = 0; while( nIn>0 ){ c = utf8Read(zIn, nIn, &sz); zIn += sz; nIn -= sz; if( c<=127 ){ zOut[nOut++] = c; }else{ int xTop, xBtm, x; |
︙ | ︙ | |||
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 | } if( c ) zOut[nOut++] = '?'; } } zOut[nOut] = 0; return zOut; } /* ** spellfix1_translit(X) ** ** Convert a string that contains non-ASCII Roman characters into ** pure ASCII. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | } if( c ) zOut[nOut++] = '?'; } } zOut[nOut] = 0; return zOut; } /* ** Return the number of characters in the shortest prefix of the input ** string that transliterates to an ASCII string nTrans bytes or longer. ** Or, if the transliteration of the input string is less than nTrans ** bytes in size, return the number of characters in the input string. */ static int translen_to_charlen(const char *zIn, int nIn, int nTrans){ int i, c, sz, nOut; int nChar; i = nOut = 0; for(nChar=0; i<nIn && nOut<nTrans; nChar++){ c = utf8Read((const unsigned char *)&zIn[i], nIn-i, &sz); i += sz; nOut++; if( c>=128 ){ int xTop, xBtm, x; xTop = sizeof(translit)/sizeof(translit[0]) - 1; xBtm = 0; while( xTop>=xBtm ){ x = (xTop + xBtm)/2; if( translit[x].cFrom==c ){ if( translit[x].cTo1 ) nOut++; if( c==0x0429 || c== 0x0449 ) nOut += 2; break; }else if( translit[x].cFrom>c ){ xTop = x-1; }else{ xBtm = x+1; } } } } return nChar; } /* ** spellfix1_translit(X) ** ** Convert a string that contains non-ASCII Roman characters into ** pure ASCII. */ |
︙ | ︙ | |||
1218 1219 1220 1221 1222 1223 1224 | case SCRIPT_CYRILLIC: res = 220; break; case SCRIPT_GREEK: res = 200; break; default: res = 998; break; } sqlite3_result_int(context, res); } | > | < | > > > > > > > > | | | | > > | > | > | > > | 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 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 | case SCRIPT_CYRILLIC: res = 220; break; case SCRIPT_GREEK: res = 200; break; default: res = 998; break; } sqlite3_result_int(context, res); } /* End transliterate ****************************************************************************** ****************************************************************************** ** Begin spellfix1 virtual table. */ /* Maximum length of a phonehash used for querying the shadow table */ #define SPELLFIX_MX_HASH 8 /* Maximum number of hash strings to examine per query */ #define SPELLFIX_MX_RUN 1 typedef struct spellfix1_vtab spellfix1_vtab; typedef struct spellfix1_cursor spellfix1_cursor; /* Fuzzy-search virtual table object */ struct spellfix1_vtab { sqlite3_vtab base; /* Base class - must be first */ sqlite3 *db; /* Database connection */ char *zDbName; /* Name of database holding this table */ char *zTableName; /* Name of the virtual table */ char *zCostTable; /* Table holding edit-distance cost numbers */ EditDist3Config *pConfig3; /* Parsed edit distance costs */ }; /* Fuzzy-search cursor object */ struct spellfix1_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ spellfix1_vtab *pVTab; /* The table to which this cursor belongs */ char *zPattern; /* rhs of MATCH clause */ int nRow; /* Number of rows of content */ int nAlloc; /* Number of allocated rows */ int iRow; /* Current row of content */ int iLang; /* Value of the langid= constraint */ int iTop; /* Value of the top= constraint */ int iScope; /* Value of the scope= constraint */ int nSearch; /* Number of vocabulary items checked */ sqlite3_stmt *pFullScan; /* Shadow query for a full table scan */ struct spellfix1_row { /* For each row of content */ sqlite3_int64 iRowid; /* Rowid for this row */ char *zWord; /* Text for this row */ int iRank; /* Rank for this row */ int iDistance; /* Distance from pattern for this row */ int iScore; /* Score for sorting */ int iMatchlen; /* Value of matchlen column (or -1) */ char zHash[SPELLFIX_MX_HASH]; /* the phonehash used for this match */ } *a; }; /* ** Construct one or more SQL statements from the format string given ** and then evaluate those statements. The success code is written ** into *pRc. |
︙ | ︙ | |||
1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 | if( isDestroy ){ sqlite3 *db = p->db; spellfix1DbExec(&rc, db, "DROP TABLE IF EXISTS \"%w\".\"%w_vocab\"", p->zDbName, p->zTableName); } if( rc==SQLITE_OK ){ sqlite3_free(p->zTableName); sqlite3_free(p); } return rc; } static int spellfix1Disconnect(sqlite3_vtab *pVTab){ return spellfix1Uninit(0, pVTab); } static int spellfix1Destroy(sqlite3_vtab *pVTab){ return spellfix1Uninit(1, pVTab); } /* ** xConnect/xCreate method for the spellfix1 module. Arguments are: ** ** argv[0] -> module name ("spellfix1") ** argv[1] -> database name ** argv[2] -> table name | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > < < < < < < | | | | | | | | | | | | | | | > | | | > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | > > > > > | > > | | > > > > > | > | 1820 1821 1822 1823 1824 1825 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 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 | if( isDestroy ){ sqlite3 *db = p->db; spellfix1DbExec(&rc, db, "DROP TABLE IF EXISTS \"%w\".\"%w_vocab\"", p->zDbName, p->zTableName); } if( rc==SQLITE_OK ){ sqlite3_free(p->zTableName); editDist3ConfigDelete(p->pConfig3); sqlite3_free(p->zCostTable); sqlite3_free(p); } return rc; } static int spellfix1Disconnect(sqlite3_vtab *pVTab){ return spellfix1Uninit(0, pVTab); } static int spellfix1Destroy(sqlite3_vtab *pVTab){ return spellfix1Uninit(1, pVTab); } /* ** Make a copy of a string. Remove leading and trailing whitespace ** and dequote it. */ static char *spellfix1Dequote(const char *zIn){ char *zOut; int i, j; char c; while( isspace(zIn[0]) ) zIn++; zOut = sqlite3_mprintf("%s", zIn); if( zOut==0 ) return 0; i = (int)strlen(zOut); #if 0 /* The parser will never leave spaces at the end */ while( i>0 && isspace(zOut[i-1]) ){ i--; } #endif zOut[i] = 0; c = zOut[0]; if( c=='\'' || c=='"' ){ for(i=1, j=0; ALWAYS(zOut[i]); i++){ zOut[j++] = zOut[i]; if( zOut[i]==c ){ if( zOut[i+1]==c ){ i++; }else{ zOut[j-1] = 0; break; } } } } return zOut; } /* ** xConnect/xCreate method for the spellfix1 module. Arguments are: ** ** argv[0] -> module name ("spellfix1") ** argv[1] -> database name ** argv[2] -> table name ** argv[3].. -> optional arguments (i.e. "edit_cost_table" parameter) */ static int spellfix1Init( int isCreate, sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr ){ spellfix1_vtab *pNew = 0; const char *zModule = argv[0]; const char *zDbName = argv[1]; const char *zTableName = argv[2]; int nDbName; int rc = SQLITE_OK; int i; nDbName = 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); pNew->zTableName = sqlite3_mprintf("%s", zTableName); pNew->db = db; if( pNew->zTableName==0 ){ rc = SQLITE_NOMEM; }else{ rc = sqlite3_declare_vtab(db, "CREATE TABLE x(word,rank,distance,langid, " "score, matchlen, phonehash HIDDEN, " "top HIDDEN, scope HIDDEN, srchcnt HIDDEN, " "soundslike HIDDEN, command HIDDEN)" ); #define SPELLFIX_COL_WORD 0 #define SPELLFIX_COL_RANK 1 #define SPELLFIX_COL_DISTANCE 2 #define SPELLFIX_COL_LANGID 3 #define SPELLFIX_COL_SCORE 4 #define SPELLFIX_COL_MATCHLEN 5 #define SPELLFIX_COL_PHONEHASH 6 #define SPELLFIX_COL_TOP 7 #define SPELLFIX_COL_SCOPE 8 #define SPELLFIX_COL_SRCHCNT 9 #define SPELLFIX_COL_SOUNDSLIKE 10 #define SPELLFIX_COL_COMMAND 11 } if( rc==SQLITE_OK && isCreate ){ sqlite3_uint64 r; spellfix1DbExec(&rc, db, "CREATE TABLE IF NOT EXISTS \"%w\".\"%w_vocab\"(\n" " id INTEGER PRIMARY KEY,\n" " rank INT,\n" " langid INT,\n" " word TEXT,\n" " k1 TEXT,\n" " k2 TEXT\n" ");\n", zDbName, zTableName ); sqlite3_randomness(sizeof(r), &r); spellfix1DbExec(&rc, db, "CREATE INDEX IF NOT EXISTS \"%w\".\"%w_index_%llx\" " "ON \"%w_vocab\"(langid,k2);", zDbName, zModule, r, zTableName ); } for(i=3; rc==SQLITE_OK && i<argc; i++){ if( memcmp(argv[i],"edit_cost_table=",16)==0 && pNew->zCostTable==0 ){ pNew->zCostTable = spellfix1Dequote(&argv[i][16]); if( pNew->zCostTable==0 ) rc = SQLITE_NOMEM; continue; } *pzErr = sqlite3_mprintf("bad argument to spellfix1(): \"%s\"", argv[i]); rc = SQLITE_ERROR; } } if( rc && pNew ){ *ppVTab = 0; spellfix1Uninit(0, &pNew->base); }else{ *ppVTab = (sqlite3_vtab *)pNew; } return rc; } /* ** The xConnect and xCreate methods */ static int spellfix1Connect( |
︙ | ︙ | |||
1402 1403 1404 1405 1406 1407 1408 | sqlite3_vtab **ppVTab, char **pzErr ){ return spellfix1Init(1, db, pAux, argc, argv, ppVTab, pzErr); } /* | | < | < < > > > | > > > > > > > > > > > > > > > > > > > > | > > > > > > > | | | | > > > > > > > > > > | > > > > | 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 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 | sqlite3_vtab **ppVTab, char **pzErr ){ return spellfix1Init(1, db, pAux, argc, argv, ppVTab, pzErr); } /* ** Clear all of the content from a cursor. */ static void spellfix1ResetCursor(spellfix1_cursor *pCur){ int i; for(i=0; i<pCur->nRow; i++){ sqlite3_free(pCur->a[i].zWord); } pCur->nRow = 0; pCur->iRow = 0; pCur->nSearch = 0; if( pCur->pFullScan ){ sqlite3_finalize(pCur->pFullScan); pCur->pFullScan = 0; } } /* ** Resize the cursor to hold up to N rows of content */ static void spellfix1ResizeCursor(spellfix1_cursor *pCur, int N){ struct spellfix1_row *aNew; assert( N>=pCur->nRow ); aNew = sqlite3_realloc(pCur->a, sizeof(pCur->a[0])*N); if( aNew==0 && N>0 ){ spellfix1ResetCursor(pCur); sqlite3_free(pCur->a); pCur->nAlloc = 0; pCur->a = 0; }else{ pCur->nAlloc = N; pCur->a = aNew; } } /* ** Close a fuzzy-search cursor. */ static int spellfix1Close(sqlite3_vtab_cursor *cur){ spellfix1_cursor *pCur = (spellfix1_cursor *)cur; spellfix1ResetCursor(pCur); spellfix1ResizeCursor(pCur, 0); sqlite3_free(pCur->zPattern); sqlite3_free(pCur); return SQLITE_OK; } /* ** Search for terms of these forms: ** ** (A) word MATCH $str ** (B) langid == $langid ** (C) top = $top ** (D) scope = $scope ** (E) distance < $distance ** (F) distance <= $distance ** ** The plan number is a bit mask formed with these bits: ** ** 0x01 (A) is found ** 0x02 (B) is found ** 0x04 (C) is found ** 0x08 (D) is found ** 0x10 (E) is found ** 0x20 (F) is found ** ** filter.argv[*] values contains $str, $langid, $top, and $scope, ** if specified and in that order. */ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int iPlan = 0; int iLangTerm = -1; int iTopTerm = -1; int iScopeTerm = -1; int iDistTerm = -1; int i; const struct sqlite3_index_constraint *pConstraint; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ if( pConstraint->usable==0 ) continue; /* Terms of the form: word MATCH $str */ if( (iPlan & 1)==0 && pConstraint->iColumn==SPELLFIX_COL_WORD && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ iPlan |= 1; pIdxInfo->aConstraintUsage[i].argvIndex = 1; pIdxInfo->aConstraintUsage[i].omit = 1; } /* Terms of the form: langid = $langid */ if( (iPlan & 2)==0 && pConstraint->iColumn==SPELLFIX_COL_LANGID && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ iPlan |= 2; iLangTerm = i; } /* Terms of the form: top = $top */ if( (iPlan & 4)==0 && pConstraint->iColumn==SPELLFIX_COL_TOP && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ iPlan |= 4; iTopTerm = i; } /* Terms of the form: scope = $scope */ if( (iPlan & 8)==0 && pConstraint->iColumn==SPELLFIX_COL_SCOPE && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ iPlan |= 8; iScopeTerm = i; } /* Terms of the form: distance < $dist or distance <= $dist */ if( (iPlan & (16|32))==0 && pConstraint->iColumn==SPELLFIX_COL_DISTANCE && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE) ){ iPlan |= pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ? 16 : 32; iDistTerm = i; } } if( iPlan&1 ){ int idx = 2; pIdxInfo->idxNum = iPlan; if( pIdxInfo->nOrderBy==1 && pIdxInfo->aOrderBy[0].iColumn==SPELLFIX_COL_SCORE && pIdxInfo->aOrderBy[0].desc==0 ){ pIdxInfo->orderByConsumed = 1; /* Default order by iScore */ } if( iPlan&2 ){ pIdxInfo->aConstraintUsage[iLangTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iLangTerm].omit = 1; } if( iPlan&4 ){ pIdxInfo->aConstraintUsage[iTopTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iTopTerm].omit = 1; } if( iPlan&8 ){ pIdxInfo->aConstraintUsage[iScopeTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iScopeTerm].omit = 1; } if( iPlan&(16|32) ){ pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iDistTerm].omit = 1; } pIdxInfo->estimatedCost = (double)10000; }else{ pIdxInfo->idxNum = 0; pIdxInfo->estimatedCost = (double)10000000; } return SQLITE_OK; } |
︙ | ︙ | |||
1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 | ** that they sort in order of increasing distance. */ static int spellfix1RowCompare(const void *A, const void *B){ const struct spellfix1_row *a = (const struct spellfix1_row*)A; const struct spellfix1_row *b = (const struct spellfix1_row*)B; return a->iScore - b->iScore; } /* ** This version of the xFilter method work if the MATCH term is present ** and we are doing a scan. */ static int spellfix1FilterForMatch( spellfix1_cursor *pCur, int idxNum, int argc, sqlite3_value **argv ){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | < < | | | | < | > | | > > > > > > > > > > > > > | | > > > > > > | > | | > > > > > > > > > > | > > | > > > < < < < < < < < | | > > > > > < < < < < < < < < | < < < | | | | < | < | < < < < < < < < < < < < | < | | < < > | | < < < > | | | > > > > > | < | > > > | > > > > > > > > > > > > > > | | 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 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 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 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 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 2480 2481 2482 2483 2484 2485 2486 2487 2488 | ** that they sort in order of increasing distance. */ static int spellfix1RowCompare(const void *A, const void *B){ const struct spellfix1_row *a = (const struct spellfix1_row*)A; const struct spellfix1_row *b = (const struct spellfix1_row*)B; return a->iScore - b->iScore; } /* ** A structure used to pass information from spellfix1FilterForMatch() ** into spellfix1RunQuery(). */ typedef struct MatchQuery { spellfix1_cursor *pCur; /* The cursor being queried */ sqlite3_stmt *pStmt; /* shadow table query statment */ char zHash[SPELLFIX_MX_HASH]; /* The current phonehash for zPattern */ const char *zPattern; /* Transliterated input string */ int nPattern; /* Length of zPattern */ EditDist3FromString *pMatchStr3; /* Original unicode string */ EditDist3Config *pConfig3; /* Edit-distance cost coefficients */ const EditDist3Lang *pLang; /* The selected language coefficients */ int iLang; /* The language id */ int iScope; /* Default scope */ int iMaxDist; /* Maximum allowed edit distance, or -1 */ int rc; /* Error code */ int nRun; /* Number of prior runs for the same zPattern */ char azPrior[SPELLFIX_MX_RUN][SPELLFIX_MX_HASH]; /* Prior hashes */ } MatchQuery; /* ** Run a query looking for the best matches against zPattern using ** zHash as the character class seed hash. */ static void spellfix1RunQuery(MatchQuery *p, const char *zQuery, int nQuery){ const char *zK1; const char *zWord; int iDist; int iRank; int iScore; int iWorst = 0; int idx; int idxWorst = -1; int i; int iScope = p->iScope; spellfix1_cursor *pCur = p->pCur; sqlite3_stmt *pStmt = p->pStmt; char zHash1[SPELLFIX_MX_HASH]; char zHash2[SPELLFIX_MX_HASH]; char *zClass; int nClass; int rc; 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 = 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; }else{ iScope = nClass; } } memcpy(zHash1, zClass, iScope); sqlite3_free(zClass); zHash1[iScope] = 0; memcpy(zHash2, zHash1, iScope); zHash2[iScope] = 'Z'; zHash2[iScope+1] = 0; #if SPELLFIX_MX_RUN>1 for(i=0; i<p->nRun; i++){ if( strcmp(p->azPrior[i], zHash1)==0 ) return; } #endif assert( p->nRun<SPELLFIX_MX_RUN ); memcpy(p->azPrior[p->nRun++], zHash1, iScope+1); if( sqlite3_bind_text(pStmt, 1, zHash1, -1, SQLITE_STATIC)==SQLITE_NOMEM || sqlite3_bind_text(pStmt, 2, zHash2, -1, SQLITE_STATIC)==SQLITE_NOMEM ){ p->rc = SQLITE_NOMEM; return; } #if SPELLFIX_MX_RUN>1 for(i=0; i<pCur->nRow; i++){ if( pCur->a[i].iScore>iWorst ){ iWorst = pCur->a[i].iScore; idxWorst = i; } } #endif while( sqlite3_step(pStmt)==SQLITE_ROW ){ int iMatchlen = -1; iRank = sqlite3_column_int(pStmt, 2); if( p->pMatchStr3 ){ int nWord = sqlite3_column_bytes(pStmt, 1); zWord = (const char*)sqlite3_column_text(pStmt, 1); iDist = editDist3Core(p->pMatchStr3, zWord, nWord, p->pLang, &iMatchlen); }else{ zK1 = (const char*)sqlite3_column_text(pStmt, 3); if( zK1==0 ) continue; iDist = editdist1(p->zPattern, zK1, 0); } if( iDist<0 ){ p->rc = SQLITE_NOMEM; break; } pCur->nSearch++; iScore = spellfix1Score(iDist,iRank); if( p->iMaxDist>=0 ){ if( iDist>p->iMaxDist ) continue; if( pCur->nRow>=pCur->nAlloc-1 ){ spellfix1ResizeCursor(pCur, pCur->nAlloc*2 + 10); if( pCur->a==0 ) break; } idx = pCur->nRow; }else if( pCur->nRow<pCur->nAlloc ){ idx = pCur->nRow; }else if( iScore<iWorst ){ idx = idxWorst; sqlite3_free(pCur->a[idx].zWord); }else{ continue; } pCur->a[idx].zWord = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); if( pCur->a[idx].zWord==0 ){ p->rc = SQLITE_NOMEM; break; } pCur->a[idx].iRowid = sqlite3_column_int64(pStmt, 0); pCur->a[idx].iRank = iRank; pCur->a[idx].iDistance = iDist; pCur->a[idx].iScore = iScore; pCur->a[idx].iMatchlen = iMatchlen; memcpy(pCur->a[idx].zHash, zHash1, iScope+1); if( pCur->nRow<pCur->nAlloc ) pCur->nRow++; if( pCur->nRow==pCur->nAlloc ){ iWorst = pCur->a[0].iScore; idxWorst = 0; for(i=1; i<pCur->nRow; i++){ iScore = pCur->a[i].iScore; if( iWorst<iScore ){ iWorst = iScore; idxWorst = i; } } } } rc = sqlite3_reset(pStmt); if( rc ) p->rc = rc; } /* ** This version of the xFilter method work if the MATCH term is present ** and we are doing a scan. */ static int spellfix1FilterForMatch( spellfix1_cursor *pCur, int idxNum, int argc, sqlite3_value **argv ){ const unsigned char *zMatchThis; /* RHS of the MATCH operator */ EditDist3FromString *pMatchStr3 = 0; /* zMatchThis as an editdist string */ char *zPattern; /* Transliteration of zMatchThis */ int nPattern; /* Length of zPattern */ int iLimit = 20; /* Max number of rows of output */ int iScope = 3; /* Use this many characters of zClass */ int iLang = 0; /* Language code */ char *zSql; /* SQL of shadow table query */ sqlite3_stmt *pStmt = 0; /* Shadow table query */ int rc; /* Result code */ int idx = 1; /* Next available filter parameter */ spellfix1_vtab *p = pCur->pVTab; /* The virtual table that owns pCur */ MatchQuery x; /* For passing info to RunQuery() */ /* Load the cost table if we have not already done so */ if( p->zCostTable!=0 && p->pConfig3==0 ){ p->pConfig3 = sqlite3_malloc( sizeof(p->pConfig3[0]) ); if( p->pConfig3==0 ) return SQLITE_NOMEM; memset(p->pConfig3, 0, sizeof(p->pConfig3[0])); rc = editDist3ConfigLoad(p->pConfig3, p->db, p->zCostTable); if( rc ) return rc; } memset(&x, 0, sizeof(x)); x.iScope = 3; /* Default scope if none specified by "WHERE scope=N" */ x.iMaxDist = -1; /* Maximum allowed edit distance */ if( idxNum&2 ){ iLang = sqlite3_value_int(argv[idx++]); } if( idxNum&4 ){ iLimit = sqlite3_value_int(argv[idx++]); if( iLimit<1 ) iLimit = 1; } if( idxNum&8 ){ x.iScope = sqlite3_value_int(argv[idx++]); if( x.iScope<1 ) x.iScope = 1; if( x.iScope>SPELLFIX_MX_HASH-2 ) x.iScope = SPELLFIX_MX_HASH-2; } if( idxNum&(16|32) ){ x.iMaxDist = sqlite3_value_int(argv[idx++]); if( idxNum&16 ) x.iMaxDist--; if( x.iMaxDist<0 ) x.iMaxDist = 0; } spellfix1ResetCursor(pCur); spellfix1ResizeCursor(pCur, iLimit); zMatchThis = sqlite3_value_text(argv[0]); if( zMatchThis==0 ) return SQLITE_OK; if( p->pConfig3 ){ x.pLang = editDist3FindLang(p->pConfig3, iLang); pMatchStr3 = editDist3FromStringNew(x.pLang, (const char*)zMatchThis, -1); if( pMatchStr3==0 ){ x.rc = SQLITE_NOMEM; goto filter_exit; } }else{ x.pLang = 0; } 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 = 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 ); if( zSql==0 ){ x.rc = SQLITE_NOMEM; pStmt = 0; goto filter_exit; } rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); pCur->iLang = iLang; x.pCur = pCur; x.pStmt = pStmt; x.zPattern = zPattern; x.nPattern = nPattern; x.pMatchStr3 = pMatchStr3; x.iLang = iLang; x.rc = rc; x.pConfig3 = p->pConfig3; if( x.rc==SQLITE_OK ){ spellfix1RunQuery(&x, zPattern, nPattern); } if( pCur->a ){ qsort(pCur->a, pCur->nRow, sizeof(pCur->a[0]), spellfix1RowCompare); pCur->iTop = iLimit; pCur->iScope = iScope; }else{ x.rc = SQLITE_NOMEM; } filter_exit: sqlite3_finalize(pStmt); editDist3FromStringDelete(pMatchStr3); return x.rc; } /* ** This version of xFilter handles a full-table scan case */ static int spellfix1FilterForFullScan( spellfix1_cursor *pCur, int idxNum, int argc, sqlite3_value **argv ){ int rc; char *zSql; spellfix1_vtab *pVTab = pCur->pVTab; spellfix1ResetCursor(pCur); zSql = sqlite3_mprintf( "SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"", pVTab->zDbName, pVTab->zTableName); if( zSql==0 ) return SQLITE_NOMEM; rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pFullScan, 0); sqlite3_free(zSql); pCur->nRow = pCur->iRow = 0; if( rc==SQLITE_OK ){ rc = sqlite3_step(pCur->pFullScan); if( rc==SQLITE_ROW ){ pCur->iRow = -1; rc = SQLITE_OK; } if( rc==SQLITE_DONE ){ rc = SQLITE_OK; } }else{ pCur->iRow = 0; } return rc; } /* ** Called to "rewind" a cursor back to the beginning so that ** it starts its output over again. Always called at least once ** prior to any spellfix1Column, spellfix1Rowid, or spellfix1Eof call. |
︙ | ︙ | |||
1707 1708 1709 1710 1711 1712 1713 | /* ** Advance a cursor to its next row of output */ static int spellfix1Next(sqlite3_vtab_cursor *cur){ spellfix1_cursor *pCur = (spellfix1_cursor *)cur; | | > > > > > > > | > > > > > > > > > > > > | | | | | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > | | > > > | > | 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 | /* ** Advance a cursor to its next row of output */ static int spellfix1Next(sqlite3_vtab_cursor *cur){ spellfix1_cursor *pCur = (spellfix1_cursor *)cur; if( pCur->iRow < pCur->nRow ){ if( pCur->pFullScan ){ int rc = sqlite3_step(pCur->pFullScan); if( rc!=SQLITE_ROW ) pCur->iRow = pCur->nRow; }else{ pCur->iRow++; } } return SQLITE_OK; } /* ** Return TRUE if we are at the end-of-file */ static int spellfix1Eof(sqlite3_vtab_cursor *cur){ spellfix1_cursor *pCur = (spellfix1_cursor *)cur; return pCur->iRow>=pCur->nRow; } /* ** Return columns from the current row. */ static int spellfix1Column( sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i ){ spellfix1_cursor *pCur = (spellfix1_cursor*)cur; if( pCur->pFullScan ){ if( i<=SPELLFIX_COL_LANGID ){ sqlite3_result_value(ctx, sqlite3_column_value(pCur->pFullScan, i)); }else{ sqlite3_result_null(ctx); } return SQLITE_OK; } switch( i ){ case SPELLFIX_COL_WORD: { sqlite3_result_text(ctx, pCur->a[pCur->iRow].zWord, -1, SQLITE_STATIC); break; } case SPELLFIX_COL_RANK: { sqlite3_result_int(ctx, pCur->a[pCur->iRow].iRank); break; } case SPELLFIX_COL_DISTANCE: { sqlite3_result_int(ctx, pCur->a[pCur->iRow].iDistance); break; } case SPELLFIX_COL_LANGID: { sqlite3_result_int(ctx, pCur->iLang); break; } 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 = strlen(pCur->zPattern); char *zWord = pCur->a[pCur->iRow].zWord; int nWord = 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); sqlite3_free(zTranslit); if( res<0 ) return SQLITE_NOMEM; iMatchlen = translen_to_charlen(zWord, nWord, iMatchlen); }else{ iMatchlen = utf8Charlen(zWord, nWord); } } sqlite3_result_int(ctx, iMatchlen); break; } case SPELLFIX_COL_PHONEHASH: { sqlite3_result_text(ctx, pCur->a[pCur->iRow].zHash, -1, SQLITE_STATIC); break; } case SPELLFIX_COL_TOP: { sqlite3_result_int(ctx, pCur->iTop); break; } case SPELLFIX_COL_SCOPE: { sqlite3_result_int(ctx, pCur->iScope); break; } case SPELLFIX_COL_SRCHCNT: { sqlite3_result_int(ctx, pCur->nSearch); break; } default: { sqlite3_result_null(ctx); break; } } return SQLITE_OK; } /* ** The rowid. */ static int spellfix1Rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ spellfix1_cursor *pCur = (spellfix1_cursor*)cur; if( pCur->pFullScan ){ *pRowid = sqlite3_column_int64(pCur->pFullScan, 4); }else{ *pRowid = pCur->a[pCur->iRow].iRowid; } return SQLITE_OK; } /* ** The xUpdate() method. */ static int spellfix1Update( |
︙ | ︙ | |||
1795 1796 1797 1798 1799 1800 1801 | if( argc==1 ){ /* A delete operation on the rowid given by argv[0] */ rowid = *pRowid = sqlite3_value_int64(argv[0]); spellfix1DbExec(&rc, db, "DELETE FROM \"%w\".\"%w_vocab\" " " WHERE id=%lld", p->zDbName, p->zTableName, rowid); }else{ | | | | | | > | > > > > > > | | | > > > > > > > > > > | | | | 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 | if( argc==1 ){ /* A delete operation on the rowid given by argv[0] */ rowid = *pRowid = sqlite3_value_int64(argv[0]); spellfix1DbExec(&rc, db, "DELETE FROM \"%w\".\"%w_vocab\" " " WHERE id=%lld", p->zDbName, p->zTableName, rowid); }else{ const unsigned char *zWord = sqlite3_value_text(argv[SPELLFIX_COL_WORD+2]); int nWord = sqlite3_value_bytes(argv[SPELLFIX_COL_WORD+2]); int iLang = sqlite3_value_int(argv[SPELLFIX_COL_LANGID+2]); int iRank = sqlite3_value_int(argv[SPELLFIX_COL_RANK+2]); const unsigned char *zSoundslike = sqlite3_value_text(argv[SPELLFIX_COL_SOUNDSLIKE+2]); int nSoundslike = sqlite3_value_bytes(argv[SPELLFIX_COL_SOUNDSLIKE+2]); char *zK1, *zK2; int i; char c; if( zWord==0 ){ /* Inserts of the form: INSERT INTO table(command) VALUES('xyzzy'); ** cause zWord to be NULL, so we look at the "command" column to see ** what special actions to take */ const char *zCmd = (const char*)sqlite3_value_text(argv[SPELLFIX_COL_COMMAND+2]); if( zCmd==0 ){ pVTab->zErrMsg = sqlite3_mprintf("%s.word may not be NULL", p->zTableName); return SQLITE_CONSTRAINT; } if( strcmp(zCmd,"reset")==0 ){ /* Reset the edit cost table (if there is one). */ editDist3ConfigDelete(p->pConfig3); p->pConfig3 = 0; return SQLITE_OK; } pVTab->zErrMsg = sqlite3_mprintf("unknown value for %s.command: \"%w\"", p->zTableName, zCmd); return SQLITE_ERROR; } if( iRank<1 ) iRank = 1; if( zSoundslike ){ zK1 = (char*)transliterate(zSoundslike, nSoundslike); }else{ zK1 = (char*)transliterate(zWord, nWord); } if( zK1==0 ) return SQLITE_NOMEM; for(i=0; (c = zK1[i])!=0; i++){ if( c>='A' && c<='Z' ) zK1[i] += 'a' - 'A'; } zK2 = (char*)phoneticHash((const unsigned char*)zK1, i); if( zK2==0 ){ sqlite3_free(zK1); return SQLITE_NOMEM; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ spellfix1DbExec(&rc, db, "INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) " "VALUES(%d,%d,%Q,%Q,%Q)", p->zDbName, p->zTableName, iRank, iLang, zWord, zK1, zK2 ); *pRowid = sqlite3_last_insert_rowid(db); }else{ rowid = sqlite3_value_int64(argv[0]); newRowid = *pRowid = sqlite3_value_int64(argv[1]); spellfix1DbExec(&rc, db, "UPDATE \"%w\".\"%w_vocab\" SET id=%lld, rank=%d, langid=%d," " word=%Q, k1=%Q, k2=%Q WHERE id=%lld", p->zDbName, p->zTableName, newRowid, iRank, iLang, zWord, zK1, zK2, rowid ); } sqlite3_free(zK1); sqlite3_free(zK2); } |
︙ | ︙ | |||
1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 | spellfix1DbExec(&rc, db, "ALTER TABLE \"%w\".\"%w_vocab\" RENAME TO \"%w_vocab\"", p->zDbName, p->zTableName, zNewName ); if( rc==SQLITE_OK ){ sqlite3_free(p->zTableName); p->zTableName = zNewName; } return rc; } /* ** A virtual table module that provides fuzzy search. | > > | 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 | spellfix1DbExec(&rc, db, "ALTER TABLE \"%w\".\"%w_vocab\" RENAME TO \"%w_vocab\"", p->zDbName, p->zTableName, zNewName ); if( rc==SQLITE_OK ){ sqlite3_free(p->zTableName); p->zTableName = zNewName; }else{ sqlite3_free(zNewName); } return rc; } /* ** A virtual table module that provides fuzzy search. |
︙ | ︙ | |||
1908 1909 1910 1911 1912 1913 1914 | static int spellfix1Register(sqlite3 *db){ int nErr = 0; int i; nErr += sqlite3_create_function(db, "spellfix1_translit", 1, SQLITE_UTF8, 0, transliterateSqlFunc, 0, 0); nErr += sqlite3_create_function(db, "spellfix1_editdist", 2, SQLITE_UTF8, 0, editdistSqlFunc, 0, 0); | | | > | | 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 | static int spellfix1Register(sqlite3 *db){ int nErr = 0; int i; nErr += sqlite3_create_function(db, "spellfix1_translit", 1, SQLITE_UTF8, 0, transliterateSqlFunc, 0, 0); nErr += sqlite3_create_function(db, "spellfix1_editdist", 2, SQLITE_UTF8, 0, editdistSqlFunc, 0, 0); nErr += sqlite3_create_function(db, "spellfix1_phonehash", 1, SQLITE_UTF8, 0, phoneticHashSqlFunc, 0, 0); nErr += sqlite3_create_function(db, "spellfix1_scriptcode", 1, SQLITE_UTF8, 0, scriptCodeSqlFunc, 0, 0); nErr += sqlite3_create_module(db, "spellfix1", &spellfix1Module, 0); nErr += editDist3Install(db); /* Verify sanity of the translit[] table */ for(i=0; i<sizeof(translit)/sizeof(translit[0])-1; i++){ assert( translit[i].cFrom<translit[i+1].cFrom ); } return nErr ? SQLITE_ERROR : SQLITE_OK; } #if SQLITE_CORE || defined(SQLITE_TEST) /* ** Register the spellfix1 virtual table and its associated functions. |
︙ | ︙ |
Changes to src/test_vfs.c.
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 | char *zName; /* Name of this VFS */ sqlite3_vfs *pParent; /* The VFS to use for file IO */ sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */ Tcl_Interp *interp; /* Interpreter to run script in */ Tcl_Obj *pScript; /* Script to execute */ TestvfsBuffer *pBuffer; /* List of shared buffers */ int isNoshm; int mask; /* Mask controlling [script] and [ioerr] */ TestFaultInject ioerr_err; TestFaultInject full_err; TestFaultInject cantopen_err; | > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | char *zName; /* Name of this VFS */ sqlite3_vfs *pParent; /* The VFS to use for file IO */ sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */ Tcl_Interp *interp; /* Interpreter to run script in */ Tcl_Obj *pScript; /* Script to execute */ TestvfsBuffer *pBuffer; /* List of shared buffers */ int isNoshm; int isFullshm; int mask; /* Mask controlling [script] and [ioerr] */ TestFaultInject ioerr_err; TestFaultInject full_err; TestFaultInject cantopen_err; |
︙ | ︙ | |||
356 357 358 359 360 361 362 | ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ tvfsExecTcl(p, "xWrite", | | > | 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ tvfsExecTcl(p, "xWrite", Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, Tcl_NewWideIntObj(iOfst) ); tvfsResultCode(p, &rc); } if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){ rc = SQLITE_FULL; } |
︙ | ︙ | |||
756 757 758 759 760 761 762 763 764 765 766 767 768 769 | Testvfs *p; int rc = SQLITE_OK; /* Return code */ TestvfsBuffer *pBuffer; /* Buffer to open connection to */ TestvfsFd *pFd; /* The testvfs file structure */ pFd = tvfsGetFd(pFile); p = (Testvfs *)pFd->pVfs->pAppData; assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 ); /* Evaluate the Tcl script: ** ** SCRIPT xShmOpen FILENAME */ Tcl_ResetResult(p->interp); | > | 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | Testvfs *p; int rc = SQLITE_OK; /* Return code */ TestvfsBuffer *pBuffer; /* Buffer to open connection to */ TestvfsFd *pFd; /* The testvfs file structure */ pFd = tvfsGetFd(pFile); p = (Testvfs *)pFd->pVfs->pAppData; assert( 0==p->isFullshm ); assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 ); /* Evaluate the Tcl script: ** ** SCRIPT xShmOpen FILENAME */ Tcl_ResetResult(p->interp); |
︙ | ︙ | |||
815 816 817 818 819 820 821 822 823 824 825 826 827 828 | int pgsz, /* Size of pages */ int isWrite, /* True to extend file if necessary */ void volatile **pp /* OUT: Mapped memory */ ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); if( 0==pFd->pShm ){ rc = tvfsShmOpen(pFile); if( rc!=SQLITE_OK ){ return rc; } } | > > > > | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 | int pgsz, /* Size of pages */ int isWrite, /* True to extend file if necessary */ void volatile **pp /* OUT: Mapped memory */ ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); if( p->isFullshm ){ return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp); } if( 0==pFd->pShm ){ rc = tvfsShmOpen(pFile); if( rc!=SQLITE_OK ){ return rc; } } |
︙ | ︙ | |||
859 860 861 862 863 864 865 866 867 868 869 870 871 872 | int flags ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); int nLock; char zLock[80]; if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); nLock = (int)strlen(zLock); if( flags & SQLITE_SHM_LOCK ){ strcpy(&zLock[nLock], " lock"); }else{ | > > > > | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 | int flags ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); int nLock; char zLock[80]; if( p->isFullshm ){ return sqlite3OsShmLock(pFd->pReal, ofst, n, flags); } if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); nLock = (int)strlen(zLock); if( flags & SQLITE_SHM_LOCK ){ strcpy(&zLock[nLock], " lock"); }else{ |
︙ | ︙ | |||
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 | return rc; } static void tvfsShmBarrier(sqlite3_file *pFile){ TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 ); } } static int tvfsShmUnmap( sqlite3_file *pFile, int deleteFlag ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); TestvfsBuffer *pBuffer = pFd->pShm; TestvfsFd **ppFd; if( !pBuffer ) return SQLITE_OK; assert( pFd->pShmId && pFd->pShm ); if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ tvfsExecTcl(p, "xShmUnmap", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 | > > > > > > > > > | 925 926 927 928 929 930 931 932 933 934 935 936 937 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 | return rc; } static void tvfsShmBarrier(sqlite3_file *pFile){ TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); if( p->isFullshm ){ sqlite3OsShmBarrier(pFd->pReal); return; } if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 ); } } static int tvfsShmUnmap( sqlite3_file *pFile, int deleteFlag ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); TestvfsBuffer *pBuffer = pFd->pShm; TestvfsFd **ppFd; if( p->isFullshm ){ return sqlite3OsShmUnmap(pFd->pReal, deleteFlag); } if( !pBuffer ) return SQLITE_OK; assert( pFd->pShmId && pFd->pShm ); if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ tvfsExecTcl(p, "xShmUnmap", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 |
︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 | Testvfs *p; /* New object */ sqlite3_vfs *pVfs; /* New VFS */ char *zVfs; int nByte; /* Bytes of space to allocate at p */ int i; int isNoshm = 0; /* True if -noshm is passed */ int isDefault = 0; /* True if -default is passed */ int szOsFile = 0; /* Value passed to -szosfile */ int mxPathname = -1; /* Value passed to -mxpathname */ int iVersion = 2; /* Value passed to -iversion */ if( objc<2 || 0!=(objc%2) ) goto bad_args; for(i=2; i<objc; i += 2){ int nSwitch; char *zSwitch; zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch); if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &iVersion) ){ return TCL_ERROR; } } else{ goto bad_args; } } if( szOsFile<sizeof(TestvfsFile) ){ | > > > > > > > > | 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 | Testvfs *p; /* New object */ sqlite3_vfs *pVfs; /* New VFS */ char *zVfs; int nByte; /* Bytes of space to allocate at p */ int i; int isNoshm = 0; /* True if -noshm is passed */ int isFullshm = 0; /* True if -fullshm is passed */ int isDefault = 0; /* True if -default is passed */ int szOsFile = 0; /* Value passed to -szosfile */ int mxPathname = -1; /* Value passed to -mxpathname */ int iVersion = 2; /* Value passed to -iversion */ if( objc<2 || 0!=(objc%2) ) goto bad_args; for(i=2; i<objc; i += 2){ int nSwitch; char *zSwitch; zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch); if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){ return TCL_ERROR; } if( isNoshm ) isFullshm = 0; } else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &iVersion) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-fullshm", zSwitch, nSwitch) ){ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isFullshm) ){ return TCL_ERROR; } if( isFullshm ) isNoshm = 0; } else{ goto bad_args; } } if( szOsFile<sizeof(TestvfsFile) ){ |
︙ | ︙ | |||
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 | pVfs->mxPathname = p->pParent->mxPathname; if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){ pVfs->mxPathname = mxPathname; } pVfs->szOsFile = szOsFile; p->pVfs = pVfs; p->isNoshm = isNoshm; p->mask = TESTVFS_ALL_MASK; sqlite3_vfs_register(pVfs, isDefault); return TCL_OK; bad_args: | > | 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 | pVfs->mxPathname = p->pParent->mxPathname; if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){ pVfs->mxPathname = mxPathname; } pVfs->szOsFile = szOsFile; p->pVfs = pVfs; p->isNoshm = isNoshm; p->isFullshm = isFullshm; p->mask = TESTVFS_ALL_MASK; sqlite3_vfs_register(pVfs, isDefault); return TCL_OK; bad_args: |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
367 368 369 370 371 372 373 | /* adjust the sign of significand */ s = sign<0 ? -s : s; /* if exponent, scale significand as appropriate ** and store in result. */ if( e ){ | | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | /* adjust the sign of significand */ s = sign<0 ? -s : s; /* if exponent, scale significand as appropriate ** and store in result. */ if( e ){ LONGDOUBLE_TYPE scale = 1.0; /* attempt to handle extremely small/large numbers better */ if( e>307 && e<342 ){ while( e%308 ) { scale *= 1.0e+1; e -= 1; } if( esign<0 ){ result = s / scale; result /= 1.0e+308; }else{ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 | int p2; int iDb; int wrFlag; Btree *pX; VdbeCursor *pCur; Db *pDb; if( p->expired ){ rc = SQLITE_ABORT; break; } nField = 0; pKeyInfo = 0; | > > > | 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 | int p2; int iDb; int wrFlag; Btree *pX; VdbeCursor *pCur; Db *pDb; assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); if( p->expired ){ rc = SQLITE_ABORT; break; } nField = 0; pKeyInfo = 0; |
︙ | ︙ | |||
3149 3150 3151 3152 3153 3154 3155 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; } }else{ wrFlag = 0; } | | | 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; } }else{ wrFlag = 0; } if( pOp->p5 & OPFLAG_P2ISREG ){ assert( p2>0 ); assert( p2<=p->nMem ); pIn2 = &aMem[p2]; assert( memIsValid(pIn2) ); assert( (pIn2->flags & MEM_Int)!=0 ); sqlite3VdbeMemIntegerify(pIn2); p2 = (int)pIn2->u.i; |
︙ | ︙ | |||
3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 | assert( pOp->p1>=0 ); pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; pCur->isOrdered = 1; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; /* Since it performs no memory allocation or IO, the only value that ** sqlite3BtreeCursor() may return is SQLITE_OK. */ assert( rc==SQLITE_OK ); /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of ** SQLite used to check if the root-page flags were sane at this point | > > | 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 | assert( pOp->p1>=0 ); pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; pCur->isOrdered = 1; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); /* Since it performs no memory allocation or IO, the only value that ** sqlite3BtreeCursor() may return is SQLITE_OK. */ assert( rc==SQLITE_OK ); /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of ** SQLite used to check if the root-page flags were sane at this point |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
448 449 450 451 452 453 454 | # define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK # define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK # define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK # define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK #else int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *); void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); | | | | | | | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | # define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK # define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK # define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK # define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK #else int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *); void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *); int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *); int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *); int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *); #endif #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 void sqlite3VdbeEnter(Vdbe*); void sqlite3VdbeLeave(Vdbe*); #else # define sqlite3VdbeEnter(X) |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
67 68 69 70 71 72 73 | if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL ** pointer is a harmless no-op. */ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; | < < < < < < | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL ** pointer is a harmless no-op. */ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); } return rc; } /* ** Terminate the current execution of an SQL statement and reset it ** back to its starting state so that it can be reused. A success code from |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 | ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; if( NEVER(p==0) ) return; db = p->db; if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ assert( db->pVdbe==p ); db->pVdbe = p->pNext; } if( p->pNext ){ | > | 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 | ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; if( NEVER(p==0) ) return; db = p->db; assert( sqlite3_mutex_held(db->mutex) ); if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ assert( db->pVdbe==p ); db->pVdbe = p->pNext; } if( p->pNext ){ |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include "sqliteInt.h" #include "vdbeInt.h" #ifndef SQLITE_OMIT_MERGE_SORT typedef struct VdbeSorterIter VdbeSorterIter; typedef struct SorterRecord SorterRecord; /* ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES: ** ** As keys are added to the sorter, they are written to disk in a series ** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly ** the same as the cache-size allowed for temporary databases. In order | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #include "sqliteInt.h" #include "vdbeInt.h" #ifndef SQLITE_OMIT_MERGE_SORT typedef struct VdbeSorterIter VdbeSorterIter; typedef struct SorterRecord SorterRecord; typedef struct FileWriter FileWriter; /* ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES: ** ** As keys are added to the sorter, they are written to disk in a series ** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly ** the same as the cache-size allowed for temporary databases. In order |
︙ | ︙ | |||
115 116 117 118 119 120 121 122 123 124 125 126 127 128 | i64 iReadOff; /* Current read offset */ i64 iEof; /* 1 byte past EOF for this iterator */ int nAlloc; /* Bytes of space at aAlloc */ int nKey; /* Number of bytes in key */ sqlite3_file *pFile; /* File iterator is reading from */ u8 *aAlloc; /* Allocated space */ u8 *aKey; /* Pointer to current key */ }; /* ** A structure to store a single record. All in-memory records are connected ** together into a linked list headed at VdbeSorter.pRecord using the ** SorterRecord.pNext pointer. */ | > > > > > > > > > > > > > > > > > > | 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 | i64 iReadOff; /* Current read offset */ i64 iEof; /* 1 byte past EOF for this iterator */ int nAlloc; /* Bytes of space at aAlloc */ int nKey; /* Number of bytes in key */ sqlite3_file *pFile; /* File iterator is reading from */ u8 *aAlloc; /* Allocated space */ u8 *aKey; /* Pointer to current key */ u8 *aBuffer; /* Current read buffer */ int nBuffer; /* Size of read buffer in bytes */ }; /* ** An instance of this structure is used to organize the stream of records ** being written to files by the merge-sort code into aligned, page-sized ** blocks. Doing all I/O in aligned page-sized blocks helps I/O to go ** faster on many operating systems. */ struct FileWriter { int eFWErr; /* Non-zero if in an error state */ u8 *aBuffer; /* Pointer to write buffer */ int nBuffer; /* Size of write buffer in bytes */ int iBufStart; /* First byte of buffer to write */ int iBufEnd; /* Last byte of buffer to write */ i64 iWriteOff; /* Offset of start of buffer in file */ sqlite3_file *pFile; /* File to write to */ }; /* ** A structure to store a single record. All in-memory records are connected ** together into a linked list headed at VdbeSorter.pRecord using the ** SorterRecord.pNext pointer. */ |
︙ | ︙ | |||
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /* ** Free all memory belonging to the VdbeSorterIter object passed as the second ** argument. All structure fields are set to zero before returning. */ static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){ sqlite3DbFree(db, pIter->aAlloc); memset(pIter, 0, sizeof(VdbeSorterIter)); } /* ** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if ** no error occurs, or an SQLite error code if one does. */ static int vdbeSorterIterNext( sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */ VdbeSorterIter *pIter /* Iterator to advance */ ){ int rc; /* Return Code */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < < | < < < < < | < < < < < < < < < < < < < < < < < < < < | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > > > > > > > | > | > > > > > > > | > > > | > > > > | > | > > | 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 | /* ** Free all memory belonging to the VdbeSorterIter object passed as the second ** argument. All structure fields are set to zero before returning. */ static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){ sqlite3DbFree(db, pIter->aAlloc); sqlite3DbFree(db, pIter->aBuffer); memset(pIter, 0, sizeof(VdbeSorterIter)); } /* ** Read nByte bytes of data from the stream of data iterated by object p. ** If successful, set *ppOut to point to a buffer containing the data ** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite ** error code. ** ** The buffer indicated by *ppOut may only be considered valid until the ** next call to this function. */ static int vdbeSorterIterRead( sqlite3 *db, /* Database handle (for malloc) */ VdbeSorterIter *p, /* Iterator */ int nByte, /* Bytes of data to read */ u8 **ppOut /* OUT: Pointer to buffer containing data */ ){ int iBuf; /* Offset within buffer to read from */ int nAvail; /* Bytes of data available in buffer */ assert( p->aBuffer ); /* If there is no more data to be read from the buffer, read the next ** p->nBuffer bytes of data from the file into it. Or, if there are less ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ iBuf = p->iReadOff % p->nBuffer; if( iBuf==0 ){ int nRead; /* Bytes to read from disk */ int rc; /* sqlite3OsRead() return code */ /* Determine how many bytes of data to read. */ nRead = (int)(p->iEof - p->iReadOff); if( nRead>p->nBuffer ) nRead = p->nBuffer; assert( nRead>0 ); /* Read data from the file. Return early if an error occurs. */ rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff); assert( rc!=SQLITE_IOERR_SHORT_READ ); if( rc!=SQLITE_OK ) return rc; } nAvail = p->nBuffer - iBuf; if( nByte<=nAvail ){ /* The requested data is available in the in-memory buffer. In this ** case there is no need to make a copy of the data, just return a ** pointer into the buffer to the caller. */ *ppOut = &p->aBuffer[iBuf]; p->iReadOff += nByte; }else{ /* The requested data is not all available in the in-memory buffer. ** In this case, allocate space at p->aAlloc[] to copy the requested ** range into. Then return a copy of pointer p->aAlloc to the caller. */ int nRem; /* Bytes remaining to copy */ /* Extend the p->aAlloc[] allocation if required. */ if( p->nAlloc<nByte ){ int nNew = p->nAlloc*2; while( nByte>nNew ) nNew = nNew*2; p->aAlloc = sqlite3DbReallocOrFree(db, p->aAlloc, nNew); if( !p->aAlloc ) return SQLITE_NOMEM; p->nAlloc = nNew; } /* Copy as much data as is available in the buffer into the start of ** p->aAlloc[]. */ memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail); p->iReadOff += nAvail; nRem = nByte - nAvail; /* The following loop copies up to p->nBuffer bytes per iteration into ** the p->aAlloc[] buffer. */ while( nRem>0 ){ int rc; /* vdbeSorterIterRead() return code */ int nCopy; /* Number of bytes to copy */ u8 *aNext; /* Pointer to buffer to copy data from */ nCopy = nRem; if( nRem>p->nBuffer ) nCopy = p->nBuffer; rc = vdbeSorterIterRead(db, p, nCopy, &aNext); if( rc!=SQLITE_OK ) return rc; assert( aNext!=p->aAlloc ); memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy); nRem -= nCopy; } *ppOut = p->aAlloc; } return SQLITE_OK; } /* ** Read a varint from the stream of data accessed by p. Set *pnOut to ** the value read. */ static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){ int iBuf; iBuf = p->iReadOff % p->nBuffer; if( iBuf && (p->nBuffer-iBuf)>=9 ){ p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut); }else{ u8 aVarint[16], *a; int i = 0, rc; do{ rc = vdbeSorterIterRead(db, p, 1, &a); if( rc ) return rc; aVarint[(i++)&0xf] = a[0]; }while( (a[0]&0x80)!=0 ); sqlite3GetVarint(aVarint, pnOut); } return SQLITE_OK; } /* ** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if ** no error occurs, or an SQLite error code if one does. */ static int vdbeSorterIterNext( sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */ VdbeSorterIter *pIter /* Iterator to advance */ ){ int rc; /* Return Code */ u64 nRec = 0; /* Size of record in bytes */ if( pIter->iReadOff>=pIter->iEof ){ /* This is an EOF condition */ vdbeSorterIterZero(db, pIter); return SQLITE_OK; } rc = vdbeSorterIterVarint(db, pIter, &nRec); if( rc==SQLITE_OK ){ pIter->nKey = (int)nRec; rc = vdbeSorterIterRead(db, pIter, (int)nRec, &pIter->aKey); } return rc; } /* ** Initialize iterator pIter to scan through the PMA stored in file pFile ** starting at offset iStart and ending at offset iEof-1. This function ** leaves the iterator pointing to the first key in the PMA (or EOF if the ** PMA is empty). */ static int vdbeSorterIterInit( sqlite3 *db, /* Database handle */ const VdbeSorter *pSorter, /* Sorter object */ i64 iStart, /* Start offset in pFile */ VdbeSorterIter *pIter, /* Iterator to populate */ i64 *pnByte /* IN/OUT: Increment this value by PMA size */ ){ int rc = SQLITE_OK; int nBuf; nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); assert( pSorter->iWriteOff>iStart ); assert( pIter->aAlloc==0 ); assert( pIter->aBuffer==0 ); pIter->pFile = pSorter->pTemp1; pIter->iReadOff = iStart; pIter->nAlloc = 128; pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc); pIter->nBuffer = nBuf; pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); if( !pIter->aBuffer ){ rc = SQLITE_NOMEM; }else{ int iBuf; iBuf = iStart % nBuf; if( iBuf ){ int nRead = nBuf - iBuf; if( (iStart + nRead) > pSorter->iWriteOff ){ nRead = (int)(pSorter->iWriteOff - iStart); } rc = sqlite3OsRead( pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart ); assert( rc!=SQLITE_IOERR_SHORT_READ ); } if( rc==SQLITE_OK ){ u64 nByte; /* Size of PMA in bytes */ pIter->iEof = pSorter->iWriteOff; rc = vdbeSorterIterVarint(db, pIter, &nByte); pIter->iEof = pIter->iReadOff + nByte; *pnByte += nByte; } } if( rc==SQLITE_OK ){ rc = vdbeSorterIterNext(db, pIter); } return rc; } |
︙ | ︙ | |||
299 300 301 302 303 304 305 | ** is true and key1 contains even a single NULL value, it is considered to ** be less than key2. Even if key2 also contains NULL values. ** ** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace ** has been allocated and contains an unpacked record that is used as key2. */ static void vdbeSorterCompare( | | | | | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | ** is true and key1 contains even a single NULL value, it is considered to ** be less than key2. Even if key2 also contains NULL values. ** ** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace ** has been allocated and contains an unpacked record that is used as key2. */ static void vdbeSorterCompare( const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */ int bOmitRowid, /* Ignore rowid field at end of keys */ const void *pKey1, int nKey1, /* Left side of comparison */ const void *pKey2, int nKey2, /* Right side of comparison */ int *pRes /* OUT: Result of comparison */ ){ KeyInfo *pKeyInfo = pCsr->pKeyInfo; VdbeSorter *pSorter = pCsr->pSorter; UnpackedRecord *r2 = pSorter->pUnpacked; int i; |
︙ | ︙ | |||
334 335 336 337 338 339 340 | } /* ** This function is called to compare two iterator keys when merging ** multiple b-tree segments. Parameter iOut is the index of the aTree[] ** value to recalculate. */ | | | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 | } /* ** This function is called to compare two iterator keys when merging ** multiple b-tree segments. Parameter iOut is the index of the aTree[] ** value to recalculate. */ static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){ VdbeSorter *pSorter = pCsr->pSorter; int i1; int i2; int iRes; VdbeSorterIter *p1; VdbeSorterIter *p2; |
︙ | ︙ | |||
460 461 462 463 464 465 466 | } /* ** Merge the two sorted lists p1 and p2 into a single list. ** Set *ppOut to the head of the new list. */ static void vdbeSorterMerge( | | | 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 | } /* ** Merge the two sorted lists p1 and p2 into a single list. ** Set *ppOut to the head of the new list. */ static void vdbeSorterMerge( const VdbeCursor *pCsr, /* For pKeyInfo */ SorterRecord *p1, /* First list to merge */ SorterRecord *p2, /* Second list to merge */ SorterRecord **ppOut /* OUT: Head of merged list */ ){ SorterRecord *pFinal = 0; SorterRecord **pp = &pFinal; void *pVal2 = p2 ? p2->pVal : 0; |
︙ | ︙ | |||
494 495 496 497 498 499 500 | } /* ** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK ** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error ** occurs. */ | | | 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 | } /* ** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK ** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error ** occurs. */ static int vdbeSorterSort(const VdbeCursor *pCsr){ int i; SorterRecord **aSlot; SorterRecord *p; VdbeSorter *pSorter = pCsr->pSorter; aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ |
︙ | ︙ | |||
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | } pSorter->pRecord = p; sqlite3_free(aSlot); return SQLITE_OK; } /* ** Write the current contents of the in-memory linked-list to a PMA. Return ** SQLITE_OK if successful, or an SQLite error code otherwise. ** ** The format of a PMA is: ** ** * A varint. This varint contains the total number of bytes of content ** in the PMA (not including the varint itself). ** ** * One or more records packed end-to-end in order of ascending keys. ** Each record consists of a varint followed by a blob of data (the ** key). The varint is the number of bytes in the blob of data. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > < < > | | < | < | < < < < < < < < < < < < < < < < < > | | 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 | } pSorter->pRecord = p; sqlite3_free(aSlot); return SQLITE_OK; } /* ** Initialize a file-writer object. */ static void fileWriterInit( sqlite3 *db, /* Database (for malloc) */ sqlite3_file *pFile, /* File to write to */ FileWriter *p, /* Object to populate */ i64 iStart /* Offset of pFile to begin writing at */ ){ int nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); memset(p, 0, sizeof(FileWriter)); p->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); if( !p->aBuffer ){ p->eFWErr = SQLITE_NOMEM; }else{ p->iBufEnd = p->iBufStart = (iStart % nBuf); p->iWriteOff = iStart - p->iBufStart; p->nBuffer = nBuf; p->pFile = pFile; } } /* ** Write nData bytes of data to the file-write object. Return SQLITE_OK ** if successful, or an SQLite error code if an error occurs. */ static void fileWriterWrite(FileWriter *p, u8 *pData, int nData){ int nRem = nData; while( nRem>0 && p->eFWErr==0 ){ int nCopy = nRem; if( nCopy>(p->nBuffer - p->iBufEnd) ){ nCopy = p->nBuffer - p->iBufEnd; } memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy); p->iBufEnd += nCopy; if( p->iBufEnd==p->nBuffer ){ p->eFWErr = sqlite3OsWrite(p->pFile, &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); p->iBufStart = p->iBufEnd = 0; p->iWriteOff += p->nBuffer; } assert( p->iBufEnd<p->nBuffer ); nRem -= nCopy; } } /* ** Flush any buffered data to disk and clean up the file-writer object. ** The results of using the file-writer after this call are undefined. ** Return SQLITE_OK if flushing the buffered data succeeds or is not ** required. Otherwise, return an SQLite error code. ** ** Before returning, set *piEof to the offset immediately following the ** last byte written to the file. */ static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){ int rc; if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ p->eFWErr = sqlite3OsWrite(p->pFile, &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); } *piEof = (p->iWriteOff + p->iBufEnd); sqlite3DbFree(db, p->aBuffer); rc = p->eFWErr; memset(p, 0, sizeof(FileWriter)); return rc; } /* ** Write value iVal encoded as a varint to the file-write object. Return ** SQLITE_OK if successful, or an SQLite error code if an error occurs. */ static void fileWriterWriteVarint(FileWriter *p, u64 iVal){ int nByte; u8 aByte[10]; nByte = sqlite3PutVarint(aByte, iVal); fileWriterWrite(p, aByte, nByte); } /* ** Write the current contents of the in-memory linked-list to a PMA. Return ** SQLITE_OK if successful, or an SQLite error code otherwise. ** ** The format of a PMA is: ** ** * A varint. This varint contains the total number of bytes of content ** in the PMA (not including the varint itself). ** ** * One or more records packed end-to-end in order of ascending keys. ** Each record consists of a varint followed by a blob of data (the ** key). The varint is the number of bytes in the blob of data. */ static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){ int rc = SQLITE_OK; /* Return code */ VdbeSorter *pSorter = pCsr->pSorter; FileWriter writer; memset(&writer, 0, sizeof(FileWriter)); if( pSorter->nInMemory==0 ){ assert( pSorter->pRecord==0 ); return rc; } rc = vdbeSorterSort(pCsr); /* If the first temporary PMA file has not been opened, open it now. */ if( rc==SQLITE_OK && pSorter->pTemp1==0 ){ rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1); assert( rc!=SQLITE_OK || pSorter->pTemp1 ); assert( pSorter->iWriteOff==0 ); assert( pSorter->nPMA==0 ); } if( rc==SQLITE_OK ){ SorterRecord *p; SorterRecord *pNext = 0; fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff); pSorter->nPMA++; fileWriterWriteVarint(&writer, pSorter->nInMemory); for(p=pSorter->pRecord; p; p=pNext){ pNext = p->pNext; fileWriterWriteVarint(&writer, p->nVal); fileWriterWrite(&writer, p->pVal, p->nVal); sqlite3DbFree(db, p); } pSorter->pRecord = p; rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff); } return rc; } /* ** Add a record to the sorter. */ int sqlite3VdbeSorterWrite( sqlite3 *db, /* Database handle */ const VdbeCursor *pCsr, /* Sorter cursor */ Mem *pVal /* Memory cell containing record */ ){ VdbeSorter *pSorter = pCsr->pSorter; int rc = SQLITE_OK; /* Return Code */ SorterRecord *pNew; /* New list element */ assert( pSorter ); |
︙ | ︙ | |||
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | ** * The total memory allocated for the in-memory list is greater ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true. */ if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && ( (pSorter->nInMemory>pSorter->mxPmaSize) || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull()) )){ rc = vdbeSorterListToPMA(db, pCsr); pSorter->nInMemory = 0; } return rc; } /* ** Helper function for sqlite3VdbeSorterRewind(). */ static int vdbeSorterInitMerge( sqlite3 *db, /* Database handle */ | > > > > > > | | 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 | ** * The total memory allocated for the in-memory list is greater ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true. */ if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && ( (pSorter->nInMemory>pSorter->mxPmaSize) || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull()) )){ #ifdef SQLITE_DEBUG i64 nExpect = pSorter->iWriteOff + sqlite3VarintLen(pSorter->nInMemory) + pSorter->nInMemory; #endif rc = vdbeSorterListToPMA(db, pCsr); pSorter->nInMemory = 0; assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) ); } return rc; } /* ** Helper function for sqlite3VdbeSorterRewind(). */ static int vdbeSorterInitMerge( sqlite3 *db, /* Database handle */ const VdbeCursor *pCsr, /* Cursor handle for this sorter */ i64 *pnByte /* Sum of bytes in all opened PMAs */ ){ VdbeSorter *pSorter = pCsr->pSorter; int rc = SQLITE_OK; /* Return code */ int i; /* Used to iterator through aIter[] */ i64 nByte = 0; /* Total bytes in all opened PMAs */ |
︙ | ︙ | |||
680 681 682 683 684 685 686 | return rc; } /* ** Once the sorter has been populated, this function is called to prepare ** for iterating through its contents in sorted order. */ | | | | 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | return rc; } /* ** Once the sorter has been populated, this function is called to prepare ** for iterating through its contents in sorted order. */ int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ VdbeSorter *pSorter = pCsr->pSorter; int rc; /* Return code */ sqlite3_file *pTemp2 = 0; /* Second temp file to use */ i64 iWrite2 = 0; /* Write offset for pTemp2 */ int nIter; /* Number of iterators used */ int nByte; /* Bytes of space required for aIter/aTree */ int N = 2; /* Power of 2 >= nIter */ assert( pSorter ); /* If no data has been written to disk, then do not do so now. Instead, ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly ** from the in-memory list. */ if( pSorter->nPMA==0 ){ *pbEof = !pSorter->pRecord; assert( pSorter->aTree==0 ); return vdbeSorterSort(pCsr); } /* Write the current in-memory list to a PMA. */ rc = vdbeSorterListToPMA(db, pCsr); if( rc!=SQLITE_OK ) return rc; /* Allocate space for aIter[] and aTree[]. */ nIter = pSorter->nPMA; if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT; assert( nIter>0 ); |
︙ | ︙ | |||
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | do { int iNew; /* Index of new, merged, PMA */ for(iNew=0; rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA; iNew++ ){ i64 nWrite; /* Number of bytes in new PMA */ /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1, ** initialize an iterator for each of them and break out of the loop. ** These iterators will be incrementally merged as the VDBE layer calls ** sqlite3VdbeSorterNext(). ** ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs, | > > > > | 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 | do { int iNew; /* Index of new, merged, PMA */ for(iNew=0; rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA; iNew++ ){ int rc2; /* Return code from fileWriterFinish() */ FileWriter writer; /* Object used to write to disk */ i64 nWrite; /* Number of bytes in new PMA */ memset(&writer, 0, sizeof(FileWriter)); /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1, ** initialize an iterator for each of them and break out of the loop. ** These iterators will be incrementally merged as the VDBE layer calls ** sqlite3VdbeSorterNext(). ** ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs, |
︙ | ︙ | |||
745 746 747 748 749 750 751 752 | /* Open the second temp file, if it is not already open. */ if( pTemp2==0 ){ assert( iWrite2==0 ); rc = vdbeSorterOpenTempFile(db, &pTemp2); } if( rc==SQLITE_OK ){ | < < < < > > < | | | < | | < > > | 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 | /* Open the second temp file, if it is not already open. */ if( pTemp2==0 ){ assert( iWrite2==0 ); rc = vdbeSorterOpenTempFile(db, &pTemp2); } if( rc==SQLITE_OK ){ int bEof = 0; fileWriterInit(db, pTemp2, &writer, iWrite2); fileWriterWriteVarint(&writer, nWrite); while( rc==SQLITE_OK && bEof==0 ){ VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ]; assert( pIter->pFile ); fileWriterWriteVarint(&writer, pIter->nKey); fileWriterWrite(&writer, pIter->aKey, pIter->nKey); rc = sqlite3VdbeSorterNext(db, pCsr, &bEof); } rc2 = fileWriterFinish(db, &writer, &iWrite2); if( rc==SQLITE_OK ) rc = rc2; } } if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){ break; }else{ sqlite3_file *pTmp = pSorter->pTemp1; |
︙ | ︙ | |||
788 789 790 791 792 793 794 | *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); return rc; } /* ** Advance to the next element in the sorter. */ | | | 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 | *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); return rc; } /* ** Advance to the next element in the sorter. */ int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ VdbeSorter *pSorter = pCsr->pSorter; int rc; /* Return code */ if( pSorter->aTree ){ int iPrev = pSorter->aTree[1];/* Index of iterator to advance */ int i; /* Index of aTree[] to recalculate */ |
︙ | ︙ | |||
818 819 820 821 822 823 824 | } /* ** Return a pointer to a buffer owned by the sorter that contains the ** current key. */ static void *vdbeSorterRowkey( | | | | 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 1004 1005 1006 1007 | } /* ** Return a pointer to a buffer owned by the sorter that contains the ** current key. */ static void *vdbeSorterRowkey( const VdbeSorter *pSorter, /* Sorter object */ int *pnKey /* OUT: Size of current key in bytes */ ){ void *pKey; if( pSorter->aTree ){ VdbeSorterIter *pIter; pIter = &pSorter->aIter[ pSorter->aTree[1] ]; *pnKey = pIter->nKey; pKey = pIter->aKey; }else{ *pnKey = pSorter->pRecord->nVal; pKey = pSorter->pRecord->pVal; } return pKey; } /* ** Copy the current sorter key into the memory cell pOut. */ int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){ VdbeSorter *pSorter = pCsr->pSorter; void *pKey; int nKey; /* Sorter key to copy into pOut */ pKey = vdbeSorterRowkey(pSorter, &nKey); if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){ return SQLITE_NOMEM; } |
︙ | ︙ | |||
863 864 865 866 867 868 869 | ** ** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM). ** Otherwise, set *pRes to a negative, zero or positive value if the ** key in pVal is smaller than, equal to or larger than the current sorter ** key. */ int sqlite3VdbeSorterCompare( | | | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 | ** ** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM). ** Otherwise, set *pRes to a negative, zero or positive value if the ** key in pVal is smaller than, equal to or larger than the current sorter ** key. */ int sqlite3VdbeSorterCompare( const VdbeCursor *pCsr, /* Sorter cursor */ Mem *pVal, /* Value to compare to current sorter key */ int *pRes /* OUT: Result of comparison */ ){ VdbeSorter *pSorter = pCsr->pSorter; void *pKey; int nKey; /* Sorter key to compare pVal with */ pKey = vdbeSorterRowkey(pSorter, &nKey); vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes); return SQLITE_OK; } #endif /* #ifndef SQLITE_OMIT_MERGE_SORT */ |
Changes to src/vdbetrace.c.
︙ | ︙ | |||
165 166 167 168 169 170 171 | /* ** Allocate a new Explain object */ void sqlite3ExplainBegin(Vdbe *pVdbe){ if( pVdbe ){ Explain *p; sqlite3BeginBenignMalloc(); | | < | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | /* ** Allocate a new Explain object */ void sqlite3ExplainBegin(Vdbe *pVdbe){ if( pVdbe ){ Explain *p; sqlite3BeginBenignMalloc(); p = (Explain *)sqlite3MallocZero( sizeof(Explain) ); if( p ){ p->pVdbe = pVdbe; sqlite3_free(pVdbe->pExplain); pVdbe->pExplain = p; sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase), SQLITE_MAX_LENGTH); p->str.useMalloc = 2; }else{ |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
138 139 140 141 142 143 144 | ** connection to it closes. Because the wal-index is transient, it can ** use an architecture-specific format; it does not have to be cross-platform. ** Hence, unlike the database and WAL file formats which store all values ** as big endian, the wal-index can store multi-byte values in the native ** byte order of the host computer. ** ** The purpose of the wal-index is to answer this question quickly: Given | | > | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | ** connection to it closes. Because the wal-index is transient, it can ** use an architecture-specific format; it does not have to be cross-platform. ** Hence, unlike the database and WAL file formats which store all values ** as big endian, the wal-index can store multi-byte values in the native ** byte order of the host computer. ** ** The purpose of the wal-index is to answer this question quickly: Given ** a page number P and a maximum frame index M, return the index of the ** last frame in the wal before frame M for page P in the WAL, or return ** NULL if there are no frames for page P in the WAL prior to M. ** ** The wal-index consists of a header region, followed by an one or ** more index blocks. ** ** The wal-index header contains the total number of frames within the WAL ** in the the mxFrame field. ** |
︙ | ︙ | |||
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 | ** currently holding locks that exclude all other readers, writers and ** checkpointers. */ pInfo = walCkptInfo(pWal); pInfo->nBackfill = 0; pInfo->aReadMark[0] = 0; for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; /* If more than one frame was recovered from the log file, report an ** event via sqlite3_log(). This is to help with identifying performance ** problems caused by applications routinely shutting down without ** checkpointing the log file. */ if( pWal->hdr.nPage ){ | > | 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 | ** currently holding locks that exclude all other readers, writers and ** checkpointers. */ pInfo = walCkptInfo(pWal); pInfo->nBackfill = 0; pInfo->aReadMark[0] = 0; for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame; /* If more than one frame was recovered from the log file, report an ** event via sqlite3_log(). This is to help with identifying performance ** problems caused by applications routinely shutting down without ** checkpointing the log file. */ if( pWal->hdr.nPage ){ |
︙ | ︙ | |||
1694 1695 1696 1697 1698 1699 1700 | mxPage = pWal->hdr.nPage; for(i=1; i<WAL_NREADER; i++){ u32 y = pInfo->aReadMark[i]; if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); if( rc==SQLITE_OK ){ | | | 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 | mxPage = pWal->hdr.nPage; for(i=1; i<WAL_NREADER; i++){ u32 y = pInfo->aReadMark[i]; if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); if( rc==SQLITE_OK ){ pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc==SQLITE_BUSY ){ mxSafeFrame = y; xBusy = 0; }else{ goto walcheckpoint_out; } |
︙ | ︙ | |||
2607 2608 2609 2610 2611 2612 2613 | pWal->nCkpt++; pWal->hdr.mxFrame = 0; sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); aSalt[1] = salt1; walIndexWriteHdr(pWal); pInfo->nBackfill = 0; | > | | 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 | pWal->nCkpt++; pWal->hdr.mxFrame = 0; sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); aSalt[1] = salt1; walIndexWriteHdr(pWal); pInfo->nBackfill = 0; pInfo->aReadMark[1] = 0; for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; assert( pInfo->aReadMark[0]==0 ); walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); }else if( rc!=SQLITE_BUSY ){ return rc; } } walUnlockShared(pWal, WAL_READ_LOCK(0)); |
︙ | ︙ |
Added test/atof1.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 | # 2012 June 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. # #*********************************************************************** # # Tests of the sqlite3AtoF() function. # set testdir [file dirname $argv0] source $testdir/tester.tcl if {![info exists __GNUC__]} { finish_test return } expr srand(1) for {set i 1} {$i<20000} {incr i} { set pow [expr {int((rand()-0.5)*100)}] set x [expr {pow((rand()-0.5)*2*rand(),$pow)}] set xf [format %.32e $x] # Verify that text->real conversions get exactly same ieee754 floating- # point value in SQLite as they do in TCL. # do_test atof1-1.$i.1 { set y [db eval "SELECT $xf=\$x"] if {!$y} { puts -nonewline \173[db eval "SELECT real2hex($xf), real2hex(\$x)"]\175 db eval "SELECT $xf+0.0 AS a, \$x AS b" { puts [format "\n%.60e\n%.60e\n%.60e" $x $a $b] } } set y } {1} # Verify that round-trip real->text->real conversions using the quote() # function preserve the bits of the numeric value exactly. # do_test atof1-1.$i.2 { set y [db eval {SELECT $x=CAST(quote($x) AS real)}] if {!$y} { db eval {SELECT real2hex($x) a, real2hex(CAST(quote($x) AS real)) b} {} puts "\nIN: $a $xf" puts [format {QUOTE: %16s %s} {} [db eval {SELECT quote($x)}]] db eval {SELECT CAST(quote($x) AS real) c} {} puts "OUT: $b [format %.32e $c]" } set y } {1} } finish_test |
Changes to test/backup.test.
︙ | ︙ | |||
419 420 421 422 423 424 425 | } {B} do_test backup-4.3.2 { db2 cache flush sqlite3_close db2 } {SQLITE_BUSY} do_test backup-4.3.3 { sqlite3_errmsg db2 | | | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | } {B} do_test backup-4.3.2 { db2 cache flush sqlite3_close db2 } {SQLITE_BUSY} do_test backup-4.3.3 { sqlite3_errmsg db2 } {unable to close due to unfinalized statements or unfinished backups} do_test backup-4.3.4 { B step 50 } {SQLITE_DONE} do_test backup-4.3.5 { B finish } {SQLITE_OK} |
︙ | ︙ |
Changes to test/date.test.
︙ | ︙ | |||
147 148 149 150 151 152 153 | datetest 2.51 {datetime('2003-10-22 12:24','nonsense')} NULL datetest 3.1 {strftime('%d','2003-10-31 12:34:56.432')} 31 datetest 3.2.1 {strftime('pre%fpost','2003-10-31 12:34:56.432')} pre56.432post datetest 3.2.2 {strftime('%f','2003-10-31 12:34:59.9999999')} 59.999 datetest 3.3 {strftime('%H','2003-10-31 12:34:56.432')} 12 datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304 | | | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | datetest 2.51 {datetime('2003-10-22 12:24','nonsense')} NULL datetest 3.1 {strftime('%d','2003-10-31 12:34:56.432')} 31 datetest 3.2.1 {strftime('pre%fpost','2003-10-31 12:34:56.432')} pre56.432post datetest 3.2.2 {strftime('%f','2003-10-31 12:34:59.9999999')} 59.999 datetest 3.3 {strftime('%H','2003-10-31 12:34:56.432')} 12 datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304 datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.024264259 datetest 3.6 {strftime('%m','2003-10-31 12:34:56.432')} 10 datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34 datetest 3.8.1 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696 datetest 3.8.2 {strftime('%s','2038-01-19 03:14:07')} 2147483647 datetest 3.8.3 {strftime('%s','2038-01-19 03:14:08')} 2147483648 datetest 3.8.4 {strftime('%s','2201-04-09 12:00:00')} 7298164800 datetest 3.8.5 {strftime('%s','9999-12-31 23:59:59')} 253402300799 |
︙ | ︙ |
Changes to test/fts3atoken.test.
︙ | ︙ | |||
170 171 172 173 174 175 176 177 178 179 180 181 182 183 | do_execsql_test 5.1 { CREATE VIRTUAL TABLE x1 USING fts3(name,TOKENIZE icu en_US); insert into x1 (name) values (NULL); insert into x1 (name) values (NULL); delete from x1; } } do_test fts3token-internal { execsql { SELECT fts3_tokenizer_internal_test() } } {ok} | > > > > > > > > > > | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | do_execsql_test 5.1 { CREATE VIRTUAL TABLE x1 USING fts3(name,TOKENIZE icu en_US); insert into x1 (name) values (NULL); insert into x1 (name) values (NULL); delete from x1; } proc cp_to_str {codepoint_list} { set fmt [string repeat %c [llength $codepoint_list]] eval [list format $fmt] $codepoint_list } do_test 5.2 { set str [cp_to_str {19968 26085 32822 32645 27874 23433 20986}] execsql { INSERT INTO x1 VALUES($str) } } {} } do_test fts3token-internal { execsql { SELECT fts3_tokenizer_internal_test() } } {ok} |
︙ | ︙ |
Changes to test/fts4unicode.test.
︙ | ︙ | |||
321 322 323 324 325 326 327 328 329 330 | "0 hello\u0301world hello\u0301world 1 helloworld helloworld" do_unicode_token_test3 5.11 "tokenchars=\u0301" \ "remove_diacritics=0" \ "hello\u0301world \u0301helloworld" \ "0 hello\u0301world hello\u0301world 1 helloworld helloworld" finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | "0 hello\u0301world hello\u0301world 1 helloworld helloworld" do_unicode_token_test3 5.11 "tokenchars=\u0301" \ "remove_diacritics=0" \ "hello\u0301world \u0301helloworld" \ "0 hello\u0301world hello\u0301world 1 helloworld helloworld" #------------------------------------------------------------------------- proc do_tokenize {tokenizer txt} { set res [list] foreach {a b c} [db one {SELECT fts3_tokenizer_test($tokenizer, $txt)}] { lappend res $b } set res } # Argument $lCodepoint must be a list of codepoints (integers) that # correspond to whitespace characters. This command creates a string # $W from the codepoints, then tokenizes "${W}hello{$W}world${W}" # using tokenizer $tokenizer. The test passes if the tokenizer successfully # extracts the two 5 character tokens. # proc do_isspace_test {tn tokenizer lCp} { set whitespace [format [string repeat %c [llength $lCp]] {*}$lCp] set txt "${whitespace}hello${whitespace}world${whitespace}" uplevel [list do_test $tn [list do_tokenize $tokenizer $txt] {hello world}] } set tokenizers [list unicode61] ifcapable icu { lappend tokenizers icu } # Some tests to check that the tokenizers can both identify white-space # codepoints. All codepoints tested below are of type "Zs" in the # UnicodeData.txt file. foreach T $tokenizers { do_isspace_test 6.$T.1 $T 32 do_isspace_test 6.$T.2 $T 160 do_isspace_test 6.$T.3 $T 5760 do_isspace_test 6.$T.4 $T 6158 do_isspace_test 6.$T.5 $T 8192 do_isspace_test 6.$T.6 $T 8193 do_isspace_test 6.$T.7 $T 8194 do_isspace_test 6.$T.8 $T 8195 do_isspace_test 6.$T.9 $T 8196 do_isspace_test 6.$T.10 $T 8197 do_isspace_test 6.$T.11 $T 8198 do_isspace_test 6.$T.12 $T 8199 do_isspace_test 6.$T.13 $T 8200 do_isspace_test 6.$T.14 $T 8201 do_isspace_test 6.$T.15 $T 8202 do_isspace_test 6.$T.16 $T 8239 do_isspace_test 6.$T.17 $T 8287 do_isspace_test 6.$T.18 $T 12288 do_isspace_test 6.$T.19 $T {32 160 5760 6158} do_isspace_test 6.$T.19 $T {8192 8193 8194 8195} do_isspace_test 6.$T.19 $T {8196 8197 8198 8199} do_isspace_test 6.$T.19 $T {8200 8201 8202 8239} do_isspace_test 6.$T.19 $T {8287 12288} } finish_test |
Changes to test/func.test.
︙ | ︙ | |||
308 309 310 311 312 313 314 | do_test func-4.36 { execsql {SELECT round(99999999999994.5);} } {99999999999995.0} do_test func-4.37 { execsql {SELECT round(9999999999999.55,1);} } {9999999999999.6} do_test func-4.38 { | | | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | do_test func-4.36 { execsql {SELECT round(99999999999994.5);} } {99999999999995.0} do_test func-4.37 { execsql {SELECT round(9999999999999.55,1);} } {9999999999999.6} do_test func-4.38 { execsql {SELECT round(9999999999999.556,2);} } {9999999999999.56} } # Test the upper() and lower() functions # do_test func-5.1 { execsql {SELECT upper(t1) FROM tbl1} |
︙ | ︙ |
Added test/index5.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 | # 2012 August 6 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix index5 do_test 1.1 { execsql { PRAGMA page_size = 1024; CREATE TABLE t1(x); BEGIN; } for {set i 0} {$i < 100000} {incr i} { execsql { INSERT INTO t1 VALUES(randstr(100,100)) } } execsql COMMIT execsql { CREATE INDEX i1 ON t1(x); DROP INDEX I1; PRAGMA main.page_size; } } {1024} db close testvfs tvfs tvfs filter xWrite tvfs script write_cb proc write_cb {xCall file handle iOfst} { if {[file tail $file]=="test.db"} { lappend ::write_list [expr $iOfst/1024] } puts "$xCall $file $args" } do_test 1.2 { sqlite3 db test.db -vfs tvfs set ::write_list [list] execsql { CREATE INDEX i1 ON t1(x) } } {} do_test 1.3 { set nForward 0 set nBackward 0 set nNoncont 0 set iPrev [lindex $::write_list 0] for {set i 1} {$i < [llength $::write_list]} {incr i} { set iNext [lindex $::write_list $i] if {$iNext==($iPrev+1)} { incr nForward } elseif {$iNext==($iPrev-1)} { incr nBackward } else { incr nNoncont } set iPrev $iNext } expr {$nForward > $nBackward} } {1} db close tvfs delete finish_test |
Changes to test/loadext.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ifcapable !load_ext { finish_test return } # The name of the test extension varies by operating system. # | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ifcapable !load_ext { finish_test return } # The name of the test extension varies by operating system. # if {$::tcl_platform(platform) eq "windows"} { set testextension ./testloadext.dll } else { set testextension ./libtestloadext.so } set gcc_shared "-shared -fPIC" if {$::tcl_platform(os) eq "Darwin"} { set gcc_shared -dynamiclib |
︙ | ︙ |
Changes to test/misc7.test.
︙ | ︙ | |||
373 374 375 376 377 378 379 | #---------------------------------------------------------------------- # Test the situation where a hot-journal is discovered but write-access # to it is denied. This should return SQLITE_BUSY. # # These tests do not work on windows due to restrictions in the # windows file system. # | | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | #---------------------------------------------------------------------- # Test the situation where a hot-journal is discovered but write-access # to it is denied. This should return SQLITE_BUSY. # # These tests do not work on windows due to restrictions in the # windows file system. # if {$tcl_platform(platform)!="windows"} { # Some network filesystems (ex: AFP) do not support setting read-only # permissions. Only run these tests if full unix permission setting # capabilities are supported. # file attributes test.db -permissions rw-r--r-- if {[file attributes test.db -permissions]==0644} { |
︙ | ︙ |
Changes to test/permutations.test.
︙ | ︙ | |||
110 111 112 113 114 115 116 | misc7.test mutex2.test notify2.test onefile.test pagerfault2.test savepoint4.test savepoint6.test select9.test speed1.test speed1p.test speed2.test speed3.test speed4.test speed4p.test sqllimits1.test tkt2686.test thread001.test thread002.test thread003.test thread004.test thread005.test trans2.test vacuum3.test incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test vtab_err.test walslow.test walcrash.test walcrash3.test | | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | misc7.test mutex2.test notify2.test onefile.test pagerfault2.test savepoint4.test savepoint6.test select9.test speed1.test speed1p.test speed2.test speed3.test speed4.test speed4p.test sqllimits1.test tkt2686.test thread001.test thread002.test thread003.test thread004.test thread005.test trans2.test vacuum3.test incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test vtab_err.test walslow.test walcrash.test walcrash3.test walthread.test rtree3.test indexfault.test securedel2.test }] if {[info exists ::env(QUICKTEST_INCLUDE)]} { set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)] } ############################################################################# # Start of tests |
︙ | ︙ |
Changes to test/pragma.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # # This file implements tests for the PRAGMA command. # # $Id: pragma.test,v 1.73 2009/01/12 14:01:45 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # do_not_use_codec # Test organization: | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # # This file implements tests for the PRAGMA command. # # $Id: pragma.test,v 1.73 2009/01/12 14:01:45 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix pragma # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # do_not_use_codec # Test organization: |
︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # pragma-10.*: Test the count_changes pragma in the presence of triggers. # pragma-11.*: Test the collation_list pragma. # pragma-14.*: Test the page_count pragma. # pragma-15.*: Test that the value set using the cache_size pragma is not # reset when the schema is reloaded. # pragma-16.*: Test proxy locking # pragma-20.*: Test data_store_directory. # ifcapable !pragma { finish_test return } | > > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | # pragma-10.*: Test the count_changes pragma in the presence of triggers. # pragma-11.*: Test the collation_list pragma. # pragma-14.*: Test the page_count pragma. # pragma-15.*: Test that the value set using the cache_size pragma is not # reset when the schema is reloaded. # pragma-16.*: Test proxy locking # pragma-20.*: Test data_store_directory. # pragma-22.*: Test that "PRAGMA [db].integrity_check" respects the "db" # directive - if it is present. # ifcapable !pragma { finish_test return } |
︙ | ︙ | |||
1549 1550 1551 1552 1553 1554 1555 1556 1557 | } {0 {}} do_test pragma-20.8 { catchsql {PRAGMA data_store_directory} } {0 {}} forcedelete data_dir } ;# endif windows finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1552 1553 1554 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 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 | } {0 {}} do_test pragma-20.8 { catchsql {PRAGMA data_store_directory} } {0 {}} forcedelete data_dir } ;# endif windows do_test 21.1 { # Create a corrupt database in testerr.db. And a non-corrupt at test.db. # db close forcedelete test.db sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA auto_vacuum = 0; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 1); } for {set i 0} {$i < 10} {incr i} { execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 } } db close forcecopy test.db testerr.db hexio_write testerr.db 15000 [string repeat 55 100] } {100} set mainerr {*** in database main *** Multiple uses for byte 672 of page 15} set auxerr {*** in database aux *** Multiple uses for byte 672 of page 15} do_test 22.2 { catch { db close } sqlite3 db testerr.db execsql { PRAGMA integrity_check } } [list $mainerr] do_test 22.3.1 { catch { db close } sqlite3 db test.db execsql { ATTACH 'testerr.db' AS 'aux'; PRAGMA integrity_check; } } [list $auxerr] do_test 22.3.2 { execsql { PRAGMA main.integrity_check; } } {ok} do_test 22.3.3 { execsql { PRAGMA aux.integrity_check; } } [list $auxerr] do_test 22.4.1 { catch { db close } sqlite3 db testerr.db execsql { ATTACH 'test.db' AS 'aux'; PRAGMA integrity_check; } } [list $mainerr] do_test 22.4.2 { execsql { PRAGMA main.integrity_check; } } [list $mainerr] do_test 22.4.3 { execsql { PRAGMA aux.integrity_check; } } {ok} finish_test |
Changes to test/releasetest.tcl.
︙ | ︙ | |||
214 215 216 217 218 219 220 | # Set the sub-directory to use. # set dir [string tolower [string map {- _ " " _} $name]] if {$::tcl_platform(platform)=="windows"} { append opts " -DSQLITE_OS_WIN=1" | < < | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | # Set the sub-directory to use. # set dir [string tolower [string map {- _ " " _} $name]] if {$::tcl_platform(platform)=="windows"} { append opts " -DSQLITE_OS_WIN=1" } else { append opts " -DSQLITE_OS_UNIX=1" } # Run the test. # set makefile [file normalize $::MAKEFILE] |
︙ | ︙ |
Added test/securedel2.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 | # 2012 August 7 # # 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 secure_delete pragma. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix securedel2 # Generate 1000 pseudo-random 64-bit blobs. # for {set i 1} {$i <= 1000} {incr i} { set aBlob($i) [string range [db one {SELECT quote(randomblob(8))}] 2 end-1] } proc detect_blob_prepare {zFile} { set nByte [file size $zFile] set ::detect_blob_data [hexio_read $zFile 0 $nByte] } proc detect_blob {zFile iBlob} { if {$zFile != ""} { detect_blob_prepare $zFile } string match "*$::aBlob($iBlob)*" $::detect_blob_data } do_test 1.1 { execsql { PRAGMA secure_delete = 1 } execsql { PRAGMA auto_vacuum = 0 } execsql { CREATE TABLE t1(x, y) } for {set i 1} {$i <= 1000} {incr i} { set x "X'[string repeat $aBlob($i) 1]'" set y "X'[string repeat $aBlob($i) 500]'" execsql "INSERT INTO t1 VALUES($x, $y)" } } {} do_test 1.2 { detect_blob test.db 1 } {1} forcecopy test.db test.db.bak do_execsql_test 1.3.1 { PRAGMA secure_delete = 0 } {0} do_execsql_test 1.3.2 { DELETE FROM t1 WHERE rowid = 1 } do_test 1.3.3 { detect_blob test.db 1 } {1} db close forcecopy test.db.bak test.db sqlite3 db test.db do_execsql_test 1.4.1 { PRAGMA secure_delete = 1 } {1} do_execsql_test 1.4.2 { DELETE FROM t1 WHERE rowid = 1 } do_test 1.4.3 { detect_blob test.db 1 } {0} do_execsql_test 1.5.1 { DELETE FROM t1 WHERE rowid>850 } {} do_test 1.5.2 { set n 0 detect_blob_prepare test.db for {set i 851} {$i <= 1000} {incr i 5} { incr n [detect_blob {} $i] } set n } {0} db close sqlite3 db test.db do_test 1.6.1 { execsql { PRAGMA cache_size = 200; PRAGMA secure_delete = 1; CREATE TABLE t2(x); SELECT * FROM t1; } for {set i 100} {$i < 5000} {incr i} { execsql { INSERT INTO t2 VALUES(randomblob($i)) } } execsql { DELETE FROM t1 } } {} do_test 1.6.2 { set n 0 detect_blob_prepare test.db for {set i 2} {$i <= 850} {incr i 5} { incr n [detect_blob {} $i] } set n } {0} finish_test |
Added test/spellfix.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 | # 2012 July 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix spellfix ifcapable !vtab { finish_test ; return } register_spellfix_module db set vocab { rabbi rabbit rabbits rabble rabid rabies raccoon raccoons race raced racer racers races racetrack racial racially racing rack racked racket racketeer racketeering racketeers rackets racking racks radar radars radial radially radian radiance radiant radiantly radiate radiated radiates radiating radiation radiations radiator radiators radical radically radicals radices radii radio radioactive radioastronomy radioed radiography radioing radiology radios radish radishes radium radius radix radon raft rafter rafters rafts rag rage raged rages ragged raggedly raggedness raging rags ragweed raid raided raider raiders raiding raids rail railed railer railers railing railroad railroaded railroader railroaders railroading railroads rails railway railways raiment rain rainbow raincoat raincoats raindrop raindrops rained rainfall rainier rainiest raining rains rainstorm rainy raise raised raiser raisers raises raisin raising rake raked rakes raking rallied rallies rally rallying ram ramble rambler rambles rambling ramblings ramification ramifications ramp rampage rampant rampart ramps ramrod rams ran ranch ranched rancher ranchers ranches ranching rancid random randomization randomize randomized randomizes randomly randomness randy rang range ranged rangeland ranger rangers ranges ranging rangy rank ranked ranker rankers rankest ranking rankings rankle rankly rankness ranks ransack ransacked ransacking ransacks ransom ransomer ransoming ransoms rant ranted ranter ranters ranting rants rap rapacious rape raped raper rapes rapid rapidity rapidly rapids rapier raping rapport rapprochement raps rapt raptly rapture raptures rapturous rare rarely rareness rarer rarest rarity rascal rascally rascals rash rasher rashly rashness rasp raspberry rasped rasping rasps raster rat rate rated rater raters rates rather ratification ratified ratifies ratify ratifying rating ratings ratio ration rational rationale rationales rationalities rationality rationalization rationalizations rationalize rationalized rationalizes rationalizing rationally rationals rationing rations ratios rats rattle rattled rattler rattlers rattles rattlesnake rattlesnakes rattling raucous ravage ravaged ravager ravagers ravages ravaging rave raved raven ravening ravenous ravenously ravens raves ravine ravines raving ravings raw rawer rawest rawly rawness ray rays raze razor razors re reabbreviate reabbreviated reabbreviates reabbreviating reach reachability reachable reachably reached reacher reaches reaching reacquired react reacted reacting reaction reactionaries reactionary reactions reactivate reactivated reactivates reactivating reactivation reactive reactively reactivity reactor reactors reacts read readability readable reader readers readied readier readies readiest readily readiness reading readings readjusted readout readouts reads ready readying real realest realign realigned realigning realigns realism realist realistic realistically realists realities reality } do_test 1.1 { 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 raspberry 6 rasp 4 rasps 4} 2 ril* {rail 4 railway 4 railing 4 rails 4 railways 4} 3 rilis* {realist 6 realistic 6 realistically 6 realists 6 realism 6} 4 reail* {realities 3 reality 3 real 3 realest 3 realist 3} 5 ras* {rasp 3 rash 3 rasped 3 rasping 3 rasps 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} 9 renstom* {rainstorm 8 ransomer 6 ransom 6 ransoming 6 ransoms 6} } { do_execsql_test 1.2.$tn { SELECT word, matchlen FROM t1 WHERE word MATCH $word LIMIT 5 } $res } do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING spellfix1; INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul'); INSERT INTO t2 (word, soundslike) VALUES('psalm', 'sarm'); SELECT word, matchlen FROM t2 WHERE word MATCH 'sar*' LIMIT 5; } {psalm 4} do_execsql_test 2.2 { SELECT word, matchlen FROM t2 WHERE word MATCH 'skol*' LIMIT 5; } {school 6} set vocab { kangaroo kanji kappa karate keel keeled keeling keels keen keener keenest keenly keenness keep keeper keepers keeping keeps ken kennel kennels kept kerchief kerchiefs kern kernel kernels kerosene ketchup kettle kettles key keyboard keyboards keyed keyhole keying keynote keypad keypads keys keystroke keystrokes keyword keywords kick kicked kicker kickers kicking kickoff kicks kid kidded kiddie kidding kidnap kidnapper kidnappers kidnapping kidnappings kidnaps kidney kidneys kids kill killed killer killers killing killingly killings killjoy kills kilobit kilobits kiloblock kilobyte kilobytes kilogram kilograms kilohertz kilohm kilojoule kilometer kilometers kiloton kilovolt kilowatt kiloword kimono kin kind kinder kindergarten kindest kindhearted kindle kindled kindles kindling kindly kindness kindred kinds kinetic king kingdom kingdoms kingly kingpin kings kink kinky kinship kinsman kiosk kiss kissed kisser kissers kisses kissing kit kitchen kitchenette kitchens kite kited kites kiting kits kitten kittenish kittens kitty klaxon kludge kludges klystron knack knapsack knapsacks knave knaves knead kneads knee kneecap kneed kneeing kneel kneeled kneeling kneels knees knell knells knelt knew knife knifed knifes knifing knight knighted knighthood knighting knightly knights knit knits knives knob knobs knock knockdown knocked knocker knockers knocking knockout knocks knoll knolls knot knots knotted knotting know knowable knower knowhow knowing knowingly knowledge knowledgeable known knows knuckle knuckled knuckles koala kosher kudo } do_execsql_test 3.1 { CREATE TABLE costs(iLang, cFrom, cTo, iCost); INSERT INTO costs VALUES(0, 'a', 'e', 1); INSERT INTO costs VALUES(0, 'e', 'i', 1); INSERT INTO costs VALUES(0, 'i', 'o', 1); INSERT INTO costs VALUES(0, 'o', 'u', 1); INSERT INTO costs VALUES(0, 'u', 'a', 1); CREATE VIRTUAL TABLE t3 USING spellfix1(edit_cost_table=costs); } do_test 3.2 { foreach w $vocab { execsql { INSERT INTO t3(word) VALUES($w) } } } {} breakpoint foreach {tn word res} { 1 kos* {kosher 3 kiosk 4 kudo 2 kiss 3 kissed 3} 2 kellj* {killjoy 5 kill 4 killed 4 killer 4 killers 4} 3 kellj {kill 4 kills 5 killjoy 7 keel 4 killed 6} } { do_execsql_test 1.2.$tn { SELECT word, matchlen FROM t3 WHERE word MATCH $word ORDER BY score, word LIMIT 5 } $res } finish_test |
Changes to test/wal2.test.
︙ | ︙ | |||
122 123 124 125 126 127 128 | } {4 10} set RECOVER [list \ {0 1 lock exclusive} {1 7 lock exclusive} \ {1 7 unlock exclusive} {0 1 unlock exclusive} \ ] set READ [list \ | < > > > | | 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 | } {4 10} set RECOVER [list \ {0 1 lock exclusive} {1 7 lock exclusive} \ {1 7 unlock exclusive} {0 1 unlock exclusive} \ ] set READ [list \ {4 1 lock shared} {4 1 unlock shared} \ ] set INITSLOT [list \ {4 1 lock exclusive} {4 1 unlock exclusive} \ ] foreach {tn iInsert res wal_index_hdr_mod wal_locks} " 2 5 {5 15} 0 {$RECOVER $READ} 3 6 {6 21} 1 {$RECOVER $READ} 4 7 {7 28} 2 {$RECOVER $READ} 5 8 {8 36} 3 {$RECOVER $READ} 6 9 {9 45} 4 {$RECOVER $READ} 7 10 {10 55} 5 {$RECOVER $READ} 8 11 {11 66} 6 {$RECOVER $READ} 9 12 {12 78} 7 {$RECOVER $READ} 10 13 {13 91} 8 {$RECOVER $READ} 11 14 {14 105} 9 {$RECOVER $READ} 12 15 {15 120} -1 {$INITSLOT $READ} " { do_test wal2-1.$tn.1 { execsql { INSERT INTO t1 VALUES($iInsert) } set ::locks [list] proc tvfs_cb {method args} { lappend ::locks [lindex $args 2] |
︙ | ︙ |
Changes to test/wal3.test.
︙ | ︙ | |||
651 652 653 654 655 656 657 | faultsim_save_and_close testvfs T -default 1 faultsim_restore_and_reopen T filter xShmLock T script lock_callback proc lock_callback {method file handle spec} { | | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 | faultsim_save_and_close testvfs T -default 1 faultsim_restore_and_reopen T filter xShmLock T script lock_callback proc lock_callback {method file handle spec} { if {$spec == "1 7 unlock exclusive"} { T filter {} set ::r [catchsql { SELECT * FROM b } db2] } } sqlite3 db test.db sqlite3 db2 test.db do_test wal3-8.5 { |
︙ | ︙ |
Changes to test/walro.test.
︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 64 65 | } file mkdir walro do_test 1.1.1 { code2 { sqlite3 db2 test.db } sql2 { PRAGMA journal_mode = WAL; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES('a', 'b'); } file exists test.db-shm } {1} | > | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | } file mkdir walro do_test 1.1.1 { code2 { sqlite3 db2 test.db } sql2 { PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES('a', 'b'); } file exists test.db-shm } {1} |
︙ | ︙ | |||
159 160 161 162 163 164 165 | file attributes test.db-shm -permissions r--r--r-- code1 { sqlite3 db file:test.db?readonly_shm=1 } csql1 { SELECT * FROM t1 } } {1 {attempt to write a readonly database}} do_test 1.3.2.4 { code1 { sqlite3_extended_errcode db } } {SQLITE_READONLY_RECOVERY} | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | file attributes test.db-shm -permissions r--r--r-- code1 { sqlite3 db file:test.db?readonly_shm=1 } csql1 { SELECT * FROM t1 } } {1 {attempt to write a readonly database}} do_test 1.3.2.4 { code1 { sqlite3_extended_errcode db } } {SQLITE_READONLY_RECOVERY} #----------------------------------------------------------------------- # Test cases 1.4.* check that checkpoints and log wraps don't prevent # read-only connections from reading the database. do_test 1.4.1 { code1 { db close } forcedelete test.db-shm file exists test.db-shm } {0} # Open one read-only and one read-write connection. Write some data # and then run a checkpoint using the read-write connection. Then # check the read-only connection can still read. do_test 1.4.2 { code1 { sqlite3 db file:test.db?readonly_shm=1 } code2 { sqlite3 db2 test.db } csql2 { INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); PRAGMA wal_checkpoint; } } {0 {0 3 3}} do_test 1.4.3 { csql1 { SELECT * FROM t1 } } {0 {a b c d e f g h i j k l 1 2 3 4 5 6}} # Using the read-write connection, open a transaction and write lots # of data - causing a cache spill and a log wrap. Then check that the # read-only connection can still read the database. do_test 1.4.4.1 { csql2 { PRAGMA cache_size = 10; BEGIN; CREATE TABLE t2(x, y); INSERT INTO t2 VALUES('abc', 'xyz'); INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; } file size test.db-wal } {147800} do_test 1.4.4.2 { csql1 { SELECT * FROM t1 } } {0 {a b c d e f g h i j k l 1 2 3 4 5 6}} do_test 1.4.4.3 { csql2 COMMIT csql1 { SELECT count(*) FROM t2 } } {0 512} do_test 1.4.5 { code2 { db2 close } code1 { db close } } {} } forcedelete test.db #----------------------------------------------------------------------- # Test cases 2.* check that a read-only connection may read the # database file while a checkpoint operation is ongoing. # do_multiclient_test tn { # Do not run tests with the connections in the same process. # if {$tn==2} continue # Close all connections and delete the database. # code1 { db close } code2 { db2 close } code3 { db3 close } forcedelete test.db forcedelete walro foreach c {code1 code2 code3} { $c { sqlite3_shutdown sqlite3_config_uri 1 } } proc tv_hook {x file args} { if {[file tail $file]=="test.db-wal"} { do_test 2.1.2 { code2 { sqlite3 db2 file:test.db?readonly_shm=1 } csql2 { SELECT count(*) FROM t2 } } {0 4} do_test 2.1.3 { code2 { db2 close } } {} } } do_test 2.1.1 { testvfs tv -default 1 -fullshm 1 tv script tv_hook tv filter {} code1 { sqlite3 db test.db } csql1 { PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; BEGIN; CREATE TABLE t2(x, y); INSERT INTO t2 VALUES('abc', 'xyz'); INSERT INTO t2 SELECT x||y, y||x FROM t2; INSERT INTO t2 SELECT x||y, y||x FROM t2; COMMIT; } } {0 wal} tv filter xSync set res [csql1 { PRAGMA wal_checkpoint }] do_test 2.1.4 { set res } {0 {0 2 2}} do_test 2.1.5 { code1 { db close } code1 { tv delete } } {} } finish_test |
Changes to test/walthread.test.
︙ | ︙ | |||
273 274 275 276 277 278 279 | error "Failed read transaction: $results" } } proc write_transaction {} { db eval { BEGIN; | | | | 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | error "Failed read transaction: $results" } } proc write_transaction {} { db eval { BEGIN; INSERT INTO t1 VALUES(randomblob(101 + $::E(pid))); INSERT INTO t1 VALUES(randomblob(101 + $::E(pid))); INSERT INTO t1 SELECT md5sum(x) FROM t1; COMMIT; } } # Turn off auto-checkpoint. Otherwise, an auto-checkpoint run by a # writer may cause the dedicated checkpoint thread to return an |
︙ | ︙ |
Added tool/build-all-msvc.bat.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | @ECHO OFF :: :: build-all-msvc.bat -- :: :: Multi-Platform Build Tool for MSVC :: SETLOCAL REM SET __ECHO=ECHO REM SET __ECHO2=ECHO IF NOT DEFINED _AECHO (SET _AECHO=REM) IF NOT DEFINED _CECHO (SET _CECHO=REM) IF NOT DEFINED _VECHO (SET _VECHO=REM) %_AECHO% Running %0 %* REM SET DFLAGS=/L %_VECHO% DFlags = '%DFLAGS%' SET FFLAGS=/V /F /G /H /I /R /Y /Z %_VECHO% FFlags = '%FFLAGS%' SET ROOT=%~dp0\.. SET ROOT=%ROOT:\\=\% %_VECHO% Root = '%ROOT%' REM REM NOTE: The first and only argument to this batch file should be the output REM directory where the platform-specific binary directories should be REM created. REM SET BINARYDIRECTORY=%1 IF NOT DEFINED BINARYDIRECTORY ( GOTO usage ) %_VECHO% BinaryDirectory = '%BINARYDIRECTORY%' SET DUMMY=%2 IF DEFINED DUMMY ( GOTO usage ) REM REM NOTE: From this point, we need a clean error level. Reset it now. REM CALL :fn_ResetErrorLevel REM REM NOTE: Change the current directory to the root of the source tree, saving REM the current directory on the directory stack. REM %__ECHO2% PUSHD "%ROOT%" IF ERRORLEVEL 1 ( ECHO Could not change directory to "%ROOT%". GOTO errors ) REM REM NOTE: This batch file requires the ComSpec environment variable to be set, REM typically to something like "C:\Windows\System32\cmd.exe". REM IF NOT DEFINED ComSpec ( ECHO The ComSpec environment variable must be defined. GOTO errors ) REM REM NOTE: This batch file requires the VcInstallDir environment variable to be REM set. Tyipcally, this means this batch file needs to be run from an REM MSVC command prompt. REM IF NOT DEFINED VCINSTALLDIR ( ECHO The VCINSTALLDIR environment variable must be defined. GOTO errors ) REM REM NOTE: If the list of platforms is not already set, use the default list. REM IF NOT DEFINED PLATFORMS ( SET PLATFORMS=x86 x86_amd64 x86_arm ) %_VECHO% Platforms = '%PLATFORMS%' REM REM NOTE: Setup environment variables to translate between the MSVC platform REM names and the names to be used for the platform-specific binary REM directories. REM SET x86_NAME=x86 SET x86_amd64_NAME=x64 SET x86_arm_NAME=ARM %_VECHO% x86_Name = '%x86_NAME%' %_VECHO% x86_amd64_Name = '%x86_amd64_NAME%' %_VECHO% x86_arm_Name = '%x86_arm_NAME%' REM REM NOTE: Check for the external tools needed during the build process ^(i.e. REM those that do not get compiled as part of the build process itself^) REM along the PATH. REM FOR %%T IN (gawk.exe tclsh85.exe) DO ( SET %%T_PATH=%%~dp$PATH:T ) REM REM NOTE: Set the TOOLPATH variable to contain all the directories where the REM external tools were found in the search above. REM SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH% %_VECHO% ToolPath = '%TOOLPATH%' REM REM NOTE: Check for MSVC 2012 because the Windows SDK directory handling is REM slightly different for that version. REM IF "%VisualStudioVersion%" == "11.0" ( SET SET_NSDKLIBPATH=1 ) ELSE ( CALL :fn_UnsetVariable SET_NSDKLIBPATH ) REM REM NOTE: This is the outer loop. There should be exactly one iteration per REM platform. REM FOR %%P IN (%PLATFORMS%) DO ( REM REM NOTE: Using the MSVC platform name, lookup the simpler platform name to REM be used for the name of the platform-specific binary directory via REM the environment variables setup earlier. REM CALL :fn_SetVariable %%P_NAME PLATFORMNAME REM REM NOTE: This is the inner loop. There should be exactly one iteration. REM This loop is necessary because the PlatformName environment REM variable was set above and that value is needed by some of the REM commands contained in the inner loop. If these commands were REM directly contained in the outer loop, the PlatformName environment REM variable would be stuck with its initial empty value instead. REM FOR /F "tokens=2* delims==" %%D IN ('SET PLATFORMNAME') DO ( REM REM NOTE: Attempt to clean the environment of all variables used by MSVC REM and/or Visual Studio. This block may need to be updated in the REM future to account for additional environment variables. REM CALL :fn_UnsetVariable DevEnvDir CALL :fn_UnsetVariable ExtensionSdkDir CALL :fn_UnsetVariable Framework35Version CALL :fn_UnsetVariable FrameworkDir CALL :fn_UnsetVariable FrameworkDir32 CALL :fn_UnsetVariable FrameworkVersion CALL :fn_UnsetVariable FrameworkVersion32 CALL :fn_UnsetVariable FSHARPINSTALLDIR CALL :fn_UnsetVariable INCLUDE CALL :fn_UnsetVariable LIB CALL :fn_UnsetVariable LIBPATH CALL :fn_UnsetVariable Platform REM CALL :fn_UnsetVariable VCINSTALLDIR CALL :fn_UnsetVariable VSINSTALLDIR CALL :fn_UnsetVariable WindowsSdkDir CALL :fn_UnsetVariable WindowsSdkDir_35 CALL :fn_UnsetVariable WindowsSdkDir_old REM REM NOTE: Reset the PATH here to the absolute bare minimum required. REM SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot% REM REM NOTE: Launch a nested command shell to perform the following steps: REM REM 1. Setup the MSVC environment for this platform using the REM official batch file. REM REM 2. Make sure that no stale build output files are present. REM REM 3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this REM platform. REM REM 4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this REM platform to the platform-specific directory beneath the REM binary directory. REM "%ComSpec%" /C ( REM REM NOTE: Attempt to setup the MSVC environment for this platform. REM %__ECHO% CALL "%VCINSTALLDIR%\vcvarsall.bat" %%P IF ERRORLEVEL 1 ( ECHO Failed to call "%VCINSTALLDIR%\vcvarsall.bat" for platform %%P. GOTO errors ) REM REM NOTE: If this batch file is not running in "what-if" mode, check to REM be sure we were actually able to setup the MSVC environment as REM current versions of their official batch file do not set the REM exit code upon failure. REM IF NOT DEFINED __ECHO ( IF NOT DEFINED WindowsSdkDir ( ECHO Cannot build, Windows SDK not found for platform %%P. GOTO errors ) ) REM REM NOTE: When using MSVC 2012, the native SDK path cannot simply use REM the "lib" sub-directory beneath the location specified in the REM WindowsSdkDir environment variable because that location does REM not actually contain the necessary library files for x86. REM This must be done for each iteration because it relies upon REM the WindowsSdkDir environment variable being set by the batch REM file used to setup the MSVC environment. REM IF DEFINED SET_NSDKLIBPATH ( CALL :fn_SetVariable WindowsSdkDir NSDKLIBPATH CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86 ) REM REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC REM makefile to clean any stale build output from previous REM iterations of this loop and/or previous runs of this batch REM file, etc. REM IF NOT DEFINED NOCLEAN ( %__ECHO% nmake -f Makefile.msc clean IF ERRORLEVEL 1 ( ECHO Failed to clean for platform %%P. GOTO errors ) ) ELSE ( REM REM NOTE: Even when the cleaning step has been disabled, we still need REM to remove the build output for the files we are specifically REM wanting to build for each platform. REM %__ECHO% DEL /Q sqlite3.dll sqlite3.lib sqlite3.pdb ) REM REM NOTE: Invoke NMAKE with the MSVC makefile to build the "sqlite3.dll" REM binary. The x86 compiler will be used to compile the native REM command line tools needed during the build process itself. REM Also, disable looking for and/or linking to the native Tcl REM runtime library. REM %__ECHO% nmake -f Makefile.msc sqlite3.dll "NCC=""%VCINSTALLDIR%\bin\cl.exe""" USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% IF ERRORLEVEL 1 ( ECHO Failed to build "sqlite3.dll" for platform %%P. GOTO errors ) REM REM NOTE: Copy the "sqlite3.dll" file to the platform-specific directory REM beneath the binary directory. REM %__ECHO% XCOPY sqlite3.dll "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( ECHO Failed to copy "sqlite3.dll" to "%BINARYDIRECTORY%\%%D\". GOTO errors ) REM REM NOTE: Copy the "sqlite3.lib" file to the platform-specific directory REM beneath the binary directory. REM %__ECHO% XCOPY sqlite3.lib "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( ECHO Failed to copy "sqlite3.lib" to "%BINARYDIRECTORY%\%%D\". GOTO errors ) REM REM NOTE: Copy the "sqlite3.pdb" file to the platform-specific directory REM beneath the binary directory unless we are prevented from doing REM so. REM IF NOT DEFINED NOSYMBOLS ( %__ECHO% XCOPY sqlite3.pdb "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( ECHO Failed to copy "sqlite3.pdb" to "%BINARYDIRECTORY%\%%D\". GOTO errors ) ) ) ) REM REM NOTE: Handle any errors generated during the nested command shell. REM IF ERRORLEVEL 1 ( GOTO errors ) ) REM REM NOTE: Restore the saved current directory from the directory stack. REM %__ECHO2% POPD IF ERRORLEVEL 1 ( ECHO Could not restore directory. GOTO errors ) REM REM NOTE: If we get to this point, we have succeeded. REM GOTO no_errors :fn_ResetErrorLevel VERIFY > NUL GOTO :EOF :fn_SetErrorLevel VERIFY MAYBE 2> NUL GOTO :EOF :fn_SetVariable SETLOCAL IF NOT DEFINED %1 GOTO :EOF IF "%2" == "" GOTO :EOF SET __ECHO_CMD=ECHO %%%1%% FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO ( SET VALUE=%%V ) ENDLOCAL && SET %2=%VALUE% GOTO :EOF :fn_UnsetVariable IF NOT "%1" == "" ( SET %1= CALL :fn_ResetErrorLevel ) GOTO :EOF :fn_AppendVariable SET __ECHO_CMD=ECHO %%%1%% IF DEFINED %1 ( FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO ( SET %1=%%V%~2 ) ) ELSE ( SET %1=%~2 ) SET __ECHO_CMD= CALL :fn_ResetErrorLevel GOTO :EOF :usage ECHO. ECHO Usage: %~nx0 ^<binaryDirectory^> ECHO. GOTO errors :errors CALL :fn_SetErrorLevel ENDLOCAL ECHO. ECHO Failure, errors were encountered. GOTO end_of_file :no_errors CALL :fn_ResetErrorLevel ENDLOCAL ECHO. ECHO Success, no errors were encountered. GOTO end_of_file :end_of_file %__ECHO% EXIT /B %ERRORLEVEL% |
Changes to tool/lemon.c.
︙ | ︙ | |||
4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 | char pattern[LINESIZE]; int i; if( lemp->tokenprefix ) prefix = lemp->tokenprefix; else prefix = ""; in = file_open(lemp,".h","rb"); if( in ){ for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); if( strcmp(line,pattern) ) break; } fclose(in); | > > | | 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 | char pattern[LINESIZE]; int i; if( lemp->tokenprefix ) prefix = lemp->tokenprefix; else prefix = ""; in = file_open(lemp,".h","rb"); if( in ){ int nextChar; for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); if( strcmp(line,pattern) ) break; } nextChar = fgetc(in); fclose(in); if( i==lemp->nterminal && nextChar==EOF ){ /* No change in the file. Don't rewrite it. */ return; } } out = file_open(lemp,".h","wb"); if( out ){ for(i=1; i<lemp->nterminal; i++){ |
︙ | ︙ |
Changes to tool/mksqlite3c-noext.tcl.
︙ | ︙ | |||
96 97 98 99 100 101 102 | hash.h hwtime.h keywordhash.h mutex.h opcodes.h os_common.h os.h | < | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | hash.h hwtime.h keywordhash.h mutex.h opcodes.h os_common.h os.h pager.h parse.h pcache.h sqlite3ext.h sqlite3.h sqliteicu.h sqliteInt.h |
︙ | ︙ | |||
229 230 231 232 233 234 235 | mem0.c mem1.c mem2.c mem3.c mem5.c mutex.c mutex_noop.c | < < | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | mem0.c mem1.c mem2.c mem3.c mem5.c mutex.c mutex_noop.c mutex_unix.c mutex_w32.c malloc.c printf.c random.c utf.c util.c hash.c opcodes.c os_unix.c os_win.c bitvec.c pcache.c pcache1.c rowset.c |
︙ | ︙ |
Changes to tool/mksqlite3c.tcl.
︙ | ︙ | |||
100 101 102 103 104 105 106 | hash.h hwtime.h keywordhash.h mutex.h opcodes.h os_common.h os.h | < | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | hash.h hwtime.h keywordhash.h mutex.h opcodes.h os_common.h os.h pager.h parse.h pcache.h rtree.h sqlite3ext.h sqlite3.h sqliteicu.h |
︙ | ︙ | |||
234 235 236 237 238 239 240 | mem0.c mem1.c mem2.c mem3.c mem5.c mutex.c mutex_noop.c | < < | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | mem0.c mem1.c mem2.c mem3.c mem5.c mutex.c mutex_noop.c mutex_unix.c mutex_w32.c malloc.c printf.c random.c utf.c util.c hash.c opcodes.c os_unix.c os_win.c bitvec.c pcache.c pcache1.c rowset.c |
︙ | ︙ |
Changes to tool/mksqlite3internalh.tcl.
︙ | ︙ | |||
57 58 59 60 61 62 63 | btreeInt.h hash.h hwtime.h keywordhash.h opcodes.h os_common.h os.h | < | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | btreeInt.h hash.h hwtime.h keywordhash.h opcodes.h os_common.h os.h pager.h parse.h sqlite3ext.h sqlite3.h sqliteInt.h sqliteLimit.h vdbe.h |
︙ | ︙ |
Added tool/mkvsix.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 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 | #!/usr/bin/tclsh # # This script is used to generate a VSIX (Visual Studio Extension) file for # SQLite usable by Visual Studio. proc fail { {error ""} {usage false} } { if {[string length $error] > 0} then { puts stdout $error if {!$usage} then {exit 1} } puts stdout "usage:\ [file tail [info nameofexecutable]]\ [file tail [info script]] <binaryDirectory> \[sourceDirectory\]" exit 1 } proc getEnvironmentVariable { name } { # # NOTE: Returns the value of the specified environment variable or an empty # string for environment variables that do not exist in the current # process environment. # return [expr {[info exists ::env($name)] ? $::env($name) : ""}] } proc getTemporaryPath {} { # # NOTE: Returns the normalized path to the first temporary directory found # in the typical set of environment variables used for that purpose # or an empty string to signal a failure to locate such a directory. # set names [list] foreach name [list TEMP TMP] { lappend names [string toupper $name] [string tolower $name] \ [string totitle $name] } foreach name $names { set value [getEnvironmentVariable $name] if {[string length $value] > 0} then { return [file normalize $value] } } return "" } proc appendArgs { args } { # # NOTE: Returns all passed arguments joined together as a single string with # no intervening spaces between arguments. # eval append result $args } proc readFile { fileName } { # # NOTE: Reads and returns the entire contents of the specified file, which # may contain binary data. # set file_id [open $fileName RDONLY] fconfigure $file_id -encoding binary -translation binary set result [read $file_id] close $file_id return $result } proc writeFile { fileName data } { # # NOTE: Writes the entire contents of the specified file, which may contain # binary data. # set file_id [open $fileName {WRONLY CREAT TRUNC}] fconfigure $file_id -encoding binary -translation binary puts -nonewline $file_id $data close $file_id return "" } proc substFile { fileName } { # # NOTE: Performs all Tcl command, variable, and backslash substitutions in # the specified file and then re-writes the contents of that same file # with the substituted data. # return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]] } proc replacePlatform { fileName platformName } { # # NOTE: Returns the specified file name containing the platform name instead # of platform placeholder tokens. # return [string map [list <platform> $platformName] $fileName] } set script [file normalize [info script]] if {[string length $script] == 0} then { fail "script file currently being evaluated is unknown" true } set path [file dirname $script] set rootName [file rootname [file tail $script]] ############################################################################### # # NOTE: Process and verify all the command line arguments. # set argc [llength $argv] if {$argc != 1 && $argc != 2} then {fail} set binaryDirectory [lindex $argv 0] if {[string length $binaryDirectory] == 0} then { fail "invalid binary directory" } if {![file exists $binaryDirectory] || \ ![file isdirectory $binaryDirectory]} then { fail "binary directory does not exist" } if {$argc == 2} then { set sourceDirectory [lindex $argv 1] } else { # # NOTE: Assume that the source directory is the parent directory of the one # that contains this script file. # set sourceDirectory [file dirname $path] } if {[string length $sourceDirectory] == 0} then { fail "invalid source directory" } if {![file exists $sourceDirectory] || \ ![file isdirectory $sourceDirectory]} then { fail "source directory does not exist" } ############################################################################### # # NOTE: Evaluate the user-specific customizations file, if it exists. # set userFile [file join $path [appendArgs \ $rootName . $tcl_platform(user) .tcl]] if {[file exists $userFile] && \ [file isfile $userFile]} then { source $userFile } ############################################################################### set templateFile [file join $path win sqlite.vsix] if {![file exists $templateFile] || \ ![file isfile $templateFile]} then { fail [appendArgs "template file \"" $templateFile "\" does not exist"] } set currentDirectory [pwd] set outputFile [file join $currentDirectory sqlite-output.vsix] if {[file exists $outputFile]} then { fail [appendArgs "output file \"" $outputFile "\" already exists"] } ############################################################################### # # NOTE: Make sure that a valid temporary directory exists. # set temporaryDirectory [getTemporaryPath] if {[string length $temporaryDirectory] == 0 || \ ![file exists $temporaryDirectory] || \ ![file isdirectory $temporaryDirectory]} then { fail "cannot locate a usable temporary directory" } # # NOTE: Setup the staging directory to have a unique name inside of the # configured temporary directory. # set stagingDirectory [file normalize [file join $temporaryDirectory \ [appendArgs $rootName . [pid]]]] ############################################################################### # # NOTE: Configure the external zipping tool. First, see if it has already # been pre-configured. If not, try to query it from the environment. # Finally, fallback on the default of simply "zip", which will then # be assumed to exist somewhere along the PATH. # if {![info exists zip]} then { if {[info exists env(ZipTool)]} then { set zip $env(ZipTool) } if {![info exists zip] || ![file exists $zip]} then { set zip zip } } # # NOTE: Configure the external unzipping tool. First, see if it has already # been pre-configured. If not, try to query it from the environment. # Finally, fallback on the default of simply "unzip", which will then # be assumed to exist somewhere along the PATH. # if {![info exists unzip]} then { if {[info exists env(UnZipTool)]} then { set unzip $env(UnZipTool) } if {![info exists unzip] || ![file exists $unzip]} then { set unzip unzip } } ############################################################################### # # NOTE: Attempt to extract the SQLite version from the "sqlite3.h" header file # in the source directory. This script assumes that the header file has # already been generated by the build process. # set pattern {^#define\s+SQLITE_VERSION\s+"(.*)"$} set data [readFile [file join $sourceDirectory sqlite3.h]] if {![regexp -line -- $pattern $data dummy version]} then { fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \ [file join $sourceDirectory sqlite3.h] \"] } ############################################################################### # # NOTE: Setup the master file list data, including the necessary flags. # if {![info exists fileNames(source)]} then { set fileNames(source) [list "" "" "" \ [file join $sourceDirectory sqlite3.h] \ [file join $binaryDirectory <platform> sqlite3.lib] \ [file join $binaryDirectory <platform> sqlite3.dll]] if {![info exists no(symbols)]} then { lappend fileNames(source) \ [file join $binaryDirectory <platform> sqlite3.pdb] } } if {![info exists fileNames(destination)]} then { set fileNames(destination) [list \ [file join $stagingDirectory extension.vsixmanifest] \ [file join $stagingDirectory SDKManifest.xml] \ [file join $stagingDirectory DesignTime CommonConfiguration \ <platform> SQLite.WinRT.props] \ [file join $stagingDirectory DesignTime CommonConfiguration \ <platform> sqlite3.h] \ [file join $stagingDirectory DesignTime CommonConfiguration \ <platform> sqlite3.lib] \ [file join $stagingDirectory Redist CommonConfiguration \ <platform> sqlite3.dll]] if {![info exists no(symbols)]} then { lappend fileNames(destination) \ [file join $stagingDirectory Redist Debug \ <platform> sqlite3.pdb] } } if {![info exists fileNames(neutral)]} then { set fileNames(neutral) [list 1 1 1 1 0 0] if {![info exists no(symbols)]} then { lappend fileNames(neutral) 0 } } if {![info exists fileNames(subst)]} then { set fileNames(subst) [list 1 1 1 0 0 0] if {![info exists no(symbols)]} then { lappend fileNames(subst) 0 } } ############################################################################### # # NOTE: Setup the list of platforms supported by this script. # if {![info exists platformNames]} then { set platformNames [list x86 x64 ARM] } ############################################################################### # # NOTE: Make sure the staging directory exists, creating it if necessary. # file mkdir $stagingDirectory # # NOTE: Build the Tcl command used to extract the template package to the # staging directory. # set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory] # # NOTE: Extract the template package to the staging directory. # eval $extractCommand ############################################################################### # # NOTE: Process each file in the master file list. There are actually four # parallel lists that contain the source file names, destination file # names, the platform-neutral flags, and the use-subst flags. When the # platform-neutral flag is non-zero, the file is not platform-specific. # When the use-subst flag is non-zero, the file is considered to be a # text file that may contain Tcl variable and/or command replacements, # to be dynamically replaced during processing. If the source file name # is an empty string, then the destination file name will be assumed to # already exist in the staging directory and will not be copied; however, # dynamic replacements may still be performed on the destination file # prior to the package being re-zipped. # foreach sourceFileName $fileNames(source) \ destinationFileName $fileNames(destination) \ isNeutral $fileNames(neutral) useSubst $fileNames(subst) { # # NOTE: If the current file is platform-neutral, then only one platform will # be processed for it, namely "neutral"; otherwise, each supported # platform will be processed for it individually. # foreach platformName [expr {$isNeutral ? [list neutral] : $platformNames}] { # # NOTE: Use the actual platform name in the destination file name. # set newDestinationFileName [replacePlatform $destinationFileName \ $platformName] # # NOTE: Does the source file need to be copied to the destination file? # if {[string length $sourceFileName] > 0} then { # # NOTE: First, make sure the destination directory exists. # file mkdir [file dirname $newDestinationFileName] # # NOTE: Then, copy the source file to the destination file verbatim. # file copy [replacePlatform $sourceFileName $platformName] \ $newDestinationFileName } # # NOTE: Does the destination file contain dynamic replacements that must # be processed now? # if {$useSubst} then { # # NOTE: Perform any dynamic replacements contained in the destination # file and then re-write it in-place. # substFile $newDestinationFileName } } } ############################################################################### # # NOTE: Change the current directory to the staging directory so that the # external archive building tool can pickup the necessary files using # relative paths. # cd $stagingDirectory # # NOTE: Build the Tcl command used to archive the final package in the # output directory. # set archiveCommand [list exec -- $zip -r $outputFile *] # # NOTE: Build the final package archive in the output directory. # eval $archiveCommand # # NOTE: Change back to the previously saved current directory. # cd $currentDirectory # # NOTE: Cleanup the temporary staging directory. # file delete -force $stagingDirectory ############################################################################### # # NOTE: Success, emit the fully qualified path of the generated VSIX file. # puts stdout $outputFile |
Changes to tool/omittest.tcl.
︙ | ︙ | |||
49 50 51 52 53 54 55 | # proc run_quick_test {dir omit_symbol_list} { # Compile the value of the OPTS Makefile variable. set opts "" if {$::tcl_platform(platform)=="windows"} { append opts "OPTS += -DSQLITE_OS_WIN=1\n" set target "testfixture.exe" | < < | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # proc run_quick_test {dir omit_symbol_list} { # Compile the value of the OPTS Makefile variable. set opts "" if {$::tcl_platform(platform)=="windows"} { append opts "OPTS += -DSQLITE_OS_WIN=1\n" set target "testfixture.exe" } else { append opts "OPTS += -DSQLITE_OS_UNIX=1\n" } foreach sym $omit_symbol_list { append opts "OPTS += -D${sym}=1\n" } |
︙ | ︙ | |||
89 90 91 92 93 94 95 | puts "Ok" } # Create an empty file "$dir/sqlite3". This is to trick the makefile out # of trying to build the sqlite shell. The sqlite shell won't build # with some of the OMIT options (i.e OMIT_COMPLETE). set sqlite3_dummy $dir/sqlite3 | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | puts "Ok" } # Create an empty file "$dir/sqlite3". This is to trick the makefile out # of trying to build the sqlite shell. The sqlite shell won't build # with some of the OMIT options (i.e OMIT_COMPLETE). set sqlite3_dummy $dir/sqlite3 if {$::tcl_platform(platform)=="windows"} { append sqlite3_dummy ".exe" } if {![file exists $sqlite3_dummy]} { set wr [open $sqlite3_dummy w] puts $wr "dummy" close $wr } |
︙ | ︙ | |||
123 124 125 126 127 128 129 | # This proc processes the command line options passed to this script. # Currently the only option supported is "-makefile", default # "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this # option. # proc process_options {argv} { set ::MAKEBIN make ;# Default value | | | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | # This proc processes the command line options passed to this script. # Currently the only option supported is "-makefile", default # "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this # option. # proc process_options {argv} { set ::MAKEBIN make ;# Default value if {$::tcl_platform(platform)=="windows"} { set ::MAKEFILE ./Makefile ;# Default value on Windows } else { set ::MAKEFILE ./Makefile.linux-gcc ;# Default value } set ::SKIP_RUN 0 ;# Default to attempt test set ::TARGET testfixture ;# Default thing to build for {set i 0} {$i < [llength $argv]} {incr i} { |
︙ | ︙ |
Added tool/win/sqlite.vsix.
cannot compute difference between binary files