Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the latest trunk enhancements into the wal2 branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | wal2 |
Files: | files | file ages | folders |
SHA3-256: |
c8d8f613ed0d7639a8b859e8c7fa7da2 |
User & Date: | drh 2025-03-15 20:28:42.705 |
Context
2025-03-22
| ||
14:19 | Merge the latest trunk enhancements into the wal2 branch. (check-in: 80e6ddd560 user: drh tags: wal2) | |
2025-03-15
| ||
20:32 | Merge the latest trunk enhancements into the bedrock branch via the wal2 intermediary. (check-in: b1860b6372 user: drh tags: bedrock) | |
20:28 | Merge the latest trunk enhancements into the wal2 branch. (check-in: c8d8f613ed user: drh tags: wal2) | |
19:55 | Make use of the C99 flexible array feature, when available, so that the -fsanitize=bounds-strict option can be used, when available. Forum thread 311dbf9a1c. (check-in: d4307a0d43 user: drh tags: trunk) | |
2025-03-03
| ||
15:57 | Merge the latest trunk enhancements into the wal2 branch. (check-in: 6baea938f0 user: drh tags: wal2) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
131 132 133 134 135 136 137 138 139 140 141 142 143 144 | libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@ # libsqlite3.out.implib => the output filename part of LDFLAGS_OUT_IMPLIB. ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@ ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@ HAVE_WASI_SDK = @HAVE_WASI_SDK@ libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@ T.cc.sqlite = $(T.cc) @TARGET_DEBUG@ # # Define -D_HAVE_SQLITE_CONFIG_H so that the code knows it # can include the generated sqlite_cfg.h. # # main.mk will fill out T.cc.sqlite with additional flags common to | > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@ # libsqlite3.out.implib => the output filename part of LDFLAGS_OUT_IMPLIB. ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@ ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@ HAVE_WASI_SDK = @HAVE_WASI_SDK@ libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@ # -fsanitize flags for the fuzzcheck-asap app CFLAGS.fuzzcheck.fsanitize = @CFLAGS_FUZZCHECK_FSANITIZE@ T.cc.sqlite = $(T.cc) @TARGET_DEBUG@ # # Define -D_HAVE_SQLITE_CONFIG_H so that the code knows it # can include the generated sqlite_cfg.h. # # main.mk will fill out T.cc.sqlite with additional flags common to |
︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 266 267 268 269 270 | # invoked with to produce this makefile. # AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@ USE_AMALGAMATION ?= @USE_AMALGAMATION@ LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@ AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@ # # CFLAGS for sqlite3$(T.exe) # SHELL_OPT ?= @OPT_SHELL@ Makefile: $(TOP)/Makefile.in $(AS_AUTO_DEF) | > | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | # invoked with to produce this makefile. # AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@ USE_AMALGAMATION ?= @USE_AMALGAMATION@ LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@ AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@ EXTRA_SRC ?= @AMALGAMATION_EXTRA_SRC@ # # CFLAGS for sqlite3$(T.exe) # SHELL_OPT ?= @OPT_SHELL@ Makefile: $(TOP)/Makefile.in $(AS_AUTO_DEF) |
︙ | ︙ | |||
318 319 320 321 322 323 324 | $(TCLSH_CMD) ./tool/spellsift.tcl ./src/*.c ./src/*.h ./src/*.in # # clean/distclean are mostly defined in main.mk. In this makefile we # perform cleanup known to be relevant to (only) the autosetup-driven # build. # | < < < < < < | | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | $(TCLSH_CMD) ./tool/spellsift.tcl ./src/*.c ./src/*.h ./src/*.in # # clean/distclean are mostly defined in main.mk. In this makefile we # perform cleanup known to be relevant to (only) the autosetup-driven # build. # distclean-autosetup: rm -f sqlite_cfg.h config.log config.status config.defines.* Makefile sqlite3.pc rm -f $(TOP)/tool/emcc.sh rm -f libsqlite3*$(T.dll) rm -f jimsh0* distclean: distclean-autosetup # |
︙ | ︙ |
Changes to auto.def.
︙ | ︙ | |||
21 22 23 24 25 26 27 | proj-opt-set all 1 proj-opt-set debug 1 proj-opt-set amalgamation 0 define CFLAGS [get-env CFLAGS {-O0 -g}] # -------------^^^^^^^ intentionally using [get-env] instead of # [proj-get-env] here because [sqlite-setup-default-cflags] uses # [proj-get-env] and we want this to supercede that. | | > > > > > | > | 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 | proj-opt-set all 1 proj-opt-set debug 1 proj-opt-set amalgamation 0 define CFLAGS [get-env CFLAGS {-O0 -g}] # -------------^^^^^^^ intentionally using [get-env] instead of # [proj-get-env] here because [sqlite-setup-default-cflags] uses # [proj-get-env] and we want this to supercede that. sqlite-munge-cflags; # straighten out -DSQLITE_ENABLE/OMIT flags } sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk] sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment sqlite-check-common-system-deps proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?" proj-define-for-opt gcov USE_GCOV "Use gcov?" proj-define-for-opt test-status TSTRNNR_OPTS \ "test-runner flags:" {--status} {} proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \ "Use #line macros in the amalgamation:" define AMALGAMATION_EXTRA_SRC \ [join [opt-val amalgamation-extra-src ""] " "] define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools] define CFLAGS_FUZZCHECK_FSANITIZE [proj-check-fsanitize {address bounds-strict}] sqlite-handle-tcl sqlite-handle-emsdk } |
Changes to autoconf/Makefile.in.
︙ | ︙ | |||
216 217 218 219 220 221 222 | install-lib-1: $(install-dir.lib) $(libsqlite3.LIB) $(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)" install-lib-0 install-lib-: install-lib: install-lib-$(ENABLE_LIB_STATIC) install: install-lib | | | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | install-lib-1: $(install-dir.lib) $(libsqlite3.LIB) $(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)" install-lib-0 install-lib-: install-lib: install-lib-$(ENABLE_LIB_STATIC) install: install-lib # # Flags to link the shell app either directly against sqlite3.c # (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0). # ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@ sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3) sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib) sqlite3-shell-deps.1 = $(TOP)/sqlite3.c |
︙ | ︙ | |||
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | README.txt VERSION \ auto.def autosetup configure tea \ sqlite3.h sqlite3.c shell.c sqlite3ext.h \ Makefile.in Makefile.msc Makefile.fallback \ sqlite3.rc sqlite3rc.h Replace.cs \ sqlite3.pc.in sqlite3.1 # Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so # that tool/mkautoconfamal.sh knows how to find it. dist_name = sqlite-$(PACKAGE_VERSION) dist_tarball = $(dist_name).tar.gz dist: rm -fr $(dist_name) mkdir -p $(dist_name) cp -rp $(DIST_FILES) $(dist_name)/. rm -f $(dist_name)/tea/configure.ac.in tar czf $(dist_tarball) $(dist_name) rm -fr $(dist_name) ls -l $(dist_tarball) | > > | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | README.txt VERSION \ auto.def autosetup configure tea \ sqlite3.h sqlite3.c shell.c sqlite3ext.h \ Makefile.in Makefile.msc Makefile.fallback \ sqlite3.rc sqlite3rc.h Replace.cs \ sqlite3.pc.in sqlite3.1 # # Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so # that tool/mkautoconfamal.sh knows how to find it. # dist_name = sqlite-$(PACKAGE_VERSION) dist_tarball = $(dist_name).tar.gz dist: rm -fr $(dist_name) mkdir -p $(dist_name) cp -rp $(DIST_FILES) $(dist_name)/. rm -f $(dist_name)/tea/configure.ac.in tar czf $(dist_tarball) $(dist_name) rm -fr $(dist_name) ls -l $(dist_tarball) |
Changes to autosetup/proj.tcl.
︙ | ︙ | |||
179 180 181 182 183 184 185 186 187 188 189 190 191 192 | } set r [lrange $l 0 [incr count -1]] set l [lreplace $l [set l 0] $count] return $r } ######################################################################## # Expects to receive string input, which it splits on newlines, strips # out any lines which begin with any number of whitespace followed by # a '#', and returns a value containing the [append]ed results of each # remaining line with a \n between each. proc proj-strip-hash-comments {val} { set x {} foreach line [split $val \n] { | > > | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | } set r [lrange $l 0 [incr count -1]] set l [lreplace $l [set l 0] $count] return $r } ######################################################################## # @proj-strip-hash-comments value # # Expects to receive string input, which it splits on newlines, strips # out any lines which begin with any number of whitespace followed by # a '#', and returns a value containing the [append]ed results of each # remaining line with a \n between each. proc proj-strip-hash-comments {val} { set x {} foreach line [split $val \n] { |
︙ | ︙ | |||
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 | return 1 } else { define LDFLAGS_SONAME_PREFIX "" return 0 } } } ######################################################################## # Internal helper for proj-dump-defs-json. Expects to be passed a # [define] name and the variadic $args which are passed to # proj-dump-defs-json. If it finds a pattern match for the given # $name in the various $args, it returns the type flag for that $name, # e.g. "-str" or "-bare", else returns an empty string. | > > > > > > > > > > > > > > > > > > > > > > > | 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 | return 1 } else { define LDFLAGS_SONAME_PREFIX "" return 0 } } } ######################################################################## # @proj-check-fsanitize ?list-of-opts? # # Checks whether CC supports -fsanitize=X, where X is each entry of # the given list of flags. If any of those flags are supported, it # returns the string "-fsanitize=X..." where X... is a comma-separated # list of all supported flags. If none of the given options are # supported then it returns an empty string. proc proj-check-fsanitize {{opts {address bounds-strict}}} { set sup {} foreach opt $opts { cc-with {} { if {[cc-check-flags "-fsanitize=$opt"]} { lappend sup $opt } } } if {[llength $sup] > 0} { return "-fsanitize=[join $sup ,]" } return "" } ######################################################################## # Internal helper for proj-dump-defs-json. Expects to be passed a # [define] name and the variadic $args which are passed to # proj-dump-defs-json. If it finds a pattern match for the given # $name in the various $args, it returns the type flag for that $name, # e.g. "-str" or "-bare", else returns an empty string. |
︙ | ︙ |
Changes to autosetup/sqlite-config.tcl.
︙ | ︙ | |||
57 58 59 60 61 62 63 | # build options, so it's important that config code which checks for # cross-compilation uses this var instead of # [proj-is-cross-compiling]. # set sqliteConfig(is-cross-compiling) [proj-is-cross-compiling] ######################################################################## | | > | > > > > > > > | 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 | # build options, so it's important that config code which checks for # cross-compilation uses this var instead of # [proj-is-cross-compiling]. # set sqliteConfig(is-cross-compiling) [proj-is-cross-compiling] ######################################################################## # Processes all configure --flags for this build, run build-specific # config checks, then finalize the configure process. $buildMode must # be either "canonical" or "autoconf", and others may be added in the # future. After bootstrapping, $configScript is eval'd in the caller's # scope, then post-configuration finalization is run. $configScript is # intended to hold configure code which is specific to the given # $buildMode, with the caveat that _some_ build-specific code is # encapsulated in the configuration finalization step. # # The intent is that all build-mode-specific configuration goes inside # the $configScript argument to this function, and that an auto.def file # contains only two commands: # # use sqlite-config # sqlite-configure BUILD_NAME { build-specific configure script } proc sqlite-configure {buildMode configScript} { set allBuildModes {canonical autoconf} if {$buildMode ni $allBuildModes} { user-error "Invalid build mode: $buildMode. Expecting one of: $allBuildModes" } set ::sqliteConfig(build-mode) $buildMode ######################################################################## |
︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 | # FLAG => {Help text} # # Where FLAG can have any of the following formats: # # boolopt => "a boolean option which defaults to disabled" # boolopt2=1 => "a boolean option which defaults to enabled" # stringopt: => "an option which takes an argument, e.g. --stringopt=value" # stringopt2:=value => "an option where the argument is optional and defaults to 'value'" # optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help" # # Autosetup does no small amount of specialized handling for flags, # especially booleans. Each bool-type --FLAG implicitly gets # --enable-FLAG and --disable-FLAG forms. That can lead lead to some # confusion when writing help text. For example: | > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | # FLAG => {Help text} # # Where FLAG can have any of the following formats: # # boolopt => "a boolean option which defaults to disabled" # boolopt2=1 => "a boolean option which defaults to enabled" # stringopt: => "an option which takes an argument, e.g. --stringopt=value" # stringopt:DESCR => As for stringopt: with a description for the value # stringopt2:=value => "an option where the argument is optional and defaults to 'value'" # optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help" # # Autosetup does no small amount of specialized handling for flags, # especially booleans. Each bool-type --FLAG implicitly gets # --enable-FLAG and --disable-FLAG forms. That can lead lead to some # confusion when writing help text. For example: |
︙ | ︙ | |||
126 127 128 129 130 131 132 | # # [proj-opt-was-provided] can be used to determine whether a flag was # explicitly provided, which is often useful for distinguishing from # the case of a default value. ######################################################################## set allFlags { # Structure: a list of M {Z} pairs, where M is a descriptive | | | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | # # [proj-opt-was-provided] can be used to determine whether a flag was # explicitly provided, which is often useful for distinguishing from # the case of a default value. ######################################################################## set allFlags { # Structure: a list of M {Z} pairs, where M is a descriptive # option group name and Z is a list of X Y pairs. X is a list of # $buildMode name(s) to which the Y flags apply, or {*} to apply # to all builds. Y is a {block} in the form expected by # autosetup's [options] command. Each block which is applicable # to $buildMode is appended to a new list before that list is # passed on to [options]. The order of each Y and sub-Y is # retained, which is significant for rendering of --help. |
︙ | ︙ | |||
163 164 165 166 167 168 169 | lib-features { {*} { threadsafe=1 => {Disable mutexing} with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always} largefile=1 => {This legacy flag has no effect on the library but may influence the contents of the generated sqlite_cfg.h} | | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | lib-features { {*} { threadsafe=1 => {Disable mutexing} with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always} largefile=1 => {This legacy flag has no effect on the library but may influence the contents of the generated sqlite_cfg.h} # ^^^ It's not clear that LFS support actually does anything, # as HAVE_LFS is not checked anywhere in the .c/.h/.in files. load-extension=1 => {Disable loading of external extensions} math=1 => {Disable math functions} json=1 => {Disable JSON functions} memsys5 => {Enable MEMSYS5} memsys3 => {Enable MEMSYS3} fts3 => {Enable the FTS3 extension} fts4 => {Enable the FTS4 extension} |
︙ | ︙ | |||
255 256 257 258 259 260 261 262 263 264 265 266 267 268 | # build with-wasi-sdk:=/opt/wasi-sdk => {Top-most dir of the wasi-sdk for a WASI build} with-emsdk:=auto => {Top-most dir of the Emscripten SDK installation. Needed only by ext/wasm. Default=EMSDK env var.} } } # Options primarily for downstream packagers/package maintainers packaging { {autoconf} { # --disable-static-shell: https://sqlite.org/forum/forumpost/cc219ee704 | > > > > | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | # build with-wasi-sdk:=/opt/wasi-sdk => {Top-most dir of the wasi-sdk for a WASI build} with-emsdk:=auto => {Top-most dir of the Emscripten SDK installation. Needed only by ext/wasm. Default=EMSDK env var.} amalgamation-extra-src:FILES => {Space-separated list of soure files to append as-is to the resulting sqlite3.c amalgamation file. May be provided multiple times.} } } # Options primarily for downstream packagers/package maintainers packaging { {autoconf} { # --disable-static-shell: https://sqlite.org/forum/forumpost/cc219ee704 |
︙ | ︙ | |||
356 357 358 359 360 361 362 | } sqlite-post-options-init uplevel 1 $configScript sqlite-configure-finalize }; # sqlite-configure ######################################################################## | | | > | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | } sqlite-post-options-init uplevel 1 $configScript sqlite-configure-finalize }; # sqlite-configure ######################################################################## # Performs late-stage config steps common to all supported # $::sqliteConfig(build-mode) values. proc sqlite-configure-finalize {} { set buildMode $::sqliteConfig(build-mode) set isCanonical [expr {$buildMode eq "canonical"}] set isAutoconf [expr {$buildMode eq "autoconf"}] proj-assert {$isCanonical || $isAutoconf} "Unknown build mode: $buildMode" define HAVE_LFS 0 if {[opt-bool largefile]} { # # Insofar as we can determine HAVE_LFS has no effect on the # library. Perhaps it did back in the early 2000's. The # --enable/disable-largefile flag is retained because it's |
︙ | ︙ | |||
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | sqlite-handle-threadsafe sqlite-handle-tempstore sqlite-handle-line-editing sqlite-handle-load-extension sqlite-handle-math sqlite-handle-icu sqlite-handle-env-quirks sqlite-process-dot-in-files sqlite-post-config-validation sqlite-dump-defines }; # sqlite-configure-finalize ######################################################################## # Runs some common initialization which must happen immediately after # autosetup's [options] function is called. This is also a convenient # place to put some generic pieces common to both the canonical # top-level build and the "autoconf" build, but it's not intended to # be a catch-all dumping ground for such. proc sqlite-post-options-init {} { define PACKAGE_NAME "sqlite" define PACKAGE_URL {https://sqlite.org} define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]" | > > > > > > > < > | | | < < | 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 | sqlite-handle-threadsafe sqlite-handle-tempstore sqlite-handle-line-editing sqlite-handle-load-extension sqlite-handle-math sqlite-handle-icu sqlite-handle-env-quirks sqlite-handle-common-feature-flags sqlite-finalize-feature-flags ######################################################################## # When cross-compiling, we have to avoid using the -s flag to # /usr/bin/install: # https://sqlite.org/forum/forumpost/9a67df63eda9925c define IS_CROSS_COMPILING $::sqliteConfig(is-cross-compiling) sqlite-process-dot-in-files sqlite-post-config-validation sqlite-dump-defines }; # sqlite-configure-finalize ######################################################################## # Runs some common initialization which must happen immediately after # autosetup's [options] function is called. This is also a convenient # place to put some generic pieces common to both the canonical # top-level build and the "autoconf" build, but it's not intended to # be a catch-all dumping ground for such. proc sqlite-post-options-init {} { define PACKAGE_NAME "sqlite" define PACKAGE_URL {https://sqlite.org} define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]" proj-xfer-options-aliases { # Carry values from hidden --flag aliases over to their canonical # flag forms. This list must include only options which are common # to all build modes supported by [sqlite-configure]. with-readline-inc => with-readline-cflags with-readline-lib => with-readline-ldflags with-debug => debug } sqlite-autoreconfig proj-file-extensions if {".exe" eq [get-define TARGET_EXEEXT]} { |
︙ | ︙ | |||
459 460 461 462 463 464 465 | puts stderr [proj-bold "** DEBUG: $msg"] } } ######################################################################## # Sets up the SQLITE_AUTORECONFIG define. proc sqlite-autoreconfig {} { | < | < | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | puts stderr [proj-bold "** DEBUG: $msg"] } } ######################################################################## # Sets up the SQLITE_AUTORECONFIG define. proc sqlite-autoreconfig {} { # SQLITE_AUTORECONFIG contains make target rules for re-running the # configure script with the same arguments it was initially invoked # with. This can be used to automatically reconfigure. set squote {{arg} { # Wrap $arg in single-quotes if it looks like it might need that # to avoid mis-handling as a shell argument. We assume that $arg # will never contain any single-quote characters. if {[string match {*[ &;$*"]*} $arg]} { return '$arg' } return $arg }} |
︙ | ︙ | |||
498 499 500 501 502 503 504 505 506 507 508 509 510 511 | if {"" ne $args} { if {"" ne $shell} { sqlite-add-shell-opt {*}$args } define-append OPT_FEATURE_FLAGS {*}$args } } # Appends $args, if not empty, to OPT_SHELL. proc sqlite-add-shell-opt {args} { if {"" ne $args} { define-append OPT_SHELL {*}$args } } | > > | 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | if {"" ne $args} { if {"" ne $shell} { sqlite-add-shell-opt {*}$args } define-append OPT_FEATURE_FLAGS {*}$args } } ######################################################################## # Appends $args, if not empty, to OPT_SHELL. proc sqlite-add-shell-opt {args} { if {"" ne $args} { define-append OPT_SHELL {*}$args } } |
︙ | ︙ | |||
536 537 538 539 540 541 542 | } } ######################################################################## # Run checks for system-level includes and libs which are common to # both the canonical build and the "autoconf" bundle. proc sqlite-check-common-system-deps {} { | < < < | 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 | } } ######################################################################## # Run checks for system-level includes and libs which are common to # both the canonical build and the "autoconf" bundle. proc sqlite-check-common-system-deps {} { # Check for needed/wanted data types cc-with {-includes stdint.h} \ {cc-check-types int8_t int16_t int32_t int64_t intptr_t \ uint8_t uint16_t uint32_t uint64_t uintptr_t} # Check for needed/wanted functions cc-check-functions gmtime_r isnan localtime_r localtime_s \ malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64 set ldrt "" # Collapse funcs from librt into LDFLAGS_RT. # Some systems (ex: SunOS) require -lrt in order to use nanosleep foreach func {fdatasync nanosleep} { if {[proj-check-function-in-lib $func rt]} { lappend ldrt [get-define lib_${func}] } } define LDFLAGS_RT [join [lsort -unique $ldrt] ""] # Check for needed/wanted headers cc-check-includes \ sys/types.h sys/stat.h dlfcn.h unistd.h \ stdlib.h malloc.h memory.h \ string.h strings.h \ inttypes.h |
︙ | ︙ | |||
579 580 581 582 583 584 585 | define LDFLAGS_ZLIB "" } } ######################################################################## # Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and # CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS. | < | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | define LDFLAGS_ZLIB "" } } ######################################################################## # Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and # CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS. proc sqlite-munge-cflags {} { # Move CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and # -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived # from the legacy build and was missing the 3.48.0 release (the # initial Autosetup port). # https://sqlite.org/forum/forumpost/9801e54665afd728 # |
︙ | ︙ | |||
725 726 727 728 729 730 731 732 733 734 735 736 737 738 | define OPT_FEATURE_FLAGS [lsort -unique $oFF] msg-result "Library feature flags: [get-define OPT_FEATURE_FLAGS]" } set oFF [get-define OPT_SHELL] if {"" ne $oFF} { define OPT_SHELL [lsort -unique $oFF] msg-result "Shell options: [get-define OPT_SHELL]" } } ######################################################################## # Checks for the --debug flag, defining SQLITE_DEBUG to 1 if it is # true. TARGET_DEBUG gets defined either way, with content depending # on whether --debug is true or false. | > > > > | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 | define OPT_FEATURE_FLAGS [lsort -unique $oFF] msg-result "Library feature flags: [get-define OPT_FEATURE_FLAGS]" } set oFF [get-define OPT_SHELL] if {"" ne $oFF} { define OPT_SHELL [lsort -unique $oFF] msg-result "Shell options: [get-define OPT_SHELL]" } if {"" ne [set extraSrc [get-define AMALGAMATION_EXTRA_SRC ""]]} { proj-assert {"canonical" eq $::sqliteConfig(build-mode)} msg-result "Appending source files to amalgamation: $extraSrc" } } ######################################################################## # Checks for the --debug flag, defining SQLITE_DEBUG to 1 if it is # true. TARGET_DEBUG gets defined either way, with content depending # on whether --debug is true or false. |
︙ | ︙ | |||
1460 1461 1462 1463 1464 1465 1466 | # If the given platform identifier (defaulting to [get-define host]) # appears to be one of the Unix-on-Windows environments, returns a # brief symbolic name for that environment, else returns an empty # string. # # It does not distinguish between msys and msys2, returning msys for # both. The build does not, as of this writing, specifically support | | > | | 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 | # If the given platform identifier (defaulting to [get-define host]) # appears to be one of the Unix-on-Windows environments, returns a # brief symbolic name for that environment, else returns an empty # string. # # It does not distinguish between msys and msys2, returning msys for # both. The build does not, as of this writing, specifically support # msys v1. Similarly, this function returns "mingw" for both "mingw32" # and "mingw64". proc sqlite-env-is-unix-on-windows {{envTuple ""}} { if {"" eq $envTuple} { set envTuple [get-define host] } set name "" switch -glob -- $envTuple { *-*-cygwin { set name cygwin } *-*-ming* { set name mingw } *-*-msys { set name msys } } return $name } ######################################################################## # Performs various tweaks to the build which are only relevant on # certain platforms, e.g. Mac and "Unix on Windows" platforms (msys2, # cygwin, ...). # |
︙ | ︙ | |||
1547 1548 1549 1550 1551 1552 1553 | sqlite-handle-mac-cversion } ######################################################################## # Perform some late-stage work and generate the configure-process # output file(s). proc sqlite-process-dot-in-files {} { | < < < < < < < < < < < < | 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 | sqlite-handle-mac-cversion } ######################################################################## # Perform some late-stage work and generate the configure-process # output file(s). proc sqlite-process-dot-in-files {} { ######################################################################## # "Re-export" the autoconf-conventional --XYZdir flags into something # which is more easily overridable from a make invocation. See the docs # for [proj-remap-autoconf-dir-vars] for the explanation of why. # # We do this late in the config process, immediately before we export # the Makefile and other generated files, so that configure tests |
︙ | ︙ | |||
1827 1828 1829 1830 1831 1832 1833 | eval [exec sh "$srcdir/tool/tclConfigShToAutoDef.sh" "$cfg"] # ---------^^ a Windows/msys workaround, without which it cannot # exec a .sh file: https://sqlite.org/forum/forumpost/befb352a42a7cd6d if {"" eq $with_tclsh && $cfg ne ""} { # We have tclConfig.sh but no tclsh. Attempt to locate a tclsh # based on info from tclConfig.sh. | > | > | > > | | > > > | | < < < | 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 | eval [exec sh "$srcdir/tool/tclConfigShToAutoDef.sh" "$cfg"] # ---------^^ a Windows/msys workaround, without which it cannot # exec a .sh file: https://sqlite.org/forum/forumpost/befb352a42a7cd6d if {"" eq $with_tclsh && $cfg ne ""} { # We have tclConfig.sh but no tclsh. Attempt to locate a tclsh # based on info from tclConfig.sh. set tclExecPrefix [get-define TCL_EXEC_PREFIX] proj-assert {"" ne $tclExecPrefix} set tryThese [list \ $tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \ $tclExecPrefix/bin/tclsh ] foreach trySh $tryThese { if {[file-isexec $trySh]} { set with_tclsh $trySh break } } if {![file-isexec $with_tclsh]} { proj-warn "Cannot find a usable tclsh (tried: $tryThese) } } define TCLSH_CMD $with_tclsh if {$use_tcl} { # Set up the TCLLIBDIR # # 2024-10-28: calculation of TCLLIBDIR is now done via the shell |
︙ | ︙ |
Changes to ext/fts3/README.syntax.
︙ | ︙ | |||
58 59 60 61 62 63 64 | case is treated as an ordinary token. For example, the following query: <col> MATCH 'engineering NEAR consultancy' matches rows that contain both the "engineering" and "consultancy" tokens in the same column with not more than 10 other words between them. It does not matter which of the two terms occurs first in the document, only that | | | | | 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 | case is treated as an ordinary token. For example, the following query: <col> MATCH 'engineering NEAR consultancy' matches rows that contain both the "engineering" and "consultancy" tokens in the same column with not more than 10 other words between them. It does not matter which of the two terms occurs first in the document, only that they be separated by only 10 tokens or less. The user may also specify a different required proximity by adding "/N" immediately after the NEAR operator, where N is an integer. For example: <col> MATCH 'engineering NEAR/5 consultancy' searches for a row containing an instance of each specified token separated by not more than 5 other tokens. More than one NEAR operator can be used in as sequence. For example this query: <col> MATCH 'reliable NEAR/2 engineering NEAR/5 consultancy' searches for a row that contains an instance of the token "reliable" separated by not more than two tokens from an instance of "engineering", which is in turn separated by not more than 5 other tokens from an instance of the term "consultancy". Phrases enclosed in quotes may also be used as arguments to the NEAR operator. Similar to the NEAR operator, one or more tokens or phrases may be separated by OR operators. In this case, only one of the specified tokens or phrases must appear in the document. For example, the query: |
︙ | ︙ |
Changes to ext/fts3/fts3Int.h.
︙ | ︙ | |||
197 198 199 200 201 202 203 204 205 206 207 208 209 210 | # define TESTONLY(X) #endif #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) #define deliberate_fall_through #endif /* SQLITE_AMALGAMATION */ #ifdef SQLITE_DEBUG int sqlite3Fts3Corrupt(void); # define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt() #else | > > > > > > > > > > > > > | 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 | # define TESTONLY(X) #endif #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) #define deliberate_fall_through /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof # define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif #endif /* SQLITE_AMALGAMATION */ #ifdef SQLITE_DEBUG int sqlite3Fts3Corrupt(void); # define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt() #else |
︙ | ︙ | |||
427 428 429 430 431 432 433 | i64 iOrDocid; /* Variables below this point are populated by fts3_expr.c when parsing ** a MATCH expression. Everything above is part of the evaluation phase. */ int nToken; /* Number of tokens in the phrase */ int iColumn; /* Index of column this phrase must match */ | | > > > > | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | i64 iOrDocid; /* Variables below this point are populated by fts3_expr.c when parsing ** a MATCH expression. Everything above is part of the evaluation phase. */ int nToken; /* Number of tokens in the phrase */ int iColumn; /* Index of column this phrase must match */ Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */ }; /* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */ #define SZ_FTS3PHRASE(N) \ (offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken)) /* ** A tree of these objects forms the RHS of a MATCH operator. ** ** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist ** points to a malloced buffer, size nDoclist bytes, containing the results ** of this phrase query in FTS3 doclist format. As usual, the initial |
︙ | ︙ |
Changes to ext/fts3/fts3_expr.c.
︙ | ︙ | |||
156 157 158 159 160 161 162 163 164 165 166 167 168 169 | } /* ** Function getNextNode(), which is called by fts3ExprParse(), may itself ** call fts3ExprParse(). So this forward declaration is required. */ static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *); /* ** Extract the next token from buffer z (length n) using the tokenizer ** and other information (column names etc.) in pParse. Create an Fts3Expr ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this ** single token and set *ppExpr to point to it. If the end of the buffer is ** reached before a token is found, set *ppExpr to zero. It is the | > > > > > > > > > > > > > > > > > | 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 | } /* ** Function getNextNode(), which is called by fts3ExprParse(), may itself ** call fts3ExprParse(). So this forward declaration is required. */ static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *); /* ** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis ** is defined, search for '(' and ')' as well. Return the index of the first ** such character in the buffer. If there is no such character, return -1. */ static int findBarredChar(const char *z, int n){ int ii; for(ii=0; ii<n; ii++){ if( (z[ii]=='"') || (sqlite3_fts3_enable_parentheses && (z[ii]=='(' || z[ii]==')')) ){ return ii; } } return -1; } /* ** Extract the next token from buffer z (length n) using the tokenizer ** and other information (column names etc.) in pParse. Create an Fts3Expr ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this ** single token and set *ppExpr to point to it. If the end of the buffer is ** reached before a token is found, set *ppExpr to zero. It is the |
︙ | ︙ | |||
181 182 183 184 185 186 187 | int *pnConsumed /* OUT: Number of bytes consumed */ ){ sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; int rc; sqlite3_tokenizer_cursor *pCursor; Fts3Expr *pRet = 0; | < < < < < < < | | > > > > > > > > > > > | | | 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 | int *pnConsumed /* OUT: Number of bytes consumed */ ){ sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; int rc; sqlite3_tokenizer_cursor *pCursor; Fts3Expr *pRet = 0; *pnConsumed = n; rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); if( rc==SQLITE_OK ){ const char *zToken; int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0; sqlite3_int64 nByte; /* total space to allocate */ rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); if( rc==SQLITE_OK ){ /* Check that this tokenization did not gobble up any " characters. Or, ** if enable_parenthesis is true, that it did not gobble up any ** open or close parenthesis characters either. If it did, call ** getNextToken() again, but pass only that part of the input buffer ** up to the first such character. */ int iBarred = findBarredChar(z, iEnd); if( iBarred>=0 ){ pModule->xClose(pCursor); return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed); } nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken; pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte); if( !pRet ){ rc = SQLITE_NOMEM; }else{ pRet->eType = FTSQUERY_PHRASE; pRet->pPhrase = (Fts3Phrase *)&pRet[1]; pRet->pPhrase->nToken = 1; pRet->pPhrase->iColumn = iCol; pRet->pPhrase->aToken[0].n = nToken; pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1]; memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken); if( iEnd<n && z[iEnd]=='*' ){ pRet->pPhrase->aToken[0].isPrefix = 1; iEnd++; } |
︙ | ︙ | |||
232 233 234 235 236 237 238 | }else{ break; } } } *pnConsumed = iEnd; | | > > > > | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | }else{ break; } } } *pnConsumed = iEnd; }else if( n && rc==SQLITE_DONE ){ int iBarred = findBarredChar(z, n); if( iBarred>=0 ){ *pnConsumed = iBarred; } rc = SQLITE_OK; } pModule->xClose(pCursor); } *ppExpr = pRet; |
︙ | ︙ | |||
281 282 283 284 285 286 287 | sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; int rc; Fts3Expr *p = 0; sqlite3_tokenizer_cursor *pCursor = 0; char *zTemp = 0; i64 nTemp = 0; | | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; int rc; Fts3Expr *p = 0; sqlite3_tokenizer_cursor *pCursor = 0; char *zTemp = 0; i64 nTemp = 0; const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1); int nToken = 0; /* The final Fts3Expr data structure, including the Fts3Phrase, ** Fts3PhraseToken structures token buffers are all stored as a single ** allocation so that the expression can be freed with a single call to ** sqlite3_free(). Setting this up requires a two pass approach. ** |
︙ | ︙ | |||
1235 1236 1237 1238 1239 1240 1241 | }else{ rc = fts3ExprParseUnbalanced( pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr ); } if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ | < | 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 | }else{ rc = fts3ExprParseUnbalanced( pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr ); } if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ sqlite3_result_error(context, "Error parsing expression", -1); }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){ sqlite3_result_error_nomem(context); }else{ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); sqlite3_free(zBuf); } |
︙ | ︙ |
Changes to ext/fts3/fts3_snippet.c.
︙ | ︙ | |||
104 105 106 107 108 109 110 | ** for details. */ struct MatchinfoBuffer { u8 aRef[3]; int nElem; int bGlobal; /* Set if global data is loaded */ char *zMatchinfo; | | > > > > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | ** for details. */ struct MatchinfoBuffer { u8 aRef[3]; int nElem; int bGlobal; /* Set if global data is loaded */ char *zMatchinfo; u32 aMI[FLEXARRAY]; }; /* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */ #define SZ_MATCHINFOBUFFER(N) \ (offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64)) /* ** The snippet() and offsets() functions both return text values. An instance ** of the following structure is used to accumulate those values while the ** functions are running. See fts3StringAppend() for details. */ |
︙ | ︙ | |||
131 132 133 134 135 136 137 | /* ** Allocate a two-slot MatchinfoBuffer object. */ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){ MatchinfoBuffer *pRet; sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1) | | | | | | | | | | | | 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 | /* ** Allocate a two-slot MatchinfoBuffer object. */ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){ MatchinfoBuffer *pRet; sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1) + SZ_MATCHINFOBUFFER(1); sqlite3_int64 nStr = strlen(zMatchinfo); pRet = sqlite3Fts3MallocZero(nByte + nStr+1); if( pRet ){ pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet; pRet->aMI[1+nElem] = pRet->aMI[0] + sizeof(u32)*((int)nElem+1); pRet->nElem = (int)nElem; pRet->zMatchinfo = ((char*)pRet) + nByte; memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1); pRet->aRef[0] = 1; } return pRet; } static void fts3MIBufferFree(void *p){ MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]); assert( (u32*)p==&pBuf->aMI[1] || (u32*)p==&pBuf->aMI[pBuf->nElem+2] ); if( (u32*)p==&pBuf->aMI[1] ){ pBuf->aRef[1] = 0; }else{ pBuf->aRef[2] = 0; } if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){ sqlite3_free(pBuf); } } static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){ void (*xRet)(void*) = 0; u32 *aOut = 0; if( p->aRef[1]==0 ){ p->aRef[1] = 1; aOut = &p->aMI[1]; xRet = fts3MIBufferFree; } else if( p->aRef[2]==0 ){ p->aRef[2] = 1; aOut = &p->aMI[p->nElem+2]; xRet = fts3MIBufferFree; }else{ aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32)); if( aOut ){ xRet = sqlite3_free; if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32)); } } *paOut = aOut; return xRet; } static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){ p->bGlobal = 1; memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32)); } /* ** Free a MatchinfoBuffer object allocated using fts3MIBufferNew() */ void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){ if( p ){ |
︙ | ︙ |
Changes to ext/fts5/fts5Int.h.
︙ | ︙ | |||
71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) #else # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) #endif #endif /* Truncate very long tokens to this many bytes. Hard limit is ** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset ** field that occurs at the start of each leaf page (see fts5_index.c). */ #define FTS5_MAX_TOKEN_SIZE 32768 | > > > > > > > > > > > > | 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 | #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) #else # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) #endif /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof # define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif #endif /* Truncate very long tokens to this many bytes. Hard limit is ** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset ** field that occurs at the start of each leaf page (see fts5_index.c). */ #define FTS5_MAX_TOKEN_SIZE 32768 |
︙ | ︙ | |||
143 144 145 146 147 148 149 | ** then an object of the following type is used to record the set of columns. ** Each entry in the aiCol[] array is a column that may be matched. ** ** This object is used by fts5_expr.c and fts5_index.c. */ struct Fts5Colset { int nCol; | | | > | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | ** then an object of the following type is used to record the set of columns. ** Each entry in the aiCol[] array is a column that may be matched. ** ** This object is used by fts5_expr.c and fts5_index.c. */ struct Fts5Colset { int nCol; int aiCol[FLEXARRAY]; }; /* Size (int bytes) of a complete Fts5Colset object with N columns. */ #define SZ_FTS5COLSET(N) (sizeof(i64)*((N+2)/2)) /************************************************************************** ** Interface to code in fts5_config.c. fts5_config.c contains contains code ** to parse the arguments passed to the CREATE VIRTUAL TABLE statement. */ typedef struct Fts5Config Fts5Config; |
︙ | ︙ |
Changes to ext/fts5/fts5_expr.c.
︙ | ︙ | |||
82 83 84 85 86 87 88 | i64 iRowid; /* Current rowid */ Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ /* Child nodes. For a NOT node, this array always contains 2 entries. For ** AND or OR nodes, it contains 2 or more entries. */ int nChild; /* Number of child nodes */ | | > > > > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | i64 iRowid; /* Current rowid */ Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ /* Child nodes. For a NOT node, this array always contains 2 entries. For ** AND or OR nodes, it contains 2 or more entries. */ int nChild; /* Number of child nodes */ Fts5ExprNode *apChild[FLEXARRAY]; /* Array of child nodes */ }; /* Size (in bytes) of an Fts5ExprNode object that holds up to N children */ #define SZ_FTS5EXPRNODE(N) \ (offsetof(Fts5ExprNode,apChild) + (N)*sizeof(Fts5ExprNode*)) #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) /* ** Invoke the xNext method of an Fts5ExprNode object. This macro should be ** used as if it has the same signature as the xNext() methods themselves. */ |
︙ | ︙ | |||
115 116 117 118 119 120 121 | ** A phrase. One or more terms that must appear in a contiguous sequence ** within a document for it to match. */ struct Fts5ExprPhrase { Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */ Fts5Buffer poslist; /* Current position list */ int nTerm; /* Number of entries in aTerm[] */ | | > > > > | > > > | 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 | ** A phrase. One or more terms that must appear in a contiguous sequence ** within a document for it to match. */ struct Fts5ExprPhrase { Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */ Fts5Buffer poslist; /* Current position list */ int nTerm; /* Number of entries in aTerm[] */ Fts5ExprTerm aTerm[FLEXARRAY]; /* Terms that make up this phrase */ }; /* Size (in bytes) of an Fts5ExprPhrase object that holds up to N terms */ #define SZ_FTS5EXPRPHRASE(N) \ (offsetof(Fts5ExprPhrase,aTerm) + (N)*sizeof(Fts5ExprTerm)) /* ** One or more phrases that must appear within a certain token distance of ** each other within each matching document. */ struct Fts5ExprNearset { int nNear; /* NEAR parameter */ Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */ int nPhrase; /* Number of entries in aPhrase[] array */ Fts5ExprPhrase *apPhrase[FLEXARRAY]; /* Array of phrase pointers */ }; /* Size (in bytes) of an Fts5ExprNearset object covering up to N phrases */ #define SZ_FTS5EXPRNEARSET(N) \ (offsetof(Fts5ExprNearset,apPhrase)+(N)*sizeof(Fts5ExprPhrase*)) /* ** Parse context. */ struct Fts5Parse { Fts5Config *pConfig; char *zErr; |
︙ | ︙ | |||
288 289 290 291 292 293 294 | assert( sParse.pExpr || sParse.rc!=SQLITE_OK ); assert_expr_depth_ok(sParse.rc, sParse.pExpr); /* If the LHS of the MATCH expression was a user column, apply the ** implicit column-filter. */ if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){ | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | assert( sParse.pExpr || sParse.rc!=SQLITE_OK ); assert_expr_depth_ok(sParse.rc, sParse.pExpr); /* If the LHS of the MATCH expression was a user column, apply the ** implicit column-filter. */ if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){ int n = SZ_FTS5COLSET(1); Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n); if( pColset ){ pColset->nCol = 1; pColset->aiCol[0] = iCol; sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset); } } |
︙ | ︙ | |||
1646 1647 1648 1649 1650 1651 1652 | ){ const int SZALLOC = 8; Fts5ExprNearset *pRet = 0; if( pParse->rc==SQLITE_OK ){ if( pNear==0 ){ sqlite3_int64 nByte; | | | | 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 | ){ const int SZALLOC = 8; Fts5ExprNearset *pRet = 0; if( pParse->rc==SQLITE_OK ){ if( pNear==0 ){ sqlite3_int64 nByte; nByte = SZ_FTS5EXPRNEARSET(SZALLOC+1); pRet = sqlite3_malloc64(nByte); if( pRet==0 ){ pParse->rc = SQLITE_NOMEM; }else{ memset(pRet, 0, (size_t)nByte); } }else if( (pNear->nPhrase % SZALLOC)==0 ){ int nNew = pNear->nPhrase + SZALLOC; sqlite3_int64 nByte; nByte = SZ_FTS5EXPRNEARSET(nNew+1); pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte); if( pRet==0 ){ pParse->rc = SQLITE_NOMEM; } }else{ pRet = pNear; } |
︙ | ︙ | |||
1748 1749 1750 1751 1752 1753 1754 | }else{ Fts5ExprTerm *pTerm; if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){ Fts5ExprPhrase *pNew; int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0); pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase, | | | | 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 | }else{ Fts5ExprTerm *pTerm; if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){ Fts5ExprPhrase *pNew; int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0); pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase, SZ_FTS5EXPRPHRASE(nNew+1) ); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ if( pPhrase==0 ) memset(pNew, 0, SZ_FTS5EXPRPHRASE(1)); pCtx->pPhrase = pPhrase = pNew; pNew->nTerm = nNew - SZALLOC; } } if( rc==SQLITE_OK ){ pTerm = &pPhrase->aTerm[pPhrase->nTerm++]; |
︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 | } pParse->nPhrase++; } if( sCtx.pPhrase==0 ){ /* This happens when parsing a token or quoted phrase that contains ** no token characters at all. (e.g ... MATCH '""'). */ | | | 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 | } pParse->nPhrase++; } if( sCtx.pPhrase==0 ){ /* This happens when parsing a token or quoted phrase that contains ** no token characters at all. (e.g ... MATCH '""'). */ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5EXPRPHRASE(1)); }else if( sCtx.pPhrase->nTerm ){ sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix; } assert( pParse->apPhrase!=0 ); pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase; } |
︙ | ︙ | |||
1896 1897 1898 1899 1900 1901 1902 | pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); } if( rc==SQLITE_OK ){ pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase*)); } if( rc==SQLITE_OK ){ | | < | < > | | 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 | pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); } if( rc==SQLITE_OK ){ pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase*)); } if( rc==SQLITE_OK ){ pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNODE(1)); } if( rc==SQLITE_OK ){ pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNEARSET(2)); } if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){ Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset; if( pColsetOrig ){ sqlite3_int64 nByte; Fts5Colset *pColset; nByte = SZ_FTS5COLSET(pColsetOrig->nCol); pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte); if( pColset ){ memcpy(pColset, pColsetOrig, (size_t)nByte); } pNew->pRoot->pNear->pColset = pColset; } } |
︙ | ︙ | |||
1936 1937 1938 1939 1940 1941 1942 | sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; } } }else{ /* This happens when parsing a token or quoted phrase that contains ** no token characters at all. (e.g ... MATCH '""'). */ | | | 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 | sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; } } }else{ /* This happens when parsing a token or quoted phrase that contains ** no token characters at all. (e.g ... MATCH '""'). */ sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRPHRASE(1)); } } if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){ /* All the allocations succeeded. Put the expression object together. */ pNew->pIndex = pExpr->pIndex; pNew->pConfig = pExpr->pConfig; |
︙ | ︙ | |||
2030 2031 2032 2033 2034 2035 2036 | ){ int nCol = p ? p->nCol : 0; /* Num. columns already in colset object */ Fts5Colset *pNew; /* New colset object to return */ assert( pParse->rc==SQLITE_OK ); assert( iCol>=0 && iCol<pParse->pConfig->nCol ); | | | 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 | ){ int nCol = p ? p->nCol : 0; /* Num. columns already in colset object */ Fts5Colset *pNew; /* New colset object to return */ assert( pParse->rc==SQLITE_OK ); assert( iCol>=0 && iCol<pParse->pConfig->nCol ); pNew = sqlite3_realloc64(p, SZ_FTS5COLSET(nCol+1)); if( pNew==0 ){ pParse->rc = SQLITE_NOMEM; }else{ int *aiCol = pNew->aiCol; int i, j; for(i=0; i<nCol; i++){ if( aiCol[i]==iCol ) return pNew; |
︙ | ︙ | |||
2065 2066 2067 2068 2069 2070 2071 | ** as the second argument before returning. */ Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){ Fts5Colset *pRet; int nCol = pParse->pConfig->nCol; pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc, | | | 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 | ** as the second argument before returning. */ Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){ Fts5Colset *pRet; int nCol = pParse->pConfig->nCol; pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5COLSET(nCol+1) ); if( pRet ){ int i; int iOld = 0; for(i=0; i<nCol; i++){ if( iOld>=p->nCol || p->aiCol[iOld]!=i ){ pRet->aiCol[pRet->nCol++] = i; |
︙ | ︙ | |||
2126 2127 2128 2129 2130 2131 2132 | ** Otherwise, a copy of (*pOrig) is made into memory obtained from ** sqlite3Fts5MallocZero() and a pointer to it returned. If the allocation ** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned. */ static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){ Fts5Colset *pRet; if( pOrig ){ | | | 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 | ** Otherwise, a copy of (*pOrig) is made into memory obtained from ** sqlite3Fts5MallocZero() and a pointer to it returned. If the allocation ** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned. */ static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){ Fts5Colset *pRet; if( pOrig ){ sqlite3_int64 nByte = SZ_FTS5COLSET(pOrig->nCol); pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte); if( pRet ){ memcpy(pRet, pOrig, (size_t)nByte); } }else{ pRet = 0; } |
︙ | ︙ | |||
2294 2295 2296 2297 2298 2299 2300 | int ii; int nByte; Fts5ExprNode *pRet; assert( pNear->nPhrase==1 ); assert( pParse->bPhraseToAnd ); | | | | 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 | int ii; int nByte; Fts5ExprNode *pRet; assert( pNear->nPhrase==1 ); assert( pParse->bPhraseToAnd ); nByte = SZ_FTS5EXPRNODE(nTerm+1); pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); if( pRet ){ pRet->eType = FTS5_AND; pRet->nChild = nTerm; pRet->iHeight = 1; fts5ExprAssignXNext(pRet); pParse->nPhrase--; for(ii=0; ii<nTerm; ii++){ Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero( &pParse->rc, SZ_FTS5EXPRPHRASE(1) ); if( pPhrase ){ if( parseGrowPhraseArray(pParse) ){ fts5ExprPhraseFree(pPhrase); }else{ Fts5ExprTerm *p = &pNear->apPhrase[0]->aTerm[ii]; Fts5ExprTerm *pTo = &pPhrase->aTerm[0]; |
︙ | ︙ | |||
2373 2374 2375 2376 2377 2378 2379 | nChild = 2; }else if( eType==FTS5_AND || eType==FTS5_OR ){ nChild = 2; if( pLeft->eType==eType ) nChild += pLeft->nChild-1; if( pRight->eType==eType ) nChild += pRight->nChild-1; } | | | 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 | nChild = 2; }else if( eType==FTS5_AND || eType==FTS5_OR ){ nChild = 2; if( pLeft->eType==eType ) nChild += pLeft->nChild-1; if( pRight->eType==eType ) nChild += pRight->nChild-1; } nByte = SZ_FTS5EXPRNODE(nChild); pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); if( pRet ){ pRet->eType = eType; pRet->pNear = pNear; fts5ExprAssignXNext(pRet); if( eType==FTS5_STRING ){ |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
418 419 420 421 422 423 424 | }; struct Fts5Structure { int nRef; /* Object reference count */ u64 nWriteCounter; /* Total leaves written to level 0 */ u64 nOriginCntr; /* Origin value for next top-level segment */ int nSegment; /* Total segments in this structure */ int nLevel; /* Number of levels in this index */ | | > > > > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | }; struct Fts5Structure { int nRef; /* Object reference count */ u64 nWriteCounter; /* Total leaves written to level 0 */ u64 nOriginCntr; /* Origin value for next top-level segment */ int nSegment; /* Total segments in this structure */ int nLevel; /* Number of levels in this index */ Fts5StructureLevel aLevel[FLEXARRAY]; /* Array of nLevel level objects */ }; /* Size (in bytes) of an Fts5Structure object holding up to N levels */ #define SZ_FTS5STRUCTURE(N) \ (offsetof(Fts5Structure,aLevel) + (N)*sizeof(Fts5StructureLevel)) /* ** An object of type Fts5SegWriter is used to write to segments. */ struct Fts5PageWriter { int pgno; /* Page number for this page */ int iPrevPgidx; /* Previous value written into pgidx */ Fts5Buffer buf; /* Buffer containing leaf data */ |
︙ | ︙ | |||
550 551 552 553 554 555 556 | u8 bDel; /* True if the delete flag is set */ }; /* ** Array of tombstone pages. Reference counted. */ struct Fts5TombstoneArray { | | | > > > > | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 | u8 bDel; /* True if the delete flag is set */ }; /* ** Array of tombstone pages. Reference counted. */ struct Fts5TombstoneArray { int nRef; /* Number of pointers to this object */ int nTombstone; Fts5Data *apTombstone[FLEXARRAY]; /* Array of tombstone pages */ }; /* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */ #define SZ_FTS5TOMBSTONEARRAY(N) \ (offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*)) /* ** Argument is a pointer to an Fts5Data structure that contains a ** leaf page. */ #define ASSERT_SZLEAF_OK(x) assert( \ (x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \ |
︙ | ︙ | |||
623 624 625 626 627 628 629 | int nSeg; /* Size of aSeg[] array */ int bRev; /* True to iterate in reverse order */ u8 bSkipEmpty; /* True to skip deleted entries */ i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ Fts5CResult *aFirst; /* Current merge state (see above) */ | | > > > | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 | int nSeg; /* Size of aSeg[] array */ int bRev; /* True to iterate in reverse order */ u8 bSkipEmpty; /* True to skip deleted entries */ i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ Fts5CResult *aFirst; /* Current merge state (see above) */ Fts5SegIter aSeg[FLEXARRAY]; /* Array of segment iterators */ }; /* Size (in bytes) of an Fts5Iter object holding up to N segment iterators */ #define SZ_FTS5ITER(N) (offsetof(Fts5Iter,aSeg)+(N)*sizeof(Fts5SegIter)) /* ** An instance of the following type is used to iterate through the contents ** of a doclist-index record. ** ** pData: ** Record containing the doclist-index data. |
︙ | ︙ | |||
652 653 654 655 656 657 658 | /* Output variables */ int iLeafPgno; /* Page number of current leaf page */ i64 iRowid; /* First rowid on leaf iLeafPgno */ }; struct Fts5DlidxIter { int nLvl; int iSegid; | | > > > > | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | /* Output variables */ int iLeafPgno; /* Page number of current leaf page */ i64 iRowid; /* First rowid on leaf iLeafPgno */ }; struct Fts5DlidxIter { int nLvl; int iSegid; Fts5DlidxLvl aLvl[FLEXARRAY]; }; /* Size (in bytes) of an Fts5DlidxIter object with up to N levels */ #define SZ_FTS5DLIDXITER(N) \ (offsetof(Fts5DlidxIter,aLvl)+(N)*sizeof(Fts5DlidxLvl)) static void fts5PutU16(u8 *aOut, u16 iVal){ aOut[0] = (iVal>>8); aOut[1] = (iVal&0xFF); } static u16 fts5GetU16(const u8 *aIn){ |
︙ | ︙ | |||
1022 1023 1024 1025 1026 1027 1028 | ** ** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If ** an error occurs, (*pRc) is set to an SQLite error code before returning. */ static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){ Fts5Structure *p = *pp; if( *pRc==SQLITE_OK && p->nRef>1 ){ | | | 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | ** ** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If ** an error occurs, (*pRc) is set to an SQLite error code before returning. */ static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){ Fts5Structure *p = *pp; if( *pRc==SQLITE_OK && p->nRef>1 ){ i64 nByte = SZ_FTS5STRUCTURE(p->nLevel); Fts5Structure *pNew; pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte); if( pNew ){ int i; memcpy(pNew, p, nByte); for(i=0; i<p->nLevel; i++) pNew->aLevel[i].aSeg = 0; for(i=0; i<p->nLevel; i++){ |
︙ | ︙ | |||
1096 1097 1098 1099 1100 1101 1102 | i += fts5GetVarint32(&pData[i], nLevel); i += fts5GetVarint32(&pData[i], nSegment); if( nLevel>FTS5_MAX_SEGMENT || nLevel<0 || nSegment>FTS5_MAX_SEGMENT || nSegment<0 ){ return FTS5_CORRUPT; } | | < < < | 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 | i += fts5GetVarint32(&pData[i], nLevel); i += fts5GetVarint32(&pData[i], nSegment); if( nLevel>FTS5_MAX_SEGMENT || nLevel<0 || nSegment>FTS5_MAX_SEGMENT || nSegment<0 ){ return FTS5_CORRUPT; } nByte = SZ_FTS5STRUCTURE(nLevel); pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte); if( pRet ){ pRet->nRef = 1; pRet->nLevel = nLevel; pRet->nSegment = nSegment; i += sqlite3Fts5GetVarint(&pData[i], &pRet->nWriteCounter); |
︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 | */ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){ fts5StructureMakeWritable(pRc, ppStruct); assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK ); if( *pRc==SQLITE_OK ){ Fts5Structure *pStruct = *ppStruct; int nLevel = pStruct->nLevel; | | < < < | 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 | */ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){ fts5StructureMakeWritable(pRc, ppStruct); assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK ); if( *pRc==SQLITE_OK ){ Fts5Structure *pStruct = *ppStruct; int nLevel = pStruct->nLevel; sqlite3_int64 nByte = SZ_FTS5STRUCTURE(nLevel+2); pStruct = sqlite3_realloc64(pStruct, nByte); if( pStruct ){ memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel)); pStruct->nLevel++; *ppStruct = pStruct; }else{ |
︙ | ︙ | |||
1721 1722 1723 1724 1725 1726 1727 | int iLeafPg /* Leaf page number to load dlidx for */ ){ Fts5DlidxIter *pIter = 0; int i; int bDone = 0; for(i=0; p->rc==SQLITE_OK && bDone==0; i++){ | | | 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 | int iLeafPg /* Leaf page number to load dlidx for */ ){ Fts5DlidxIter *pIter = 0; int i; int bDone = 0; for(i=0; p->rc==SQLITE_OK && bDone==0; i++){ sqlite3_int64 nByte = SZ_FTS5DLIDXITER(i+1); Fts5DlidxIter *pNew; pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte); if( pNew==0 ){ p->rc = SQLITE_NOMEM; }else{ i64 iRowid = FTS5_DLIDX_ROWID(iSegid, i, iLeafPg); |
︙ | ︙ | |||
1939 1940 1941 1942 1943 1944 1945 | ** Allocate a tombstone hash page array object (pIter->pTombArray) for ** the iterator passed as the second argument. If an OOM error occurs, ** leave an error in the Fts5Index object. */ static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){ const int nTomb = pIter->pSeg->nPgTombstone; if( nTomb>0 ){ | | | 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 | ** Allocate a tombstone hash page array object (pIter->pTombArray) for ** the iterator passed as the second argument. If an OOM error occurs, ** leave an error in the Fts5Index object. */ static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){ const int nTomb = pIter->pSeg->nPgTombstone; if( nTomb>0 ){ int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1); Fts5TombstoneArray *pNew; pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ pNew->nTombstone = nTomb; pNew->nRef = 1; pIter->pTombArray = pNew; } |
︙ | ︙ | |||
3400 3401 3402 3403 3404 3405 3406 | int nSeg ){ Fts5Iter *pNew; i64 nSlot; /* Power of two >= nSeg */ for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2); pNew = fts5IdxMalloc(p, | | < | 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 | int nSeg ){ Fts5Iter *pNew; i64 nSlot; /* Power of two >= nSeg */ for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2); pNew = fts5IdxMalloc(p, SZ_FTS5ITER(nSlot) + /* pNew + pNew->aSeg[] */ sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ ); if( pNew ){ pNew->nSeg = nSlot; pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; pNew->pIndex = p; pNew->xSetOutputs = fts5IterSetOutputs_Noop; |
︙ | ︙ | |||
5767 5768 5769 5770 5771 5772 5773 | } static Fts5Structure *fts5IndexOptimizeStruct( Fts5Index *p, Fts5Structure *pStruct ){ Fts5Structure *pNew = 0; | | | 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 | } static Fts5Structure *fts5IndexOptimizeStruct( Fts5Index *p, Fts5Structure *pStruct ){ Fts5Structure *pNew = 0; sqlite3_int64 nByte = SZ_FTS5STRUCTURE(1); int nSeg = pStruct->nSegment; int i; /* Figure out if this structure requires optimization. A structure does ** not require optimization if either: ** ** 1. it consists of fewer than two segments, or |
︙ | ︙ | |||
5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 | fts5StructureRef(pStruct); return pStruct; } assert( pStruct->aLevel[i].nMerge<=nThis ); } nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel); pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ Fts5StructureLevel *pLvl; nByte = nSeg * sizeof(Fts5StructureSegment); pNew->nLevel = MIN(pStruct->nLevel+1, FTS5_MAX_LEVEL); pNew->nRef = 1; | > | 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 | fts5StructureRef(pStruct); return pStruct; } assert( pStruct->aLevel[i].nMerge<=nThis ); } nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel); assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) ); pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ Fts5StructureLevel *pLvl; nByte = nSeg * sizeof(Fts5StructureSegment); pNew->nLevel = MIN(pStruct->nLevel+1, FTS5_MAX_LEVEL); pNew->nRef = 1; |
︙ | ︙ | |||
6373 6374 6375 6376 6377 6378 6379 | Fts5Buffer terms; /* The following are used for other full-token tokendata queries only. */ int nIter; int nIterAlloc; Fts5PoslistReader *aPoslistReader; int *aPoslistToIter; | | > > > > | 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 | Fts5Buffer terms; /* The following are used for other full-token tokendata queries only. */ int nIter; int nIterAlloc; Fts5PoslistReader *aPoslistReader; int *aPoslistToIter; Fts5Iter *apIter[FLEXARRAY]; }; /* Size in bytes of an Fts5TokenDataIter object holding up to N iterators */ #define SZ_FTS5TOKENDATAITER(N) \ (offsetof(Fts5TokenDataIter,apIter) + (N)*sizeof(Fts5Iter)) /* ** The two input arrays - a1[] and a2[] - are in sorted order. This function ** merges the two arrays together and writes the result to output array ** aOut[]. aOut[] is guaranteed to be large enough to hold the result. ** ** Duplicate entries are copied into the output. So the size of the output |
︙ | ︙ | |||
6638 6639 6640 6641 6642 6643 6644 | s.iLastRowid = 0; s.nBuf = 32; if( iIdx==0 && p->pConfig->eDetail==FTS5_DETAIL_FULL && p->pConfig->bPrefixInsttoken ){ s.pTokendata = &s2; | | | 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 | s.iLastRowid = 0; s.nBuf = 32; if( iIdx==0 && p->pConfig->eDetail==FTS5_DETAIL_FULL && p->pConfig->bPrefixInsttoken ){ s.pTokendata = &s2; s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, SZ_FTS5TOKENDATAITER(1)); } if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ s.xMerge = fts5MergeRowidLists; s.xAppend = fts5AppendRowid; }else{ s.nMerge = FTS5_MERGE_NLIST-1; |
︙ | ︙ | |||
6766 6767 6768 6769 6770 6771 6772 | /* ** The %_data table is completely empty when this function is called. This ** function populates it with the initial structure objects for each index, ** and the initial version of the "averages" record (a zero-byte blob). */ int sqlite3Fts5IndexReinit(Fts5Index *p){ | | > | > | | | 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 | /* ** The %_data table is completely empty when this function is called. This ** function populates it with the initial structure objects for each index, ** and the initial version of the "averages" record (a zero-byte blob). */ int sqlite3Fts5IndexReinit(Fts5Index *p){ Fts5Structure *pTmp; u8 tmpSpace[SZ_FTS5STRUCTURE(1)]; fts5StructureInvalidate(p); fts5IndexDiscardData(p); pTmp = (Fts5Structure*)tmpSpace; memset(pTmp, 0, SZ_FTS5STRUCTURE(1)); if( p->pConfig->bContentlessDelete ){ pTmp->nOriginCntr = 1; } fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0); fts5StructureWrite(p, pTmp); return fts5IndexReturn(p); } /* ** Open a new Fts5Index handle. If the bCreate argument is true, create ** and initialize the underlying %_data table. ** |
︙ | ︙ | |||
6982 6983 6984 6985 6986 6987 6988 | Fts5Iter *pAppend /* Append this iterator */ ){ Fts5TokenDataIter *pRet = pIn; if( p->rc==SQLITE_OK ){ if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){ int nAlloc = pIn ? pIn->nIterAlloc*2 : 16; | | | 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 | Fts5Iter *pAppend /* Append this iterator */ ){ Fts5TokenDataIter *pRet = pIn; if( p->rc==SQLITE_OK ){ if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){ int nAlloc = pIn ? pIn->nIterAlloc*2 : 16; int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1); Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte); if( pNew==0 ){ p->rc = SQLITE_NOMEM; }else{ if( pIn==0 ) memset(pNew, 0, nByte); pRet = pNew; |
︙ | ︙ | |||
7498 7499 7500 7501 7502 7503 7504 | Fts5Buffer token = {0, 0, 0}; TokendataSetupCtx ctx; memset(&ctx, 0, sizeof(ctx)); fts5BufferGrow(&p->rc, &token, nToken+1); assert( token.p!=0 || p->rc!=SQLITE_OK ); | | > | 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 | Fts5Buffer token = {0, 0, 0}; TokendataSetupCtx ctx; memset(&ctx, 0, sizeof(ctx)); fts5BufferGrow(&p->rc, &token, nToken+1); assert( token.p!=0 || p->rc!=SQLITE_OK ); ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, SZ_FTS5TOKENDATAITER(1)); if( p->rc==SQLITE_OK ){ /* Fill in the token prefix to search for */ token.p[0] = FTS5_MAIN_PREFIX; memcpy(&token.p[1], pToken, nToken); token.n = nToken+1; |
︙ | ︙ | |||
7629 7630 7631 7632 7633 7634 7635 | i64 iPos = (((i64)iCol)<<32) + iOff; assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL ); assert( pIter->pTokenDataIter || pIter->nSeg>0 ); if( pIter->nSeg>0 ){ /* This is a prefix term iterator. */ if( pT==0 ){ | | > | 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 | i64 iPos = (((i64)iCol)<<32) + iOff; assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL ); assert( pIter->pTokenDataIter || pIter->nSeg>0 ); if( pIter->nSeg>0 ){ /* This is a prefix term iterator. */ if( pT==0 ){ pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, SZ_FTS5TOKENDATAITER(1)); pIter->pTokenDataIter = pT; } if( pT ){ fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos); fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken); } }else{ |
︙ | ︙ |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
166 167 168 169 170 171 172 | ** byte of the position list for the corresponding phrase. */ struct Fts5Sorter { sqlite3_stmt *pStmt; i64 iRowid; /* Current rowid */ const u8 *aPoslist; /* Position lists for current row */ int nIdx; /* Number of entries in aIdx[] */ | | > > | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | ** byte of the position list for the corresponding phrase. */ struct Fts5Sorter { sqlite3_stmt *pStmt; i64 iRowid; /* Current rowid */ const u8 *aPoslist; /* Position lists for current row */ int nIdx; /* Number of entries in aIdx[] */ int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */ }; /* Size (int bytes) of an Fts5Sorter object with N indexes */ #define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64)) /* ** Virtual-table cursor object. ** ** iSpecial: ** If this is a 'special' query (refer to function fts5SpecialMatch()), ** then this variable contains the result of the query. |
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 | int nPhrase; sqlite3_int64 nByte; int rc; const char *zRank = pCsr->zRank; const char *zRankArgs = pCsr->zRankArgs; nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); | | | 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | int nPhrase; sqlite3_int64 nByte; int rc; const char *zRank = pCsr->zRank; const char *zRankArgs = pCsr->zRankArgs; nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); nByte = SZ_FTS5SORTER(nPhrase); pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte); if( pSorter==0 ) return SQLITE_NOMEM; memset(pSorter, 0, (size_t)nByte); pSorter->nIdx = nPhrase; /* TODO: It would be better to have some system for reusing statement ** handles here, rather than preparing a new one for each query. But that |
︙ | ︙ |
Changes to ext/misc/completion.c.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <assert.h> #include <string.h> #include <ctype.h> #ifndef SQLITE_OMIT_VIRTUALTABLE /* completion_vtab is a subclass of sqlite3_vtab which will ** serve as the underlying representation of a completion virtual table */ typedef struct completion_vtab completion_vtab; struct completion_vtab { sqlite3_vtab base; /* Base class - must be first */ | > > > > > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <assert.h> #include <string.h> #include <ctype.h> #ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef IsAlnum #define IsAlnum(X) isalnum((unsigned char)X) #endif /* completion_vtab is a subclass of sqlite3_vtab which will ** serve as the underlying representation of a completion virtual table */ typedef struct completion_vtab completion_vtab; struct completion_vtab { sqlite3_vtab base; /* Base class - must be first */ |
︙ | ︙ | |||
373 374 375 376 377 378 379 | if( pCur->nLine>0 ){ pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); if( pCur->zLine==0 ) return SQLITE_NOMEM; } } if( pCur->zLine!=0 && pCur->zPrefix==0 ){ int i = pCur->nLine; | | | 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | if( pCur->nLine>0 ){ pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); if( pCur->zLine==0 ) return SQLITE_NOMEM; } } if( pCur->zLine!=0 && pCur->zPrefix==0 ){ int i = pCur->nLine; while( i>0 && (IsAlnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){ i--; } pCur->nPrefix = pCur->nLine - i; if( pCur->nPrefix>0 ){ pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i); if( pCur->zPrefix==0 ) return SQLITE_NOMEM; } |
︙ | ︙ |
Changes to ext/misc/decimal.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /* Mark a function parameter as unused, to suppress nuisance compiler ** warnings. */ #ifndef UNUSED_PARAMETER # define UNUSED_PARAMETER(X) (void)(X) #endif /* A decimal object */ typedef struct Decimal Decimal; struct Decimal { char sign; /* 0 for positive, 1 for negative */ char oom; /* True if an OOM is encountered */ char isNull; /* True if holds a NULL rather than a number */ | > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /* Mark a function parameter as unused, to suppress nuisance compiler ** warnings. */ #ifndef UNUSED_PARAMETER # define UNUSED_PARAMETER(X) (void)(X) #endif #ifndef IsSpace #define IsSpace(X) isspace((unsigned char)X) #endif /* A decimal object */ typedef struct Decimal Decimal; struct Decimal { char sign; /* 0 for positive, 1 for negative */ char oom; /* True if an OOM is encountered */ char isNull; /* True if holds a NULL rather than a number */ |
︙ | ︙ | |||
72 73 74 75 76 77 78 | p->oom = 0; p->isInit = 1; p->isNull = 0; p->nDigit = 0; p->nFrac = 0; p->a = sqlite3_malloc64( n+1 ); if( p->a==0 ) goto new_from_text_failed; | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | p->oom = 0; p->isInit = 1; p->isNull = 0; p->nDigit = 0; p->nFrac = 0; p->a = sqlite3_malloc64( n+1 ); if( p->a==0 ) goto new_from_text_failed; for(i=0; IsSpace(zIn[i]); i++){} if( zIn[i]=='-' ){ p->sign = 1; i++; }else if( zIn[i]=='+' ){ i++; } while( i<n && zIn[i]=='0' ) i++; |
︙ | ︙ |
Changes to ext/misc/series.c.
︙ | ︙ | |||
515 516 517 518 519 520 521 | if( pCur->ss.iStep>0 ){ sqlite3_int64 szStep = pCur->ss.iStep; if( pCur->ss.iBase<iMin ){ sqlite3_uint64 d = iMin - pCur->ss.iBase; pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep; } if( pCur->ss.iTerm>iMax ){ | < | < | | 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 | if( pCur->ss.iStep>0 ){ sqlite3_int64 szStep = pCur->ss.iStep; if( pCur->ss.iBase<iMin ){ sqlite3_uint64 d = iMin - pCur->ss.iBase; pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep; } if( pCur->ss.iTerm>iMax ){ pCur->ss.iTerm = iMax; } }else{ sqlite3_int64 szStep = -pCur->ss.iStep; assert( szStep>0 ); if( pCur->ss.iBase>iMax ){ sqlite3_uint64 d = pCur->ss.iBase - iMax; pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep; } if( pCur->ss.iTerm<iMin ){ pCur->ss.iTerm = iMin; } } } /* Apply LIMIT and OFFSET constraints, if any */ if( idxNum & 0x20 ){ if( iOffset>0 ){ |
︙ | ︙ |
Changes to ext/recover/recoverslowidx.test.
︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 | } {} do_test 1.2 { set lSql } [list {*}{ {BEGIN} {PRAGMA writable_schema = on} {PRAGMA encoding = 'UTF-8'} {PRAGMA page_size = '1024'} {PRAGMA auto_vacuum = '0'} {PRAGMA user_version = '0'} {PRAGMA application_id = '0'} {CREATE TABLE t1(a, b)} {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (1, 1, 1)} | > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | } {} do_test 1.2 { set lSql } [list {*}{ {BEGIN} {PRAGMA writable_schema = on} {PRAGMA foreign_keys = off} {PRAGMA encoding = 'UTF-8'} {PRAGMA page_size = '1024'} {PRAGMA auto_vacuum = '0'} {PRAGMA user_version = '0'} {PRAGMA application_id = '0'} {CREATE TABLE t1(a, b)} {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (1, 1, 1)} |
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 | } {} do_test 1.4 { set lSql } [list {*}{ {BEGIN} {PRAGMA writable_schema = on} {PRAGMA encoding = 'UTF-8'} {PRAGMA page_size = '1024'} {PRAGMA auto_vacuum = '0'} {PRAGMA user_version = '0'} {PRAGMA application_id = '0'} {CREATE TABLE t1(a, b)} {CREATE INDEX i1 ON t1(a)} | > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | } {} do_test 1.4 { set lSql } [list {*}{ {BEGIN} {PRAGMA writable_schema = on} {PRAGMA foreign_keys = off} {PRAGMA encoding = 'UTF-8'} {PRAGMA page_size = '1024'} {PRAGMA auto_vacuum = '0'} {PRAGMA user_version = '0'} {PRAGMA application_id = '0'} {CREATE TABLE t1(a, b)} {CREATE INDEX i1 ON t1(a)} |
︙ | ︙ |
Changes to ext/recover/sqlite3recover.c.
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #endif int sqlite3_dbdata_init(sqlite3*, char**, const sqlite3_api_routines*); typedef unsigned int u32; typedef unsigned char u8; typedef sqlite3_int64 i64; typedef struct RecoverTable RecoverTable; typedef struct RecoverColumn RecoverColumn; /* ** When recovering rows of data that can be associated with table ** definitions recovered from the sqlite_schema table, each table is ** represented by an instance of the following object. | > > > > > > > > > > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #endif int sqlite3_dbdata_init(sqlite3*, char**, const sqlite3_api_routines*); typedef unsigned int u32; typedef unsigned char u8; typedef sqlite3_int64 i64; /* ** Work around C99 "flex-array" syntax for pre-C99 compilers, so as ** to avoid complaints from -fsanitize=strict-bounds. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif typedef struct RecoverTable RecoverTable; typedef struct RecoverColumn RecoverColumn; /* ** When recovering rows of data that can be associated with table ** definitions recovered from the sqlite_schema table, each table is ** represented by an instance of the following object. |
︙ | ︙ | |||
136 137 138 139 140 141 142 | ** false if it is clear: ** ** (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0 */ typedef struct RecoverBitmap RecoverBitmap; struct RecoverBitmap { i64 nPg; /* Size of bitmap */ | | > > > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | ** false if it is clear: ** ** (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0 */ typedef struct RecoverBitmap RecoverBitmap; struct RecoverBitmap { i64 nPg; /* Size of bitmap */ u32 aElem[FLEXARRAY]; /* Array of 32-bit bitmasks */ }; /* Size in bytes of a RecoverBitmap object sufficient to cover 32 pages */ #define SZ_RECOVERBITMAP_32 (16) /* ** State variables (part of the sqlite3_recover structure) used while ** recovering data for tables identified in the recovered schema (state ** RECOVER_STATE_WRITING). */ typedef struct RecoverStateW1 RecoverStateW1; |
︙ | ︙ | |||
378 379 380 381 382 383 384 | ** ** Otherwise, an attempt is made to allocate and return a bitmap object ** large enough to store a bit for all page numbers between 1 and nPg, ** inclusive. The bitmap is initially zeroed. */ static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){ int nElem = (nPg+1+31) / 32; | | | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | ** ** Otherwise, an attempt is made to allocate and return a bitmap object ** large enough to store a bit for all page numbers between 1 and nPg, ** inclusive. The bitmap is initially zeroed. */ static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){ int nElem = (nPg+1+31) / 32; int nByte = SZ_RECOVERBITMAP_32 + nElem*sizeof(u32); RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte); if( pRet ){ pRet->nPg = nPg; } return pRet; } |
︙ | ︙ | |||
2570 2571 2572 2573 2574 2575 2576 | ** This function does the work of a single sqlite3_recover_step() call. It ** is guaranteed that the handle is not in an error state when this ** function is called. */ static void recoverStep(sqlite3_recover *p){ assert( p && p->errCode==SQLITE_OK ); switch( p->eState ){ | | > > < > > > > > > > > > | > | | | | | | | | | > > > | | < > > > | 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 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 | ** This function does the work of a single sqlite3_recover_step() call. It ** is guaranteed that the handle is not in an error state when this ** function is called. */ static void recoverStep(sqlite3_recover *p){ assert( p && p->errCode==SQLITE_OK ); switch( p->eState ){ case RECOVER_STATE_INIT: { int bUseWrapper = 1; /* This is the very first call to sqlite3_recover_step() on this object. */ recoverSqlCallback(p, "BEGIN"); recoverSqlCallback(p, "PRAGMA writable_schema = on"); recoverSqlCallback(p, "PRAGMA foreign_keys = off"); recoverEnterMutex(); /* Open the output database. And register required virtual tables and ** user functions with the new handle. */ recoverOpenOutput(p); /* Attempt to open a transaction and read page 1 of the input database. ** Two attempts may be made - one with a wrapper installed to ensure ** that the database header is sane, and then if that attempt returns ** SQLITE_NOTADB, then again with no wrapper. The second attempt is ** required for encrypted databases. */ if( p->errCode==SQLITE_OK ){ do{ p->errCode = SQLITE_OK; if( bUseWrapper ) recoverInstallWrapper(p); /* Open a transaction on the input database. */ sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0); recoverExec(p, p->dbIn, "PRAGMA writable_schema = on"); recoverExec(p, p->dbIn, "BEGIN"); if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1; recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema"); recoverTransferSettings(p); recoverOpenRecovery(p); recoverCacheSchema(p); if( bUseWrapper ) recoverUninstallWrapper(p); }while( p->errCode==SQLITE_NOTADB && (bUseWrapper--) && SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0) ); } recoverLeaveMutex(); recoverExec(p, p->dbOut, "BEGIN"); recoverWriteSchema1(p); p->eState = RECOVER_STATE_WRITING; break; } case RECOVER_STATE_WRITING: { if( p->w1.pTbls==0 ){ recoverWriteDataInit(p); } if( SQLITE_DONE==recoverWriteDataStep(p) ){ recoverWriteDataCleanup(p); |
︙ | ︙ |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
90 91 92 93 94 95 96 97 98 99 100 101 102 103 | #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif #endif /* !defined(SQLITE_AMALGAMATION) */ /* Macro to check for 4-byte alignment. Only used inside of assert() */ #ifdef SQLITE_DEBUG # define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0) #endif | > > > > > > > > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif #endif /* !defined(SQLITE_AMALGAMATION) */ /* Macro to check for 4-byte alignment. Only used inside of assert() */ #ifdef SQLITE_DEBUG # define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0) #endif |
︙ | ︙ | |||
410 411 412 413 414 415 416 | ** operand to the MATCH operator of an R-Tree. */ struct RtreeMatchArg { u32 iSize; /* Size of this object */ RtreeGeomCallback cb; /* Info about the callback functions */ int nParam; /* Number of parameters to the SQL function */ sqlite3_value **apSqlParam; /* Original SQL parameter values */ | | > > > > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | ** operand to the MATCH operator of an R-Tree. */ struct RtreeMatchArg { u32 iSize; /* Size of this object */ RtreeGeomCallback cb; /* Info about the callback functions */ int nParam; /* Number of parameters to the SQL function */ sqlite3_value **apSqlParam; /* Original SQL parameter values */ RtreeDValue aParam[FLEXARRAY]; /* Values for parameters to the SQL function */ }; /* Size of an RtreeMatchArg object with N parameters */ #define SZ_RTREEMATCHARG(N) \ (offsetof(RtreeMatchArg,aParam)+(N)*sizeof(RtreeDValue)) #ifndef MAX # define MAX(x,y) ((x) < (y) ? (y) : (x)) #endif #ifndef MIN # define MIN(x,y) ((x) > (y) ? (y) : (x)) #endif |
︙ | ︙ | |||
4365 4366 4367 4368 4369 4370 4371 | */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); RtreeMatchArg *pBlob; sqlite3_int64 nBlob; int memErr = 0; | < | | 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 | */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); RtreeMatchArg *pBlob; sqlite3_int64 nBlob; int memErr = 0; nBlob = SZ_RTREEMATCHARG(nArg) + nArg*sizeof(sqlite3_value*); pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob); if( !pBlob ){ sqlite3_result_error_nomem(ctx); }else{ int i; pBlob->iSize = nBlob; pBlob->cb = pGeomCtx[0]; |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
18 19 20 21 22 23 24 | # invoked. This file will use defaults, very possibly invalid, for any # which are not defined. ######################################################################## all: # # $(TOP) = # | | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | # invoked. This file will use defaults, very possibly invalid, for any # which are not defined. ######################################################################## all: # # $(TOP) = # # The top-level directory of the source tree. For canonical builds # this is the directory that contains this "Makefile.in" and the # "auto.def" script. For out-of-tree builds, this will differ from # $(PWD). # TOP ?= $(PWD) # # $(PACKAGE_VERSION) = # # The MAJOR.MINOR.PATCH version number of this build. # |
︙ | ︙ | |||
111 112 113 114 115 116 117 | CFLAGS.jimsh ?= -DHAVE_REALPATH JIMSH ?= ./jimsh$(T.exe) # # $(B.tclsh) = # # The TCL interpreter for in-tree code generation. May be either the # in-tree JimTCL ($(JIMSH)) or the canonical TCL ($(TCLSH_CMD). If | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | CFLAGS.jimsh ?= -DHAVE_REALPATH JIMSH ?= ./jimsh$(T.exe) # # $(B.tclsh) = # # The TCL interpreter for in-tree code generation. May be either the # in-tree JimTCL ($(JIMSH)) or the canonical TCL ($(TCLSH_CMD). If # it's JimTCL, it must be compiled with -DHAVE_REALPATH (Unix) or # -DHAVE__FULLPATH (Windows). # B.tclsh ?= $(JIMSH) # # Autotools-conventional vars which are (in this tree) used only by # package installation rules and for generating sqlite3.pc (pkg-config # data file). |
︙ | ︙ | |||
227 228 229 230 231 232 233 234 235 236 237 238 239 240 | LINK_TOOLS_DYNAMICALLY ?= 0 # # $(AMALGAMATION_GEN_FLAGS) = # # Optional flags for the amalgamation generator. # AMALGAMATION_GEN_FLAGS ?= --linemacros=0 # # $(OPT_FEATURE_FLAGS) = # # Preprocessor flags for enabling and disabling specific libsqlite3 # features (-DSQLITE_OMIT*, -DSQLITE_ENABLE*). The same set of OMIT # and ENABLE flags must be passed to the LEMON parser generator and # the mkkeywordhash tool as well. This is normally set by the | > > > > > > > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | LINK_TOOLS_DYNAMICALLY ?= 0 # # $(AMALGAMATION_GEN_FLAGS) = # # Optional flags for the amalgamation generator. # AMALGAMATION_GEN_FLAGS ?= --linemacros=0 # # EXTRA_SRC = list of C files to append as-is to the generated # amalgamation. It should arguably be called AMALGAMATION_EXTRA_SRC # but this older name is already in use by clients. # EXTRA_SRC ?= # # $(OPT_FEATURE_FLAGS) = # # Preprocessor flags for enabling and disabling specific libsqlite3 # features (-DSQLITE_OMIT*, -DSQLITE_ENABLE*). The same set of OMIT # and ENABLE flags must be passed to the LEMON parser generator and # the mkkeywordhash tool as well. This is normally set by the |
︙ | ︙ | |||
444 445 446 447 448 449 450 | # it was built in a way compatible with this project's scripts: # # 1) Ensure that it was built with realpath() or _fullpath() support. # Without that flag the [file normalize] command will always resolve # to an empty string. # # 2) Ensure that it is built with -DJIM_COMPAT (which may be | | | > | 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | # it was built in a way compatible with this project's scripts: # # 1) Ensure that it was built with realpath() or _fullpath() support. # Without that flag the [file normalize] command will always resolve # to an empty string. # # 2) Ensure that it is built with -DJIM_COMPAT (which may be # hard-coded into jimsh0.c). Without this, the [expr] command accepts # only a single argument. (That said: the real fix for that is to # update any scripts which still pass multiple arguments to [expr].) # $(JIMSH): $(TOP)/autosetup/jimsh0.c $(B.cc) -o $@ $(CFLAGS.jimsh) $(TOP)/autosetup/jimsh0.c @if [ x = "x$$($(JIMSH) -e 'file normalize $(JIMSH)' 2>/dev/null)" ]; then \ echo "$(JIMSH) was built without -DHAVE_REALPATH or -DHAVE__FULLPATH." 1>&2; \ exit 1; \ fi |
︙ | ︙ | |||
1096 1097 1098 1099 1100 1101 1102 | sqlite3.h: $(MAKE_SANITY_CHECK) $(TOP)/src/sqlite.h.in \ $(TOP)/manifest mksourceid$(B.exe) \ $(TOP)/VERSION $(B.tclsh) $(B.tclsh) $(TOP)/tool/mksqlite3h.tcl $(TOP) -o sqlite3.h sqlite3.c: .target_source sqlite3.h $(TOP)/tool/mksqlite3c.tcl src-verify$(B.exe) \ | | | 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 | sqlite3.h: $(MAKE_SANITY_CHECK) $(TOP)/src/sqlite.h.in \ $(TOP)/manifest mksourceid$(B.exe) \ $(TOP)/VERSION $(B.tclsh) $(B.tclsh) $(TOP)/tool/mksqlite3h.tcl $(TOP) -o sqlite3.h sqlite3.c: .target_source sqlite3.h $(TOP)/tool/mksqlite3c.tcl src-verify$(B.exe) \ $(B.tclsh) $(EXTRA_SRC) $(B.tclsh) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_GEN_FLAGS) $(EXTRA_SRC) cp tsrc/sqlite3ext.h . cp $(TOP)/ext/session/sqlite3session.h . sqlite3r.h: sqlite3.h $(B.tclsh) $(B.tclsh) $(TOP)/tool/mksqlite3h.tcl $(TOP) --enable-recover -o sqlite3r.h |
︙ | ︙ | |||
2157 2158 2159 2160 2161 2162 2163 2164 | xbin: fuzzershell$(T.exe) fuzzcheck$(T.exe): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) $(T.link) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(LDFLAGS.libsqlite3) fuzzy: fuzzcheck$(T.exe) xbin: fuzzcheck$(T.exe) fuzzcheck-asan$(T.exe): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) | > > > | | 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 | xbin: fuzzershell$(T.exe) fuzzcheck$(T.exe): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) $(T.link) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(LDFLAGS.libsqlite3) fuzzy: fuzzcheck$(T.exe) xbin: fuzzcheck$(T.exe) # -fsanitize=... flags for fuzzcheck-asan. CFLAGS.fuzzcheck.fsanitize ?= -fsanitize=address fuzzcheck-asan$(T.exe): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) $(T.link) -o $@ $(CFLAGS.fuzzcheck.fsanitize) $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) \ sqlite3.c $(LDFLAGS.libsqlite3) fuzzy: fuzzcheck-asan$(T.exe) xbin: fuzzcheck-asan$(T.exe) fuzzcheck-ubsan$(T.exe): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) $(T.link) -o $@ -fsanitize=undefined $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) \ sqlite3.c $(LDFLAGS.libsqlite3) |
︙ | ︙ | |||
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 | stmt.o: $(TOP)/ext/misc/stmt.c $(DEPS_EXT_COMMON) $(T.cc.extension) -c $(TOP)/ext/misc/stmt.c # # Windows section # dll: sqlite3.dll sqlite3.def: $(LIBOBJ) echo 'EXPORTS' >sqlite3.def nm $(LIBOBJ) | grep ' T ' | grep ' _sqlite3_' \ | sed 's/^.* _//' >>sqlite3.def sqlite3.dll: $(LIBOBJ) sqlite3.def $(T.cc.sqlite) $(LDFLAGS.shlib) -o $@ sqlite3.def \ -Wl,"--strip-all" $(LIBOBJ) $(LDFLAGS.configure) # # Emit a list of commonly-used targets help: @echo; echo "Frequently-used high-level make targets:"; echo; \ echo " - all [default] = builds most components"; \ echo " - clean = cleans up most build products"; \ echo " - distclean = cleans up all build products"; \ echo " - install = installs activated components"; \ echo; echo "Testing-related targets:"; echo; \ | > > > > | 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 | stmt.o: $(TOP)/ext/misc/stmt.c $(DEPS_EXT_COMMON) $(T.cc.extension) -c $(TOP)/ext/misc/stmt.c # # Windows section # # 2025-03-03: sqlite3.def and sqlite3.dll might no longer be relevant # in this particular build, but that's difficult to verify. # dll: sqlite3.dll sqlite3.def: $(LIBOBJ) echo 'EXPORTS' >sqlite3.def nm $(LIBOBJ) | grep ' T ' | grep ' _sqlite3_' \ | sed 's/^.* _//' >>sqlite3.def sqlite3.dll: $(LIBOBJ) sqlite3.def $(T.cc.sqlite) $(LDFLAGS.shlib) -o $@ sqlite3.def \ -Wl,"--strip-all" $(LIBOBJ) $(LDFLAGS.configure) # # Emit a list of commonly-used targets # help: @echo; echo "Frequently-used high-level make targets:"; echo; \ echo " - all [default] = builds most components"; \ echo " - clean = cleans up most build products"; \ echo " - distclean = cleans up all build products"; \ echo " - install = installs activated components"; \ echo; echo "Testing-related targets:"; echo; \ |
︙ | ︙ | |||
2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 | echo " - fuzztest = The core fuzz tester (see target docs for important info)"; \ echo " - valgrindfuzz = Runs fuzztest under valgrind"; \ echo " - soaktest = Really, really long tests"; \ echo " - alltest = Runs most or all TCL tests"; \ echo # Remove build products sufficient so that subsequent makes will recompile # everything from scratch. Do not remove: # # * test results and test logs # * output from ./configure # | > > | < | 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 | echo " - fuzztest = The core fuzz tester (see target docs for important info)"; \ echo " - valgrindfuzz = Runs fuzztest under valgrind"; \ echo " - soaktest = Really, really long tests"; \ echo " - alltest = Runs most or all TCL tests"; \ echo # # Remove build products sufficient so that subsequent makes will recompile # everything from scratch. Do not remove: # # * test results and test logs # * output from ./configure # # tidy: rm -f *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(T.exe) rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h rm -rf .libs .deps tsrc .target_source rm -f lemon$(B.exe) sqlite*.tar.gz rm -f mkkeywordhash$(B.exe) mksourceid$(B.exe) rm -f parse.* fts5parse.* rm -f $(libsqlite3.DLL) $(libsqlite3.LIB) $(libtclsqlite3.SO) libsqlite3$(T.dll).a |
︙ | ︙ | |||
2403 2404 2405 2406 2407 2408 2409 | rm -f tclsqlite3.c has_tclsh* $(T.tcl.env.sh) rm -f sqlite3rc.h sqlite3.def rm -f ctime.c pragma.h # # Removes build products and test logs. Retains ./configure outputs. # | < | > | > > > > > > | | | > | 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 | rm -f tclsqlite3.c has_tclsh* $(T.tcl.env.sh) rm -f sqlite3rc.h sqlite3.def rm -f ctime.c pragma.h # # Removes build products and test logs. Retains ./configure outputs. # clean: tidy rm -rf omittest* testrunner* testdir* # # Clean up everything. No exceptions. From an out-of-tree build which # starts in an empty directory, this should result in an empty # directory (assuming the user does not create new files in this # directory). # # The main distclean rules are in Makefile.in. # distclean: clean # # Show important variable settings. # show-variables: @echo "CC = $(CC)" @echo "B.cc = $(B.cc)" @echo "T.cc = $(T.cc)" @echo "T.cc.sqlite = $(T.cc.sqlite)" |
Changes to src/alter.c.
︙ | ︙ | |||
1132 1133 1134 1135 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 | Parse *p, /* Memory to use for Parse object */ const char *zDb, /* Name of schema SQL belongs to */ sqlite3 *db, /* Database handle */ const char *zSql, /* SQL to parse */ int bTemp /* True if SQL is from temp schema */ ){ int rc; sqlite3ParseObjectInit(p, db); if( zSql==0 ){ return SQLITE_NOMEM; } if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){ return SQLITE_CORRUPT_BKPT; } if( bTemp ){ db->init.iDb = 1; }else{ int iDb = sqlite3FindDbName(db, zDb); assert( iDb>=0 && iDb<=0xff ); db->init.iDb = (u8)iDb; } p->eParseMode = PARSE_MODE_RENAME; p->db = db; p->nQueryLoop = 1; rc = sqlite3RunParser(p, zSql); if( db->mallocFailed ) rc = SQLITE_NOMEM; if( rc==SQLITE_OK && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0) ){ rc = SQLITE_CORRUPT_BKPT; } | > > > > > | 1132 1133 1134 1135 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 | Parse *p, /* Memory to use for Parse object */ const char *zDb, /* Name of schema SQL belongs to */ sqlite3 *db, /* Database handle */ const char *zSql, /* SQL to parse */ int bTemp /* True if SQL is from temp schema */ ){ int rc; u64 flags; sqlite3ParseObjectInit(p, db); if( zSql==0 ){ return SQLITE_NOMEM; } if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){ return SQLITE_CORRUPT_BKPT; } if( bTemp ){ db->init.iDb = 1; }else{ int iDb = sqlite3FindDbName(db, zDb); assert( iDb>=0 && iDb<=0xff ); db->init.iDb = (u8)iDb; } p->eParseMode = PARSE_MODE_RENAME; p->db = db; p->nQueryLoop = 1; flags = db->flags; testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 ); db->flags |= SQLITE_Comments; rc = sqlite3RunParser(p, zSql); db->flags = flags; if( db->mallocFailed ) rc = SQLITE_NOMEM; if( rc==SQLITE_OK && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0) ){ rc = SQLITE_CORRUPT_BKPT; } |
︙ | ︙ | |||
2046 2047 2048 2049 2050 2051 2052 | if( zDb && zInput ){ int rc; Parse sParse; u64 flags = db->flags; if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); | | | 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 | if( zDb && zInput ){ int rc; Parse sParse; u64 flags = db->flags; if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); db->flags = flags; if( rc==SQLITE_OK ){ if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = &sParse; sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC); if( sParse.nErr ) rc = sParse.rc; |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
3629 3630 3631 3632 3633 3634 3635 | sqlite3ErrorMsg(pParse, "number of columns in foreign key does not match the number of " "columns in the referenced table"); goto fk_end; }else{ nCol = pFromCol->nExpr; } | | | 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 | sqlite3ErrorMsg(pParse, "number of columns in foreign key does not match the number of " "columns in the referenced table"); goto fk_end; }else{ nCol = pFromCol->nExpr; } nByte = SZ_FKEY(nCol) + pTo->n + 1; if( pToCol ){ for(i=0; i<pToCol->nExpr; i++){ nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1; } } pFKey = sqlite3DbMallocZero(db, nByte ); if( pFKey==0 ){ |
︙ | ︙ | |||
4688 4689 4690 4691 4692 4693 4694 | ** ** A new IdList is returned, or NULL if malloc() fails. */ IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ sqlite3 *db = pParse->db; int i; if( pList==0 ){ | | | < | 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 | ** ** A new IdList is returned, or NULL if malloc() fails. */ IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ sqlite3 *db = pParse->db; int i; if( pList==0 ){ pList = sqlite3DbMallocZero(db, SZ_IDLIST(1)); if( pList==0 ) return 0; }else{ IdList *pNew; pNew = sqlite3DbRealloc(db, pList, SZ_IDLIST(pList->nId+1)); if( pNew==0 ){ sqlite3IdListDelete(db, pList); return 0; } pList = pNew; } i = pList->nId++; |
︙ | ︙ | |||
4792 4793 4794 4795 4796 4797 4798 | if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){ sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d", SQLITE_MAX_SRCLIST); return 0; } if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST; | | < | 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 | if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){ sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d", SQLITE_MAX_SRCLIST); return 0; } if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST; pNew = sqlite3DbRealloc(db, pSrc, SZ_SRCLIST(nAlloc)); if( pNew==0 ){ assert( db->mallocFailed ); return 0; } pSrc = pNew; pSrc->nAlloc = nAlloc; } |
︙ | ︙ | |||
4868 4869 4870 4871 4872 4873 4874 | SrcItem *pItem; sqlite3 *db; assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ assert( pParse!=0 ); assert( pParse->db!=0 ); db = pParse->db; if( pList==0 ){ | | | 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 | SrcItem *pItem; sqlite3 *db; assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ assert( pParse!=0 ); assert( pParse->db!=0 ); db = pParse->db; if( pList==0 ){ pList = sqlite3DbMallocRawNN(pParse->db, SZ_SRCLIST(1)); if( pList==0 ) return 0; pList->nAlloc = 1; pList->nSrc = 1; memset(&pList->a[0], 0, sizeof(pList->a[0])); pList->a[0].iCursor = -1; }else{ SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc); |
︙ | ︙ | |||
5754 5755 5756 5757 5758 5759 5760 | if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName); } } } if( pWith ){ | < | | | 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 | if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName); } } } if( pWith ){ pNew = sqlite3DbRealloc(db, pWith, SZ_WITH(pWith->nCte+1)); }else{ pNew = sqlite3DbMallocZero(db, SZ_WITH(1)); } assert( (pNew!=0 && zName!=0) || db->mallocFailed ); if( db->mallocFailed ){ sqlite3CteDelete(db, pCte); pNew = pWith; }else{ |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1734 1735 1736 1737 1738 1739 1740 | ** argument. If an OOM condition is encountered, NULL is returned ** and the db->mallocFailed flag set. */ #ifndef SQLITE_OMIT_CTE With *sqlite3WithDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ | | | 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 | ** argument. If an OOM condition is encountered, NULL is returned ** and the db->mallocFailed flag set. */ #ifndef SQLITE_OMIT_CTE With *sqlite3WithDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ sqlite3_int64 nByte = SZ_WITH(p->nCte); pRet = sqlite3DbMallocZero(db, nByte); if( pRet ){ int i; pRet->nCte = p->nCte; for(i=0; i<p->nCte; i++){ pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); |
︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 | ** called with a NULL argument. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ || !defined(SQLITE_OMIT_SUBQUERY) SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){ SrcList *pNew; int i; | < < | | 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 | ** called with a NULL argument. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ || !defined(SQLITE_OMIT_SUBQUERY) SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){ SrcList *pNew; int i; assert( db!=0 ); if( p==0 ) return 0; pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; i<p->nSrc; i++){ SrcItem *pNewItem = &pNew->a[i]; const SrcItem *pOldItem = &p->a[i]; Table *pTab; pNewItem->fg = pOldItem->fg; |
︙ | ︙ | |||
1927 1928 1929 1930 1931 1932 1933 | return pNew; } IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){ IdList *pNew; int i; assert( db!=0 ); if( p==0 ) return 0; | | | 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 | return pNew; } IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){ IdList *pNew; int i; assert( db!=0 ); if( p==0 ) return 0; pNew = sqlite3DbMallocRawNN(db, SZ_IDLIST(p->nId)); if( pNew==0 ) return 0; pNew->nId = p->nId; for(i=0; i<p->nId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; const struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); } |
︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 | SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew( sqlite3 *db, /* Database handle. Used for memory allocation */ Expr *pExpr /* Expression to be appended. Might be NULL */ ){ struct ExprList_item *pItem; ExprList *pList; | | | < | 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 | SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew( sqlite3 *db, /* Database handle. Used for memory allocation */ Expr *pExpr /* Expression to be appended. Might be NULL */ ){ struct ExprList_item *pItem; ExprList *pList; pList = sqlite3DbMallocRawNN(db, SZ_EXPRLIST(4)); if( pList==0 ){ sqlite3ExprDelete(db, pExpr); return 0; } pList->nAlloc = 4; pList->nExpr = 1; pItem = &pList->a[0]; *pItem = zeroItem; pItem->pExpr = pExpr; return pList; } SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow( sqlite3 *db, /* Database handle. Used for memory allocation */ ExprList *pList, /* List to which to append. Might be NULL */ Expr *pExpr /* Expression to be appended. Might be NULL */ ){ struct ExprList_item *pItem; ExprList *pNew; pList->nAlloc *= 2; pNew = sqlite3DbRealloc(db, pList, SZ_EXPRLIST(pList->nAlloc)); if( pNew==0 ){ sqlite3ExprListDelete(db, pList); sqlite3ExprDelete(db, pExpr); return 0; }else{ pList = pNew; } |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
3841 3842 3843 3844 3845 3846 3847 | return SQLITE_OK; } }else if( pData==0 ){ sqlite3_mutex_leave(db->mutex); return SQLITE_OK; }else{ size_t n = strlen(zName); | | | 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 | return SQLITE_OK; } }else if( pData==0 ){ sqlite3_mutex_leave(db->mutex); return SQLITE_OK; }else{ size_t n = strlen(zName); p = sqlite3_malloc64( SZ_DBCLIENTDATA(n+1) ); if( p==0 ){ if( xDestructor ) xDestructor(pData); sqlite3_mutex_leave(db->mutex); return SQLITE_NOMEM; } memcpy(p->zName, zName, n+1); p->pNext = db->pDbData; |
︙ | ︙ |
Changes to src/pcache1.c.
︙ | ︙ | |||
228 229 230 231 232 233 234 | int nSlot; /* The number of pcache slots */ int nReserve; /* Try to keep nFreeSlot above this */ void *pStart, *pEnd; /* Bounds of global page cache memory */ /* Above requires no mutex. Use mutex below for variable that follow. */ sqlite3_mutex *mutex; /* Mutex for accessing the following: */ PgFreeslot *pFree; /* Free page blocks */ int nFreeSlot; /* Number of unused pcache slots */ | < < < < | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | int nSlot; /* The number of pcache slots */ int nReserve; /* Try to keep nFreeSlot above this */ void *pStart, *pEnd; /* Bounds of global page cache memory */ /* Above requires no mutex. Use mutex below for variable that follow. */ sqlite3_mutex *mutex; /* Mutex for accessing the following: */ PgFreeslot *pFree; /* Free page blocks */ int nFreeSlot; /* Number of unused pcache slots */ int bUnderPressure; /* True if low on PAGECACHE memory */ } pcache1_g; /* ** All code in this file should access the global structure above via the ** alias "pcache1". This ensures that the WSD emulation is used when ** compiling for systems that do not support real WSD. |
︙ | ︙ | |||
279 280 281 282 283 284 285 | if( n==0 ) sz = 0; sz = ROUNDDOWN8(sz); pcache1.szSlot = sz; pcache1.nSlot = pcache1.nFreeSlot = n; pcache1.nReserve = n>90 ? 10 : (n/10 + 1); pcache1.pStart = pBuf; pcache1.pFree = 0; | | | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | if( n==0 ) sz = 0; sz = ROUNDDOWN8(sz); pcache1.szSlot = sz; pcache1.nSlot = pcache1.nFreeSlot = n; pcache1.nReserve = n>90 ? 10 : (n/10 + 1); pcache1.pStart = pBuf; pcache1.pFree = 0; AtomicStore(&pcache1.bUnderPressure,0); while( n-- ){ p = (PgFreeslot*)pBuf; p->pNext = pcache1.pFree; pcache1.pFree = p; pBuf = (void*)&((char*)pBuf)[sz]; } pcache1.pEnd = pBuf; |
︙ | ︙ | |||
347 348 349 350 351 352 353 | assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); if( nByte<=pcache1.szSlot ){ sqlite3_mutex_enter(pcache1.mutex); p = (PgHdr1 *)pcache1.pFree; if( p ){ pcache1.pFree = pcache1.pFree->pNext; pcache1.nFreeSlot--; | | | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); if( nByte<=pcache1.szSlot ){ sqlite3_mutex_enter(pcache1.mutex); p = (PgHdr1 *)pcache1.pFree; if( p ){ pcache1.pFree = pcache1.pFree->pNext; pcache1.nFreeSlot--; AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve); assert( pcache1.nFreeSlot>=0 ); sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte); sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1); } sqlite3_mutex_leave(pcache1.mutex); } if( p==0 ){ |
︙ | ︙ | |||
386 387 388 389 390 391 392 | PgFreeslot *pSlot; sqlite3_mutex_enter(pcache1.mutex); sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1); pSlot = (PgFreeslot*)p; pSlot->pNext = pcache1.pFree; pcache1.pFree = pSlot; pcache1.nFreeSlot++; | | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | PgFreeslot *pSlot; sqlite3_mutex_enter(pcache1.mutex); sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1); pSlot = (PgFreeslot*)p; pSlot->pNext = pcache1.pFree; pcache1.pFree = pSlot; pcache1.nFreeSlot++; AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve); assert( pcache1.nFreeSlot<=pcache1.nSlot ); sqlite3_mutex_leave(pcache1.mutex); }else{ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS { |
︙ | ︙ | |||
517 518 519 520 521 522 523 | ** Or, the heap is used for all page cache memory but the heap is ** under memory pressure, then again it is desirable to avoid ** allocating a new page cache entry in order to avoid stressing ** the heap even further. */ static int pcache1UnderMemoryPressure(PCache1 *pCache){ if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){ | | | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | ** Or, the heap is used for all page cache memory but the heap is ** under memory pressure, then again it is desirable to avoid ** allocating a new page cache entry in order to avoid stressing ** the heap even further. */ static int pcache1UnderMemoryPressure(PCache1 *pCache){ if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){ return AtomicLoad(&pcache1.bUnderPressure); }else{ return sqlite3HeapNearlyFull(); } } /******************************************************************************/ /******** General Implementation Functions ************************************/ |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
2273 2274 2275 2276 2277 2278 2279 | int sqlite3ResolveSelfReference( Parse *pParse, /* Parsing context */ Table *pTab, /* The table being referenced, or NULL */ int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */ Expr *pExpr, /* Expression to resolve. May be NULL. */ ExprList *pList /* Expression list to resolve. May be NULL. */ ){ | | > > | | | | | | | 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 | int sqlite3ResolveSelfReference( Parse *pParse, /* Parsing context */ Table *pTab, /* The table being referenced, or NULL */ int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */ Expr *pExpr, /* Expression to resolve. May be NULL. */ ExprList *pList /* Expression list to resolve. May be NULL. */ ){ SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */ int rc; u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */ assert( type==0 || pTab!=0 ); assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr || type==NC_GenCol || pTab==0 ); memset(&sNC, 0, sizeof(sNC)); pSrc = (SrcList*)srcSpace; memset(pSrc, 0, SZ_SRCLIST_1); if( pTab ){ pSrc->nSrc = 1; pSrc->a[0].zName = pTab->zName; pSrc->a[0].pSTab = pTab; pSrc->a[0].iCursor = -1; if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){ /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP ** schema elements */ type |= NC_FromDDL; } } sNC.pParse = pParse; sNC.pSrcList = pSrc; sNC.ncFlags = type | NC_IsDDL; if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc; if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList); return rc; } |
Changes to src/select.c.
︙ | ︙ | |||
150 151 152 153 154 155 156 | pNew->selFlags = selFlags; pNew->iLimit = 0; pNew->iOffset = 0; pNew->selId = ++pParse->nSelect; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = 0; | | | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | pNew->selFlags = selFlags; pNew->iLimit = 0; pNew->iOffset = 0; pNew->selId = ++pParse->nSelect; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = 0; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1); pNew->pSrc = pSrc; pNew->pWhere = pWhere; pNew->pGroupBy = pGroupBy; pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->pPrior = 0; pNew->pNext = 0; |
︙ | ︙ | |||
1533 1534 1535 1536 1537 1538 1539 | } /* ** Allocate a KeyInfo object sufficient for an index of N key columns and ** X extra columns. */ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ | | | | | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 | } /* ** Allocate a KeyInfo object sufficient for an index of N key columns and ** X extra columns. */ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ int nExtra = (N+X)*(sizeof(CollSeq*)+1); KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra); if( p ){ p->aSortFlags = (u8*)&p->aColl[N+X]; p->nKeyField = (u16)N; p->nAllField = (u16)(N+X); p->enc = ENC(db); p->db = db; p->nRef = 1; memset(p->aColl, 0, nExtra); }else{ return (KeyInfo*)sqlite3OomFault(db); } return p; } /* |
︙ | ︙ | |||
6058 6059 6060 6061 6062 6063 6064 | /* Renumber selId because it has been copied from a view */ p->selId = ++pParse->nSelect; } pTabList = p->pSrc; pEList = p->pEList; if( pParse->pWith && (p->selFlags & SF_View) ){ if( p->pWith==0 ){ | | | 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 | /* Renumber selId because it has been copied from a view */ p->selId = ++pParse->nSelect; } pTabList = p->pSrc; pEList = p->pEList; if( pParse->pWith && (p->selFlags & SF_View) ){ if( p->pWith==0 ){ p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) ); if( p->pWith==0 ){ return WRC_Abort; } } p->pWith->bView = 1; } sqlite3WithPush(pParse, p->pWith, 0); |
︙ | ︙ | |||
7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 | ** The transformation only works if all of the following are true: ** ** * The subquery is a UNION ALL of two or more terms ** * The subquery does not have a LIMIT clause ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries ** * The outer query is a simple count(*) with no WHERE clause or other ** extraneous syntax. ** ** Return TRUE if the optimization is undertaken. */ static int countOfViewOptimization(Parse *pParse, Select *p){ Select *pSub, *pPrior; Expr *pExpr; Expr *pCount; | > | 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 | ** The transformation only works if all of the following are true: ** ** * The subquery is a UNION ALL of two or more terms ** * The subquery does not have a LIMIT clause ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries ** * The outer query is a simple count(*) with no WHERE clause or other ** extraneous syntax. ** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10) ** ** Return TRUE if the optimization is undertaken. */ static int countOfViewOptimization(Parse *pParse, Select *p){ Select *pSub, *pPrior; Expr *pExpr; Expr *pCount; |
︙ | ︙ | |||
7229 7230 7231 7232 7233 7234 7235 | pSub = pFrom->u4.pSubq->pSelect; if( pSub->pPrior==0 ) return 0; /* Must be a compound */ if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */ do{ if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ if( pSub->pWhere ) return 0; /* No WHERE clause */ if( pSub->pLimit ) return 0; /* No LIMIT clause */ | > | > > > | | 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 | pSub = pFrom->u4.pSubq->pSelect; if( pSub->pPrior==0 ) return 0; /* Must be a compound */ if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */ do{ if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ if( pSub->pWhere ) return 0; /* No WHERE clause */ if( pSub->pLimit ) return 0; /* No LIMIT clause */ if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){ testcase( pSub->selFlags & SF_Aggregate ); testcase( pSub->selFlags & SF_Distinct ); return 0; /* Not an aggregate nor DISTINCT */ } assert( pSub->pHaving==0 ); /* Due to the previous */ pSub = pSub->pPrior; /* Repeat over compound */ }while( pSub ); /* If we reach this point then it is OK to perform the transformation */ db = pParse->db; pCount = pExpr; pExpr = 0; pSub = sqlite3SubqueryDetach(db, pFrom); sqlite3SrcListDelete(db, p->pSrc); p->pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1); while( pSub ){ Expr *pTerm; pPrior = pSub->pPrior; pSub->pPrior = 0; pSub->pNext = 0; pSub->selFlags |= SF_Aggregate; pSub->selFlags &= ~(u32)SF_Compound; |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 | case MODE_Pretty: { /* .schema and .fullschema with --indent */ char *z; int j; int nParen = 0; char cEnd = 0; char c; int nLine = 0; assert( nArg==1 ); if( azArg[0]==0 ) break; if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 ){ sqlite3_fprintf(p->out, "%s;\n", azArg[0]); break; } z = sqlite3_mprintf("%s", azArg[0]); shell_check_oom(z); j = 0; for(i=0; IsSpace(z[i]); i++){} for(; (c = z[i])!=0; i++){ if( IsSpace(c) ){ if( z[j-1]=='\r' ) z[j-1] = '\n'; | > > > > | 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 | case MODE_Pretty: { /* .schema and .fullschema with --indent */ char *z; int j; int nParen = 0; char cEnd = 0; char c; int nLine = 0; int isIndex; int isWhere = 0; assert( nArg==1 ); if( azArg[0]==0 ) break; if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 ){ sqlite3_fprintf(p->out, "%s;\n", azArg[0]); break; } isIndex = sqlite3_strlike("CREATE INDEX%", azArg[0], 0)==0 || sqlite3_strlike("CREATE UNIQUE INDEX%", azArg[0], 0)==0; z = sqlite3_mprintf("%s", azArg[0]); shell_check_oom(z); j = 0; for(i=0; IsSpace(z[i]); i++){} for(; (c = z[i])!=0; i++){ if( IsSpace(c) ){ if( z[j-1]=='\r' ) z[j-1] = '\n'; |
︙ | ︙ | |||
2774 2775 2776 2777 2778 2779 2780 | cEnd = ']'; }else if( c=='-' && z[i+1]=='-' ){ cEnd = '\n'; }else if( c=='(' ){ nParen++; }else if( c==')' ){ nParen--; | | > > > > > > > > > > > > | 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 | cEnd = ']'; }else if( c=='-' && z[i+1]=='-' ){ cEnd = '\n'; }else if( c=='(' ){ nParen++; }else if( c==')' ){ nParen--; if( nLine>0 && nParen==0 && j>0 && !isWhere ){ printSchemaLineN(p->out, z, j, "\n"); j = 0; } }else if( (c=='w' || c=='W') && nParen==0 && isIndex && sqlite3_strnicmp("WHERE",&z[i],5)==0 && !IsAlnum(z[i+5]) && z[i+5]!='_' ){ isWhere = 1; }else if( isWhere && (c=='A' || c=='a') && nParen==0 && sqlite3_strnicmp("AND",&z[i],3)==0 && !IsAlnum(z[i+3]) && z[i+3]!='_' ){ printSchemaLineN(p->out, z, j, "\n "); j = 0; } z[j++] = c; if( nParen==1 && cEnd==0 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) && !isWhere ){ if( c=='\n' ) j--; printSchemaLineN(p->out, z, j, "\n "); j = 0; nLine++; while( IsSpace(z[i+1]) ){ i++; } } |
︙ | ︙ | |||
8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 | ); sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */ sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF); sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids); sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist); sqlite3_recover_run(p); if( sqlite3_recover_errcode(p)!=SQLITE_OK ){ const char *zErr = sqlite3_recover_errmsg(p); int errCode = sqlite3_recover_errcode(p); sqlite3_fprintf(stderr,"sql error: %s (%d)\n", zErr, errCode); } rc = sqlite3_recover_finish(p); | > | 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 | ); sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */ sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF); sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids); sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist); sqlite3_fprintf(pState->out, ".dbconfig defensive off\n"); sqlite3_recover_run(p); if( sqlite3_recover_errcode(p)!=SQLITE_OK ){ const char *zErr = sqlite3_recover_errmsg(p); int errCode = sqlite3_recover_errcode(p); sqlite3_fprintf(stderr,"sql error: %s (%d)\n", zErr, errCode); } rc = sqlite3_recover_finish(p); |
︙ | ︙ | |||
12254 12255 12256 12257 12258 12259 12260 | } /* ** The CLI needs a working sqlite3_complete() to work properly. So error ** out of the build if compiling with SQLITE_OMIT_COMPLETE. */ #ifdef SQLITE_OMIT_COMPLETE | | | 12271 12272 12273 12274 12275 12276 12277 12278 12279 12280 12281 12282 12283 12284 12285 | } /* ** The CLI needs a working sqlite3_complete() to work properly. So error ** out of the build if compiling with SQLITE_OMIT_COMPLETE. */ #ifdef SQLITE_OMIT_COMPLETE # error the CLI application is incompatible with SQLITE_OMIT_COMPLETE. #endif /* ** Return true if zSql is a complete SQL statement. Return false if it ** ends in the middle of a string literal or C-style comment. */ static int line_is_complete(char *zSql, int nSql){ |
︙ | ︙ | |||
13454 13455 13456 13457 13458 13459 13460 13461 13462 13463 13464 13465 13466 13467 13468 | if( !readStdin ){ /* Run all arguments that do not begin with '-' as if they were separate ** command-line inputs, except for the argToSkip argument which contains ** the database filename. */ for(i=0; i<nCmd; i++){ if( azCmd[i][0]=='.' ){ rc = do_meta_command(azCmd[i], &data); if( rc ){ if( rc==2 ) rc = 0; goto shell_main_exit; } }else{ open_db(&data, 0); | > < | 13471 13472 13473 13474 13475 13476 13477 13478 13479 13480 13481 13482 13483 13484 13485 13486 13487 13488 13489 13490 13491 13492 13493 | if( !readStdin ){ /* Run all arguments that do not begin with '-' as if they were separate ** command-line inputs, except for the argToSkip argument which contains ** the database filename. */ for(i=0; i<nCmd; i++){ echo_group_input(&data, azCmd[i]); if( azCmd[i][0]=='.' ){ rc = do_meta_command(azCmd[i], &data); if( rc ){ if( rc==2 ) rc = 0; goto shell_main_exit; } }else{ open_db(&data, 0); rc = shell_exec(&data, azCmd[i], &zErrMsg); if( zErrMsg || rc ){ if( zErrMsg!=0 ){ shellEmitError(zErrMsg); }else{ sqlite3_fprintf(stderr, "Error: unable to process SQL: %s\n", azCmd[i]); |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 | ** to be invoked whenever a row is updated, inserted or deleted in ** a [rowid table]. ** ^Any callback set by a previous call to this function ** for the same database connection is overridden. ** ** ^The second argument is a pointer to the function to invoke when a ** row is updated, inserted or deleted in a rowid table. ** ^The first argument to the callback is a copy of the third argument ** to sqlite3_update_hook(). ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], ** or [SQLITE_UPDATE], depending on the operation that caused the callback ** to be invoked. ** ^The third and fourth arguments to the callback contain pointers to the ** database and table name containing the affected row. | > > | 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 | ** to be invoked whenever a row is updated, inserted or deleted in ** a [rowid table]. ** ^Any callback set by a previous call to this function ** for the same database connection is overridden. ** ** ^The second argument is a pointer to the function to invoke when a ** row is updated, inserted or deleted in a rowid table. ** ^The update hook is disabled by invoking sqlite3_update_hook() ** with a NULL pointer as the second parameter. ** ^The first argument to the callback is a copy of the third argument ** to sqlite3_update_hook(). ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], ** or [SQLITE_UPDATE], depending on the operation that caused the callback ** to be invoked. ** ^The third and fourth arguments to the callback contain pointers to the ** database and table name containing the affected row. |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
761 762 763 764 765 766 767 | #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof | | > > > > > > > > > > | 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 | #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif /* ** Work around C99 "flex-array" syntax for pre-C99 compilers, so as ** to avoid complaints from -fsanitize=strict-bounds. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif /* ** Macros to compute minimum and maximum of two numbers. */ #ifndef MIN # define MIN(A,B) ((A)<(B)?(A):(B)) |
︙ | ︙ | |||
2573 2574 2575 2576 2577 2578 2579 | /* EV: R-30323-21917 */ u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ Trigger *apTrigger[2];/* Triggers for aAction[] actions */ struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ int iFrom; /* Index of column in pFrom */ char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */ | | > > > > | 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 | /* EV: R-30323-21917 */ u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ Trigger *apTrigger[2];/* Triggers for aAction[] actions */ struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ int iFrom; /* Index of column in pFrom */ char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */ } aCol[FLEXARRAY]; /* One entry for each of nCol columns */ }; /* The size (in bytes) of an FKey object holding N columns. The answer ** does NOT include space to hold the zTo name. */ #define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap)) /* ** SQLite supports many different ways to resolve a constraint ** error. ROLLBACK processing means that a constraint violation ** causes the operation in process to fail and for the current transaction ** to be rolled back. ABORT processing means the operation in process ** fails and any prior changes from that one operation are backed out, |
︙ | ︙ | |||
2637 2638 2639 2640 2641 2642 2643 | struct KeyInfo { u32 nRef; /* Number of references to this KeyInfo object */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ u16 nKeyField; /* Number of key columns in the index */ u16 nAllField; /* Total columns, including key plus others */ sqlite3 *db; /* The database connection */ u8 *aSortFlags; /* Sort order for each column. */ | | > > > | 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 | struct KeyInfo { u32 nRef; /* Number of references to this KeyInfo object */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ u16 nKeyField; /* Number of key columns in the index */ u16 nAllField; /* Total columns, including key plus others */ sqlite3 *db; /* The database connection */ u8 *aSortFlags; /* Sort order for each column. */ CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */ }; /* The size (in bytes) of a KeyInfo object with up to N fields */ #define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*)) /* ** Allowed bit values for entries in the KeyInfo.aSortFlags[] array. */ #define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */ #define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */ /* |
︙ | ︙ | |||
3212 3213 3214 3215 3216 3217 3218 | struct { /* Used by any ExprList other than Parse.pConsExpr */ u16 iOrderByCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } x; int iConstExprReg; /* Register in which Expr value is cached. Used only ** by Parse.pConstExpr */ } u; | | > > > > > | 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 | struct { /* Used by any ExprList other than Parse.pConsExpr */ u16 iOrderByCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } x; int iConstExprReg; /* Register in which Expr value is cached. Used only ** by Parse.pConstExpr */ } u; } a[FLEXARRAY]; /* One slot for each expression in the list */ }; /* The size (in bytes) of an ExprList object that is big enough to hold ** as many as N expressions. */ #define SZ_EXPRLIST(N) \ (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item)) /* ** Allowed values for Expr.a.eEName */ #define ENAME_NAME 0 /* The AS clause of a result set */ #define ENAME_SPAN 1 /* Complete text of the result set expression */ #define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */ |
︙ | ︙ | |||
3242 3243 3244 3245 3246 3247 3248 | ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { int nId; /* Number of identifiers on the list */ struct IdList_item { char *zName; /* Name of the identifier */ | | > > > | 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 | ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { int nId; /* Number of identifiers on the list */ struct IdList_item { char *zName; /* Name of the identifier */ } a[FLEXARRAY]; }; /* The size (in bytes) of an IdList object that can hold up to N IDs. */ #define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item)) /* ** Allowed values for IdList.eType, which determines which value of the a.u4 ** is valid. */ #define EU4_NONE 0 /* Does not use IdList.a.u4 */ #define EU4_IDX 1 /* Uses IdList.a.u4.idx */ #define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */ |
︙ | ︙ | |||
3364 3365 3366 3367 3368 3369 3370 | ** This object represents one or more tables that are the source of ** content for an SQL statement. For example, a single SrcList object ** is used to hold the FROM clause of a SELECT statement. SrcList also ** represents the target tables for DELETE, INSERT, and UPDATE statements. ** */ struct SrcList { | | | | > > > > > > > > | 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 | ** This object represents one or more tables that are the source of ** content for an SQL statement. For example, a single SrcList object ** is used to hold the FROM clause of a SELECT statement. SrcList also ** represents the target tables for DELETE, INSERT, and UPDATE statements. ** */ struct SrcList { int nSrc; /* Number of tables or subqueries in the FROM clause */ u32 nAlloc; /* Number of entries allocated in a[] below */ SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */ }; /* Size (in bytes) of a SrcList object that can hold as many as N ** SrcItem objects. */ #define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem)) /* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a ** special case of SZ_SRCITEM(1) that comes up often. */ #define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem)) /* ** Permitted values of the SrcList.a.jointype field */ #define JT_INNER 0x01 /* Any kind of inner or cross join */ #define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */ #define JT_NATURAL 0x04 /* True for a "natural" join */ |
︙ | ︙ | |||
4432 4433 4434 4435 4436 4437 4438 | ** An instance of the With object represents a WITH clause containing ** one or more CTEs (common table expressions). */ struct With { int nCte; /* Number of CTEs in the WITH clause */ int bView; /* Belongs to the outermost Select of a view */ With *pOuter; /* Containing WITH clause, or NULL */ | | > > > > | 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 | ** An instance of the With object represents a WITH clause containing ** one or more CTEs (common table expressions). */ struct With { int nCte; /* Number of CTEs in the WITH clause */ int bView; /* Belongs to the outermost Select of a view */ With *pOuter; /* Containing WITH clause, or NULL */ Cte a[FLEXARRAY]; /* For each CTE in the WITH clause.... */ }; /* The size (in bytes) of a With object that can hold as many ** as N different CTEs. */ #define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte)) /* ** The Cte object is not guaranteed to persist for the entire duration ** of code generation. (The query flattener or other parser tree ** edits might delete it.) The following object records information ** about each Common Table Expression that must be preserved for the ** duration of the parse. |
︙ | ︙ | |||
4463 4464 4465 4466 4467 4468 4469 | /* Client data associated with sqlite3_set_clientdata() and ** sqlite3_get_clientdata(). */ struct DbClientData { DbClientData *pNext; /* Next in a linked list */ void *pData; /* The data */ void (*xDestructor)(void*); /* Destructor. Might be NULL */ | | > > > > | 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 | /* Client data associated with sqlite3_set_clientdata() and ** sqlite3_get_clientdata(). */ struct DbClientData { DbClientData *pNext; /* Next in a linked list */ void *pData; /* The data */ void (*xDestructor)(void*); /* Destructor. Might be NULL */ char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */ }; /* The size (in bytes) of a DbClientData object that can has a name ** that is N bytes long, including the zero-terminator. */ #define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N)) #ifdef SQLITE_DEBUG /* ** An instance of the TreeView object is used for printing the content of ** data structures on sqlite3DebugPrintf() using a tree-like view. */ struct TreeView { |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 | }else{ rc = 999; } return rc; } #endif /* SQLITE_OMIT_AUTHORIZATION */ /* ** This routine reads a line of text from FILE in, stores ** the text in memory obtained from malloc() and returns a pointer ** to the text. NULL is returned at end of file, or if malloc() ** fails. ** ** The interface is like "readline" but no command-line editing | > | 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 | }else{ rc = 999; } return rc; } #endif /* SQLITE_OMIT_AUTHORIZATION */ #if 0 /* ** This routine reads a line of text from FILE in, stores ** the text in memory obtained from malloc() and returns a pointer ** to the text. NULL is returned at end of file, or if malloc() ** fails. ** ** The interface is like "readline" but no command-line editing |
︙ | ︙ | |||
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 | zLine[n] = 0; break; } } zLine = realloc( zLine, n+1 ); return zLine; } /* ** This function is part of the implementation of the command: ** ** $db transaction [-deferred|-immediate|-exclusive] SCRIPT ** | > | 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 | zLine[n] = 0; break; } } zLine = realloc( zLine, n+1 ); return zLine; } #endif /* ** This function is part of the implementation of the command: ** ** $db transaction [-deferred|-immediate|-exclusive] SCRIPT ** |
︙ | ︙ | |||
2053 2054 2055 2056 2057 2058 2059 | ** ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) ** (2) First descriptive name (depends on authorization type) ** (3) Second descriptive name ** (4) Name of the database (ex: "main", "temp") ** (5) Name of trigger that is doing the access ** | | | 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 | ** ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) ** (2) First descriptive name (depends on authorization type) ** (3) Second descriptive name ** (4) Name of the database (ex: "main", "temp") ** (5) Name of trigger that is doing the access ** ** The callback should return one of the following strings: SQLITE_OK, ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error. ** ** If this method is invoked with no arguments, the current authorization ** callback string is returned. */ case DB_AUTHORIZER: { #ifdef SQLITE_OMIT_AUTHORIZATION |
︙ | ︙ | |||
2516 2517 2518 2519 2520 2521 2522 | int i, j; /* Loop counters */ int nSep; /* Number of bytes in zSep[] */ int nNull; /* Number of bytes in zNull[] */ char *zSql; /* An SQL statement */ char *zLine; /* A single line of input from the file */ char **azCol; /* zLine[] broken up into columns */ const char *zCommit; /* How to commit changes */ | | > | 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 | int i, j; /* Loop counters */ int nSep; /* Number of bytes in zSep[] */ int nNull; /* Number of bytes in zNull[] */ char *zSql; /* An SQL statement */ char *zLine; /* A single line of input from the file */ char **azCol; /* zLine[] broken up into columns */ const char *zCommit; /* How to commit changes */ Tcl_Channel in; /* The input file */ int lineno = 0; /* Line number of input file */ char zLineNum[80]; /* Line number print buffer */ Tcl_DString str; Tcl_Obj *pResult; /* interp result */ const char *zSep; const char *zNull; if( objc<5 || objc>7 ){ Tcl_WrongNumArgs(interp, 2, objv, "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"); |
︙ | ︙ | |||
2597 2598 2599 2600 2601 2602 2603 | rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); free(zSql); if( rc ){ Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0); sqlite3_finalize(pStmt); return TCL_ERROR; } | | < | > | > | 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 | rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); free(zSql); if( rc ){ Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0); sqlite3_finalize(pStmt); return TCL_ERROR; } in = Tcl_OpenFileChannel(interp, zFile, "rb", 0666); if( in==0 ){ sqlite3_finalize(pStmt); return TCL_ERROR; } azCol = malloc( sizeof(azCol[0])*(nCol+1) ); if( azCol==0 ) { Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0); Tcl_Close(interp, in); return TCL_ERROR; } Tcl_DStringInit(&str); (void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0); zCommit = "COMMIT"; while( Tcl_Gets(in, &str)>=0 ) { char *z; lineno++; zLine = Tcl_DStringValue(&str); azCol[0] = zLine; for(i=0, z=zLine; *z; z++){ if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){ *z = 0; i++; if( i<nCol ){ azCol[i] = &z[nSep]; |
︙ | ︙ | |||
2651 2652 2653 2654 2655 2656 2657 | sqlite3_bind_null(pStmt, i+1); }else{ sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); } } sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); | | > | | 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 | sqlite3_bind_null(pStmt, i+1); }else{ sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); } } sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); Tcl_DStringSetLength(&str, 0); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0); zCommit = "ROLLBACK"; break; } } Tcl_DStringFree(&str); free(azCol); Tcl_Close(interp, in); sqlite3_finalize(pStmt); (void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0); if( zCommit[0] == 'C' ){ /* success, set result as number of lines processed */ pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, lineno); |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
688 689 690 691 692 693 694 | }else if( tokenType==TK_OVER ){ assert( n==4 ); tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed); }else if( tokenType==TK_FILTER ){ assert( n==6 ); tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); #endif /* SQLITE_OMIT_WINDOWFUNC */ | | > > > > | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 | }else if( tokenType==TK_OVER ){ assert( n==4 ); tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed); }else if( tokenType==TK_FILTER ){ assert( n==6 ); tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); #endif /* SQLITE_OMIT_WINDOWFUNC */ }else if( tokenType==TK_COMMENT && (db->init.busy || (db->flags & SQLITE_Comments)!=0) ){ /* Ignore SQL comments if either (1) we are reparsing the schema or ** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */ zSql += n; continue; }else if( tokenType!=TK_QNUMBER ){ Token x; x.z = zSql; x.n = n; sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
1035 1036 1037 1038 1039 1040 1041 | int regIn /* The first in an array of registers */ ){ Vdbe *v = pParse->pVdbe; sqlite3 *db = pParse->db; ExprList *pNew; Returning *pReturning; Select sSelect; | | > > | | | | | | | 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 | int regIn /* The first in an array of registers */ ){ Vdbe *v = pParse->pVdbe; sqlite3 *db = pParse->db; ExprList *pNew; Returning *pReturning; Select sSelect; SrcList *pFrom; u8 fromSpace[SZ_SRCLIST_1]; assert( v!=0 ); if( !pParse->bReturning ){ /* This RETURNING trigger must be for a different statement as ** this statement lacks a RETURNING clause. */ return; } assert( db->pParse==pParse ); assert( !pParse->isCreate ); pReturning = pParse->u1.d.pReturning; if( pTrigger != &(pReturning->retTrig) ){ /* This RETURNING trigger is for a different statement */ return; } memset(&sSelect, 0, sizeof(sSelect)); pFrom = (SrcList*)fromSpace; memset(pFrom, 0, SZ_SRCLIST_1); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = pFrom; pFrom->nSrc = 1; pFrom->a[0].pSTab = pTab; pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */ pFrom->a[0].iCursor = -1; sqlite3SelectPrep(pParse, &sSelect, 0); if( pParse->nErr==0 ){ assert( db->mallocFailed==0 ); sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
191 192 193 194 195 196 197 | ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; | | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments; db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_Defensive | SQLITE_CountRows); db->mTrace = 0; zDbMain = db->aDb[iDb].zDbSName; pMain = db->aDb[iDb].pBt; |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
274 275 276 277 278 279 280 | ** the top of the register space. Cursor 1 is at Mem[p->nMem-1]. ** Cursor 2 is at Mem[p->nMem-2]. And so forth. */ Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem; i64 nByte; VdbeCursor *pCx = 0; | | | | | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | ** the top of the register space. Cursor 1 is at Mem[p->nMem-1]. ** Cursor 2 is at Mem[p->nMem-2]. And so forth. */ Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem; i64 nByte; VdbeCursor *pCx = 0; nByte = SZ_VDBECURSOR(nField); assert( ROUND8(nByte)==nByte ); if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize(); assert( iCur>=0 && iCur<p->nCursor ); if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/ sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } |
︙ | ︙ | |||
309 310 311 312 313 314 315 | p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc; memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); pCx->eCurType = eCurType; pCx->nField = nField; pCx->aOffset = &pCx->aType[nField]; if( eCurType==CURTYPE_BTREE ){ | > | < | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc; memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); pCx->eCurType = eCurType; pCx->nField = nField; pCx->aOffset = &pCx->aType[nField]; if( eCurType==CURTYPE_BTREE ){ assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) ); pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)]; sqlite3BtreeCursorZero(pCx->uc.pCursor); } return pCx; } /* ** The string in pRec is known to look like an integer and to have a |
︙ | ︙ | |||
6052 6053 6054 6055 6056 6057 6058 | assert( pC->nullRow==0 ); assert( pC->uc.pCursor!=0 ); pCrsr = pC->uc.pCursor; /* The OP_RowData opcodes always follow OP_NotExists or ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions ** that might invalidate the cursor. | | | 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 | assert( pC->nullRow==0 ); assert( pC->uc.pCursor!=0 ); pCrsr = pC->uc.pCursor; /* The OP_RowData opcodes always follow OP_NotExists or ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions ** that might invalidate the cursor. ** If this were not the case, one of the following assert()s ** would fail. Should this ever change (because of changes in the code ** generator) then the fix would be to insert a call to ** sqlite3VdbeCursorMoveto(). */ assert( pC->deferredMoveto==0 ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); |
︙ | ︙ | |||
7701 7702 7703 7704 7705 7706 7707 | /* Allocate space for (a) the context object and (n-1) extra pointers ** to append to the sqlite3_context.argv[1] array, and (b) a memory ** cell in which to store the accumulation. Be careful that the memory ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits. ** ** Note: We could avoid this by using a regular memory cell from aMem[] for ** the accumulator, instead of allocating one here. */ | | | 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 | /* Allocate space for (a) the context object and (n-1) extra pointers ** to append to the sqlite3_context.argv[1] array, and (b) a memory ** cell in which to store the accumulation. Be careful that the memory ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits. ** ** Note: We could avoid this by using a regular memory cell from aMem[] for ** the accumulator, instead of allocating one here. */ nAlloc = ROUND8P( SZ_CONTEXT(n) ); pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem)); if( pCtx==0 ) goto no_mem; pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc); assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) ); sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); pCtx->pMem = 0; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
315 316 317 318 319 320 321 | void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val); int sqlite3NotPureFunc(sqlite3_context*); #ifdef SQLITE_ENABLE_BYTECODE_VTAB int sqlite3VdbeBytecodeVtabInit(sqlite3*); #endif | | | | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val); int sqlite3NotPureFunc(sqlite3_context*); #ifdef SQLITE_ENABLE_BYTECODE_VTAB int sqlite3VdbeBytecodeVtabInit(sqlite3*); #endif /* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra ** comments on each VDBE opcode. ** ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op ** comments in VDBE programs that show key decision points in the code ** generator. */ #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS void sqlite3VdbeComment(Vdbe*, const char*, ...); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
129 130 131 132 133 134 135 | u32 payloadSize; /* Total number of bytes in the record */ u32 szRow; /* Byte available in aRow */ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK u64 maskUsed; /* Mask of columns used by this cursor */ #endif VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */ | | < | | > > > > > > > > | 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 | u32 payloadSize; /* Total number of bytes in the record */ u32 szRow; /* Byte available in aRow */ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK u64 maskUsed; /* Mask of columns used by this cursor */ #endif VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */ /* Space is allocated for aType to hold at least 2*nField+1 entries: ** nField slots for aType[] and nField+1 array slots for aOffset[] */ u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */ }; /* ** The size (in bytes) of a VdbeCursor object that has an nField value of N ** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple ** of 8. */ #define SZ_VDBECURSOR(N) \ (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64)) /* Return true if P is a null-only cursor */ #define IsNullCursor(P) \ ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0) /* ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. |
︙ | ︙ | |||
391 392 393 394 395 396 397 | Mem *pMem; /* Memory cell used to store aggregate context */ Vdbe *pVdbe; /* The VM that owns this context */ int iOp; /* Instruction number of OP_Function */ int isError; /* Error code returned by the function. */ u8 enc; /* Encoding to use for results */ u8 skipFlag; /* Skip accumulator loading if true */ u16 argc; /* Number of arguments */ | | > > > > > > > | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 | Mem *pMem; /* Memory cell used to store aggregate context */ Vdbe *pVdbe; /* The VM that owns this context */ int iOp; /* Instruction number of OP_Function */ int isError; /* Error code returned by the function. */ u8 enc; /* Encoding to use for results */ u8 skipFlag; /* Skip accumulator loading if true */ u16 argc; /* Number of arguments */ sqlite3_value *argv[FLEXARRAY]; /* Argument set */ }; /* ** The size (in bytes) of an sqlite3_context object that holds N ** argv[] arguments. */ #define SZ_CONTEXT(N) \ (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*)) /* The ScanStatus object holds a single value for the ** sqlite3_stmt_scanstatus() interface. ** ** aAddrRange[]: ** This array is used by ScanStatus elements associated with EQP ** notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is |
︙ | ︙ | |||
527 528 529 530 531 532 533 | ** sqlite3_preupdate_*() API functions. */ struct PreUpdate { Vdbe *v; VdbeCursor *pCsr; /* Cursor to read old values from */ int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ u8 *aRecord; /* old.* database record */ | | > | 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 | ** sqlite3_preupdate_*() API functions. */ struct PreUpdate { Vdbe *v; VdbeCursor *pCsr; /* Cursor to read old values from */ int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ u8 *aRecord; /* old.* database record */ KeyInfo *pKeyinfo; /* Key information */ UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ int iNewReg; /* Register for new.* values */ int iBlobWrite; /* Value returned by preupdate_blobwrite() */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem oldipk; /* Memory cell holding "old" IPK value */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being updated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ sqlite3_value **apDflt; /* Array of default values, if required */ u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */ }; /* ** An instance of this object is used to pass an vector of values into ** OP_VFilter, the xFilter method of a virtual table. The vector is the ** set of values on the right-hand side of an IN constraint. ** |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
2212 2213 2214 2215 2216 2217 2218 | assert( p->pCsr->eCurType==CURTYPE_BTREE ); nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); aRec = sqlite3DbMallocRaw(db, nRec); if( !aRec ) goto preupdate_old_out; rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec); if( rc==SQLITE_OK ){ | | | 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 | assert( p->pCsr->eCurType==CURTYPE_BTREE ); nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); aRec = sqlite3DbMallocRaw(db, nRec); if( !aRec ) goto preupdate_old_out; rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec); if( rc==SQLITE_OK ){ p->pUnpacked = vdbeUnpackRecord(p->pKeyinfo, nRec, aRec); if( !p->pUnpacked ) rc = SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ sqlite3DbFree(db, aRec); goto preupdate_old_out; } p->aRecord = aRec; |
︙ | ︙ | |||
2277 2278 2279 2280 2281 2282 2283 | int sqlite3_preupdate_count(sqlite3 *db){ PreUpdate *p; #ifdef SQLITE_ENABLE_API_ARMOR p = db!=0 ? db->pPreUpdate : 0; #else p = db->pPreUpdate; #endif | | | 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 | int sqlite3_preupdate_count(sqlite3 *db){ PreUpdate *p; #ifdef SQLITE_ENABLE_API_ARMOR p = db!=0 ? db->pPreUpdate : 0; #else p = db->pPreUpdate; #endif return (p ? p->pKeyinfo->nKeyField : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** This function is designed to be called from within a pre-update callback ** only. It returns zero if the change that caused the callback was made |
︙ | ︙ | |||
2360 2361 2362 2363 2364 2365 2366 | /* For an INSERT, memory cell p->iNewReg contains the serialized record ** that is being inserted. Deserialize it. */ UnpackedRecord *pUnpack = p->pNewUnpacked; if( !pUnpack ){ Mem *pData = &p->v->aMem[p->iNewReg]; rc = ExpandBlob(pData); if( rc!=SQLITE_OK ) goto preupdate_new_out; | | | 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 | /* For an INSERT, memory cell p->iNewReg contains the serialized record ** that is being inserted. Deserialize it. */ UnpackedRecord *pUnpack = p->pNewUnpacked; if( !pUnpack ){ Mem *pData = &p->v->aMem[p->iNewReg]; rc = ExpandBlob(pData); if( rc!=SQLITE_OK ) goto preupdate_new_out; pUnpack = vdbeUnpackRecord(p->pKeyinfo, pData->n, pData->z); if( !pUnpack ){ rc = SQLITE_NOMEM; goto preupdate_new_out; } p->pNewUnpacked = pUnpack; } pMem = &pUnpack->aMem[iStore]; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
441 442 443 444 445 446 447 | int p2, /* First argument register */ int p3, /* Register into which results are written */ int nArg, /* Number of argument */ const FuncDef *pFunc, /* The function to be invoked */ int eCallCtx /* Calling context */ ){ Vdbe *v = pParse->pVdbe; | < < | | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 | int p2, /* First argument register */ int p3, /* Register into which results are written */ int nArg, /* Number of argument */ const FuncDef *pFunc, /* The function to be invoked */ int eCallCtx /* Calling context */ ){ Vdbe *v = pParse->pVdbe; int addr; sqlite3_context *pCtx; assert( v ); pCtx = sqlite3DbMallocRawNN(pParse->db, SZ_CONTEXT(nArg)); if( pCtx==0 ){ assert( pParse->db->mallocFailed ); freeEphemeralFunction(pParse->db, (FuncDef*)pFunc); return 0; } pCtx->pOut = 0; pCtx->pFunc = (FuncDef*)pFunc; |
︙ | ︙ | |||
5523 5524 5525 5526 5527 5528 5529 | || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1) ); preupdate.v = v; preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; | > | | | | | | | 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 | || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1) ); preupdate.v = v; preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace; preupdate.pKeyinfo->db = db; preupdate.pKeyinfo->enc = ENC(db); preupdate.pKeyinfo->nKeyField = pTab->nCol; preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; preupdate.iBlobWrite = iBlobWrite; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; sqlite3DbFree(db, preupdate.aRecord); vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pUnpacked); vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pNewUnpacked); sqlite3VdbeMemRelease(&preupdate.oldipk); if( preupdate.aNew ){ int i; for(i=0; i<pCsr->nField; i++){ sqlite3VdbeMemRelease(&preupdate.aNew[i]); } sqlite3DbNNFreeNN(db, preupdate.aNew); |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 | ){ int nAttempt = 0; int iCol; /* Index of zColumn in row-record */ int rc = SQLITE_OK; char *zErr = 0; Table *pTab; Incrblob *pBlob = 0; Parse sParse; #ifdef SQLITE_ENABLE_API_ARMOR if( ppBlob==0 ){ return SQLITE_MISUSE_BKPT; } #endif | > | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | ){ int nAttempt = 0; int iCol; /* Index of zColumn in row-record */ int rc = SQLITE_OK; char *zErr = 0; Table *pTab; Incrblob *pBlob = 0; int iDb; Parse sParse; #ifdef SQLITE_ENABLE_API_ARMOR if( ppBlob==0 ){ return SQLITE_MISUSE_BKPT; } #endif |
︙ | ︙ | |||
174 175 176 177 178 179 180 | } #ifndef SQLITE_OMIT_VIEW if( pTab && IsView(pTab) ){ pTab = 0; sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); } #endif | | > > > | | 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 | } #ifndef SQLITE_OMIT_VIEW if( pTab && IsView(pTab) ){ pTab = 0; sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); } #endif if( pTab==0 || ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 && sqlite3OpenTempDatabase(&sParse)) ){ if( sParse.zErrMsg ){ sqlite3DbFree(db, zErr); zErr = sParse.zErrMsg; sParse.zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); goto blob_open_out; } pBlob->pTab = pTab; pBlob->zDb = db->aDb[iDb].zDbSName; /* Now search pTab for the exact column. */ iCol = sqlite3ColumnIndex(pTab, zColumn); if( iCol<0 ){ sqlite3DbFree(db, zErr); zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); rc = SQLITE_ERROR; |
︙ | ︙ | |||
269 270 271 272 273 274 275 | /* blobSeekToRow() will initialize r[1] to the desired rowid */ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ {OP_Column, 0, 0, 1}, /* 3 */ {OP_ResultRow, 1, 0, 0}, /* 4 */ {OP_Halt, 0, 0, 0}, /* 5 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; | < | 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | /* blobSeekToRow() will initialize r[1] to the desired rowid */ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ {OP_Column, 0, 0, 1}, /* 3 */ {OP_ResultRow, 1, 0, 0}, /* 4 */ {OP_Halt, 0, 0, 0}, /* 5 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; VdbeOp *aOp; sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, pTab->pSchema->schema_cookie, pTab->pSchema->iGeneration); sqlite3VdbeChangeP5(v, 1); assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed ); |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
328 329 330 331 332 333 334 | int iMemory; /* Offset of free space in list.aMemory */ int nMemory; /* Size of list.aMemory allocation in bytes */ u8 bUsePMA; /* True if one or more PMAs created */ u8 bUseThreads; /* True to use background threads */ u8 iPrev; /* Previous thread used to flush PMA */ u8 nTask; /* Size of aTask[] array */ u8 typeMask; | | > > > | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | int iMemory; /* Offset of free space in list.aMemory */ int nMemory; /* Size of list.aMemory allocation in bytes */ u8 bUsePMA; /* True if one or more PMAs created */ u8 bUseThreads; /* True to use background threads */ u8 iPrev; /* Previous thread used to flush PMA */ u8 nTask; /* Size of aTask[] array */ u8 typeMask; SortSubtask aTask[FLEXARRAY]; /* One or more subtasks */ }; /* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */ #define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask)) #define SORTER_TYPE_INTEGER 0x01 #define SORTER_TYPE_TEXT 0x02 /* ** An instance of the following object is used to read records out of a ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. |
︙ | ︙ | |||
962 963 964 965 966 967 968 | #endif assert( pCsr->pKeyInfo ); assert( !pCsr->isEphemeral ); assert( pCsr->eCurType==CURTYPE_SORTER ); assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*) < 0x7fffffff ); | | | | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 | #endif assert( pCsr->pKeyInfo ); assert( !pCsr->isEphemeral ); assert( pCsr->eCurType==CURTYPE_SORTER ); assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*) < 0x7fffffff ); szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1); sz = SZ_VDBESORTER(nWorker+1); pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); pCsr->uc.pSorter = pSorter; if( pSorter==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ Btree *pBt = db->aDb[0].pBt; |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
856 857 858 859 860 861 862 | int nSegment; /* Number of entries in aSegment[] */ struct WalSegment { int iNext; /* Next slot in aIndex[] not yet returned */ ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */ u32 *aPgno; /* Array of page numbers. */ int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */ int iZero; /* Frame number associated with aPgno[0] */ | | > > > > | 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 | int nSegment; /* Number of entries in aSegment[] */ struct WalSegment { int iNext; /* Next slot in aIndex[] not yet returned */ ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */ u32 *aPgno; /* Array of page numbers. */ int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */ int iZero; /* Frame number associated with aPgno[0] */ } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */ }; /* Size (in bytes) of a WalIterator object suitable for N or fewer segments */ #define SZ_WALITERATOR(N) \ (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment)) /* ** Define the parameters of the hash tables in the wal-index file. There ** is a hash-table following every HASHTABLE_NPAGE page numbers in the ** wal-index. ** ** Changing any of these constants will alter the wal-index format and |
︙ | ︙ | |||
2459 2460 2461 2462 2463 2464 2465 | iLastSeg = walFramePage2(iWal, iLast); }else{ iLastSeg = walFramePage(iLast); } nSegment = 1 + (iLastSeg/iMode); /* Allocate space for the WalIterator object. */ | | < | 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 | iLastSeg = walFramePage2(iWal, iLast); }else{ iLastSeg = walFramePage(iLast); } nSegment = 1 + (iLastSeg/iMode); /* Allocate space for the WalIterator object. */ nByte = SZ_WALITERATOR(nSegment) + iLast*sizeof(ht_slot); p = (WalIterator *)sqlite3_malloc64(nByte + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) ); if( !p ){ return SQLITE_NOMEM_BKPT; } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
31 32 33 34 35 36 37 | typedef struct HiddenIndexInfo HiddenIndexInfo; struct HiddenIndexInfo { WhereClause *pWC; /* The Where clause being analyzed */ Parse *pParse; /* The parsing context */ int eDistinct; /* Value to return from sqlite3_vtab_distinct() */ u32 mIn; /* Mask of terms that are <col> IN (...) */ u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */ | | | | > > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | typedef struct HiddenIndexInfo HiddenIndexInfo; struct HiddenIndexInfo { WhereClause *pWC; /* The Where clause being analyzed */ Parse *pParse; /* The parsing context */ int eDistinct; /* Value to return from sqlite3_vtab_distinct() */ u32 mIn; /* Mask of terms that are <col> IN (...) */ u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */ sqlite3_value *aRhs[FLEXARRAY]; /* RHS values for constraints. MUST BE LAST ** Extra space is allocated to hold up ** to nTerm such values */ }; /* Size (in bytes) of a HiddenIndeInfo object sufficient to hold as ** many as N constraints */ #define SZ_HIDDENINDEXINFO(N) \ (offsetof(HiddenIndexInfo,aRhs) + (N)*sizeof(sqlite3_value*)) /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* ** Return the estimated number of output rows from a WHERE clause */ LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ |
︙ | ︙ | |||
1513 1514 1515 1516 1517 1518 1519 | } } /* Allocate the sqlite3_index_info structure */ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm | | | | 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 | } } /* Allocate the sqlite3_index_info structure */ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + sizeof(*pIdxOrderBy)*nOrderBy + SZ_HIDDENINDEXINFO(nTerm) ); if( pIdxInfo==0 ){ sqlite3ErrorMsg(pParse, "out of memory"); return 0; } pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; pIdxCons = (struct sqlite3_index_constraint*)&pHidden->aRhs[nTerm]; pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; |
︙ | ︙ | |||
6708 6709 6710 6711 6712 6713 6714 | /* Allocate and initialize the WhereInfo structure that will become the ** return value. A single allocation is used to store the WhereInfo ** struct, the contents of WhereInfo.a[], the WhereClause structure ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ | | < < < | 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 | /* Allocate and initialize the WhereInfo structure that will become the ** return value. A single allocation is used to store the WhereInfo ** struct, the contents of WhereInfo.a[], the WhereClause structure ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ nByteWInfo = SZ_WHEREINFO(nTabList); pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); if( db->mallocFailed ){ sqlite3DbFree(db, pWInfo); pWInfo = 0; goto whereBeginError; } pWInfo->pParse = pParse; |
︙ | ︙ |
Changes to src/whereInt.h.
︙ | ︙ | |||
497 498 499 500 501 502 503 | int iTop; /* The very beginning of the WHERE loop */ int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ | | > > > > > | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | int iTop; /* The very beginning of the WHERE loop */ int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */ }; /* ** The size (in bytes) of a WhereInfo object that holds N WhereLevels. */ #define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel)) /* ** Private interfaces - callable only by other where.c routines. ** ** where.c: */ Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); #ifdef WHERETRACE_ENABLED |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
2309 2310 2311 2312 2313 2314 2315 | ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. ** This becomes the SrcList in the recursive call to sqlite3WhereBegin(). */ if( pWInfo->nLevel>1 ){ int nNotReady; /* The number of notReady tables */ SrcItem *origSrc; /* Original list of tables */ nNotReady = pWInfo->nLevel - iLevel - 1; | | < | 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 | ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. ** This becomes the SrcList in the recursive call to sqlite3WhereBegin(). */ if( pWInfo->nLevel>1 ){ int nNotReady; /* The number of notReady tables */ SrcItem *origSrc; /* Original list of tables */ nNotReady = pWInfo->nLevel - iLevel - 1; pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1)); if( pOrTab==0 ) return notReady; pOrTab->nAlloc = (u8)(nNotReady + 1); pOrTab->nSrc = pOrTab->nAlloc; memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem)); origSrc = pWInfo->pTabList->a; for(k=1; k<=nNotReady; k++){ memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k])); |
︙ | ︙ | |||
2853 2854 2855 2856 2857 2858 2859 | Vdbe *v = pParse->pVdbe; WhereRightJoin *pRJ = pLevel->pRJ; Expr *pSubWhere = 0; WhereClause *pWC = &pWInfo->sWC; WhereInfo *pSubWInfo; WhereLoop *pLoop = pLevel->pWLoop; SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; | | > | 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 | Vdbe *v = pParse->pVdbe; WhereRightJoin *pRJ = pLevel->pRJ; Expr *pSubWhere = 0; WhereClause *pWC = &pWInfo->sWC; WhereInfo *pSubWInfo; WhereLoop *pLoop = pLevel->pWLoop; SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; SrcList *pFrom; u8 fromSpace[SZ_SRCLIST_1]; Bitmask mAll = 0; int k; ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName)); sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn, pRJ->regReturn); for(k=0; k<iLevel; k++){ |
︙ | ︙ | |||
2897 2898 2899 2900 2901 2902 2903 | } if( pTerm->prereqAll & ~mAll ) continue; if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue; pSubWhere = sqlite3ExprAnd(pParse, pSubWhere, sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); } } | > | | | | | | 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 | } if( pTerm->prereqAll & ~mAll ) continue; if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue; pSubWhere = sqlite3ExprAnd(pParse, pSubWhere, sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); } } pFrom = (SrcList*)fromSpace; pFrom->nSrc = 1; pFrom->nAlloc = 1; memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem)); pFrom->a[0].fg.jointype = 0; assert( pParse->withinRJSubrtn < 100 ); pParse->withinRJSubrtn++; pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0, WHERE_RIGHT_JOIN, 0); if( pSubWInfo ){ int iCur = pLevel->iTabCur; int r = ++pParse->nMem; int nPk; int jmp; int addrCont = sqlite3WhereContinueLabel(pSubWInfo); |
︙ | ︙ |
Changes to test/fuzzcheck.c.
︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #include <stdarg.h> #include <ctype.h> #include <assert.h> #include "sqlite3.h" #include "sqlite3recover.h" #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) #ifdef __unix__ # include <signal.h> # include <unistd.h> #endif | > > > > > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | #include <stdarg.h> #include <ctype.h> #include <assert.h> #include "sqlite3.h" #include "sqlite3recover.h" #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif #ifdef __unix__ # include <signal.h> # include <unistd.h> #endif |
︙ | ︙ | |||
125 126 127 128 129 130 131 | */ typedef struct Blob Blob; struct Blob { Blob *pNext; /* Next in a list */ int id; /* Id of this Blob */ int seq; /* Sequence number */ int sz; /* Size of this Blob in bytes */ | | > > > | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | */ typedef struct Blob Blob; struct Blob { Blob *pNext; /* Next in a list */ int id; /* Id of this Blob */ int seq; /* Sequence number */ int sz; /* Size of this Blob in bytes */ unsigned char a[FLEXARRAY]; /* Blob content. Allocated as needed. */ }; /* Size in bytes of a Blob object sufficient to store N byte of content */ #define SZ_BLOB(N) (offsetof(Blob,a) + (((N)+7)&~7)) /* ** Maximum number of files in the in-memory virtual filesystem. */ #define MX_FILE 10 /* |
︙ | ︙ | |||
508 509 510 511 512 513 514 | sqlite3 *db, /* Read from this database */ const char *zSql, /* Query used to extract the blobs */ int firstId, /* First sqlid to load */ int lastId, /* Last sqlid to load */ int *pN, /* OUT: Write number of blobs loaded here */ Blob **ppList /* OUT: Write the head of the blob list here */ ){ | | > > | | | | | 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 | sqlite3 *db, /* Read from this database */ const char *zSql, /* Query used to extract the blobs */ int firstId, /* First sqlid to load */ int lastId, /* Last sqlid to load */ int *pN, /* OUT: Write number of blobs loaded here */ Blob **ppList /* OUT: Write the head of the blob list here */ ){ Blob *head; Blob *p; sqlite3_stmt *pStmt; int n = 0; int rc; char *z2; unsigned char tmp[SZ_BLOB(8)]; head = (Blob*)tmp; if( firstId>0 ){ z2 = sqlite3_mprintf("%s WHERE rowid BETWEEN %d AND %d", zSql, firstId, lastId); }else{ z2 = sqlite3_mprintf("%s", zSql); } rc = sqlite3_prepare_v2(db, z2, -1, &pStmt, 0); sqlite3_free(z2); if( rc ) fatalError("%s", sqlite3_errmsg(db)); head->pNext = 0; p = head; while( SQLITE_ROW==sqlite3_step(pStmt) ){ int sz = sqlite3_column_bytes(pStmt, 1); Blob *pNew = safe_realloc(0, SZ_BLOB(sz+1)); pNew->id = sqlite3_column_int(pStmt, 0); pNew->sz = sz; pNew->seq = n++; pNew->pNext = 0; memcpy(pNew->a, sqlite3_column_blob(pStmt,1), sz); pNew->a[sz] = 0; p->pNext = pNew; p = pNew; } sqlite3_finalize(pStmt); *pN = n; *ppList = head->pNext; } /* ** Free a list of Blob objects */ static void blobListFree(Blob *p){ Blob *pNext; |
︙ | ︙ |
Changes to test/recover.test.
︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 | proc recover_with_opts {opts} { set cmd ".recover $opts" set fd [open [list |$::CLI test.db $cmd]] fconfigure $fd -translation binary set sql [read $fd] close $fd forcedelete test.db2 sqlite3 db2 test.db2 execsql $sql db2 db2 close } proc do_recover_test {tn {tsql {}} {res {}}} { | > > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | proc recover_with_opts {opts} { set cmd ".recover $opts" set fd [open [list |$::CLI test.db $cmd]] fconfigure $fd -translation binary set sql [read $fd] close $fd # Remove the ".dbconfig defensive off" line set sql [string map {".dbconfig defensive off" ""} $sql] forcedelete test.db2 sqlite3 db2 test.db2 execsql $sql db2 db2 close } proc do_recover_test {tn {tsql {}} {res {}}} { |
︙ | ︙ |
Changes to test/shared.test.
︙ | ︙ | |||
308 309 310 311 312 313 314 | do_test shared-$av.4.1.3 { execsql {ATTACH 'test.db' AS test} db2 set sqlite_open_file_count expr $sqlite_open_file_count-($extrafds_postlock*2) } {2} # Sanity check: Create a table in ./test.db via handle db, and test that handle | | | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | do_test shared-$av.4.1.3 { execsql {ATTACH 'test.db' AS test} db2 set sqlite_open_file_count expr $sqlite_open_file_count-($extrafds_postlock*2) } {2} # Sanity check: Create a table in ./test.db via handle db, and test that handle # db2 can "see" the new table immediately. A handle using a separate pager # cache would have to reload the database schema before this were possible. # do_test shared-$av.4.2.1 { execsql { CREATE TABLE abc(a, b, c); CREATE TABLE def(d, e, f); INSERT INTO abc VALUES('i', 'ii', 'iii'); |
︙ | ︙ |
Changes to test/tabfunc01.test.
︙ | ︙ | |||
176 177 178 179 180 181 182 183 184 185 186 187 188 189 | SELECT * FROM aux1.generate_series(1,4) } {1 2 3 4} # 2018-12-03: Fix bug reported by by private email. do_execsql_test tabfunc01-4.4 { SELECT * FROM (generate_series(1,5,2)) AS x LIMIT 10; } {1 3 5} # The next series of tests is verifying that virtual table are able # to optimize the IN operator, even on terms that are not marked "omit". # When the generate_series virtual table is compiled for the testfixture, # the special -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 option is used, which # causes the xBestIndex method of generate_series to leave the # sqlite3_index_constraint_usage.omit flag set to 0, which should cause | > > > > > > > > > > > > > | 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 | SELECT * FROM aux1.generate_series(1,4) } {1 2 3 4} # 2018-12-03: Fix bug reported by by private email. do_execsql_test tabfunc01-4.4 { SELECT * FROM (generate_series(1,5,2)) AS x LIMIT 10; } {1 3 5} # 2025-03-13 forum post bf2dc8e909983511 # do_execsql_test tabfunc01-5.1 { SELECT value FROM generate_series(60,73,6) WHERE value=66; } 66 do_execsql_test tabfunc01-5.2 { SELECT value FROM generate_series(73,60,-6) WHERE value=67; } 67 # The next series of tests is verifying that virtual table are able # to optimize the IN operator, even on terms that are not marked "omit". # When the generate_series virtual table is compiled for the testfixture, # the special -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 option is used, which # causes the xBestIndex method of generate_series to leave the # sqlite3_index_constraint_usage.omit flag set to 0, which should cause |
︙ | ︙ |
Changes to test/tableapi.test.
︙ | ︙ | |||
226 227 228 229 230 231 232 | ifcapable schema_pragmas { do_test tableapi-6.1 { sqlite3_get_table_printf $::dbx {PRAGMA user_version} {} } {0 1 1 user_version 0} } # do_malloc_test closes and deletes the usual db connections and files on | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | ifcapable schema_pragmas { do_test tableapi-6.1 { sqlite3_get_table_printf $::dbx {PRAGMA user_version} {} } {0 1 1 user_version 0} } # do_malloc_test closes and deletes the usual db connections and files on # each iteration. $::dbx is a separate connection, and on Windows, will # cause the file deletion of test.db to fail, so we move the close of $::dbx # up to here before the do_malloc_test. do_test tableapi-99.0 { sqlite3_close $::dbx } {SQLITE_OK} do_malloc_test tableapi-7 -sqlprep { |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
1721 1722 1723 1724 1725 1726 1727 | set c [catch {uplevel 1 $code} r] } else { set c [catch {uplevel 1 $elsecode} r] } return -code $c $r } | | | 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | set c [catch {uplevel 1 $code} r] } else { set c [catch {uplevel 1 $elsecode} r] } return -code $c $r } # This proc execs a separate process that crashes midway through executing # the SQL script $sql on database test.db. # # The crash occurs during a sync() of file $crashfile. When the crash # occurs a random subset of all unsynced writes made by the process are # written into the files on disk. Argument $crashdelay indicates the # number of file syncs to wait before crashing. # |
︙ | ︙ |
Changes to test/walsetlk.test.
︙ | ︙ | |||
311 312 313 314 315 316 317 318 319 320 321 322 323 324 | BEGIN EXCLUSIVE; INSERT INTO x1 VALUES(7, 8); } after 2000 db eval { COMMIT } } after 500 {set ok 1} vwait ok db2 timeout 0x7FFFFFFF do_test 3.7 { | > | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | BEGIN EXCLUSIVE; INSERT INTO x1 VALUES(7, 8); } after 2000 db eval { COMMIT } db close } after 500 {set ok 1} vwait ok db2 timeout 0x7FFFFFFF do_test 3.7 { |
︙ | ︙ |
Changes to tool/sqlite3_analyzer.c.in.
︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 | }else{ Tcl_AppendResult(interp, "bad argument: ", zArg, 0); return TCL_ERROR; } } sqlite3_fputs(zOut, pOut); if( addNewLine ) sqlite3_fputs("\n", pOut); return TCL_OK; } #endif /* defined(_WIN32) */ const char *sqlite3_analyzer_init_proc(Tcl_Interp *interp){ #if defined(_WIN32) Tcl_CreateObjCommand(interp, "puts", subst_puts, 0, 0); | > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | }else{ Tcl_AppendResult(interp, "bad argument: ", zArg, 0); return TCL_ERROR; } } sqlite3_fputs(zOut, pOut); if( addNewLine ) sqlite3_fputs("\n", pOut); fflush(pOut); return TCL_OK; } #endif /* defined(_WIN32) */ const char *sqlite3_analyzer_init_proc(Tcl_Interp *interp){ #if defined(_WIN32) Tcl_CreateObjCommand(interp, "puts", subst_puts, 0, 0); |
︙ | ︙ |