Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Pull over from the trunk all recent changes for which we have clear title. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | clear-title |
| Files: | files | file ages | folders |
| SHA1: |
b9d3b4288fe7de54223e27023ca2a8ff |
| User & Date: | drh 2010-03-05 00:10:13.000 |
Context
|
2010-03-05
| ||
| 23:14 | Pull in all clear-title changes from trunk. ... (check-in: dfb5fd64cd user: drh tags: clear-title) | |
| 00:10 | Pull over from the trunk all recent changes for which we have clear title. ... (check-in: b9d3b4288f user: drh tags: clear-title) | |
| 00:08 | Disable prompts for a password if fossil is not running on an interactive terminal. ... (check-in: 554d4caa5a user: drh tags: trunk) | |
|
2010-02-25
| ||
| 14:06 | Pull over the latest clear-title changes from trunk. ... (check-in: 16e703be11 user: drh tags: clear-title) | |
Changes
Changes to BUILD.txt.
1 2 3 4 5 6 7 8 9 10 | All of the source code for fossil is contained in the src/ subdirectory. But there is a lot of generated code, so you will probably want to use the Makefile. To do a complete build, just type: make That should work out-of-the-box on Macs and Linux systems. If you are building on a Windows box, install MinGW as well as MinGW's make (or MSYS). You can then type: | | | | | | | | < | < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
All of the source code for fossil is contained in the src/ subdirectory.
But there is a lot of generated code, so you will probably want to
use the Makefile. To do a complete build, just type:
make
That should work out-of-the-box on Macs and Linux systems. If you are
building on a Windows box, install MinGW as well as MinGW's make (or
MSYS). You can then type:
make -f Makefile.w32
If you have trouble, or you want to do something fancy, just look at
top level makefile. There are 6 configuration options that are all well
commented. Instead of editing the Makefile, consider copying the Makefile
to an alternative name such as "GNUMakefile", "BSDMakefile", or "makefile"
and editing the copy.
Out of source builds?
--------------------------------------------------------------------------
An out of source build is pretty easy:
1. Make a new directory to do the builds in.
2. Copy "Makefile" from the source into the build directory and
modify the SRCDIR macro along the lines of:
SRCDIR=../src
3. type: "make"
This will now keep all generates files seperate from the maintained
source code.
--------------------------------------------------------------------------
Here are some notes on what is happening behind the scenes:
|
| ︙ | ︙ |
Changes to src/add.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** Copyright (c) 2007 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public ** License version 2 as published by the Free Software Foundation. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** Copyright (c) 2007 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public ** License version 2 as published by the Free Software Foundation. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public ** License along with this library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com |
| ︙ | ︙ | |||
30 31 32 33 34 35 36 | #include <dirent.h> /* ** Set to true if files whose names begin with "." should be ** included when processing a recursive "add" command. */ static int includeDotFiles = 0; | | | | > | > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#include <dirent.h>
/*
** Set to true if files whose names begin with "." should be
** included when processing a recursive "add" command.
*/
static int includeDotFiles = 0;
/*
** Add a single file
*/
static void add_one_file(const char *zName, int vid, Blob *pOmit){
Blob pathname;
const char *zPath;
file_tree_name(zName, &pathname, 1);
zPath = blob_str(&pathname);
if( strcmp(zPath, "manifest")==0
|| strcmp(zPath, "_FOSSIL_")==0
|| strcmp(zPath, "manifest.uuid")==0
|| blob_compare(&pathname, pOmit)==0
){
fossil_warning("cannot add %s", zPath);
}else{
if( !file_is_simple_pathname(zPath) ){
fossil_fatal("filename contains illegal characters: %s", zPath);
}
#ifdef __MINGW32__
if( db_exists("SELECT 1 FROM vfile"
" WHERE pathname=%Q COLLATE nocase", zPath) ){
db_multi_exec("UPDATE vfile SET deleted=0"
" WHERE pathname=%Q COLLATE nocase", zPath);
}
#else
if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
}
#endif
else{
|
| ︙ | ︙ | |||
124 125 126 127 128 129 130 | } /* ** COMMAND: add ** ** Usage: %fossil add FILE... ** | | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
}
/*
** COMMAND: add
**
** Usage: %fossil add FILE...
**
** Make arrangements to add one or more files to the current checkout
** at the next commit.
**
** When adding files recursively, filenames that begin with "." are
** excluded by default. To include such files, add the "--dotfiles"
** option to the command-line.
*/
void add_cmd(void){
|
| ︙ | ︙ | |||
270 271 272 273 274 275 276 |
free(zName);
}
db_multi_exec("DELETE FROM vfile WHERE deleted AND rid=0");
db_end_transaction(0);
}
/*
| | | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
free(zName);
}
db_multi_exec("DELETE FROM vfile WHERE deleted AND rid=0");
db_end_transaction(0);
}
/*
** Rename a single file.
**
** The original name of the file is zOrig. The new filename is zNew.
*/
static void mv_one_file(int vid, const char *zOrig, const char *zNew){
printf("RENAME %s %s\n", zOrig, zNew);
db_multi_exec(
"UPDATE vfile SET pathname='%s' WHERE pathname='%s' AND vid=%d",
|
| ︙ | ︙ |
Changes to src/checkin.c.
| ︙ | ︙ | |||
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
** ancestor identified rid and zUuid. Throw a fatal error if not.
*/
static void checkin_verify_younger(
int rid, /* The record ID of the ancestor */
const char *zUuid, /* The artifact ID of the ancestor */
const char *zDate /* Date & time of the current check-in */
){
int b;
b = db_exists(
"SELECT 1 FROM event"
" WHERE datetime(mtime)>=%Q"
" AND type='ci' AND objid=%d",
zDate, rid
);
if( b ){
fossil_fatal("ancestor check-in [%.10s] (%s) is younger (clock skew?)",
zUuid, zDate);
}
}
/*
** COMMAND: ci
** COMMAND: commit
**
** Usage: %fossil commit ?OPTIONS? ?FILE...?
| > > | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
** ancestor identified rid and zUuid. Throw a fatal error if not.
*/
static void checkin_verify_younger(
int rid, /* The record ID of the ancestor */
const char *zUuid, /* The artifact ID of the ancestor */
const char *zDate /* Date & time of the current check-in */
){
#ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES
int b;
b = db_exists(
"SELECT 1 FROM event"
" WHERE datetime(mtime)>=%Q"
" AND type='ci' AND objid=%d",
zDate, rid
);
if( b ){
fossil_fatal("ancestor check-in [%.10s] (%s) is younger (clock skew?)",
zUuid, zDate);
}
#endif
}
/*
** COMMAND: ci
** COMMAND: commit
**
** Usage: %fossil commit ?OPTIONS? ?FILE...?
|
| ︙ | ︙ |
Changes to src/graph.c.
| ︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
/*
** Compute the complete graph
*/
void graph_finish(GraphContext *p, int omitDescenders){
GraphRow *pRow, *pDesc;
Bag allRids;
int i;
int nRow;
u32 mask;
u32 inUse;
if( p==0 || p->pFirst==0 || p->nErr ) return;
/* Initialize all rows */
bag_init(&allRids);
nRow = 0;
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
if( pRow->pNext ) pRow->pNext->pPrev = pRow;
pRow->idx = ++nRow;
pRow->iRail = -1;
pRow->mergeOut = -1;
bag_insert(&allRids, pRow->rid);
}
p->mxRail = -1;
/* Purge merge-parents that are out-of-graph
*/
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
for(i=1; i<pRow->nParent; i++){
if( !bag_find(&allRids, pRow->aParent[i]) ){
pRow->aParent[i] = pRow->aParent[--pRow->nParent];
i--;
}
}
}
/* Identify rows where the primary parent is off screen. Assign
** each to a rail and draw descenders to the bottom of the screen.
*/
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
| > > > > > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
/*
** Compute the complete graph
*/
void graph_finish(GraphContext *p, int omitDescenders){
GraphRow *pRow, *pDesc;
Bag allRids;
Bag notLeaf;
int i;
int nRow;
u32 mask;
u32 inUse;
if( p==0 || p->pFirst==0 || p->nErr ) return;
/* Initialize all rows */
bag_init(&allRids);
bag_init(¬Leaf);
nRow = 0;
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
if( pRow->pNext ) pRow->pNext->pPrev = pRow;
pRow->idx = ++nRow;
pRow->iRail = -1;
pRow->mergeOut = -1;
bag_insert(&allRids, pRow->rid);
}
p->mxRail = -1;
/* Purge merge-parents that are out-of-graph
*/
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
for(i=1; i<pRow->nParent; i++){
if( !bag_find(&allRids, pRow->aParent[i]) ){
pRow->aParent[i] = pRow->aParent[--pRow->nParent];
i--;
}
}
if( pRow->nParent>0 && bag_find(&allRids, pRow->aParent[0]) ){
bag_insert(¬Leaf, pRow->aParent[0]);
}
}
/* Identify rows where the primary parent is off screen. Assign
** each to a rail and draw descenders to the bottom of the screen.
*/
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
|
| ︙ | ︙ | |||
265 266 267 268 269 270 271 |
if( pDesc->aiRaiser[pDesc->iRail]==0 && pDesc->zBranch==pRow->zBranch ){
pRow->iRail = pDesc->iRail;
}else{
pRow->iRail = findFreeRail(p, 0, pDesc->idx, inUse, 0);
}
pDesc->aiRaiser[pRow->iRail] = pRow->idx;
mask = 1<<pRow->iRail;
| | | | | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
if( pDesc->aiRaiser[pDesc->iRail]==0 && pDesc->zBranch==pRow->zBranch ){
pRow->iRail = pDesc->iRail;
}else{
pRow->iRail = findFreeRail(p, 0, pDesc->idx, inUse, 0);
}
pDesc->aiRaiser[pRow->iRail] = pRow->idx;
mask = 1<<pRow->iRail;
if( bag_find(¬Leaf, pRow->rid) ){
inUse |= mask;
}else{
inUse &= ~mask;
}
for(pDesc = pRow; ; pDesc=pDesc->pNext){
assert( pDesc!=0 );
pDesc->railInUse |= mask;
if( pDesc->rid==parentRid ) break;
}
}
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
if( tagtype==2 ){
if( zOrigUuid && zOrigUuid[0] ){
@ inherited from
hyperlink_to_uuid(zOrigUuid);
}else{
@ propagates to descendants
}
}
if( zSrcUuid && zSrcUuid[0] ){
if( tagtype==0 ){
@ by
}else{
@ added by
}
| > > > > | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
if( tagtype==2 ){
if( zOrigUuid && zOrigUuid[0] ){
@ inherited from
hyperlink_to_uuid(zOrigUuid);
}else{
@ propagates to descendants
}
if( zValue && strcmp(zTagname,"branch")==0 ){
@
@ <a href="%s(g.zBaseURL)/timeline?t=%T(zValue)">branch timeline</a>
}
}
if( zSrcUuid && zSrcUuid[0] ){
if( tagtype==0 ){
@ by
}else{
@ added by
}
|
| ︙ | ︙ |
Changes to src/main.mk.
| ︙ | ︙ | |||
748 749 750 751 752 753 754 | ./translate $(SRCDIR)/zip.c >zip_.c $(OBJDIR)/zip.o: zip_.c zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c zip_.c zip.h: headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c | | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | ./translate $(SRCDIR)/zip.c >zip_.c $(OBJDIR)/zip.o: zip_.c zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c zip_.c zip.h: headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o $(OBJDIR)/th.o: $(SRCDIR)/th.c $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
puts "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1}
append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4"
#append opt " -DSQLITE_ENABLE_FTS3=1"
append opt " -Dlocaltime=fossil_localtime"
puts "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
puts "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"
puts "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"
| > | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
puts "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1}
append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4"
#append opt " -DSQLITE_ENABLE_FTS3=1"
append opt " -Dlocaltime=fossil_localtime"
append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0"
puts "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
puts "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"
puts "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"
|
Changes to src/sqlite3.c.
1 2 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite | | | 1 2 3 4 5 6 7 8 9 10 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.6.23. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a one translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% are more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other |
| ︙ | ︙ | |||
303 304 305 306 307 308 309 310 311 312 | #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #define SQLITE_INDEX_SAMPLES 10 /* | > > > > > | < < | > > < < < | | | | | | > > | | < > | | < | | | < | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif /* ** The number of samples of an index that SQLite takes in order to ** construct a histogram of the table content when running ANALYZE ** and with SQLITE_ENABLE_STAT2 */ #define SQLITE_INDEX_SAMPLES 10 /* ** The following macros are used to cast pointers to integers and ** integers to pointers. The way you do this varies from one compiler ** to the next, so we have developed the following set of #if statements ** to generate appropriate macros for a wide range of compilers. ** ** The correct "ANSI" way to do this is to use the intptr_t type. ** Unfortunately, that typedef is not available on all compilers, or ** if it is available, it requires an #include of specific headers ** that very from one machine to the next. ** ** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on ** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). ** So we have to define the macros in different ways depending on the ** compiler. */ #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ # define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) #elif !defined(__GNUC__) /* Works for compilers other than LLVM */ # define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) #elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ # define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) #else /* Generates a warning - but it always works */ # define SQLITE_INT_TO_PTR(X) ((void*)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif /* ** The SQLITE_THREADSAFE macro must be defined as either 0 or 1. ** Older versions of SQLite used an optional THREADSAFE macro. ** We support that for legacy */ #if !defined(SQLITE_THREADSAFE) |
| ︙ | ︙ | |||
367 368 369 370 371 372 373 | /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_MEMDEBUG // Debugging version of system malloc() | | | | | < < | < | < < | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_MEMDEBUG // Debugging version of system malloc() ** ** (Historical note: There used to be several other options, but we've ** pared it down to just these two.) ** ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as ** the default. */ #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1 # error "At most one of the following compile-time configuration options\ is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG" #endif #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ |
| ︙ | ︙ | |||
627 628 629 630 631 632 633 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.6.23" #define SQLITE_VERSION_NUMBER 3006023 #define SQLITE_SOURCE_ID "2010-03-04 17:58:45 5e472896e02eed05c6c0886a48acd0bdc7a38731" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ** but are associated with the library instead of the header file. ^(Cautious ** programmers might include assert() statements in their application to ** verify that values returned by these interfaces match the macros in ** the header, and thus insure that the application is |
| ︙ | ︙ | |||
655 656 657 658 659 660 661 | ** ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] ** macro. ^The sqlite3_libversion() function returns a pointer to the ** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 | ** ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] ** macro. ^The sqlite3_libversion() function returns a pointer to the ** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the ** [SQLITE_SOURCE_ID] C preprocessor macro. ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; SQLITE_API const char *sqlite3_libversion(void); SQLITE_API const char *sqlite3_sourceid(void); SQLITE_API int sqlite3_libversion_number(void); #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics ** ** ^The sqlite3_compileoption_used() function returns 0 or 1 ** indicating whether the specified option was defined at ** compile time. ^The SQLITE_ prefix may be omitted from the ** option name passed to sqlite3_compileoption_used(). ** ** ^The sqlite3_compileoption_get() function allows interating ** over the list of options that were defined at compile time by ** returning the N-th compile time option string. ^If N is out of range, ** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ ** prefix is omitted from any strings returned by ** sqlite3_compileoption_get(). ** ** ^Support for the diagnostic functions sqlite3_compileoption_used() ** and sqlite3_compileoption_get() may be omitted by specifing the ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. ** ** See also: SQL functions [sqlite_compileoption_used()] and ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ SQLITE_API int sqlite3_compileoption_used(const char *zOptName); SQLITE_API const char *sqlite3_compileoption_get(int N); #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ /* ** CAPI3REF: Test To See If The Library Is Threadsafe ** ** ^The sqlite3_threadsafe() function returns zero if and only if ** SQLite was compiled mutexing code omitted due to the ** [SQLITE_THREADSAFE] compile-time option being set to 0. ** |
| ︙ | ︙ | |||
957 958 959 960 961 962 963 964 965 966 967 968 969 970 | ** [sqlite3_vfs] object. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ | > | 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 | ** [sqlite3_vfs] object. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ |
| ︙ | ︙ | |||
1438 1439 1440 1441 1442 1443 1444 | SQLITE_API int sqlite3_initialize(void); SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library | < | 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | SQLITE_API int sqlite3_initialize(void); SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** ** The sqlite3_config() interface is used to make global configuration ** changes to SQLite in order to tune SQLite to the specific needs of ** the application. The default configuration is recommended for most ** applications and so this routine is usually not necessary. It is ** provided to support rare applications with unusual needs. ** |
| ︙ | ︙ | |||
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 | #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ #define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ /* ** CAPI3REF: Configuration Options ** EXPERIMENTAL ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. | > | 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 | #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ #define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ /* ** CAPI3REF: Configuration Options ** EXPERIMENTAL ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. |
| ︙ | ︙ | |||
4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 | ); SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); /* ** Specify the key for an encrypted database. This routine should be ** called right after sqlite3_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ | > | 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 | ); SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); #if SQLITE_HAS_CODEC /* ** Specify the key for an encrypted database. This routine should be ** called right after sqlite3_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ |
| ︙ | ︙ | |||
4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 | ** of SQLite. */ SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); /* ** CAPI3REF: Suspend Execution For A Short Time ** ** ^The sqlite3_sleep() function causes the current thread to suspend execution ** for at least a number of milliseconds specified in its parameter. ** ** ^If the operating system does not support sleep requests with | > > > > > > > > > > > > > > > > > > > | 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 | ** of SQLite. */ SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); /* ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif #ifdef SQLITE_ENABLE_CEROD /* ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif /* ** CAPI3REF: Suspend Execution For A Short Time ** ** ^The sqlite3_sleep() function causes the current thread to suspend execution ** for at least a number of milliseconds specified in its parameter. ** ** ^If the operating system does not support sleep requests with |
| ︙ | ︙ | |||
6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 | ** ^The [sqlite3_strnicmp()] API allows applications and extensions to ** compare the contents of two buffers containing UTF-8 strings in a ** case-indendent fashion, using the same definition of case independence ** that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif | > > > > > > > > > > > > > > > > > > > > > > > > | 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 | ** ^The [sqlite3_strnicmp()] API allows applications and extensions to ** compare the contents of two buffers containing UTF-8 strings in a ** case-indendent fashion, using the same definition of case independence ** that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: Error Logging Interface ** EXPERIMENTAL ** ** ^The [sqlite3_log()] interface writes a message into the error log ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are ** passed through to [sqlite3_vmprintf()] to generate the final output string. ** ** The sqlite3_log() interface is intended for use by extensions such as ** virtual tables, collating functions, and SQL functions. While there is ** nothing to prevent an application from calling sqlite3_log(), doing so ** is considered bad form. ** ** The zFormat string must not be NULL. ** ** To avoid deadlocks and other threading problems, the sqlite3_log() routine ** will not use dynamically allocated memory. The log message is stored in ** a fixed-length buffer on the stack. If the log message is longer than ** a few hundred characters, it will be truncated to the length of the ** buffer. */ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif |
| ︙ | ︙ | |||
6482 6483 6484 6485 6486 6487 6488 | */ #ifdef SQLITE_OMIT_TEMPDB #define OMIT_TEMPDB 1 #else #define OMIT_TEMPDB 0 #endif | < < < < < < < < < < < < < < > > > > | 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 | */ #ifdef SQLITE_OMIT_TEMPDB #define OMIT_TEMPDB 1 #else #define OMIT_TEMPDB 0 #endif /* ** The "file format" number is an integer that is incremented whenever ** the VDBE-level file format changes. The following macros define the ** the default file format for new databases and the maximum file format ** that the library can read. */ #define SQLITE_MAX_FILE_FORMAT 4 #ifndef SQLITE_DEFAULT_FILE_FORMAT # define SQLITE_DEFAULT_FILE_FORMAT 1 #endif /* ** Determine whether triggers are recursive by default. This can be ** changed at run-time using a pragma. */ #ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS # define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 #endif /* ** Provide a default value for SQLITE_TEMP_STORE in case it is not specified ** on the command-line |
| ︙ | ︙ | |||
6751 6752 6753 6754 6755 6756 6757 | /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; | < > | | | | 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 | /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; typedef struct CollSeq CollSeq; typedef struct Column Column; typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; typedef struct VTable VTable; typedef struct Walker Walker; typedef struct WherePlan WherePlan; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; |
| ︙ | ︙ | |||
6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 | SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*); SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); | > | 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 | SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*); SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); |
| ︙ | ︙ | |||
7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 | SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); | > | 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 | SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); |
| ︙ | ︙ | |||
8184 8185 8186 8187 8188 8189 8190 | #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3 *db; /* "Owner" connection. See comment above */ #endif }; /* ** These macros can be used to test, set, or clear bits in the | | | | 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 | #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3 *db; /* "Owner" connection. See comment above */ #endif }; /* ** These macros can be used to test, set, or clear bits in the ** Db.pSchema->flags field. */ #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) /* ** Allowed values for the DB.pSchema->flags field. ** ** The DB_SchemaLoaded flag is set after the database schema has been ** read into internal hash tables. ** ** DB_UnresetViews means that one or more views have column names that ** have been filled out. If the schema changes, these column names might ** changes and so the view will need to be reset. |
| ︙ | ︙ | |||
8256 8257 8258 8259 8260 8261 8262 |
** Collisions are on the FuncDef.pHash chain.
*/
struct FuncDefHash {
FuncDef *a[23]; /* Hash table for functions */
};
/*
| | | 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 |
** Collisions are on the FuncDef.pHash chain.
*/
struct FuncDefHash {
FuncDef *a[23]; /* Hash table for functions */
};
/*
** Each database connection is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
** insert statement. Inserts on views do not affect its value. Each
** trigger has its own context, so that lastRowid can be updated inside
** triggers as usual. The previous value will be restored once the trigger
** exits. Upon entering a before or instead of trigger, lastRowid is no
** longer (since after version 2.8.12) reset to -1.
|
| ︙ | ︙ | |||
8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 | int errMask; /* & result codes with this before returning */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ u8 dfltJournalMode; /* Default journal mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ int nextPagesize; /* Pagesize after VACUUM if >0 */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ i64 lastRowid; /* ROWID of most recent insert (see above) */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ | > | 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 | int errMask; /* & result codes with this before returning */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ u8 dfltJournalMode; /* Default journal mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ int nextPagesize; /* Pagesize after VACUUM if >0 */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ i64 lastRowid; /* ROWID of most recent insert (see above) */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ |
| ︙ | ︙ | |||
9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 |
int isInit; /* True after initialization has finished */
int inProgress; /* True while initialization in progress */
int isMutexInit; /* True after mutexes are initialized */
int isMallocInit; /* True after malloc is initialized */
int isPCacheInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
};
/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
| > > | 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 |
int isInit; /* True after initialization has finished */
int inProgress; /* True while initialization in progress */
int isMutexInit; /* True after mutexes are initialized */
int isMallocInit; /* True after malloc is initialized */
int isPCacheInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
void (*xLog)(void*,int,const char*); /* Function for logging */
void *pLogArg; /* First argument to xLog() */
};
/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
|
| ︙ | ︙ | |||
9912 9913 9914 9915 9916 9917 9918 |
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
} \
}
/*
| | | > > | < | | > | > > | > > > > > > > | | 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 |
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
} \
}
/*
** The SQLITE_*_BKPT macros are substitutes for the error codes with
** the same name but without the _BKPT suffix. These macros invoke
** routines that report the line-number on which the error originated
** using sqlite3_log(). The routines also provide a convenient place
** to set a debugger breakpoint.
*/
SQLITE_PRIVATE int sqlite3CorruptError(int);
SQLITE_PRIVATE int sqlite3MisuseError(int);
SQLITE_PRIVATE int sqlite3CantopenError(int);
#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
/*
** FTS4 is really an extension for FTS3. It is enabled using the
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
*/
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
# define SQLITE_ENABLE_FTS3
#endif
/*
** The ctype.h header is needed for non-ASCII systems. It is also
** needed by FTS3 when FTS3 is included in the amalgamation.
*/
#if !defined(SQLITE_ASCII) || \
|
| ︙ | ︙ | |||
10023 10024 10025 10026 10027 10028 10029 | SQLITE_PRIVATE int sqlite3MutexEnd(void); #endif SQLITE_PRIVATE int sqlite3StatusValue(int); SQLITE_PRIVATE void sqlite3StatusAdd(int, int); SQLITE_PRIVATE void sqlite3StatusSet(int, int); | > | > > > < | 10098 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132 | SQLITE_PRIVATE int sqlite3MutexEnd(void); #endif SQLITE_PRIVATE int sqlite3StatusValue(int); SQLITE_PRIVATE void sqlite3StatusAdd(int, int); SQLITE_PRIVATE void sqlite3StatusSet(int, int); #ifndef SQLITE_OMIT_FLOATING_POINT SQLITE_PRIVATE int sqlite3IsNaN(double); #else # define sqlite3IsNaN(X) 0 #endif SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); #ifndef SQLITE_OMIT_TRACE SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); #endif SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...); #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); SQLITE_PRIVATE int sqlite3Dequote(char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int); |
| ︙ | ︙ | |||
10210 10211 10212 10213 10214 10215 10216 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); | < < < < < < < | 10288 10289 10290 10291 10292 10293 10294 10295 10296 10297 10298 10299 10300 10301 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int); #endif |
| ︙ | ︙ | |||
10752 10753 10754 10755 10756 10757 10758 10759 10760 10761 10762 10763 10764 10765 | 0, /* isInit */ 0, /* inProgress */ 0, /* isMutexInit */ 0, /* isMallocInit */ 0, /* isPCacheInit */ 0, /* pInitMutex */ 0, /* nRefInitMutex */ }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. | > > | 10823 10824 10825 10826 10827 10828 10829 10830 10831 10832 10833 10834 10835 10836 10837 10838 | 0, /* isInit */ 0, /* inProgress */ 0, /* isMutexInit */ 0, /* isMallocInit */ 0, /* isPCacheInit */ 0, /* pInitMutex */ 0, /* nRefInitMutex */ 0, /* xLog */ 0, /* pLogArg */ }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. |
| ︙ | ︙ | |||
10876 10877 10878 10879 10880 10881 10882 |
** This implementation assumes that reading or writing an aligned
** 32-bit integer is an atomic operation. If that assumption is not true,
** then this routine is not threadsafe.
*/
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
wsdStatInit;
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
| | | 10949 10950 10951 10952 10953 10954 10955 10956 10957 10958 10959 10960 10961 10962 10963 |
** This implementation assumes that reading or writing an aligned
** 32-bit integer is an atomic operation. If that assumption is not true,
** then this routine is not threadsafe.
*/
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
wsdStatInit;
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
return SQLITE_MISUSE_BKPT;
}
*pCurrent = wsdStat.nowValue[op];
*pHighwater = wsdStat.mxValue[op];
if( resetFlag ){
wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
return SQLITE_OK;
|
| ︙ | ︙ | |||
12005 12006 12007 12008 12009 12010 12011 |
FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
FUNCTION(current_date, 0, 0, 0, cdateFunc ),
#else
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
| | | | 12078 12079 12080 12081 12082 12083 12084 12085 12086 12087 12088 12089 12090 12091 12092 12093 |
FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
FUNCTION(current_date, 0, 0, 0, cdateFunc ),
#else
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
#endif
};
int i;
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
for(i=0; i<ArraySize(aDateTimeFuncs); i++){
|
| ︙ | ︙ | |||
12133 12134 12135 12136 12137 12138 12139 |
const char *zPath,
sqlite3_file *pFile,
int flags,
int *pFlagsOut
){
int rc;
DO_OS_MALLOC_TEST(0);
| | | | 12206 12207 12208 12209 12210 12211 12212 12213 12214 12215 12216 12217 12218 12219 12220 12221 12222 12223 12224 |
const char *zPath,
sqlite3_file *pFile,
int flags,
int *pFlagsOut
){
int rc;
DO_OS_MALLOC_TEST(0);
/* 0x7f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
** reaching the VFS. */
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f3f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return pVfs->xDelete(pVfs, zPath, dirSync);
}
SQLITE_PRIVATE int sqlite3OsAccess(
|
| ︙ | ︙ | |||
12512 12513 12514 12515 12516 12517 12518 12519 12520 12521 12522 12523 12524 12525 12526 12527 12528 12529 12530 12531 12532 12533 12534 12535 12536 12537 12538 12539 12540 12541 12542 12543 12544 12545 12546 12547 12548 12549 12550 12551 |
sqlite3_int64 *p;
assert( nByte>0 );
nByte = ROUND8(nByte);
p = malloc( nByte+8 );
if( p ){
p[0] = nByte;
p++;
}
return (void *)p;
}
/*
** Like free() but works for allocations obtained from sqlite3MemMalloc()
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since
** cases where pPrior==0 will have been intecepted and dealt with
** by higher-level routines.
*/
static void sqlite3MemFree(void *pPrior){
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 );
p--;
free(p);
}
/*
** Like realloc(). Resize an allocation previously obtained from
** sqlite3MemMalloc().
**
** For this low-level interface, we know that pPrior!=0. Cases where
** pPrior==0 while have been intercepted by higher-level routine and
** redirected to xMalloc. Similarly, we know that nByte>0 becauses
** cases where nByte<=0 will have been intercepted by higher-level
** routines and redirected to xFree.
*/
static void *sqlite3MemRealloc(void *pPrior, int nByte){
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 && nByte>0 );
nByte = ROUND8(nByte);
| > > > > > > > > > > > > > > > < > > > > > < < < < < < < < < < < < | 12585 12586 12587 12588 12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600 12601 12602 12603 12604 12605 12606 12607 12608 12609 12610 12611 12612 12613 12614 12615 12616 12617 12618 12619 12620 12621 12622 12623 12624 12625 12626 12627 12628 12629 12630 12631 12632 12633 12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644 12645 12646 12647 12648 12649 12650 12651 12652 12653 12654 12655 12656 12657 12658 12659 12660 |
sqlite3_int64 *p;
assert( nByte>0 );
nByte = ROUND8(nByte);
p = malloc( nByte+8 );
if( p ){
p[0] = nByte;
p++;
}else{
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
}
return (void *)p;
}
/*
** Like free() but works for allocations obtained from sqlite3MemMalloc()
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since
** cases where pPrior==0 will have been intecepted and dealt with
** by higher-level routines.
*/
static void sqlite3MemFree(void *pPrior){
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 );
p--;
free(p);
}
/*
** Report the allocated size of a prior return from xMalloc()
** or xRealloc().
*/
static int sqlite3MemSize(void *pPrior){
sqlite3_int64 *p;
if( pPrior==0 ) return 0;
p = (sqlite3_int64*)pPrior;
p--;
return (int)p[0];
}
/*
** Like realloc(). Resize an allocation previously obtained from
** sqlite3MemMalloc().
**
** For this low-level interface, we know that pPrior!=0. Cases where
** pPrior==0 while have been intercepted by higher-level routine and
** redirected to xMalloc. Similarly, we know that nByte>0 becauses
** cases where nByte<=0 will have been intercepted by higher-level
** routines and redirected to xFree.
*/
static void *sqlite3MemRealloc(void *pPrior, int nByte){
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 && nByte>0 );
nByte = ROUND8(nByte);
p--;
p = realloc(p, nByte+8 );
if( p ){
p[0] = nByte;
p++;
}else{
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM,
"failed memory resize %u to %u bytes",
sqlite3MemSize(pPrior), nByte);
}
return (void*)p;
}
/*
** Round up a request size to the next valid allocation size.
*/
static int sqlite3MemRoundup(int n){
return ROUND8(n);
}
|
| ︙ | ︙ | |||
12823 12824 12825 12826 12827 12828 12829 12830 12831 12832 12833 12834 12835 12836 |
/*
** Round up a request size to the next valid allocation size.
*/
static int sqlite3MemRoundup(int n){
return ROUND8(n);
}
/*
** Allocate nByte bytes of memory.
*/
static void *sqlite3MemMalloc(int nByte){
struct MemBlockHdr *pHdr;
void **pBt;
| > > > > > > > > > > > > > > > > > > > > > > > > > | 12903 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923 12924 12925 12926 12927 12928 12929 12930 12931 12932 12933 12934 12935 12936 12937 12938 12939 12940 12941 |
/*
** Round up a request size to the next valid allocation size.
*/
static int sqlite3MemRoundup(int n){
return ROUND8(n);
}
/*
** Fill a buffer with pseudo-random bytes. This is used to preset
** the content of a new memory allocation to unpredictable values and
** to clear the content of a freed allocation to unpredictable values.
*/
static void randomFill(char *pBuf, int nByte){
unsigned int x, y, r;
x = SQLITE_PTR_TO_INT(pBuf);
y = nByte | 1;
while( nByte >= 4 ){
x = (x>>1) ^ (-(x&1) & 0xd0000001);
y = y*1103515245 + 12345;
r = x ^ y;
*(int*)pBuf = r;
pBuf += 4;
nByte -= 4;
}
while( nByte-- > 0 ){
x = (x>>1) ^ (-(x&1) & 0xd0000001);
y = y*1103515245 + 12345;
r = x ^ y;
*(pBuf++) = r & 0xff;
}
}
/*
** Allocate nByte bytes of memory.
*/
static void *sqlite3MemMalloc(int nByte){
struct MemBlockHdr *pHdr;
void **pBt;
|
| ︙ | ︙ | |||
12874 12875 12876 12877 12878 12879 12880 |
if( mem.nTitle ){
memcpy(z, mem.zTitle, mem.nTitle);
}
pHdr->iSize = nByte;
adjustStats(nByte, +1);
pInt = (int*)&pHdr[1];
pInt[nReserve/sizeof(int)] = REARGUARD;
| > | | 12979 12980 12981 12982 12983 12984 12985 12986 12987 12988 12989 12990 12991 12992 12993 12994 |
if( mem.nTitle ){
memcpy(z, mem.zTitle, mem.nTitle);
}
pHdr->iSize = nByte;
adjustStats(nByte, +1);
pInt = (int*)&pHdr[1];
pInt[nReserve/sizeof(int)] = REARGUARD;
randomFill((char*)pInt, nByte);
memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
p = (void*)pInt;
}
sqlite3_mutex_leave(mem.mutex);
return p;
}
/*
|
| ︙ | ︙ | |||
12910 12911 12912 12913 12914 12915 12916 |
}else{
assert( mem.pLast==pHdr );
mem.pLast = pHdr->pPrev;
}
z = (char*)pBt;
z -= pHdr->nTitle;
adjustStats(pHdr->iSize, -1);
| | | | 13016 13017 13018 13019 13020 13021 13022 13023 13024 13025 13026 13027 13028 13029 13030 13031 |
}else{
assert( mem.pLast==pHdr );
mem.pLast = pHdr->pPrev;
}
z = (char*)pBt;
z -= pHdr->nTitle;
adjustStats(pHdr->iSize, -1);
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
pHdr->iSize + sizeof(int) + pHdr->nTitle);
free(z);
sqlite3_mutex_leave(mem.mutex);
}
/*
** Change the size of an existing memory allocation.
**
|
| ︙ | ︙ | |||
12934 12935 12936 12937 12938 12939 12940 |
void *pNew;
assert( mem.disallow==0 );
pOldHdr = sqlite3MemsysGetHeader(pPrior);
pNew = sqlite3MemMalloc(nByte);
if( pNew ){
memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
if( nByte>pOldHdr->iSize ){
| | | 13040 13041 13042 13043 13044 13045 13046 13047 13048 13049 13050 13051 13052 13053 13054 |
void *pNew;
assert( mem.disallow==0 );
pOldHdr = sqlite3MemsysGetHeader(pPrior);
pNew = sqlite3MemMalloc(nByte);
if( pNew ){
memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
if( nByte>pOldHdr->iSize ){
randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
}
sqlite3MemFree(pPrior);
}
return pNew;
}
/*
|
| ︙ | ︙ | |||
14015 14016 14017 14018 14019 14020 14021 |
for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
/* Make sure mem5.aiFreelist[iLogsize] contains at least one free
** block. If not, then split a block of the next larger power of
** two in order to create a new free block of size iLogsize.
*/
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
| | > > > > | 14121 14122 14123 14124 14125 14126 14127 14128 14129 14130 14131 14132 14133 14134 14135 14136 14137 14138 14139 |
for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
/* Make sure mem5.aiFreelist[iLogsize] contains at least one free
** block. If not, then split a block of the next larger power of
** two in order to create a new free block of size iLogsize.
*/
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
if( iBin>LOGMAX ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
return 0;
}
i = memsys5UnlinkFirst(iBin);
while( iBin>iLogsize ){
int newSize;
iBin--;
newSize = 1 << iBin;
mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
|
| ︙ | ︙ | |||
15292 15293 15294 15295 15296 15297 15298 15299 15300 15301 15302 15303 15304 15305 15306 |
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
int nRef; /* Number of enterances */
DWORD owner; /* Thread holding this mutex */
};
/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
** or WinCE. Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
| > > > > > > > > > | 15402 15403 15404 15405 15406 15407 15408 15409 15410 15411 15412 15413 15414 15415 15416 15417 15418 15419 15420 15421 15422 15423 15424 15425 |
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
int nRef; /* Number of enterances */
DWORD owner; /* Thread holding this mutex */
#ifdef SQLITE_DEBUG
int trace; /* True to trace changes */
#endif
};
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
#ifdef SQLITE_DEBUG
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
#else
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 }
#endif
/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
** or WinCE. Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
|
| ︙ | ︙ | |||
15335 15336 15337 15338 15339 15340 15341 15342 |
#ifdef SQLITE_DEBUG
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use only inside assert() statements.
*/
static int winMutexHeld(sqlite3_mutex *p){
return p->nRef!=0 && p->owner==GetCurrentThreadId();
}
| | | > > > > | > > > > > > > | 15454 15455 15456 15457 15458 15459 15460 15461 15462 15463 15464 15465 15466 15467 15468 15469 15470 15471 15472 15473 15474 15475 15476 15477 15478 15479 15480 15481 15482 15483 15484 15485 15486 15487 15488 15489 |
#ifdef SQLITE_DEBUG
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use only inside assert() statements.
*/
static int winMutexHeld(sqlite3_mutex *p){
return p->nRef!=0 && p->owner==GetCurrentThreadId();
}
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
return p->nRef==0 || p->owner!=tid;
}
static int winMutexNotheld(sqlite3_mutex *p){
DWORD tid = GetCurrentThreadId();
return winMutexNotheld2(p, tid);
}
#endif
/*
** Initialize and deinitialize the mutex subsystem.
*/
static sqlite3_mutex winMutex_staticMutexes[6] = {
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER
};
static int winMutex_isInit = 0;
/* As winMutexInit() and winMutexEnd() are called as part
** of the sqlite3_initialize and sqlite3_shutdown()
** processing, the "interlocked" magic is probably not
** strictly necessary.
*/
static long winMutex_lock = 0;
|
| ︙ | ︙ | |||
15479 15480 15481 15482 15483 15484 15485 |
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
** be entered multiple times by the same thread. In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter. If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
| > | | > > > | > > > | | > > > > > > | > > > > > | 15609 15610 15611 15612 15613 15614 15615 15616 15617 15618 15619 15620 15621 15622 15623 15624 15625 15626 15627 15628 15629 15630 15631 15632 15633 15634 15635 15636 15637 15638 15639 15640 15641 15642 15643 15644 15645 15646 15647 15648 15649 15650 15651 15652 15653 15654 15655 15656 15657 15658 15659 15660 15661 15662 15663 15664 15665 15666 15667 15668 15669 15670 15671 15672 15673 15674 15675 15676 15677 15678 15679 15680 15681 15682 15683 |
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
** be entered multiple times by the same thread. In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter. If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
DWORD tid = GetCurrentThreadId();
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
EnterCriticalSection(&p->mutex);
p->owner = tid;
p->nRef++;
#ifdef SQLITE_DEBUG
if( p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
}
static int winMutexTry(sqlite3_mutex *p){
DWORD tid = GetCurrentThreadId();
int rc = SQLITE_BUSY;
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
/*
** The sqlite3_mutex_try() routine is very rarely used, and when it
** is used it is merely an optimization. So it is OK for it to always
** fail.
**
** The TryEnterCriticalSection() interface is only available on WinNT.
** And some windows compilers complain if you try to use it without
** first doing some #defines that prevent SQLite from building on Win98.
** For that reason, we will omit this optimization for now. See
** ticket #2685.
*/
#if 0
if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
p->owner = tid;
p->nRef++;
rc = SQLITE_OK;
}
#else
UNUSED_PARAMETER(p);
#endif
#ifdef SQLITE_DEBUG
if( rc==SQLITE_OK && p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
return rc;
}
/*
** The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated. SQLite will never do either.
*/
static void winMutexLeave(sqlite3_mutex *p){
DWORD tid = GetCurrentThreadId();
assert( p->nRef>0 );
assert( p->owner==tid );
p->nRef--;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
if( p->trace ){
printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
}
SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
static sqlite3_mutex_methods sMutex = {
winMutexInit,
winMutexEnd,
winMutexAlloc,
|
| ︙ | ︙ | |||
16720 16721 16722 16723 16724 16725 16726 |
}
length = (int)(&buf[etBUFSIZE-1]-bufpt);
break;
case etFLOAT:
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
| | > > | 16868 16869 16870 16871 16872 16873 16874 16875 16876 16877 16878 16879 16880 16881 16882 16883 16884 |
}
length = (int)(&buf[etBUFSIZE-1]-bufpt);
break;
case etFLOAT:
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
#ifdef SQLITE_OMIT_FLOATING_POINT
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
}else{
if( flag_plussign ) prefix = '+';
|
| ︙ | ︙ | |||
16866 16867 16868 16869 16870 16871 16872 |
for(i=width; i>=nPad; i--){
bufpt[i] = bufpt[i-nPad];
}
i = prefix!=0;
while( nPad-- ) bufpt[i++] = '0';
length = width;
}
| | | 17016 17017 17018 17019 17020 17021 17022 17023 17024 17025 17026 17027 17028 17029 17030 |
for(i=width; i>=nPad; i--){
bufpt[i] = bufpt[i-nPad];
}
i = prefix!=0;
while( nPad-- ) bufpt[i++] = '0';
length = width;
}
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
break;
case etSIZE:
*(va_arg(ap,int*)) = pAccum->nChar;
length = width = 0;
break;
case etPERCENT:
buf[0] = '%';
|
| ︙ | ︙ | |||
16913 16914 16915 16916 16917 16918 16919 |
int needQuote;
char ch;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg = va_arg(ap,char*);
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
k = precision;
| | | 17063 17064 17065 17066 17067 17068 17069 17070 17071 17072 17073 17074 17075 17076 17077 |
int needQuote;
char ch;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg = va_arg(ap,char*);
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
k = precision;
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
if( ch==q ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqlite3Malloc( n );
if( bufpt==0 ){
|
| ︙ | ︙ | |||
17196 17197 17198 17199 17200 17201 17202 17203 17204 17205 17206 17207 17208 17209 | acc.useMalloc = 0; va_start(ap,zFormat); sqlite3VXPrintf(&acc, 0, zFormat, ap); va_end(ap); z = sqlite3StrAccumFinish(&acc); return z; } #if defined(SQLITE_DEBUG) /* ** A version of printf() that understands %lld. Used for debugging. ** The printf() built into some versions of windows does not understand %lld ** and segfaults if you give it a long long int. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 17346 17347 17348 17349 17350 17351 17352 17353 17354 17355 17356 17357 17358 17359 17360 17361 17362 17363 17364 17365 17366 17367 17368 17369 17370 17371 17372 17373 17374 17375 17376 17377 17378 17379 17380 17381 17382 17383 17384 17385 17386 17387 17388 17389 17390 17391 |
acc.useMalloc = 0;
va_start(ap,zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
z = sqlite3StrAccumFinish(&acc);
return z;
}
/*
** This is the routine that actually formats the sqlite3_log() message.
** We house it in a separate routine from sqlite3_log() to avoid using
** stack space on small-stack systems when logging is disabled.
**
** sqlite3_log() must render into a static buffer. It cannot dynamically
** allocate memory because it might be called while the memory allocator
** mutex is held.
*/
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
acc.useMalloc = 0;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
sqlite3StrAccumFinish(&acc));
}
/*
** Format and write a message to the log if logging is enabled.
*/
SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
va_list ap; /* Vararg list */
if( sqlite3GlobalConfig.xLog ){
va_start(ap, zFormat);
renderLogMsg(iErrCode, zFormat, ap);
va_end(ap);
}
}
#if defined(SQLITE_DEBUG)
/*
** A version of printf() that understands %lld. Used for debugging.
** The printf() built into some versions of windows does not understand %lld
** and segfaults if you give it a long long int.
*/
|
| ︙ | ︙ | |||
17719 17720 17721 17722 17723 17724 17725 17726 17727 17728 17729 17730 17731 17732 | u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ char *zErrMsg; /* Error message written here */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 expired; /* True if the VM needs to be recompiled */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ u8 usesStmtJournal; /* True if uses a statement journal */ u8 readOnly; /* True for read-only statements */ u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ int btreeMask; /* Bitmask of db->aDb[] entries referenced */ | > | 17901 17902 17903 17904 17905 17906 17907 17908 17909 17910 17911 17912 17913 17914 17915 | u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ char *zErrMsg; /* Error message written here */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 expired; /* True if the VM needs to be recompiled */ u8 runOnlyOnce; /* Automatically expire on reset */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ u8 usesStmtJournal; /* True if uses a statement journal */ u8 readOnly; /* True for read-only statements */ u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ int btreeMask; /* Bitmask of db->aDb[] entries referenced */ |
| ︙ | ︙ | |||
17780 17781 17782 17783 17784 17785 17786 | SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); | > > > | > | 17963 17964 17965 17966 17967 17968 17969 17970 17971 17972 17973 17974 17975 17976 17977 17978 17979 17980 17981 | SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); #ifdef SQLITE_OMIT_FLOATING_POINT # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 #else SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); #endif SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); |
| ︙ | ︙ | |||
18386 18387 18388 18389 18390 18391 18392 18393 18394 18395 18396 18397 18398 18399 |
#ifdef SQLITE_COVERAGE_TEST
SQLITE_PRIVATE void sqlite3Coverage(int x){
static int dummy = 0;
dummy += x;
}
#endif
/*
** Return true if the floating point value is Not a Number (NaN).
**
** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
** Otherwise, we have our own implementation that works on most systems.
*/
SQLITE_PRIVATE int sqlite3IsNaN(double x){
| > | 18573 18574 18575 18576 18577 18578 18579 18580 18581 18582 18583 18584 18585 18586 18587 |
#ifdef SQLITE_COVERAGE_TEST
SQLITE_PRIVATE void sqlite3Coverage(int x){
static int dummy = 0;
dummy += x;
}
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
**
** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
** Otherwise, we have our own implementation that works on most systems.
*/
SQLITE_PRIVATE int sqlite3IsNaN(double x){
|
| ︙ | ︙ | |||
18430 18431 18432 18433 18434 18435 18436 18437 18438 18439 18440 18441 18442 18443 | rc = (y!=z); #else /* if defined(SQLITE_HAVE_ISNAN) */ rc = isnan(x); #endif /* SQLITE_HAVE_ISNAN */ testcase( rc ); return rc; } /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. ** ** The value returned will never be negative. Nor will it ever be greater ** than the actual length of the string. For very long strings (greater | > | 18618 18619 18620 18621 18622 18623 18624 18625 18626 18627 18628 18629 18630 18631 18632 | rc = (y!=z); #else /* if defined(SQLITE_HAVE_ISNAN) */ rc = isnan(x); #endif /* SQLITE_HAVE_ISNAN */ testcase( rc ); return rc; } #endif /* SQLITE_OMIT_FLOATING_POINT */ /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. ** ** The value returned will never be negative. Nor will it ever be greater ** than the actual length of the string. For very long strings (greater |
| ︙ | ︙ | |||
18501 18502 18503 18504 18505 18506 18507 18508 18509 |
** compiling an SQL statement (i.e. within sqlite3_prepare()). The
** last thing the sqlite3_prepare() function does is copy the error
** stored by this function into the database handle using sqlite3Error().
** Function sqlite3Error() should be used during statement execution
** (sqlite3_step() etc.).
*/
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
va_list ap;
sqlite3 *db = pParse->db;
| > < < | > | | | < < < < | | | > | 18690 18691 18692 18693 18694 18695 18696 18697 18698 18699 18700 18701 18702 18703 18704 18705 18706 18707 18708 18709 18710 18711 18712 18713 18714 18715 18716 18717 |
** compiling an SQL statement (i.e. within sqlite3_prepare()). The
** last thing the sqlite3_prepare() function does is copy the error
** stored by this function into the database handle using sqlite3Error().
** Function sqlite3Error() should be used during statement execution
** (sqlite3_step() etc.).
*/
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
char *zMsg;
va_list ap;
sqlite3 *db = pParse->db;
va_start(ap, zFormat);
zMsg = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( db->suppressErr ){
sqlite3DbFree(db, zMsg);
}else{
pParse->nErr++;
sqlite3DbFree(db, pParse->zErrMsg);
pParse->zErrMsg = zMsg;
pParse->rc = SQLITE_ERROR;
}
}
/*
** Convert an SQL-style quoted string into a normal string by removing
** the quote characters. The conversion is done in-place. If the
** input does not begin with a quote character, then this routine
** is a no-op.
|
| ︙ | ︙ | |||
18610 18611 18612 18613 18614 18615 18616 18617 18618 18619 18620 18621 18622 18623 18624 18625 18626 18627 18628 18629 18630 18631 18632 18633 18634 18635 18636 |
if( *z=='-' || *z=='+' ) z += incr;
if( !sqlite3Isdigit(*z) ){
return 0;
}
z += incr;
*realnum = 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
if( *z=='.' ){
z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
*realnum = 1;
}
if( *z=='e' || *z=='E' ){
z += incr;
if( *z=='+' || *z=='-' ) z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
*realnum = 1;
}
return *z==0;
}
/*
** The string z[] is an ASCII representation of a real number.
** Convert this string to a double.
**
| > > | 18796 18797 18798 18799 18800 18801 18802 18803 18804 18805 18806 18807 18808 18809 18810 18811 18812 18813 18814 18815 18816 18817 18818 18819 18820 18821 18822 18823 18824 |
if( *z=='-' || *z=='+' ) z += incr;
if( !sqlite3Isdigit(*z) ){
return 0;
}
z += incr;
*realnum = 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
#ifndef SQLITE_OMIT_FLOATING_POINT
if( *z=='.' ){
z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
*realnum = 1;
}
if( *z=='e' || *z=='E' ){
z += incr;
if( *z=='+' || *z=='-' ) z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
*realnum = 1;
}
#endif
return *z==0;
}
/*
** The string z[] is an ASCII representation of a real number.
** Convert this string to a double.
**
|
| ︙ | ︙ | |||
18784 18785 18786 18787 18788 18789 18790 18791 18792 18793 18794 18795 18796 18797 |
** will return -8.
*/
static int compare2pow63(const char *zNum){
int c;
c = memcmp(zNum,"922337203685477580",18)*10;
if( c==0 ){
c = zNum[18] - '8';
}
return c;
}
/*
** Return TRUE if zNum is a 64-bit signed integer and write
| > > > | 18972 18973 18974 18975 18976 18977 18978 18979 18980 18981 18982 18983 18984 18985 18986 18987 18988 |
** will return -8.
*/
static int compare2pow63(const char *zNum){
int c;
c = memcmp(zNum,"922337203685477580",18)*10;
if( c==0 ){
c = zNum[18] - '8';
testcase( c==(-1) );
testcase( c==0 );
testcase( c==(+1) );
}
return c;
}
/*
** Return TRUE if zNum is a 64-bit signed integer and write
|
| ︙ | ︙ | |||
18820 18821 18822 18823 18824 18825 18826 18827 18828 18829 18830 18831 18832 18833 |
}
zStart = zNum;
while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
v = v*10 + c - '0';
}
*pNum = neg ? -v : v;
if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranting that it is too large) */
return 0;
}else if( i<19 ){
/* Less than 19 digits, so we know that it fits in 64 bits */
return 1;
| > > > | 19011 19012 19013 19014 19015 19016 19017 19018 19019 19020 19021 19022 19023 19024 19025 19026 19027 |
}
zStart = zNum;
while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
v = v*10 + c - '0';
}
*pNum = neg ? -v : v;
testcase( i==18 );
testcase( i==19 );
testcase( i==20 );
if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranting that it is too large) */
return 0;
}else if( i<19 ){
/* Less than 19 digits, so we know that it fits in 64 bits */
return 1;
|
| ︙ | ︙ | |||
18863 18864 18865 18866 18867 18868 18869 18870 18871 18872 18873 18874 18875 18876 |
assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */
if( negFlag ) neg = 1-neg;
while( *zNum=='0' ){
zNum++; /* Skip leading zeros. Ticket #2454 */
}
for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
if( i<19 ){
/* Guaranteed to fit if less than 19 digits */
return 1;
}else if( i>19 ){
/* Guaranteed to be too big if greater than 19 digits */
return 0;
}else{
| > > > | 19057 19058 19059 19060 19061 19062 19063 19064 19065 19066 19067 19068 19069 19070 19071 19072 19073 |
assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */
if( negFlag ) neg = 1-neg;
while( *zNum=='0' ){
zNum++; /* Skip leading zeros. Ticket #2454 */
}
for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
testcase( i==18 );
testcase( i==19 );
testcase( i==20 );
if( i<19 ){
/* Guaranteed to fit if less than 19 digits */
return 1;
}else if( i>19 ){
/* Guaranteed to be too big if greater than 19 digits */
return 0;
}else{
|
| ︙ | ︙ | |||
18903 18904 18905 18906 18907 18908 18909 18910 18911 18912 18913 18914 18915 18916 18917 18918 18919 |
}
/* The longest decimal representation of a 32 bit integer is 10 digits:
**
** 1234567890
** 2^31 -> 2147483648
*/
if( i>10 ){
return 0;
}
if( v-neg>2147483647 ){
return 0;
}
if( neg ){
v = -v;
}
*pValue = (int)v;
| > > | 19100 19101 19102 19103 19104 19105 19106 19107 19108 19109 19110 19111 19112 19113 19114 19115 19116 19117 19118 |
}
/* The longest decimal representation of a 32 bit integer is 10 digits:
**
** 1234567890
** 2^31 -> 2147483648
*/
testcase( i==10 );
if( i>10 ){
return 0;
}
testcase( v-neg==2147483647 );
if( v-neg>2147483647 ){
return 0;
}
if( neg ){
v = -v;
}
*pValue = (int)v;
|
| ︙ | ︙ | |||
18992 18993 18994 18995 18996 18997 18998 18999 19000 19001 19002 19003 19004 19005 |
if( (v & ~0x3fff)==0 ){
p[0] = (u8)((v>>7) | 0x80);
p[1] = (u8)(v & 0x7f);
return 2;
}
return sqlite3PutVarint(p, v);
}
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read. The value is stored in *v.
*/
SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
u32 a,b,s;
| > > > > > > > > > > > > > | 19191 19192 19193 19194 19195 19196 19197 19198 19199 19200 19201 19202 19203 19204 19205 19206 19207 19208 19209 19210 19211 19212 19213 19214 19215 19216 19217 |
if( (v & ~0x3fff)==0 ){
p[0] = (u8)((v>>7) | 0x80);
p[1] = (u8)(v & 0x7f);
return 2;
}
return sqlite3PutVarint(p, v);
}
/*
** Bitmasks used by sqlite3GetVarint(). These precomputed constants
** are defined here rather than simply putting the constant expressions
** inline in order to work around bugs in the RVT compiler.
**
** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
**
** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
*/
#define SLOT_2_0 0x001fc07f
#define SLOT_4_2_0 0xf01fc07f
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read. The value is stored in *v.
*/
SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
u32 a,b,s;
|
| ︙ | ︙ | |||
19020 19021 19022 19023 19024 19025 19026 19027 19028 19029 19030 19031 19032 |
a &= 0x7f;
a = a<<7;
a |= b;
*v = a;
return 2;
}
p++;
a = a<<14;
a |= *p;
/* a: p0<<14 | p2 (unmasked) */
if (!(a&0x80))
{
| > > > > | | | | | 19232 19233 19234 19235 19236 19237 19238 19239 19240 19241 19242 19243 19244 19245 19246 19247 19248 19249 19250 19251 19252 19253 19254 19255 19256 19257 19258 19259 19260 19261 19262 19263 19264 19265 19266 19267 19268 19269 19270 19271 19272 19273 19274 19275 19276 19277 19278 19279 19280 19281 19282 19283 19284 19285 19286 |
a &= 0x7f;
a = a<<7;
a |= b;
*v = a;
return 2;
}
/* Verify that constants are precomputed correctly */
assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
assert( SLOT_4_2_0 == ((0xf<<28) | (0x7f<<14) | (0x7f)) );
p++;
a = a<<14;
a |= *p;
/* a: p0<<14 | p2 (unmasked) */
if (!(a&0x80))
{
a &= SLOT_2_0;
b &= 0x7f;
b = b<<7;
a |= b;
*v = a;
return 3;
}
/* CSE1 from below */
a &= SLOT_2_0;
p++;
b = b<<14;
b |= *p;
/* b: p1<<14 | p3 (unmasked) */
if (!(b&0x80))
{
b &= SLOT_2_0;
/* moved CSE1 up */
/* a &= (0x7f<<14)|(0x7f); */
a = a<<7;
a |= b;
*v = a;
return 4;
}
/* a: p0<<14 | p2 (masked) */
/* b: p1<<14 | p3 (unmasked) */
/* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
/* moved CSE1 up */
/* a &= (0x7f<<14)|(0x7f); */
b &= SLOT_2_0;
s = a;
/* s: p0<<14 | p2 (masked) */
p++;
a = a<<14;
a |= *p;
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
|
| ︙ | ︙ | |||
19089 19090 19091 19092 19093 19094 19095 |
b = b<<14;
b |= *p;
/* b: p1<<28 | p3<<14 | p5 (unmasked) */
if (!(b&0x80))
{
/* we can skip this cause it was (effectively) done above in calc'ing s */
/* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
| | | | | | | | 19305 19306 19307 19308 19309 19310 19311 19312 19313 19314 19315 19316 19317 19318 19319 19320 19321 19322 19323 19324 19325 19326 19327 19328 19329 19330 19331 19332 19333 19334 19335 19336 19337 19338 19339 19340 19341 19342 19343 19344 19345 19346 19347 19348 19349 19350 19351 19352 19353 19354 19355 19356 19357 19358 19359 19360 19361 19362 19363 19364 19365 19366 19367 |
b = b<<14;
b |= *p;
/* b: p1<<28 | p3<<14 | p5 (unmasked) */
if (!(b&0x80))
{
/* we can skip this cause it was (effectively) done above in calc'ing s */
/* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
a &= SLOT_2_0;
a = a<<7;
a |= b;
s = s>>18;
*v = ((u64)s)<<32 | a;
return 6;
}
p++;
a = a<<14;
a |= *p;
/* a: p2<<28 | p4<<14 | p6 (unmasked) */
if (!(a&0x80))
{
a &= SLOT_4_2_0;
b &= SLOT_2_0;
b = b<<7;
a |= b;
s = s>>11;
*v = ((u64)s)<<32 | a;
return 7;
}
/* CSE2 from below */
a &= SLOT_2_0;
p++;
b = b<<14;
b |= *p;
/* b: p3<<28 | p5<<14 | p7 (unmasked) */
if (!(b&0x80))
{
b &= SLOT_4_2_0;
/* moved CSE2 up */
/* a &= (0x7f<<14)|(0x7f); */
a = a<<7;
a |= b;
s = s>>4;
*v = ((u64)s)<<32 | a;
return 8;
}
p++;
a = a<<15;
a |= *p;
/* a: p4<<29 | p6<<15 | p8 (unmasked) */
/* moved CSE2 up */
/* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
b &= SLOT_2_0;
b = b<<8;
a |= b;
s = s<<4;
b = p[-4];
b &= 0x7f;
b = b>>3;
|
| ︙ | ︙ | |||
19257 19258 19259 19260 19261 19262 19263 |
p++;
a = a<<14;
a |= *p;
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
if (!(a&0x80))
{
| | | | | 19473 19474 19475 19476 19477 19478 19479 19480 19481 19482 19483 19484 19485 19486 19487 19488 19489 |
p++;
a = a<<14;
a |= *p;
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
if (!(a&0x80))
{
/* Values between 268435456 and 34359738367 */
a &= SLOT_4_2_0;
b &= SLOT_4_2_0;
b = b<<7;
*v = a | b;
return 5;
}
/* We can only reach this point when reading a corrupt database
** file. In that case we are not in any hurry. Use the (relatively
|
| ︙ | ︙ | |||
19352 19353 19354 19355 19356 19357 19358 |
}
zBlob[i/2] = 0;
}
return zBlob;
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
| < < | < < < | < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < < < < < | < > > | < < | > > > | < < > > | < > | > > > > | > | 19568 19569 19570 19571 19572 19573 19574 19575 19576 19577 19578 19579 19580 19581 19582 19583 19584 19585 19586 19587 19588 19589 19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 19601 19602 19603 19604 19605 19606 19607 19608 19609 19610 19611 19612 19613 19614 19615 19616 19617 19618 19619 19620 19621 19622 19623 19624 19625 19626 19627 19628 19629 19630 19631 19632 19633 19634 19635 19636 |
}
zBlob[i/2] = 0;
}
return zBlob;
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
/*
** Log an error that is an API call on a connection pointer that should
** not have been used. The "type" of connection pointer is given as the
** argument. The zType is a word like "NULL" or "closed" or "invalid".
*/
static void logBadConnection(const char *zType){
sqlite3_log(SQLITE_MISUSE,
"API call with %s database connection pointer",
zType
);
}
/*
** Check to make sure we have a valid db pointer. This test is not
** foolproof but it does provide some measure of protection against
** misuse of the interface such as passing in db pointers that are
** NULL or which have been previously closed. If this routine returns
** 1 it means that the db pointer is valid and 0 if it should not be
** dereferenced for any reason. The calling function should invoke
** SQLITE_MISUSE immediately.
**
** sqlite3SafetyCheckOk() requires that the db pointer be valid for
** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
** open properly and is not fit for general use but which can be
** used as an argument to sqlite3_errmsg() or sqlite3_close().
*/
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
u32 magic;
if( db==0 ){
logBadConnection("NULL");
return 0;
}
magic = db->magic;
if( magic!=SQLITE_MAGIC_OPEN ){
if( sqlite3SafetyCheckSickOrOk(db) ){
testcase( sqlite3GlobalConfig.xLog!=0 );
logBadConnection("unopened");
}
return 0;
}else{
return 1;
}
}
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
u32 magic;
magic = db->magic;
if( magic!=SQLITE_MAGIC_SICK &&
magic!=SQLITE_MAGIC_OPEN &&
magic!=SQLITE_MAGIC_BUSY ){
testcase( sqlite3GlobalConfig.xLog!=0 );
logBadConnection("invalid");
return 0;
}else{
return 1;
}
}
/************** End of util.c ************************************************/
/************** Begin file hash.c ********************************************/
/*
** 2001 September 22
**
|
| ︙ | ︙ | |||
21363 21364 21365 21366 21367 21368 21369 21370 21371 21372 21373 21374 21375 21376 | # else # include <sys/file.h> # include <sys/param.h> # include <sys/mount.h> # endif #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* ** If we are to be thread-safe, include the pthreads header and define ** the SQLITE_UNIX_THREADS macro. */ #if SQLITE_THREADSAFE # define SQLITE_UNIX_THREADS 1 #endif | > > > > > | 21540 21541 21542 21543 21544 21545 21546 21547 21548 21549 21550 21551 21552 21553 21554 21555 21556 21557 21558 | # else # include <sys/file.h> # include <sys/param.h> # include <sys/mount.h> # endif #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* ** Allowed values of unixFile.fsFlags */ #define SQLITE_FSFLAGS_IS_MSDOS 0x1 /* ** If we are to be thread-safe, include the pthreads header and define ** the SQLITE_UNIX_THREADS macro. */ #if SQLITE_THREADSAFE # define SQLITE_UNIX_THREADS 1 #endif |
| ︙ | ︙ | |||
21429 21430 21431 21432 21433 21434 21435 21436 21437 21438 21439 21440 21441 21442 | int lastErrno; /* The unix errno from the last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ int fileFlags; /* Miscellanous flags */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_THREADSAFE && defined(__linux__) pthread_t tid; /* The thread that "owns" this unixFile */ #endif #if OS_VXWORKS int isDelete; /* Delete on close if true */ struct vxworksFileId *pId; /* Unique file ID */ #endif | > > > | 21611 21612 21613 21614 21615 21616 21617 21618 21619 21620 21621 21622 21623 21624 21625 21626 21627 | int lastErrno; /* The unix errno from the last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ int fileFlags; /* Miscellanous flags */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if SQLITE_THREADSAFE && defined(__linux__) pthread_t tid; /* The thread that "owns" this unixFile */ #endif #if OS_VXWORKS int isDelete; /* Delete on close if true */ struct vxworksFileId *pId; /* Unique file ID */ #endif |
| ︙ | ︙ | |||
22196 22197 22198 22199 22200 22201 22202 22203 22204 22205 22206 22207 22208 22209 |
** object keeps a count of the number of unixFile pointing to it.
*/
struct unixLockInfo {
struct unixLockKey lockKey; /* The lookup key */
int cnt; /* Number of SHARED locks held */
int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
int nRef; /* Number of pointers to this structure */
struct unixLockInfo *pNext; /* List of all unixLockInfo objects */
struct unixLockInfo *pPrev; /* .... doubly linked */
};
/*
** An instance of the following structure is allocated for each open
** inode. This structure keeps track of the number of locks on that
| > > > | 22381 22382 22383 22384 22385 22386 22387 22388 22389 22390 22391 22392 22393 22394 22395 22396 22397 |
** object keeps a count of the number of unixFile pointing to it.
*/
struct unixLockInfo {
struct unixLockKey lockKey; /* The lookup key */
int cnt; /* Number of SHARED locks held */
int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
int nRef; /* Number of pointers to this structure */
#if defined(SQLITE_ENABLE_LOCKING_STYLE)
unsigned long long sharedByte; /* for AFP simulated shared lock */
#endif
struct unixLockInfo *pNext; /* List of all unixLockInfo objects */
struct unixLockInfo *pPrev; /* .... doubly linked */
};
/*
** An instance of the following structure is allocated for each open
** inode. This structure keeps track of the number of locks on that
|
| ︙ | ︙ | |||
22439 22440 22441 22442 22443 22444 22445 | ** we always increase the file size to 1 by writing a single byte ** prior to accessing the inode number. The one byte written is ** an ASCII 'S' character which also happens to be the first byte ** in the header of every SQLite database. In this way, if there ** is a race condition such that another thread has already populated ** the first page of the database, no damage is done. */ | | > | 22627 22628 22629 22630 22631 22632 22633 22634 22635 22636 22637 22638 22639 22640 22641 22642 22643 22644 |
** we always increase the file size to 1 by writing a single byte
** prior to accessing the inode number. The one byte written is
** an ASCII 'S' character which also happens to be the first byte
** in the header of every SQLite database. In this way, if there
** is a race condition such that another thread has already populated
** the first page of the database, no damage is done.
*/
if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
rc = write(fd, "S", 1);
if( rc!=1 ){
pFile->lastErrno = errno;
return SQLITE_IOERR;
}
rc = fstat(fd, &statbuf);
if( rc!=0 ){
pFile->lastErrno = errno;
return SQLITE_IOERR;
}
|
| ︙ | ︙ | |||
22481 22482 22483 22484 22485 22486 22487 22488 22489 22490 22491 22492 22493 22494 |
rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey));
pLock->nRef = 1;
pLock->cnt = 0;
pLock->locktype = 0;
pLock->pNext = lockList;
pLock->pPrev = 0;
if( lockList ) lockList->pPrev = pLock;
lockList = pLock;
}else{
pLock->nRef++;
}
| > > > | 22670 22671 22672 22673 22674 22675 22676 22677 22678 22679 22680 22681 22682 22683 22684 22685 22686 |
rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey));
pLock->nRef = 1;
pLock->cnt = 0;
pLock->locktype = 0;
#if defined(SQLITE_ENABLE_LOCKING_STYLE)
pLock->sharedByte = 0;
#endif
pLock->pNext = lockList;
pLock->pPrev = 0;
if( lockList ) lockList->pPrev = pLock;
lockList = pLock;
}else{
pLock->nRef++;
}
|
| ︙ | ︙ | |||
22545 22546 22547 22548 22549 22550 22551 |
if( pthread_equal(pFile->tid, hSelf) ){
/* We are still in the same thread */
OSTRACE1("No-transfer, same thread\n");
return SQLITE_OK;
}
if( pFile->locktype!=NO_LOCK ){
/* We cannot change ownership while we are holding a lock! */
| | | 22737 22738 22739 22740 22741 22742 22743 22744 22745 22746 22747 22748 22749 22750 22751 |
if( pthread_equal(pFile->tid, hSelf) ){
/* We are still in the same thread */
OSTRACE1("No-transfer, same thread\n");
return SQLITE_OK;
}
if( pFile->locktype!=NO_LOCK ){
/* We cannot change ownership while we are holding a lock! */
return SQLITE_MISUSE_BKPT;
}
OSTRACE4("Transfer ownership of %d from %d to %d\n",
pFile->h, pFile->tid, hSelf);
pFile->tid = hSelf;
if (pFile->pLock != NULL) {
releaseLockInfo(pFile->pLock);
rc = findLockInfo(pFile, &pFile->pLock, 0);
|
| ︙ | ︙ | |||
22611 22612 22613 22614 22615 22616 22617 |
}
#endif
unixLeaveMutex();
OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved);
*pResOut = reserved;
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 22803 22804 22805 22806 22807 22808 22809 22810 22811 22812 22813 22814 22815 22816 |
}
#endif
unixLeaveMutex();
OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
|
| ︙ | ︙ | |||
22738 22739 22740 22741 22742 22743 22744 | ** even if the locking primitive used is always a write-lock. */ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; struct unixLockInfo *pLock = pFile->pLock; struct flock lock; int s = 0; | | | 22874 22875 22876 22877 22878 22879 22880 22881 22882 22883 22884 22885 22886 22887 22888 |
** even if the locking primitive used is always a write-lock.
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
struct unixLockInfo *pLock = pFile->pLock;
struct flock lock;
int s = 0;
int tErrno = 0;
assert( pFile );
OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
locktypeName(locktype), locktypeName(pFile->locktype),
locktypeName(pLock->locktype), pLock->cnt , getpid());
/* If there is already a lock of this type or more restrictive on the
|
| ︙ | ︙ | |||
22834 22835 22836 22837 22838 22839 22840 |
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
assert( pLock->cnt==0 );
assert( pLock->locktype==0 );
/* Now get the read-lock */
| > > > | | | 22970 22971 22972 22973 22974 22975 22976 22977 22978 22979 22980 22981 22982 22983 22984 22985 22986 22987 22988 |
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
assert( pLock->cnt==0 );
assert( pLock->locktype==0 );
/* Now get the read-lock */
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
tErrno = errno;
}
/* Drop the temporary PENDING lock */
lock.l_start = PENDING_BYTE;
lock.l_len = 1L;
lock.l_type = F_UNLCK;
if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
if( s != -1 ){
/* This could happen with a network mount */
|
| ︙ | ︙ | |||
22875 22876 22877 22878 22879 22880 22881 |
** already.
*/
assert( 0!=pFile->locktype );
lock.l_type = F_WRLCK;
switch( locktype ){
case RESERVED_LOCK:
lock.l_start = RESERVED_BYTE;
| < < < > > > > | 23014 23015 23016 23017 23018 23019 23020 23021 23022 23023 23024 23025 23026 23027 23028 23029 23030 23031 23032 23033 23034 23035 23036 23037 23038 |
** already.
*/
assert( 0!=pFile->locktype );
lock.l_type = F_WRLCK;
switch( locktype ){
case RESERVED_LOCK:
lock.l_start = RESERVED_BYTE;
break;
case EXCLUSIVE_LOCK:
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
break;
default:
assert(0);
}
s = fcntl(pFile->h, F_SETLK, &lock);
if( s==(-1) ){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
}
}
|
| ︙ | ︙ | |||
22974 22975 22976 22977 22978 22979 22980 22981 | /* ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ | > > > > > > | | | | | | | | 23114 23115 23116 23117 23118 23119 23120 23121 23122 23123 23124 23125 23126 23127 23128 23129 23130 23131 23132 23133 23134 23135 23136 23137 23138 23139 23140 23141 23142 23143 23144 23145 23146 23147 23148 23149 23150 23151 23152 |
/*
** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
**
** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
** the byte range is divided into 2 parts and the first part is unlocked then
** set to a read lock, then the other part is simply unlocked. This works
** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
** remove the write lock on a region when a read lock is set.
*/
static int _posixUnlock(sqlite3_file *id, int locktype, int handleNFSUnlock){
unixFile *pFile = (unixFile*)id;
struct unixLockInfo *pLock;
struct flock lock;
int rc = SQLITE_OK;
int h;
int tErrno; /* Error code from system call errors */
assert( pFile );
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype,
pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
assert( locktype<=SHARED_LOCK );
if( pFile->locktype<=locktype ){
return SQLITE_OK;
}
if( CHECK_THREADID(pFile) ){
return SQLITE_MISUSE_BKPT;
}
unixEnterMutex();
h = pFile->h;
pLock = pFile->pLock;
assert( pLock->cnt!=0 );
if( pFile->locktype>SHARED_LOCK ){
assert( pLock->locktype==pFile->locktype );
|
| ︙ | ︙ | |||
23019 23020 23021 23022 23023 23024 23025 |
*/
assert( pFile->inNormalWrite==0
|| pFile->dbUpdate==0
|| pFile->transCntrChng==1 );
pFile->inNormalWrite = 0;
#endif
| | > > > > > > > > > > | > > > > > > > > > > > > > > > > > > | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > | 23165 23166 23167 23168 23169 23170 23171 23172 23173 23174 23175 23176 23177 23178 23179 23180 23181 23182 23183 23184 23185 23186 23187 23188 23189 23190 23191 23192 23193 23194 23195 23196 23197 23198 23199 23200 23201 23202 23203 23204 23205 23206 23207 23208 23209 23210 23211 23212 23213 23214 23215 23216 23217 23218 23219 23220 23221 23222 23223 23224 23225 23226 23227 23228 23229 23230 23231 23232 23233 23234 23235 23236 23237 23238 23239 23240 |
*/
assert( pFile->inNormalWrite==0
|| pFile->dbUpdate==0
|| pFile->transCntrChng==1 );
pFile->inNormalWrite = 0;
#endif
/* downgrading to a shared lock on NFS involves clearing the write lock
** before establishing the readlock - to avoid a race condition we downgrade
** the lock in 2 blocks, so that part of the range will be covered by a
** write lock until the rest is covered by a read lock:
** 1: [WWWWW]
** 2: [....W]
** 3: [RRRRW]
** 4: [RRRR.]
*/
if( locktype==SHARED_LOCK ){
if( handleNFSUnlock ){
off_t divSize = SHARED_SIZE - 1;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = divSize;
if( fcntl(h, F_SETLK, &lock)==(-1) ){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
goto end_unlock;
}
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = divSize;
if( fcntl(h, F_SETLK, &lock)==(-1) ){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
goto end_unlock;
}
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST+divSize;
lock.l_len = SHARED_SIZE-divSize;
if( fcntl(h, F_SETLK, &lock)==(-1) ){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
goto end_unlock;
}
}else{
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
if( fcntl(h, F_SETLK, &lock)==(-1) ){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
goto end_unlock;
}
}
}
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
if( fcntl(h, F_SETLK, &lock)!=(-1) ){
|
| ︙ | ︙ | |||
23092 23093 23094 23095 23096 23097 23098 23099 23100 23101 23102 23103 23104 23105 | } end_unlock: unixLeaveMutex(); if( rc==SQLITE_OK ) pFile->locktype = locktype; return rc; } /* ** This function performs the parts of the "close file" operation ** common to all locking schemes. It closes the directory and file ** handles, if they are valid, and sets all fields of the unixFile ** structure to 0. ** | > > > > > > > > > > > | 23292 23293 23294 23295 23296 23297 23298 23299 23300 23301 23302 23303 23304 23305 23306 23307 23308 23309 23310 23311 23312 23313 23314 23315 23316 |
}
end_unlock:
unixLeaveMutex();
if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
}
/*
** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int unixUnlock(sqlite3_file *id, int locktype){
return _posixUnlock(id, locktype, 0);
}
/*
** This function performs the parts of the "close file" operation
** common to all locking schemes. It closes the directory and file
** handles, if they are valid, and sets all fields of the unixFile
** structure to 0.
**
|
| ︙ | ︙ | |||
23804 23805 23806 23807 23808 23809 23810 |
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** The afpLockingContext structure contains all afp lock specific state
*/
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
| | | 24015 24016 24017 24018 24019 24020 24021 24022 24023 24024 24025 24026 24027 24028 24029 |
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** The afpLockingContext structure contains all afp lock specific state
*/
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
int reserved;
const char *dbPath; /* Name of the open file */
};
struct ByteRangeLockPB2
{
unsigned long long offset; /* offset to first byte to lock */
unsigned long long length; /* nbr of bytes to lock */
|
| ︙ | ︙ | |||
23881 23882 23883 23884 23885 23886 23887 | int reserved = 0; unixFile *pFile = (unixFile*)id; SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); assert( pFile ); afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; | > > > | > > | | 24092 24093 24094 24095 24096 24097 24098 24099 24100 24101 24102 24103 24104 24105 24106 24107 24108 24109 24110 24111 24112 24113 |
int reserved = 0;
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
if( context->reserved ){
*pResOut = 1;
return SQLITE_OK;
}
unixEnterMutex(); /* Because pFile->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
if( pFile->pLock->locktype>SHARED_LOCK ){
reserved = 1;
}
/* Otherwise see if some other process holds it.
*/
if( !reserved ){
/* lock the RESERVED byte */
|
| ︙ | ︙ | |||
23905 23906 23907 23908 23909 23910 23911 23912 23913 23914 23915 23916 23917 23918 |
reserved = 1;
}
if( IS_LOCK_ERROR(lrc) ){
rc=lrc;
}
}
OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
| > | 24121 24122 24123 24124 24125 24126 24127 24128 24129 24130 24131 24132 24133 24134 24135 |
reserved = 1;
}
if( IS_LOCK_ERROR(lrc) ){
rc=lrc;
}
}
unixLeaveMutex();
OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
|
| ︙ | ︙ | |||
23938 23939 23940 23941 23942 23943 23944 23945 23946 23947 |
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
static int afpLock(sqlite3_file *id, int locktype){
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
assert( pFile );
| > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 24155 24156 24157 24158 24159 24160 24161 24162 24163 24164 24165 24166 24167 24168 24169 24170 24171 24172 24173 24174 24175 24176 24177 24178 24179 24180 24181 24182 24183 24184 24185 24186 24187 24188 24189 24190 24191 24192 24193 24194 24195 24196 24197 24198 24199 24200 24201 24202 24203 24204 24205 24206 24207 24208 24209 24210 24211 24212 24213 24214 24215 24216 24217 24218 24219 24220 24221 24222 24223 24224 24225 24226 24227 24228 24229 24230 24231 |
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
static int afpLock(sqlite3_file *id, int locktype){
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
struct unixLockInfo *pLock = pFile->pLock;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
assert( pFile );
OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
locktypeName(locktype), locktypeName(pFile->locktype),
locktypeName(pLock->locktype), pLock->cnt , getpid());
/* If there is already a lock of this type or more restrictive on the
** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
** unixEnterMutex() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
OSTRACE3("LOCK %d %s ok (already held) (afp)\n", pFile->h,
locktypeName(locktype));
return SQLITE_OK;
}
/* Make sure the locking sequence is correct
** (1) We never move from unlocked to anything higher than shared lock.
** (2) SQLite never explicitly requests a pendig lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
/* This mutex is needed because pFile->pLock is shared across threads
*/
unixEnterMutex();
/* Make sure the current thread owns the pFile.
*/
rc = transferOwnership(pFile);
if( rc!=SQLITE_OK ){
unixLeaveMutex();
return rc;
}
pLock = pFile->pLock;
/* If some thread using this PID has a lock via a different unixFile*
** handle that precludes the requested lock, return BUSY.
*/
if( (pFile->locktype!=pLock->locktype &&
(pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK))
){
rc = SQLITE_BUSY;
goto afp_end_lock;
}
/* If a SHARED lock is requested, and some thread using this PID already
** has a SHARED or RESERVED lock, then increment reference counts and
** return SQLITE_OK.
*/
if( locktype==SHARED_LOCK &&
(pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){
assert( locktype==SHARED_LOCK );
assert( pFile->locktype==0 );
assert( pLock->cnt>0 );
pFile->locktype = SHARED_LOCK;
pLock->cnt++;
pFile->pOpen->nLock++;
goto afp_end_lock;
}
/* A PENDING lock is needed before acquiring a SHARED lock and before
** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
** be released.
*/
if( locktype==SHARED_LOCK
|
| ︙ | ︙ | |||
23991 23992 23993 23994 23995 23996 23997 |
}
}
/* If control gets to this point, then actually go ahead and make
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
| | > | > > | > | | > > > > > > > > | | > > > | > > > > | | | > > > > > > > > > > > > > > > > > > > > > | | | | > > | | | > > | > > > > > | | > > > > | > > > > > > | | > > > | > | < > > | < < > > | | > > > > > > > > > > > > > > > > > > > > > > > | 24239 24240 24241 24242 24243 24244 24245 24246 24247 24248 24249 24250 24251 24252 24253 24254 24255 24256 24257 24258 24259 24260 24261 24262 24263 24264 24265 24266 24267 24268 24269 24270 24271 24272 24273 24274 24275 24276 24277 24278 24279 24280 24281 24282 24283 24284 24285 24286 24287 24288 24289 24290 24291 24292 24293 24294 24295 24296 24297 24298 24299 24300 24301 24302 24303 24304 24305 24306 24307 24308 24309 24310 24311 24312 24313 24314 24315 24316 24317 24318 24319 24320 24321 24322 24323 24324 24325 24326 24327 24328 24329 24330 24331 24332 24333 24334 24335 24336 24337 24338 24339 24340 24341 24342 24343 24344 24345 24346 24347 24348 24349 24350 24351 24352 24353 24354 24355 24356 24357 24358 24359 24360 24361 24362 24363 24364 24365 24366 24367 24368 24369 24370 24371 24372 24373 24374 24375 24376 24377 24378 24379 24380 24381 24382 24383 24384 24385 24386 24387 24388 24389 24390 24391 24392 24393 24394 24395 24396 24397 24398 24399 24400 24401 24402 24403 24404 24405 24406 24407 24408 24409 24410 24411 24412 24413 24414 24415 24416 24417 24418 24419 24420 24421 24422 24423 24424 24425 24426 24427 24428 24429 24430 24431 24432 24433 24434 24435 24436 24437 24438 24439 24440 24441 24442 24443 24444 24445 24446 24447 24448 24449 24450 24451 24452 24453 24454 24455 24456 24457 24458 24459 24460 24461 24462 24463 24464 24465 24466 24467 24468 24469 24470 24471 24472 24473 24474 24475 24476 24477 24478 24479 24480 24481 24482 24483 24484 24485 24486 24487 24488 24489 24490 24491 24492 24493 24494 24495 24496 24497 24498 24499 24500 24501 24502 24503 24504 24505 24506 24507 24508 24509 24510 24511 24512 24513 24514 24515 24516 24517 24518 |
}
}
/* If control gets to this point, then actually go ahead and make
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
int lrc1, lrc2, lrc1Errno;
long lk, mask;
assert( pLock->cnt==0 );
assert( pLock->locktype==0 );
mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
/* Now get the read-lock SHARED_LOCK */
/* note that the quality of the randomness doesn't matter that much */
lk = random();
pLock->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
lrc1 = afpSetLock(context->dbPath, pFile,
SHARED_FIRST+pLock->sharedByte, 1, 1);
if( IS_LOCK_ERROR(lrc1) ){
lrc1Errno = pFile->lastErrno;
}
/* Drop the temporary PENDING lock */
lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
if( IS_LOCK_ERROR(lrc1) ) {
pFile->lastErrno = lrc1Errno;
rc = lrc1;
goto afp_end_lock;
} else if( IS_LOCK_ERROR(lrc2) ){
rc = lrc2;
goto afp_end_lock;
} else if( lrc1 != SQLITE_OK ) {
rc = lrc1;
} else {
pFile->locktype = SHARED_LOCK;
pFile->pOpen->nLock++;
pLock->cnt = 1;
}
}else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
}else{
/* The request was for a RESERVED or EXCLUSIVE lock. It is
** assumed that there is a SHARED or greater lock on the file
** already.
*/
int failed = 0;
assert( 0!=pFile->locktype );
if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
/* Acquire a RESERVED lock */
failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
if( !failed ){
context->reserved = 1;
}
}
if (!failed && locktype == EXCLUSIVE_LOCK) {
/* Acquire an EXCLUSIVE lock */
/* Remove the shared lock before trying the range. we'll need to
** reestablish the shared lock if we can't get the afpUnlock
*/
if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
pLock->sharedByte, 1, 0)) ){
int failed2 = SQLITE_OK;
/* now attemmpt to get the exclusive lock range */
failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
SHARED_SIZE, 1);
if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
SHARED_FIRST + pLock->sharedByte, 1, 1)) ){
/* Can't reestablish the shared lock. Sqlite can't deal, this is
** a critical I/O error
*/
rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
SQLITE_IOERR_LOCK;
goto afp_end_lock;
}
}else{
rc = failed;
}
}
if( failed ){
rc = failed;
}
}
if( rc==SQLITE_OK ){
pFile->locktype = locktype;
pLock->locktype = locktype;
}else if( locktype==EXCLUSIVE_LOCK ){
pFile->locktype = PENDING_LOCK;
pLock->locktype = PENDING_LOCK;
}
afp_end_lock:
unixLeaveMutex();
OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype),
rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
/*
** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int afpUnlock(sqlite3_file *id, int locktype) {
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
struct unixLockInfo *pLock;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
int skipShared = 0;
#ifdef SQLITE_TEST
int h = pFile->h;
#endif
assert( pFile );
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, locktype,
pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
assert( locktype<=SHARED_LOCK );
if( pFile->locktype<=locktype ){
return SQLITE_OK;
}
if( CHECK_THREADID(pFile) ){
return SQLITE_MISUSE_BKPT;
}
unixEnterMutex();
pLock = pFile->pLock;
assert( pLock->cnt!=0 );
if( pFile->locktype>SHARED_LOCK ){
assert( pLock->locktype==pFile->locktype );
SimulateIOErrorBenign(1);
SimulateIOError( h=(-1) )
SimulateIOErrorBenign(0);
#ifndef NDEBUG
/* When reducing a lock such that other processes can start
** reading the database file again, make sure that the
** transaction counter was updated if any part of the database
** file changed. If the transaction counter is not updated,
** other connections to the same file might not realize that
** the file has changed and hence might not know to flush their
** cache. The use of a stale cache can lead to database corruption.
*/
assert( pFile->inNormalWrite==0
|| pFile->dbUpdate==0
|| pFile->transCntrChng==1 );
pFile->inNormalWrite = 0;
#endif
if( pFile->locktype==EXCLUSIVE_LOCK ){
rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1) ){
/* only re-establish the shared lock if necessary */
int sharedLockByte = SHARED_FIRST+pLock->sharedByte;
rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
} else {
skipShared = 1;
}
}
if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){
rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
}
if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK && context->reserved ){
rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
if( !rc ){
context->reserved = 0;
}
}
if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1)){
pLock->locktype = SHARED_LOCK;
}
}
if( rc==SQLITE_OK && locktype==NO_LOCK ){
/* Decrement the shared lock counter. Release the lock using an
** OS call only when all threads in this same process have released
** the lock.
*/
unsigned long long sharedLockByte = SHARED_FIRST+pLock->sharedByte;
pLock->cnt--;
if( pLock->cnt==0 ){
SimulateIOErrorBenign(1);
SimulateIOError( h=(-1) )
SimulateIOErrorBenign(0);
if( !skipShared ){
rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
}
if( !rc ){
pLock->locktype = NO_LOCK;
pFile->locktype = NO_LOCK;
}
}
if( rc==SQLITE_OK ){
struct unixOpenCnt *pOpen = pFile->pOpen;
pOpen->nLock--;
assert( pOpen->nLock>=0 );
if( pOpen->nLock==0 ){
rc = closePendingFds(pFile);
}
}
}
unixLeaveMutex();
if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
}
/*
** Close a file & cleanup AFP specific locking context
*/
static int afpClose(sqlite3_file *id) {
int rc = SQLITE_OK;
if( id ){
unixFile *pFile = (unixFile*)id;
afpUnlock(id, NO_LOCK);
unixEnterMutex();
if( pFile->pOpen && pFile->pOpen->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
** descriptor to pOpen->aPending. It will be automatically closed when
** the last lock is cleared.
*/
setPendingFd(pFile);
}
releaseLockInfo(pFile->pLock);
releaseOpenCnt(pFile->pOpen);
sqlite3_free(pFile->lockingContext);
rc = closeUnixFile(id);
unixLeaveMutex();
}
return rc;
}
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
/*
** The code above is the AFP lock implementation. The code is specific
** to MacOSX and does not work on other unix platforms. No alternative
** is available. If you don't compile for a mac, then the "unix-afp"
** VFS is not available.
**
********************* End of the AFP lock implementation **********************
******************************************************************************/
/******************************************************************************
*************************** Begin NFS Locking ********************************/
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int nfsUnlock(sqlite3_file *id, int locktype){
return _posixUnlock(id, locktype, 1);
}
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
/*
** The code above is the NFS lock implementation. The code is specific
** to MacOSX and does not work on other unix platforms. No alternative
** is available.
**
********************* End of the NFS lock implementation **********************
******************************************************************************/
/******************************************************************************
**************** Non-locking sqlite3_file methods *****************************
**
** The next division contains implementations for all methods of the
** sqlite3_file object other than the locking methods. The locking
** methods were defined in divisions above (one locking method per
|
| ︙ | ︙ | |||
24196 24197 24198 24199 24200 24201 24202 24203 24204 24205 24206 24207 24208 24209 24210 |
** See tickets #2741 and #2681.
**
** To avoid stomping the errno value on a failed read the lastErrno value
** is set before returning.
*/
static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
int got;
i64 newOffset;
TIMER_START;
#if defined(USE_PREAD)
got = pread(id->h, pBuf, cnt, offset);
SimulateIOError( got = -1 );
#elif defined(USE_PREAD64)
got = pread64(id->h, pBuf, cnt, offset);
SimulateIOError( got = -1 );
| > > | 24531 24532 24533 24534 24535 24536 24537 24538 24539 24540 24541 24542 24543 24544 24545 24546 24547 |
** See tickets #2741 and #2681.
**
** To avoid stomping the errno value on a failed read the lastErrno value
** is set before returning.
*/
static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
int got;
#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
i64 newOffset;
#endif
TIMER_START;
#if defined(USE_PREAD)
got = pread(id->h, pBuf, cnt, offset);
SimulateIOError( got = -1 );
#elif defined(USE_PREAD64)
got = pread64(id->h, pBuf, cnt, offset);
SimulateIOError( got = -1 );
|
| ︙ | ︙ | |||
24270 24271 24272 24273 24274 24275 24276 24277 24278 24279 24280 24281 24282 24283 24284 |
** Return the number of bytes actually read. Update the offset.
**
** To avoid stomping the errno value on a failed write the lastErrno value
** is set before returning.
*/
static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
int got;
i64 newOffset;
TIMER_START;
#if defined(USE_PREAD)
got = pwrite(id->h, pBuf, cnt, offset);
#elif defined(USE_PREAD64)
got = pwrite64(id->h, pBuf, cnt, offset);
#else
newOffset = lseek(id->h, offset, SEEK_SET);
| > > | 24607 24608 24609 24610 24611 24612 24613 24614 24615 24616 24617 24618 24619 24620 24621 24622 24623 |
** Return the number of bytes actually read. Update the offset.
**
** To avoid stomping the errno value on a failed write the lastErrno value
** is set before returning.
*/
static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
int got;
#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
i64 newOffset;
#endif
TIMER_START;
#if defined(USE_PREAD)
got = pwrite(id->h, pBuf, cnt, offset);
#elif defined(USE_PREAD64)
got = pwrite64(id->h, pBuf, cnt, offset);
#else
newOffset = lseek(id->h, offset, SEEK_SET);
|
| ︙ | ︙ | |||
24464 24465 24466 24467 24468 24469 24470 24471 24472 24473 24474 24475 24476 24477 |
** isn't supported for this file system. So, attempt an fsync
** and (for now) ignore the overhead of a superfluous fcntl call.
** It'd be better to detect fullfsync support once and avoid
** the fcntl call every time sync is called.
*/
if( rc ) rc = fsync(fd);
#else
rc = fdatasync(fd);
#if OS_VXWORKS
if( rc==-1 && errno==ENOTSUP ){
rc = fsync(fd);
}
#endif /* OS_VXWORKS */
| > > > > > | 24803 24804 24805 24806 24807 24808 24809 24810 24811 24812 24813 24814 24815 24816 24817 24818 24819 24820 24821 |
** isn't supported for this file system. So, attempt an fsync
** and (for now) ignore the overhead of a superfluous fcntl call.
** It'd be better to detect fullfsync support once and avoid
** the fcntl call every time sync is called.
*/
if( rc ) rc = fsync(fd);
#elif defined(__APPLE__)
/* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
** so currently we default to the macro that redefines fdatasync to fsync
*/
rc = fsync(fd);
#else
rc = fdatasync(fd);
#if OS_VXWORKS
if( rc==-1 && errno==ENOTSUP ){
rc = fsync(fd);
}
#endif /* OS_VXWORKS */
|
| ︙ | ︙ | |||
24798 24799 24800 24801 24802 24803 24804 | afpClose, /* xClose method */ afpLock, /* xLock method */ afpUnlock, /* xUnlock method */ afpCheckReservedLock /* xCheckReservedLock method */ ) #endif | < < < < < < < < < < < < < < < < < | 25142 25143 25144 25145 25146 25147 25148 25149 25150 25151 25152 25153 25154 25155 | afpClose, /* xClose method */ afpLock, /* xLock method */ afpUnlock, /* xUnlock method */ afpCheckReservedLock /* xCheckReservedLock method */ ) #endif /* ** The proxy locking method is a "super-method" in the sense that it ** opens secondary file descriptors for the conch and lock files and ** it uses proxy, dot-file, AFP, and flock() locking methods on those ** secondary files. For this reason, the division that implements ** proxy locking is located much further down in the file. But we need ** to go ahead and define the sqlite3_io_methods and finder function |
| ︙ | ︙ | |||
24839 24840 24841 24842 24843 24844 24845 24846 24847 24848 24849 24850 24851 24852 24853 24854 24855 24856 24857 24858 24859 24860 24861 24862 24863 24864 24865 |
proxyClose, /* xClose method */
proxyLock, /* xLock method */
proxyUnlock, /* xUnlock method */
proxyCheckReservedLock /* xCheckReservedLock method */
)
#endif
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** This "finder" function attempts to determine the best locking strategy
** for the database file "filePath". It then returns the sqlite3_io_methods
** object that implements that strategy.
**
** This is for MacOSX only.
*/
static const sqlite3_io_methods *autolockIoFinderImpl(
const char *filePath, /* name of the database file */
unixFile *pNew /* open file object for the database file */
){
static const struct Mapping {
const char *zFilesystem; /* Filesystem type name */
const sqlite3_io_methods *pMethods; /* Appropriate locking method */
} aMap[] = {
{ "hfs", &posixIoMethods },
{ "ufs", &posixIoMethods },
{ "afpfs", &afpIoMethods },
| > > > > > > > > > > > < < < < | 25166 25167 25168 25169 25170 25171 25172 25173 25174 25175 25176 25177 25178 25179 25180 25181 25182 25183 25184 25185 25186 25187 25188 25189 25190 25191 25192 25193 25194 25195 25196 25197 25198 25199 25200 25201 25202 25203 25204 25205 25206 25207 25208 25209 25210 25211 |
proxyClose, /* xClose method */
proxyLock, /* xLock method */
proxyUnlock, /* xUnlock method */
proxyCheckReservedLock /* xCheckReservedLock method */
)
#endif
/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(
nfsIoFinder, /* Finder function name */
nfsIoMethods, /* sqlite3_io_methods object name */
unixClose, /* xClose method */
unixLock, /* xLock method */
nfsUnlock, /* xUnlock method */
unixCheckReservedLock /* xCheckReservedLock method */
)
#endif
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** This "finder" function attempts to determine the best locking strategy
** for the database file "filePath". It then returns the sqlite3_io_methods
** object that implements that strategy.
**
** This is for MacOSX only.
*/
static const sqlite3_io_methods *autolockIoFinderImpl(
const char *filePath, /* name of the database file */
unixFile *pNew /* open file object for the database file */
){
static const struct Mapping {
const char *zFilesystem; /* Filesystem type name */
const sqlite3_io_methods *pMethods; /* Appropriate locking method */
} aMap[] = {
{ "hfs", &posixIoMethods },
{ "ufs", &posixIoMethods },
{ "afpfs", &afpIoMethods },
{ "smbfs", &afpIoMethods },
{ "webdav", &nolockIoMethods },
{ 0, 0 }
};
int i;
struct statfs fsInfo;
struct flock lockInfo;
|
| ︙ | ︙ | |||
24896 24897 24898 24899 24900 24901 24902 |
** assume that the file-system supports POSIX style locks.
*/
lockInfo.l_len = 1;
lockInfo.l_start = 0;
lockInfo.l_whence = SEEK_SET;
lockInfo.l_type = F_RDLCK;
if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
| | > > | > | 25230 25231 25232 25233 25234 25235 25236 25237 25238 25239 25240 25241 25242 25243 25244 25245 25246 25247 25248 |
** assume that the file-system supports POSIX style locks.
*/
lockInfo.l_len = 1;
lockInfo.l_start = 0;
lockInfo.l_whence = SEEK_SET;
lockInfo.l_type = F_RDLCK;
if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
return &nfsIoMethods;
} else {
return &posixIoMethods;
}
}else{
return &dotlockIoMethods;
}
}
static const sqlite3_io_methods
*(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
|
| ︙ | ︙ | |||
25008 25009 25010 25011 25012 25013 25014 |
/* Cache zFilename in the locking context (AFP and dotlock override) for
** proxyLock activation is possible (remote proxy is based on db name)
** zFilename remains valid until file is closed, to support */
pNew->lockingContext = (void*)zFilename;
#endif
}
| | > > > > | 25345 25346 25347 25348 25349 25350 25351 25352 25353 25354 25355 25356 25357 25358 25359 25360 25361 25362 25363 |
/* Cache zFilename in the locking context (AFP and dotlock override) for
** proxyLock activation is possible (remote proxy is based on db name)
** zFilename remains valid until file is closed, to support */
pNew->lockingContext = (void*)zFilename;
#endif
}
if( pLockingStyle == &posixIoMethods
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|| pLockingStyle == &nfsIoMethods
#endif
){
unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
if( rc!=SQLITE_OK ){
/* If an error occured in findLockInfo(), close the file descriptor
** immediately, before releasing the mutex. findLockInfo() may fail
** in two scenarios:
**
|
| ︙ | ︙ | |||
25050 25051 25052 25053 25054 25055 25056 25057 25058 |
if( pCtx==0 ){
rc = SQLITE_NOMEM;
}else{
/* NB: zFilename exists and remains valid until the file is closed
** according to requirement F11141. So we do not need to make a
** copy of the filename. */
pCtx->dbPath = zFilename;
srandomdev();
unixEnterMutex();
| > | > > > > > | 25391 25392 25393 25394 25395 25396 25397 25398 25399 25400 25401 25402 25403 25404 25405 25406 25407 25408 25409 25410 25411 25412 25413 |
if( pCtx==0 ){
rc = SQLITE_NOMEM;
}else{
/* NB: zFilename exists and remains valid until the file is closed
** according to requirement F11141. So we do not need to make a
** copy of the filename. */
pCtx->dbPath = zFilename;
pCtx->reserved = 0;
srandomdev();
unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
if( rc!=SQLITE_OK ){
sqlite3_free(pNew->lockingContext);
close(h);
h = -1;
}
unixLeaveMutex();
}
}
#endif
else if( pLockingStyle == &dotlockIoMethods ){
/* Dotfile locking uses the file path so it needs to be included in
|
| ︙ | ︙ | |||
25101 25102 25103 25104 25105 25106 25107 25108 25109 25110 25111 25112 25113 25114 |
unixLeaveMutex();
}
#endif
pNew->lastErrno = 0;
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
unlink(zFilename);
isDelete = 0;
}
pNew->isDelete = isDelete;
#endif
if( rc!=SQLITE_OK ){
if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */
| > > | 25448 25449 25450 25451 25452 25453 25454 25455 25456 25457 25458 25459 25460 25461 25462 25463 |
unixLeaveMutex();
}
#endif
pNew->lastErrno = 0;
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
if( h>=0 ) close(h);
h = -1;
unlink(zFilename);
isDelete = 0;
}
pNew->isDelete = isDelete;
#endif
if( rc!=SQLITE_OK ){
if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */
|
| ︙ | ︙ | |||
25144 25145 25146 25147 25148 25149 25150 |
#ifdef FD_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname);
}
}
*pFd = fd;
| | | 25493 25494 25495 25496 25497 25498 25499 25500 25501 25502 25503 25504 25505 25506 25507 |
#ifdef FD_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname);
}
}
*pFd = fd;
return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN_BKPT);
}
/*
** Create a temporary file name in zBuf. zBuf must be allocated
** by the calling process and must be big enough to hold at least
** pVfs->mxPathname bytes.
*/
|
| ︙ | ︙ | |||
25253 25254 25255 25256 25257 25258 25259 |
** For this reason, if an error occurs in the stat() call here, it is
** ignored and -1 is returned. The caller will try to open a new file
** descriptor on the same path, fail, and return an error to SQLite.
**
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a resusable file descriptor are not dire. */
if( 0==stat(zPath, &sStat) ){
| | < < < | > > > > | | | 25602 25603 25604 25605 25606 25607 25608 25609 25610 25611 25612 25613 25614 25615 25616 25617 25618 25619 25620 25621 25622 25623 25624 25625 25626 |
** For this reason, if an error occurs in the stat() call here, it is
** ignored and -1 is returned. The caller will try to open a new file
** descriptor on the same path, fail, and return an error to SQLite.
**
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a resusable file descriptor are not dire. */
if( 0==stat(zPath, &sStat) ){
struct unixOpenCnt *pOpen;
unixEnterMutex();
pOpen = openList;
while( pOpen && (pOpen->fileId.dev!=sStat.st_dev
|| pOpen->fileId.ino!=sStat.st_ino) ){
pOpen = pOpen->pNext;
}
if( pOpen ){
UnixUnusedFd **pp;
for(pp=&pOpen->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
pUnused = *pp;
if( pUnused ){
*pp = pUnused->pNext;
}
}
unixLeaveMutex();
}
|
| ︙ | ︙ | |||
25316 25317 25318 25319 25320 25321 25322 25323 25324 25325 25326 25327 25328 25329 |
int rc = SQLITE_OK; /* Function Return Code */
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
int isReadonly = (flags & SQLITE_OPEN_READONLY);
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
/* If creating a master or main-file journal, this function will open
** a file-descriptor on the directory too. The first time unixSync()
** is called the directory file descriptor will be fsync()ed and close()d.
*/
int isOpenDirectory = (isCreate &&
(eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL)
| > > > | 25666 25667 25668 25669 25670 25671 25672 25673 25674 25675 25676 25677 25678 25679 25680 25681 25682 |
int rc = SQLITE_OK; /* Function Return Code */
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
int isReadonly = (flags & SQLITE_OPEN_READONLY);
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
#if SQLITE_ENABLE_LOCKING_STYLE
int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
#endif
/* If creating a master or main-file journal, this function will open
** a file-descriptor on the directory too. The first time unixSync()
** is called the directory file descriptor will be fsync()ed and close()d.
*/
int isOpenDirectory = (isCreate &&
(eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL)
|
| ︙ | ︙ | |||
25403 25404 25405 25406 25407 25408 25409 |
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
fd = open(zName, openFlags, openMode);
}
if( fd<0 ){
| | | 25756 25757 25758 25759 25760 25761 25762 25763 25764 25765 25766 25767 25768 25769 25770 |
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
fd = open(zName, openFlags, openMode);
}
if( fd<0 ){
rc = SQLITE_CANTOPEN_BKPT;
goto open_finished;
}
}
assert( fd>=0 );
if( pOutFlags ){
*pOutFlags = flags;
}
|
| ︙ | ︙ | |||
25449 25450 25451 25452 25453 25454 25455 25456 | #ifdef FD_CLOEXEC fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif noLock = eType!=SQLITE_OPEN_MAIN_DB; #if SQLITE_PREFER_PROXY_LOCKING | > > > > > > > > > > > > > > > > > | | 25802 25803 25804 25805 25806 25807 25808 25809 25810 25811 25812 25813 25814 25815 25816 25817 25818 25819 25820 25821 25822 25823 25824 25825 25826 25827 25828 25829 25830 25831 25832 25833 25834 |
#ifdef FD_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
noLock = eType!=SQLITE_OPEN_MAIN_DB;
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
struct statfs fsInfo;
if( fstatfs(fd, &fsInfo) == -1 ){
((unixFile*)pFile)->lastErrno = errno;
if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */
close(fd); /* silently leak if fail, in error */
return SQLITE_IOERR_ACCESS;
}
if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
}
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
#if SQLITE_PREFER_PROXY_LOCKING
isAutoProxy = 1;
#endif
if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
int useProxy = 0;
/* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
** never use proxy, NULL means use proxy for non-local files only. */
if( envforce!=NULL ){
useProxy = atoi(envforce)>0;
|
| ︙ | ︙ | |||
25482 25483 25484 25485 25486 25487 25488 25489 25490 25491 25492 25493 25494 25495 |
}
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
}
if( useProxy ){
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
if( rc==SQLITE_OK ){
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
}
goto open_finished;
}
}
#endif
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
| > > > > > > > > | 25852 25853 25854 25855 25856 25857 25858 25859 25860 25861 25862 25863 25864 25865 25866 25867 25868 25869 25870 25871 25872 25873 |
}
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
}
if( useProxy ){
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
if( rc==SQLITE_OK ){
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
if( rc!=SQLITE_OK ){
/* Use unixClose to clean up the resources added in fillInUnixFile
** and clear all the structure's references. Specifically,
** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
*/
unixClose(pFile);
return rc;
}
}
goto open_finished;
}
}
#endif
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
|
| ︙ | ︙ | |||
25602 25603 25604 25605 25606 25607 25608 |
zOut[nOut-1] = '\0';
if( zPath[0]=='/' ){
sqlite3_snprintf(nOut, zOut, "%s", zPath);
}else{
int nCwd;
if( getcwd(zOut, nOut-1)==0 ){
| | | 25980 25981 25982 25983 25984 25985 25986 25987 25988 25989 25990 25991 25992 25993 25994 |
zOut[nOut-1] = '\0';
if( zPath[0]=='/' ){
sqlite3_snprintf(nOut, zOut, "%s", zPath);
}else{
int nCwd;
if( getcwd(zOut, nOut-1)==0 ){
return SQLITE_CANTOPEN_BKPT;
}
nCwd = (int)strlen(zOut);
sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
}
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
25909 25910 25911 25912 25913 25914 25915 | ** will fail and SQLITE_BUSY is returned. ** ** The proxy file - a single-byte file used for all advisory file locks ** normally taken on the database file. This allows for safe sharing ** of the database file for multiple readers and writers on the same ** host (the conch ensures that they all use the same local lock file). ** | < < < < < | 26287 26288 26289 26290 26291 26292 26293 26294 26295 26296 26297 26298 26299 26300 | ** will fail and SQLITE_BUSY is returned. ** ** The proxy file - a single-byte file used for all advisory file locks ** normally taken on the database file. This allows for safe sharing ** of the database file for multiple readers and writers on the same ** host (the conch ensures that they all use the same local lock file). ** ** Requesting the lock proxy does not immediately take the conch, it is ** only taken when the first request to lock database file is made. ** This matches the semantics of the traditional locking behavior, where ** opening a connection to a database file does not take a lock on it. ** The shared lock and an open file descriptor are maintained until ** the connection to the database is closed. ** |
| ︙ | ︙ | |||
25939 25940 25941 25942 25943 25944 25945 | ** PRAGMA lock_proxy_file=":auto:" ** ** SQLITE_PROXY_DEBUG ** ** Enables the logging of error messages during host id file ** retrieval and creation ** | < < < < | 26312 26313 26314 26315 26316 26317 26318 26319 26320 26321 26322 26323 26324 26325 | ** PRAGMA lock_proxy_file=":auto:" ** ** SQLITE_PROXY_DEBUG ** ** Enables the logging of error messages during host id file ** retrieval and creation ** ** LOCKPROXYDIR ** ** Overrides the default directory used for lock proxy files that ** are named automatically via the ":auto:" setting ** ** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS ** |
| ︙ | ︙ | |||
25967 25968 25969 25970 25971 25972 25973 | */ /* ** Proxy locking is only available on MacOSX */ #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE | < < < < < | < < | < < < < < | < < < < < | < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | < | < < < < | < < < < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > | < < < < < < < < < < < < > > > | | | > > > > > > > > > | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > | > > > > > > > > | > > > > > > > | > | > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > | | > > | | > | < < < < | | | > | > | < > | < > > > > > | > > > > > > > > > > > > > | | < < < < < < < < | | | | > > > | > > > > > > | > | | | < > > > | | < < < < < < | > > > > | | > | | | > > | > > > > > > > > > > > > | > > > > > > | | > | > > > > > | < | > > > > | | | | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > > > > > > > | > | > > > > > > > > > > > | | < < > | | < | | | | | > | | > > | 26336 26337 26338 26339 26340 26341 26342 26343 26344 26345 26346 26347 26348 26349 26350 26351 26352 26353 26354 26355 26356 26357 26358 26359 26360 26361 26362 26363 26364 26365 26366 26367 26368 26369 26370 26371 26372 26373 26374 26375 26376 26377 26378 26379 26380 26381 26382 26383 26384 26385 26386 26387 26388 26389 26390 26391 26392 26393 26394 26395 26396 26397 26398 26399 26400 26401 26402 26403 26404 26405 26406 26407 26408 26409 26410 26411 26412 26413 26414 26415 26416 26417 26418 26419 26420 26421 26422 26423 26424 26425 26426 26427 26428 26429 26430 26431 26432 26433 26434 26435 26436 26437 26438 26439 26440 26441 26442 26443 26444 26445 26446 26447 26448 26449 26450 26451 26452 26453 26454 26455 26456 26457 26458 26459 26460 26461 26462 26463 26464 26465 26466 26467 26468 26469 26470 26471 26472 26473 26474 26475 26476 26477 26478 26479 26480 26481 26482 26483 26484 26485 26486 26487 26488 26489 26490 26491 26492 26493 26494 26495 26496 26497 26498 26499 26500 26501 26502 26503 26504 26505 26506 26507 26508 26509 26510 26511 26512 26513 26514 26515 26516 26517 26518 26519 26520 26521 26522 26523 26524 26525 26526 26527 26528 26529 26530 26531 26532 26533 26534 26535 26536 26537 26538 26539 26540 26541 26542 26543 26544 26545 26546 26547 26548 26549 26550 26551 26552 26553 26554 26555 26556 26557 26558 26559 26560 26561 26562 26563 26564 26565 26566 26567 26568 26569 26570 26571 26572 26573 26574 26575 26576 26577 26578 26579 26580 26581 26582 26583 26584 26585 26586 26587 26588 26589 26590 26591 26592 26593 26594 26595 26596 26597 26598 26599 26600 26601 26602 26603 26604 26605 26606 26607 26608 26609 26610 26611 26612 26613 26614 26615 26616 26617 26618 26619 26620 26621 26622 26623 26624 26625 26626 26627 26628 26629 26630 26631 26632 26633 26634 26635 26636 26637 26638 26639 26640 26641 26642 26643 26644 26645 26646 26647 26648 26649 26650 26651 26652 26653 26654 26655 26656 26657 26658 26659 26660 26661 26662 26663 26664 26665 26666 26667 26668 26669 26670 26671 26672 26673 26674 26675 26676 26677 26678 26679 26680 26681 26682 26683 26684 26685 26686 26687 26688 26689 26690 26691 26692 26693 26694 26695 26696 26697 26698 26699 26700 26701 26702 26703 26704 26705 26706 26707 26708 26709 26710 26711 26712 26713 26714 26715 26716 26717 26718 26719 26720 26721 26722 26723 26724 26725 26726 26727 26728 26729 26730 26731 26732 26733 26734 26735 26736 26737 26738 26739 26740 26741 26742 26743 26744 26745 26746 26747 26748 26749 26750 26751 26752 26753 26754 26755 26756 26757 26758 26759 26760 26761 26762 26763 26764 26765 26766 26767 26768 26769 26770 26771 26772 26773 26774 26775 26776 26777 26778 26779 26780 26781 26782 26783 26784 26785 26786 26787 26788 26789 26790 26791 26792 26793 26794 26795 26796 26797 26798 26799 26800 26801 26802 26803 26804 26805 26806 26807 26808 26809 26810 26811 26812 26813 26814 26815 26816 26817 26818 26819 26820 26821 26822 26823 26824 26825 26826 26827 26828 26829 26830 26831 26832 26833 26834 26835 26836 26837 26838 26839 26840 26841 26842 26843 26844 26845 26846 26847 26848 26849 26850 26851 26852 26853 26854 26855 26856 26857 26858 26859 26860 26861 26862 26863 26864 26865 26866 26867 26868 26869 26870 26871 26872 26873 26874 26875 26876 26877 26878 26879 26880 26881 26882 26883 26884 26885 26886 26887 26888 26889 26890 26891 26892 26893 26894 26895 26896 26897 26898 26899 26900 26901 26902 26903 26904 26905 26906 26907 26908 26909 26910 26911 26912 26913 26914 26915 26916 26917 26918 26919 26920 26921 26922 26923 26924 26925 26926 26927 26928 26929 26930 26931 26932 26933 26934 26935 26936 26937 26938 26939 26940 26941 26942 26943 26944 26945 26946 26947 26948 26949 |
*/
/*
** Proxy locking is only available on MacOSX
*/
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** The proxyLockingContext has the path and file structures for the remote
** and local proxy files in it
*/
typedef struct proxyLockingContext proxyLockingContext;
struct proxyLockingContext {
unixFile *conchFile; /* Open conch file */
char *conchFilePath; /* Name of the conch file */
unixFile *lockProxy; /* Open proxy lock file */
char *lockProxyPath; /* Name of the proxy lock file */
char *dbPath; /* Name of the open file */
int conchHeld; /* 1 if the conch is held, -1 if lockless */
void *oldLockingContext; /* Original lockingcontext to restore on close */
sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
};
/*
** The proxy lock file path for the database at dbPath is written into lPath,
** which must point to valid, writable memory large enough for a maxLen length
** file path.
*/
static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
int len;
int dbLen;
int i;
#ifdef LOCKPROXYDIR
len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
#else
# ifdef _CS_DARWIN_USER_TEMP_DIR
{
if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
OSTRACE4("GETLOCKPATH failed %s errno=%d pid=%d\n",
lPath, errno, getpid());
return SQLITE_IOERR_LOCK;
}
len = strlcat(lPath, "sqliteplocks", maxLen);
}
# else
len = strlcpy(lPath, "/tmp/", maxLen);
# endif
#endif
if( lPath[len-1]!='/' ){
len = strlcat(lPath, "/", maxLen);
}
/* transform the db path to a unique cache name */
dbLen = (int)strlen(dbPath);
for( i=0; i<dbLen && (i+len+7)<maxLen; i++){
char c = dbPath[i];
lPath[i+len] = (c=='/')?'_':c;
}
lPath[i+len]='\0';
strlcat(lPath, ":auto:", maxLen);
OSTRACE3("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid());
return SQLITE_OK;
}
/*
** Creates the lock file and any missing directories in lockPath
*/
static int proxyCreateLockPath(const char *lockPath){
int i, len;
char buf[MAXPATHLEN];
int start = 0;
assert(lockPath!=NULL);
/* try to create all the intermediate directories */
len = (int)strlen(lockPath);
buf[0] = lockPath[0];
for( i=1; i<len; i++ ){
if( lockPath[i] == '/' && (i - start > 0) ){
/* only mkdir if leaf dir != "." or "/" or ".." */
if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
|| (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
buf[i]='\0';
if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
int err=errno;
if( err!=EEXIST ) {
OSTRACE5("CREATELOCKPATH FAILED creating %s, "
"'%s' proxy lock path=%s pid=%d\n",
buf, strerror(err), lockPath, getpid());
return err;
}
}
}
start=i+1;
}
buf[i] = lockPath[i];
}
OSTRACE3("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid());
return 0;
}
/*
** Create a new VFS file descriptor (stored in memory obtained from
** sqlite3_malloc) and open the file named "path" in the file descriptor.
**
** The caller is responsible not only for closing the file descriptor
** but also for freeing the memory associated with the file descriptor.
*/
static int proxyCreateUnixFile(
const char *path, /* path for the new unixFile */
unixFile **ppFile, /* unixFile created and returned by ref */
int islockfile /* if non zero missing dirs will be created */
) {
int fd = -1;
int dirfd = -1;
unixFile *pNew;
int rc = SQLITE_OK;
int openFlags = O_RDWR | O_CREAT;
sqlite3_vfs dummyVfs;
int terrno = 0;
UnixUnusedFd *pUnused = NULL;
/* 1. first try to open/create the file
** 2. if that fails, and this is a lock file (not-conch), try creating
** the parent directories and then try again.
** 3. if that fails, try to open the file read-only
** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
*/
pUnused = findReusableFd(path, openFlags);
if( pUnused ){
fd = pUnused->fd;
}else{
pUnused = sqlite3_malloc(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
}
if( fd<0 ){
fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
terrno = errno;
if( fd<0 && errno==ENOENT && islockfile ){
if( proxyCreateLockPath(path) == SQLITE_OK ){
fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
}
}
}
if( fd<0 ){
openFlags = O_RDONLY;
fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
terrno = errno;
}
if( fd<0 ){
if( islockfile ){
return SQLITE_BUSY;
}
switch (terrno) {
case EACCES:
return SQLITE_PERM;
case EIO:
return SQLITE_IOERR_LOCK; /* even though it is the conch */
default:
return SQLITE_CANTOPEN_BKPT;
}
}
pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
if( pNew==NULL ){
rc = SQLITE_NOMEM;
goto end_create_proxy;
}
memset(pNew, 0, sizeof(unixFile));
pNew->openFlags = openFlags;
dummyVfs.pAppData = (void*)&autolockIoFinder;
pUnused->fd = fd;
pUnused->flags = openFlags;
pNew->pUnused = pUnused;
rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0);
if( rc==SQLITE_OK ){
*ppFile = pNew;
return SQLITE_OK;
}
end_create_proxy:
close(fd); /* silently leak fd if error, we're already in error */
sqlite3_free(pNew);
sqlite3_free(pUnused);
return rc;
}
#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
SQLITE_API int sqlite3_hostid_num = 0;
#endif
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
** bytes of writable memory.
*/
static int proxyGetHostID(unsigned char *pHostID, int *pError){
struct timespec timeout = {1, 0}; /* 1 sec timeout */
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
memset(pHostID, 0, PROXY_HOSTIDLEN);
if( gethostuuid(pHostID, &timeout) ){
int err = errno;
if( pError ){
*pError = err;
}
return SQLITE_IOERR;
}
#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
if( sqlite3_hostid_num != 0){
pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
}
#endif
return SQLITE_OK;
}
/* The conch file contains the header, host id and lock file path
*/
#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */
#define PROXY_HEADERLEN 1 /* conch file header length */
#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
/*
** Takes an open conch file, copies the contents to a new path and then moves
** it back. The newly created file's file descriptor is assigned to the
** conch file structure and finally the original conch file descriptor is
** closed. Returns zero if successful.
*/
static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
unixFile *conchFile = pCtx->conchFile;
char tPath[MAXPATHLEN];
char buf[PROXY_MAXCONCHLEN];
char *cPath = pCtx->conchFilePath;
size_t readLen = 0;
size_t pathLen = 0;
char errmsg[64] = "";
int fd = -1;
int rc = -1;
/* create a new path by replace the trailing '-conch' with '-break' */
pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
if( pathLen>MAXPATHLEN || pathLen<6 ||
(strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
sprintf(errmsg, "path error (len %d)", (int)pathLen);
goto end_breaklock;
}
/* read the conch content */
readLen = pread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
if( readLen<PROXY_PATHINDEX ){
sprintf(errmsg, "read error (len %d)", (int)readLen);
goto end_breaklock;
}
/* write it out to the temporary break file */
fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS);
if( fd<0 ){
sprintf(errmsg, "create failed (%d)", errno);
goto end_breaklock;
}
if( pwrite(fd, buf, readLen, 0) != readLen ){
sprintf(errmsg, "write failed (%d)", errno);
goto end_breaklock;
}
if( rename(tPath, cPath) ){
sprintf(errmsg, "rename failed (%d)", errno);
goto end_breaklock;
}
rc = 0;
fprintf(stderr, "broke stale lock on %s\n", cPath);
close(conchFile->h);
conchFile->h = fd;
conchFile->openFlags = O_RDWR | O_CREAT;
end_breaklock:
if( rc ){
if( fd>=0 ){
unlink(tPath);
close(fd);
}
fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
}
return rc;
}
/* Take the requested lock on the conch file and break a stale lock if the
** host id matches.
*/
static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
unixFile *conchFile = pCtx->conchFile;
int rc = SQLITE_OK;
int nTries = 0;
struct timespec conchModTime;
do {
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
nTries ++;
if( rc==SQLITE_BUSY ){
/* If the lock failed (busy):
* 1st try: get the mod time of the conch, wait 0.5s and try again.
* 2nd try: fail if the mod time changed or host id is different, wait
* 10 sec and try again
* 3rd try: break the lock unless the mod time has changed.
*/
struct stat buf;
if( fstat(conchFile->h, &buf) ){
pFile->lastErrno = errno;
return SQLITE_IOERR_LOCK;
}
if( nTries==1 ){
conchModTime = buf.st_mtimespec;
usleep(500000); /* wait 0.5 sec and try the lock again*/
continue;
}
assert( nTries>1 );
if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
return SQLITE_BUSY;
}
if( nTries==2 ){
char tBuf[PROXY_MAXCONCHLEN];
int len = pread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
if( len<0 ){
pFile->lastErrno = errno;
return SQLITE_IOERR_LOCK;
}
if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
/* don't break the lock if the host id doesn't match */
if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
return SQLITE_BUSY;
}
}else{
/* don't break the lock on short read or a version mismatch */
return SQLITE_BUSY;
}
usleep(10000000); /* wait 10 sec and try the lock again */
continue;
}
assert( nTries==3 );
if( 0==proxyBreakConchLock(pFile, myHostID) ){
rc = SQLITE_OK;
if( lockType==EXCLUSIVE_LOCK ){
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
}
if( !rc ){
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
}
}
}
} while( rc==SQLITE_BUSY && nTries<3 );
return rc;
}
/* Takes the conch by taking a shared lock and read the contents conch, if
** lockPath is non-NULL, the host ID and lock file path must match. A NULL
** lockPath means that the lockPath in the conch file will be used if the
** host IDs match, or a new lock path will be generated automatically
** and written to the conch file.
*/
static int proxyTakeConch(unixFile *pFile){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
if( pCtx->conchHeld!=0 ){
return SQLITE_OK;
}else{
unixFile *conchFile = pCtx->conchFile;
uuid_t myHostID;
int pError = 0;
char readBuf[PROXY_MAXCONCHLEN];
char lockPath[MAXPATHLEN];
char *tempLockPath = NULL;
int rc = SQLITE_OK;
int createConch = 0;
int hostIdMatch = 0;
int readLen = 0;
int tryOldLockPath = 0;
int forceNewLockPath = 0;
OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h,
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid());
rc = proxyGetHostID(myHostID, &pError);
if( (rc&0xff)==SQLITE_IOERR ){
pFile->lastErrno = pError;
goto end_takeconch;
}
rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
if( rc!=SQLITE_OK ){
goto end_takeconch;
}
/* read the existing conch file */
readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
if( readLen<0 ){
/* I/O error: lastErrno set by seekAndRead */
pFile->lastErrno = conchFile->lastErrno;
rc = SQLITE_IOERR_READ;
goto end_takeconch;
}else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
readBuf[0]!=(char)PROXY_CONCHVERSION ){
/* a short read or version format mismatch means we need to create a new
** conch file.
*/
createConch = 1;
}
/* if the host id matches and the lock path already exists in the conch
** we'll try to use the path there, if we can't open that path, we'll
** retry with a new auto-generated path
*/
do { /* in case we need to try again for an :auto: named lock file */
if( !createConch && !forceNewLockPath ){
hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
PROXY_HOSTIDLEN);
/* if the conch has data compare the contents */
if( !pCtx->lockProxyPath ){
/* for auto-named local lock file, just check the host ID and we'll
** use the local lock file path that's already in there
*/
if( hostIdMatch ){
size_t pathLen = (readLen - PROXY_PATHINDEX);
if( pathLen>=MAXPATHLEN ){
pathLen=MAXPATHLEN-1;
}
memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
lockPath[pathLen] = 0;
tempLockPath = lockPath;
tryOldLockPath = 1;
/* create a copy of the lock path if the conch is taken */
goto end_takeconch;
}
}else if( hostIdMatch
&& !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
readLen-PROXY_PATHINDEX)
){
/* conch host and lock path match */
goto end_takeconch;
}
}
/* if the conch isn't writable and doesn't match, we can't take it */
if( (conchFile->openFlags&O_RDWR) == 0 ){
rc = SQLITE_BUSY;
goto end_takeconch;
}
/* either the conch didn't match or we need to create a new one */
if( !pCtx->lockProxyPath ){
proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
tempLockPath = lockPath;
/* create a copy of the lock path _only_ if the conch is taken */
}
/* update conch with host and path (this will fail if other process
** has a shared lock already), if the host id matches, use the big
** stick.
*/
futimes(conchFile->h, NULL);
if( hostIdMatch && !createConch ){
if( conchFile->pLock && conchFile->pLock->cnt>1 ){
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
} else {
rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
}
}else{
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
}
if( rc==SQLITE_OK ){
char writeBuffer[PROXY_MAXCONCHLEN];
int writeSize = 0;
writeBuffer[0] = (char)PROXY_CONCHVERSION;
memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
if( pCtx->lockProxyPath!=NULL ){
strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
}else{
strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
}
writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
ftruncate(conchFile->h, writeSize);
rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
fsync(conchFile->h);
/* If we created a new conch file (not just updated the contents of a
** valid conch file), try to match the permissions of the database
*/
if( rc==SQLITE_OK && createConch ){
struct stat buf;
int err = fstat(pFile->h, &buf);
if( err==0 ){
mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
S_IROTH|S_IWOTH);
/* try to match the database file R/W permissions, ignore failure */
#ifndef SQLITE_PROXY_DEBUG
fchmod(conchFile->h, cmode);
#else
if( fchmod(conchFile->h, cmode)!=0 ){
int code = errno;
fprintf(stderr, "fchmod %o FAILED with %d %s\n",
cmode, code, strerror(code));
} else {
fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
}
}else{
int code = errno;
fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
err, code, strerror(code));
#endif
}
}
}
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
end_takeconch:
OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h);
if( rc==SQLITE_OK && pFile->openFlags ){
if( pFile->h>=0 ){
#ifdef STRICT_CLOSE_ERROR
if( close(pFile->h) ){
pFile->lastErrno = errno;
return SQLITE_IOERR_CLOSE;
}
#else
close(pFile->h); /* silently leak fd if fail */
#endif
}
pFile->h = -1;
int fd = open(pCtx->dbPath, pFile->openFlags,
SQLITE_DEFAULT_FILE_PERMISSIONS);
OSTRACE2("TRANSPROXY: OPEN %d\n", fd);
if( fd>=0 ){
pFile->h = fd;
}else{
rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
during locking */
}
}
if( rc==SQLITE_OK && !pCtx->lockProxy ){
char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
/* we couldn't create the proxy lock file with the old lock file path
** so try again via auto-naming
*/
forceNewLockPath = 1;
tryOldLockPath = 0;
continue; /* go back to the do {} while start point, try again */
}
}
if( rc==SQLITE_OK ){
/* Need to make a copy of path if we extracted the value
** from the conch file or the path was allocated on the stack
*/
if( tempLockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
if( !pCtx->lockProxyPath ){
rc = SQLITE_NOMEM;
}
}
}
if( rc==SQLITE_OK ){
pCtx->conchHeld = 1;
if( pCtx->lockProxy->pMethod == &afpIoMethods ){
afpLockingContext *afpCtx;
afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
afpCtx->dbPath = pCtx->lockProxyPath;
}
} else {
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
}
OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed");
return rc;
} while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */
}
}
/*
** If pFile holds a lock on a conch file, then release that lock.
*/
static int proxyReleaseConch(unixFile *pFile){
int rc; /* Subroutine return code */
proxyLockingContext *pCtx; /* The locking context for the proxy lock */
unixFile *conchFile; /* Name of the conch file */
pCtx = (proxyLockingContext *)pFile->lockingContext;
conchFile = pCtx->conchFile;
OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
getpid());
if( pCtx->conchHeld>0 ){
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
}
pCtx->conchHeld = 0;
OSTRACE3("RELEASECONCH %d %s\n", conchFile->h,
(rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
/*
** Given the name of a database file, compute the name of its conch file.
|
| ︙ | ︙ | |||
26470 26471 26472 26473 26474 26475 26476 |
*/
static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
#if defined(__APPLE__)
if( pFile->pMethod == &afpIoMethods ){
/* afp style keeps a reference to the db path in the filePath field
** of the struct */
assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
| | | | | 27031 27032 27033 27034 27035 27036 27037 27038 27039 27040 27041 27042 27043 27044 27045 27046 27047 27048 27049 27050 27051 27052 27053 27054 27055 27056 |
*/
static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
#if defined(__APPLE__)
if( pFile->pMethod == &afpIoMethods ){
/* afp style keeps a reference to the db path in the filePath field
** of the struct */
assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
} else
#endif
if( pFile->pMethod == &dotlockIoMethods ){
/* dot lock style uses the locking context to store the dot lock
** file path */
int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
}else{
/* all other styles use the locking context to store the db file path */
assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
}
return SQLITE_OK;
}
/*
** Takes an already filled in unix file and alters it so all file locking
** will be performed on the local proxy lock file. The following fields
|
| ︙ | ︙ | |||
26521 26522 26523 26524 26525 26526 26527 |
if( pCtx==0 ){
return SQLITE_NOMEM;
}
memset(pCtx, 0, sizeof(*pCtx));
rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
if( rc==SQLITE_OK ){
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < > | 27082 27083 27084 27085 27086 27087 27088 27089 27090 27091 27092 27093 27094 27095 27096 27097 27098 27099 27100 27101 27102 27103 27104 27105 27106 27107 27108 27109 27110 27111 27112 27113 27114 27115 27116 27117 27118 27119 27120 27121 27122 27123 27124 27125 27126 27127 27128 27129 27130 27131 27132 27133 27134 27135 27136 27137 27138 27139 27140 27141 27142 |
if( pCtx==0 ){
return SQLITE_NOMEM;
}
memset(pCtx, 0, sizeof(*pCtx));
rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
if( rc==SQLITE_OK ){
rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
/* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
** (c) the file system is read-only, then enable no-locking access.
** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
** that openFlags will have only one of O_RDONLY or O_RDWR.
*/
struct statfs fsInfo;
struct stat conchInfo;
int goLockless = 0;
if( stat(pCtx->conchFilePath, &conchInfo) == -1 ) {
int err = errno;
if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
}
}
if( goLockless ){
pCtx->conchHeld = -1; /* read only FS/ lockless */
rc = SQLITE_OK;
}
}
}
if( rc==SQLITE_OK && lockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
}
if( rc==SQLITE_OK ){
pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
if( pCtx->dbPath==NULL ){
rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK ){
/* all memory is allocated, proxys are created and assigned,
** switch the locking context and pMethod then return.
*/
pCtx->oldLockingContext = pFile->lockingContext;
pFile->lockingContext = pCtx;
pCtx->pOldMethod = pFile->pMethod;
pFile->pMethod = &proxyIoMethods;
}else{
if( pCtx->conchFile ){
pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
sqlite3_free(pCtx->conchFile);
}
sqlite3_free(pCtx->lockProxyPath);
sqlite3_free(pCtx->conchFilePath);
sqlite3_free(pCtx);
}
OSTRACE3("TRANSPROXY %d %s\n", pFile->h,
(rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
|
| ︙ | ︙ | |||
26630 26631 26632 26633 26634 26635 26636 |
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
unixFile *pFile = (unixFile*)id;
int rc = proxyTakeConch(pFile);
if( rc==SQLITE_OK ){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
| > | | > > > | 27217 27218 27219 27220 27221 27222 27223 27224 27225 27226 27227 27228 27229 27230 27231 27232 27233 27234 27235 27236 |
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
unixFile *pFile = (unixFile*)id;
int rc = proxyTakeConch(pFile);
if( rc==SQLITE_OK ){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
if( pCtx->conchHeld>0 ){
unixFile *proxy = pCtx->lockProxy;
return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
}else{ /* conchHeld < 0 is lockless */
pResOut=0;
}
}
return rc;
}
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
|
| ︙ | ︙ | |||
26665 26666 26667 26668 26669 26670 26671 |
** routine to lower a locking level.
*/
static int proxyLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int rc = proxyTakeConch(pFile);
if( rc==SQLITE_OK ){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
| > | | | > > > > | | | > > > | 27256 27257 27258 27259 27260 27261 27262 27263 27264 27265 27266 27267 27268 27269 27270 27271 27272 27273 27274 27275 27276 27277 27278 27279 27280 27281 27282 27283 27284 27285 27286 27287 27288 27289 27290 27291 27292 27293 27294 27295 27296 27297 27298 27299 27300 |
** routine to lower a locking level.
*/
static int proxyLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int rc = proxyTakeConch(pFile);
if( rc==SQLITE_OK ){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
if( pCtx->conchHeld>0 ){
unixFile *proxy = pCtx->lockProxy;
rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype);
pFile->locktype = proxy->locktype;
}else{
/* conchHeld < 0 is lockless */
}
}
return rc;
}
/*
** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int proxyUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int rc = proxyTakeConch(pFile);
if( rc==SQLITE_OK ){
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
if( pCtx->conchHeld>0 ){
unixFile *proxy = pCtx->lockProxy;
rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype);
pFile->locktype = proxy->locktype;
}else{
/* conchHeld < 0 is lockless */
}
}
return rc;
}
/*
** Close a file that uses proxy locks.
*/
|
| ︙ | ︙ | |||
26814 26815 26816 26817 26818 26819 26820 |
#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
UNIXVFS("unix", autolockIoFinder ),
#else
UNIXVFS("unix", posixIoFinder ),
#endif
UNIXVFS("unix-none", nolockIoFinder ),
UNIXVFS("unix-dotfile", dotlockIoFinder ),
| < > | 27413 27414 27415 27416 27417 27418 27419 27420 27421 27422 27423 27424 27425 27426 27427 27428 27429 27430 27431 27432 27433 27434 27435 27436 27437 27438 |
#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
UNIXVFS("unix", autolockIoFinder ),
#else
UNIXVFS("unix", posixIoFinder ),
#endif
UNIXVFS("unix-none", nolockIoFinder ),
UNIXVFS("unix-dotfile", dotlockIoFinder ),
#if OS_VXWORKS
UNIXVFS("unix-namedsem", semIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
UNIXVFS("unix-posix", posixIoFinder ),
#if !OS_VXWORKS
UNIXVFS("unix-flock", flockIoFinder ),
#endif
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
UNIXVFS("unix-afp", afpIoFinder ),
UNIXVFS("unix-nfs", nfsIoFinder ),
UNIXVFS("unix-proxy", proxyIoFinder ),
#endif
};
unsigned int i; /* Loop counter */
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
|
| ︙ | ︙ | |||
28489 28490 28491 28492 28493 28494 28495 |
}
if( h==INVALID_HANDLE_VALUE ){
free(zConverted);
if( flags & SQLITE_OPEN_READWRITE ){
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
}else{
| | | 29088 29089 29090 29091 29092 29093 29094 29095 29096 29097 29098 29099 29100 29101 29102 |
}
if( h==INVALID_HANDLE_VALUE ){
free(zConverted);
if( flags & SQLITE_OPEN_READWRITE ){
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
}else{
return SQLITE_CANTOPEN_BKPT;
}
}
if( pOutFlags ){
if( flags & SQLITE_OPEN_READWRITE ){
*pOutFlags = SQLITE_OPEN_READWRITE;
}else{
*pOutFlags = SQLITE_OPEN_READONLY;
|
| ︙ | ︙ | |||
28511 28512 28513 28514 28515 28516 28517 |
#if SQLITE_OS_WINCE
if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) ==
(SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)
&& !winceCreateLock(zName, pFile)
){
CloseHandle(h);
free(zConverted);
| | | 29110 29111 29112 29113 29114 29115 29116 29117 29118 29119 29120 29121 29122 29123 29124 |
#if SQLITE_OS_WINCE
if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) ==
(SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)
&& !winceCreateLock(zName, pFile)
){
CloseHandle(h);
free(zConverted);
return SQLITE_CANTOPEN_BKPT;
}
if( isTemp ){
pFile->zDeleteOnClose = zConverted;
}else
#endif
{
free(zConverted);
|
| ︙ | ︙ | |||
29598 29599 29600 29601 29602 29603 29604 29605 29606 29607 29608 29609 29610 29611 |
** are no outstanding page references when this function is called.
*/
SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
assert( pCache->nRef==0 && pCache->pDirty==0 );
if( pCache->pCache ){
sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
pCache->pCache = 0;
}
pCache->szPage = szPage;
}
/*
** Try to obtain a page from the cache.
*/
| > | 30197 30198 30199 30200 30201 30202 30203 30204 30205 30206 30207 30208 30209 30210 30211 |
** are no outstanding page references when this function is called.
*/
SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
assert( pCache->nRef==0 && pCache->pDirty==0 );
if( pCache->pCache ){
sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
pCache->pCache = 0;
pCache->pPage1 = 0;
}
pCache->szPage = szPage;
}
/*
** Try to obtain a page from the cache.
*/
|
| ︙ | ︙ | |||
29651 29652 29653 29654 29655 29656 29657 29658 29659 29660 29661 29662 29663 29664 |
** unreferenced dirty page.
*/
expensive_assert( pcacheCheckSynced(pCache) );
for(pPg=pCache->pSynced;
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
);
if( !pPg ){
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
}
if( pPg ){
int rc;
rc = pCache->xStress(pCache->pStress, pPg);
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
| > | 30251 30252 30253 30254 30255 30256 30257 30258 30259 30260 30261 30262 30263 30264 30265 |
** unreferenced dirty page.
*/
expensive_assert( pcacheCheckSynced(pCache) );
for(pPg=pCache->pSynced;
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
);
pCache->pSynced = pPg;
if( !pPg ){
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
}
if( pPg ){
int rc;
rc = pCache->xStress(pCache->pStress, pPg);
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
|
| ︙ | ︙ | |||
34065 34066 34067 34068 34069 34070 34071 |
/* If there are dirty pages in the page cache with page numbers greater
** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
** make the file smaller (presumably by auto-vacuum code). Do not write
** any such pages to the file.
**
** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
| | < < | 34666 34667 34668 34669 34670 34671 34672 34673 34674 34675 34676 34677 34678 34679 34680 |
/* If there are dirty pages in the page cache with page numbers greater
** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
** make the file smaller (presumably by auto-vacuum code). Do not write
** any such pages to the file.
**
** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
** set (set by sqlite3PagerDontWrite()).
*/
if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
char *pData; /* Data to write */
/* Encode the database */
CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
|
| ︙ | ︙ | |||
34354 34355 34356 34357 34358 34359 34360 |
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
/* This branch is taken when the journal path required by
** the database being opened will be more than pVfs->mxPathname
** bytes in length. This means the database cannot be opened,
** as it will not be possible to open the journal file or even
** check for a hot-journal before reading.
*/
| | | 34953 34954 34955 34956 34957 34958 34959 34960 34961 34962 34963 34964 34965 34966 34967 |
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
/* This branch is taken when the journal path required by
** the database being opened will be more than pVfs->mxPathname
** bytes in length. This means the database cannot be opened,
** as it will not be possible to open the journal file or even
** check for a hot-journal before reading.
*/
rc = SQLITE_CANTOPEN_BKPT;
}
if( rc!=SQLITE_OK ){
sqlite3_free(zPathname);
return rc;
}
}
|
| ︙ | ︙ | |||
34813 34814 34815 34816 34817 34818 34819 |
if( res ){
int fout = 0;
int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
assert( !pPager->tempFile );
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
| | | 35412 35413 35414 35415 35416 35417 35418 35419 35420 35421 35422 35423 35424 35425 35426 |
if( res ){
int fout = 0;
int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
assert( !pPager->tempFile );
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
rc = SQLITE_CANTOPEN_BKPT;
sqlite3OsClose(pPager->jfd);
}
}else{
/* If the journal does not exist, it usually means that some
** other connection managed to get in and roll it back before
** this connection obtained the exclusive lock above. Or, it
** may mean that the pager was in the error-state when this
|
| ︙ | ︙ | |||
35032 35033 35034 35035 35036 35037 35038 |
}
rc = sqlite3PagerPagecount(pPager, &nMax);
if( rc!=SQLITE_OK ){
goto pager_acquire_err;
}
| | < < > | 35631 35632 35633 35634 35635 35636 35637 35638 35639 35640 35641 35642 35643 35644 35645 35646 35647 35648 35649 35650 35651 35652 35653 35654 35655 35656 35657 35658 35659 35660 35661 35662 35663 35664 35665 35666 |
}
rc = sqlite3PagerPagecount(pPager, &nMax);
if( rc!=SQLITE_OK ){
goto pager_acquire_err;
}
if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){
if( pgno>pPager->mxPgno ){
rc = SQLITE_FULL;
goto pager_acquire_err;
}
if( noContent ){
/* Failure to set the bits in the InJournal bit-vectors is benign.
** It merely means that we might do some extra work to journal a
** page that does not need to be journaled. Nevertheless, be sure
** to test the case where a malloc error occurs while trying to set
** a bit in a bit vector.
*/
sqlite3BeginBenignMalloc();
if( pgno<=pPager->dbOrigSize ){
TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
testcase( rc==SQLITE_NOMEM );
}
TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
testcase( rc==SQLITE_NOMEM );
sqlite3EndBenignMalloc();
}
memset(pPg->pData, 0, pPager->pageSize);
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
assert( pPg->pPager==pPager );
rc = readDbPage(pPg);
if( rc!=SQLITE_OK ){
goto pager_acquire_err;
}
|
| ︙ | ︙ | |||
35576 35577 35578 35579 35580 35581 35582 |
*/
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
return pPg->flags&PGHDR_DIRTY;
}
#endif
| < | 36174 36175 36176 36177 36178 36179 36180 36181 36182 36183 36184 36185 36186 36187 |
*/
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
return pPg->flags&PGHDR_DIRTY;
}
#endif
/*
** A call to this routine tells the pager that it is not necessary to
** write the information on page pPg back to the disk, even though
** that page might be marked as dirty. This happens, for example, when
** the page has been added as a leaf of the freelist and so its
** content no longer matters.
**
|
| ︙ | ︙ | |||
35602 35603 35604 35605 35606 35607 35608 |
IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
pPg->flags |= PGHDR_DONT_WRITE;
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
}
| < | 36199 36200 36201 36202 36203 36204 36205 36206 36207 36208 36209 36210 36211 36212 |
IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
pPg->flags |= PGHDR_DONT_WRITE;
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
}
/*
** This routine is called to increment the value of the database file
** change-counter, stored as a 4-byte big-endian integer starting at
** byte offset 24 of the pager file.
**
** If the isDirectMode flag is zero, then this is done by calling
|
| ︙ | ︙ | |||
36172 36173 36174 36175 36176 36177 36178 |
int ii; /* Iterator variable */
int nNew; /* Number of remaining savepoints after this op. */
/* Figure out how many savepoints will still be active after this
** operation. Store this value in nNew. Then free resources associated
** with any savepoints that are destroyed by this operation.
*/
| | > > > > > > > > > > > | | < < < < < < < | 36768 36769 36770 36771 36772 36773 36774 36775 36776 36777 36778 36779 36780 36781 36782 36783 36784 36785 36786 36787 36788 36789 36790 36791 36792 36793 36794 36795 36796 36797 36798 36799 36800 36801 36802 36803 36804 36805 36806 36807 36808 36809 |
int ii; /* Iterator variable */
int nNew; /* Number of remaining savepoints after this op. */
/* Figure out how many savepoints will still be active after this
** operation. Store this value in nNew. Then free resources associated
** with any savepoints that are destroyed by this operation.
*/
nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
for(ii=nNew; ii<pPager->nSavepoint; ii++){
sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
}
pPager->nSavepoint = nNew;
/* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( op==SAVEPOINT_RELEASE ){
if( nNew==0 && isOpen(pPager->sjfd) ){
/* Only truncate if it is an in-memory sub-journal. */
if( sqlite3IsMemJournal(pPager->sjfd) ){
rc = sqlite3OsTruncate(pPager->sjfd, 0);
}
pPager->nSubRec = 0;
}
}
/* Else this is a rollback operation, playback the specified savepoint.
** If this is a temp-file, it is possible that the journal file has
** not yet been opened. In this case there have been no changes to
** the database file, so the playback operation can be skipped.
*/
else if( isOpen(pPager->jfd) ){
PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
rc = pagerPlaybackSavepoint(pPager, pSavepoint);
assert(rc!=SQLITE_DONE);
}
}
return rc;
}
/*
** Return the full pathname of the database file.
*/
|
| ︙ | ︙ | |||
36955 36956 36957 36958 36959 36960 36961 36962 36963 36964 36965 36966 36967 36968 |
struct BtShared {
Pager *pPager; /* The page cache */
sqlite3 *db; /* Database connection currently using this Btree */
BtCursor *pCursor; /* A list of all open cursors */
MemPage *pPage1; /* First page of the database */
u8 readOnly; /* True if the underlying file is readonly */
u8 pageSizeFixed; /* True if the page size can no longer be changed */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
#endif
u16 pageSize; /* Total number of bytes on a page */
u16 usableSize; /* Number of usable bytes on each page */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
| > | 37555 37556 37557 37558 37559 37560 37561 37562 37563 37564 37565 37566 37567 37568 37569 |
struct BtShared {
Pager *pPager; /* The page cache */
sqlite3 *db; /* Database connection currently using this Btree */
BtCursor *pCursor; /* A list of all open cursors */
MemPage *pPage1; /* First page of the database */
u8 readOnly; /* True if the underlying file is readonly */
u8 pageSizeFixed; /* True if the page size can no longer be changed */
u8 secureDelete; /* True if secure_delete is enabled */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
#endif
u16 pageSize; /* Total number of bytes on a page */
u16 usableSize; /* Number of usable bytes on each page */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
|
| ︙ | ︙ | |||
38778 38779 38780 38781 38782 38783 38784 | assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); assert( (start + size)<=pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( size>=0 ); /* Minimum cell size is 4 */ | | | | | < > | 39379 39380 39381 39382 39383 39384 39385 39386 39387 39388 39389 39390 39391 39392 39393 39394 39395 39396 39397 |
assert( pPage->pBt!=0 );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( start>=pPage->hdrOffset+6+pPage->childPtrSize );
assert( (start + size)<=pPage->pBt->usableSize );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( size>=0 ); /* Minimum cell size is 4 */
if( pPage->pBt->secureDelete ){
/* Overwrite deleted information with zeros when the secure_delete
** option is enabled */
memset(&data[start], 0, size);
}
/* Add the space back into the linked list of freeblocks. Note that
** even though the freeblock list was checked by btreeInitPage(),
** btreeInitPage() did not detect overlapping cells or
** freeblocks that overlapped cells. Nor does it detect when the
** cell content area exceeds the value in the page header. If these
** situations arise, then subsequent insert operations might corrupt
|
| ︙ | ︙ | |||
39014 39015 39016 39017 39018 39019 39020 | u16 first; assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); assert( sqlite3PagerGetData(pPage->pDbPage) == data ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pBt->mutex) ); | | | < > | 39615 39616 39617 39618 39619 39620 39621 39622 39623 39624 39625 39626 39627 39628 39629 39630 39631 |
u16 first;
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->secureDelete ){
memset(&data[hdr], 0, pBt->usableSize - hdr);
}
data[hdr] = (char)flags;
first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
memset(&data[hdr+1], 0, 4);
data[hdr+7] = 0;
put2byte(&data[hdr+5], pBt->usableSize);
pPage->nFree = pBt->usableSize - first;
decodeFlags(pPage, flags);
|
| ︙ | ︙ | |||
39336 39337 39338 39339 39340 39341 39342 39343 39344 39345 39346 39347 39348 39349 |
pBt->db = db;
sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
pBt->pCursor = 0;
pBt->pPage1 = 0;
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
pBt->pageSize = get2byte(&zDbHeader[16]);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
pBt->pageSize = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the magic name ":memory:" will create an in-memory database, then
** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
| > > > | 39937 39938 39939 39940 39941 39942 39943 39944 39945 39946 39947 39948 39949 39950 39951 39952 39953 |
pBt->db = db;
sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
pBt->pCursor = 0;
pBt->pPage1 = 0;
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
#ifdef SQLITE_SECURE_DELETE
pBt->secureDelete = 1;
#endif
pBt->pageSize = get2byte(&zDbHeader[16]);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
pBt->pageSize = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the magic name ":memory:" will create an in-memory database, then
** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
|
| ︙ | ︙ | |||
39692 39693 39694 39695 39696 39697 39698 39699 39700 39701 39702 39703 39704 39705 |
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
int n;
sqlite3BtreeEnter(p);
n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
sqlite3BtreeLeave(p);
return n;
}
#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
/*
** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
** is disabled. The default value for the auto-vacuum property is
** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
| > > > > > > > > > > > > > > > > > | 40296 40297 40298 40299 40300 40301 40302 40303 40304 40305 40306 40307 40308 40309 40310 40311 40312 40313 40314 40315 40316 40317 40318 40319 40320 40321 40322 40323 40324 40325 40326 |
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
int n;
sqlite3BtreeEnter(p);
n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
sqlite3BtreeLeave(p);
return n;
}
/*
** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1,
** then make no changes. Always return the value of the secureDelete
** setting after the change.
*/
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
int b;
if( p==0 ) return 0;
sqlite3BtreeEnter(p);
if( newFlag>=0 ){
p->pBt->secureDelete = (newFlag!=0) ? 1 : 0;
}
b = p->pBt->secureDelete;
sqlite3BtreeLeave(p);
return b;
}
#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
/*
** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
** is disabled. The default value for the auto-vacuum property is
** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
|
| ︙ | ︙ | |||
42435 42436 42437 42438 42439 42440 42441 | /* Increment the free page count on pPage1 */ rc = sqlite3PagerWrite(pPage1->pDbPage); if( rc ) goto freepage_out; nFree = get4byte(&pPage1->aData[36]); put4byte(&pPage1->aData[36], nFree+1); | | | | | | | | | | | < > | 43056 43057 43058 43059 43060 43061 43062 43063 43064 43065 43066 43067 43068 43069 43070 43071 43072 43073 43074 43075 43076 43077 43078 43079 43080 |
/* Increment the free page count on pPage1 */
rc = sqlite3PagerWrite(pPage1->pDbPage);
if( rc ) goto freepage_out;
nFree = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], nFree+1);
if( pBt->secureDelete ){
/* If the secure_delete option is enabled, then
** always fully overwrite deleted information with zeros.
*/
if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
|| ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
){
goto freepage_out;
}
memset(pPage->aData, 0, pPage->pBt->pageSize);
}
/* If the database supports auto-vacuum, write an entry in the pointer-map
** to indicate that the page is free.
*/
if( ISAUTOVACUUM ){
ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc);
if( rc ) goto freepage_out;
|
| ︙ | ︙ | |||
42496 42497 42498 42499 42500 42501 42502 |
** to 3.6.0 or later) we should consider fixing the conditional above
** to read "usableSize/4-2" instead of "usableSize/4-8".
*/
rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], nLeaf+1);
put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
| < | < | 43117 43118 43119 43120 43121 43122 43123 43124 43125 43126 43127 43128 43129 43130 43131 43132 43133 |
** to 3.6.0 or later) we should consider fixing the conditional above
** to read "usableSize/4-2" instead of "usableSize/4-8".
*/
rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], nLeaf+1);
put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
if( pPage && !pBt->secureDelete ){
sqlite3PagerDontWrite(pPage->pDbPage);
}
rc = btreeSetHasContent(pBt, iPage);
}
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
goto freepage_out;
}
}
|
| ︙ | ︙ | |||
42574 42575 42576 42577 42578 42579 42580 |
** file the database must be corrupt. */
return SQLITE_CORRUPT_BKPT;
}
if( nOvfl ){
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
if( rc ) return rc;
}
| > > > > > > > > > > > > > > > > | > > | 43193 43194 43195 43196 43197 43198 43199 43200 43201 43202 43203 43204 43205 43206 43207 43208 43209 43210 43211 43212 43213 43214 43215 43216 43217 43218 43219 43220 43221 43222 43223 43224 43225 |
** file the database must be corrupt. */
return SQLITE_CORRUPT_BKPT;
}
if( nOvfl ){
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
if( rc ) return rc;
}
if( (pOvfl || (pOvfl = btreePageLookup(pBt, ovflPgno)))
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
){
/* There is no reason any cursor should have an outstanding reference
** to an overflow page belonging to a cell that is being deleted/updated.
** So if there exists more than one reference to this page, then it
** must not really be an overflow page and the database must be corrupt.
** It is helpful to detect this before calling freePage2(), as
** freePage2() may zero the page contents if secure-delete mode is
** enabled. If this 'overflow' page happens to be a page that the
** caller is iterating through or using in some other way, this
** can be problematic.
*/
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = freePage2(pBt, pOvfl, ovflPgno);
}
if( pOvfl ){
sqlite3PagerUnref(pOvfl->pDbPage);
}
if( rc ) return rc;
ovflPgno = iNext;
}
return SQLITE_OK;
|
| ︙ | ︙ | |||
42818 42819 42820 42821 42822 42823 42824 |
int i, /* New cell becomes the i-th cell of the page */
u8 *pCell, /* Content of the new cell */
int sz, /* Bytes of content in pCell */
u8 *pTemp, /* Temp storage space for pCell, if needed */
Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
int *pRC /* Read and write return code from here */
){
| | | 43455 43456 43457 43458 43459 43460 43461 43462 43463 43464 43465 43466 43467 43468 43469 |
int i, /* New cell becomes the i-th cell of the page */
u8 *pCell, /* Content of the new cell */
int sz, /* Bytes of content in pCell */
u8 *pTemp, /* Temp storage space for pCell, if needed */
Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
int *pRC /* Read and write return code from here */
){
int idx = 0; /* Where to write new cell content in data[] */
int j; /* Loop counter */
int end; /* First byte past the last cell pointer in data[] */
int ins; /* Index in data[] where new cell pointer is inserted */
int cellOffset; /* Address of first cell pointer in data[] */
u8 *data; /* The content of the whole page */
u8 *ptr; /* Used for moving information around in data[] */
|
| ︙ | ︙ | |||
43309 43310 43311 43312 43313 43314 43315 |
** later on.
**
** Unless SQLite is compiled in secure-delete mode. In this case,
** the dropCell() routine will overwrite the entire cell with zeroes.
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
| > > > | > > > | | < > > | 43946 43947 43948 43949 43950 43951 43952 43953 43954 43955 43956 43957 43958 43959 43960 43961 43962 43963 43964 43965 43966 43967 43968 43969 43970 |
** later on.
**
** Unless SQLite is compiled in secure-delete mode. In this case,
** the dropCell() routine will overwrite the entire cell with zeroes.
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
if( pBt->secureDelete ){
int iOff = apDiv[i] - pParent->aData;
if( (iOff+szNew[i])>pBt->usableSize ){
rc = SQLITE_CORRUPT_BKPT;
memset(apOld, 0, (i+1)*sizeof(MemPage*));
goto balance_cleanup;
}else{
memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
}
}
dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
}
}
/* Make nMaxCells a multiple of 4 in order to preserve 8-byte
** alignment */
nMaxCells = (nMaxCells + 3)&~3;
|
| ︙ | ︙ | |||
43432 43433 43434 43435 43436 43437 43438 |
subtotal += szCell[i] + 2;
if( subtotal > usableSpace ){
szNew[k] = subtotal - szCell[i];
cntNew[k] = i;
if( leafData ){ i--; }
subtotal = 0;
k++;
| | | 44076 44077 44078 44079 44080 44081 44082 44083 44084 44085 44086 44087 44088 44089 44090 |
subtotal += szCell[i] + 2;
if( subtotal > usableSpace ){
szNew[k] = subtotal - szCell[i];
cntNew[k] = i;
if( leafData ){ i--; }
subtotal = 0;
k++;
if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
}
}
szNew[k] = subtotal;
cntNew[k] = nCell;
k++;
/*
|
| ︙ | ︙ | |||
43486 43487 43488 43489 43490 43491 43492 |
nOld>=3 ? apOld[2]->pgno : 0
));
/*
** Allocate k new pages. Reuse old pages where possible.
*/
if( apOld[0]->pgno<=1 ){
| | | 44130 44131 44132 44133 44134 44135 44136 44137 44138 44139 44140 44141 44142 44143 44144 |
nOld>=3 ? apOld[2]->pgno : 0
));
/*
** Allocate k new pages. Reuse old pages where possible.
*/
if( apOld[0]->pgno<=1 ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
pageFlags = apOld[0]->aData[0];
for(i=0; i<k; i++){
MemPage *pNew;
if( i<nOld ){
pNew = apNew[i] = apOld[i];
|
| ︙ | ︙ | |||
44924 44925 44926 44927 44928 44929 44930 | ** 7. Verify that the depth of all children is the same. ** 8. Make sure this page is at least 33% full or else it is ** the root of the tree. */ static int checkTreePage( IntegrityCk *pCheck, /* Context for the sanity check */ int iPage, /* Page number of the page to check */ | | > > > > | 45568 45569 45570 45571 45572 45573 45574 45575 45576 45577 45578 45579 45580 45581 45582 45583 45584 45585 45586 45587 45588 45589 45590 45591 45592 45593 45594 45595 45596 |
** 7. Verify that the depth of all children is the same.
** 8. Make sure this page is at least 33% full or else it is
** the root of the tree.
*/
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
char *zParentContext, /* Parent context */
i64 *pnParentMinKey,
i64 *pnParentMaxKey
){
MemPage *pPage;
int i, rc, depth, d2, pgno, cnt;
int hdr, cellStart;
int nCell;
u8 *data;
BtShared *pBt;
int usableSize;
char zContext[100];
char *hit = 0;
i64 nMinKey = 0;
i64 nMaxKey = 0;
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
/* Check that the page exists
*/
pBt = pCheck->pBt;
usableSize = pBt->usableSize;
|
| ︙ | ︙ | |||
44977 44978 44979 44980 44981 44982 44983 44984 44985 44986 44987 44988 44989 44990 |
*/
sqlite3_snprintf(sizeof(zContext), zContext,
"On tree page %d cell %d: ", iPage, i);
pCell = findCell(pPage,i);
btreeParseCellPtr(pPage, pCell, &info);
sz = info.nData;
if( !pPage->intKey ) sz += (int)info.nKey;
assert( sz==info.nPayload );
if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
){
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
#ifndef SQLITE_OMIT_AUTOVACUUM
| > > > > > > > > > > | 45625 45626 45627 45628 45629 45630 45631 45632 45633 45634 45635 45636 45637 45638 45639 45640 45641 45642 45643 45644 45645 45646 45647 45648 |
*/
sqlite3_snprintf(sizeof(zContext), zContext,
"On tree page %d cell %d: ", iPage, i);
pCell = findCell(pPage,i);
btreeParseCellPtr(pPage, pCell, &info);
sz = info.nData;
if( !pPage->intKey ) sz += (int)info.nKey;
/* For intKey pages, check that the keys are in order.
*/
else if( i==0 ) nMinKey = nMaxKey = info.nKey;
else{
if( info.nKey <= nMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
}
nMaxKey = info.nKey;
}
assert( sz==info.nPayload );
if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
){
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
#ifndef SQLITE_OMIT_AUTOVACUUM
|
| ︙ | ︙ | |||
45000 45001 45002 45003 45004 45005 45006 |
if( !pPage->leaf ){
pgno = get4byte(pCell);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
| | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 45658 45659 45660 45661 45662 45663 45664 45665 45666 45667 45668 45669 45670 45671 45672 45673 45674 45675 45676 45677 45678 45679 45680 45681 45682 45683 45684 45685 45686 45687 45688 45689 45690 45691 45692 45693 45694 45695 45696 45697 45698 45699 45700 45701 45702 45703 45704 45705 45706 45707 45708 45709 45710 45711 45712 45713 45714 45715 45716 45717 45718 45719 45720 45721 45722 45723 45724 45725 45726 45727 |
if( !pPage->leaf ){
pgno = get4byte(pCell);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
}
depth = d2;
}
}
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
sqlite3_snprintf(sizeof(zContext), zContext,
"On page %d at right child: ", iPage);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
}
/* For intKey leaf pages, check that the min/max keys are in order
** with any left/parent/right pages.
*/
if( pPage->leaf && pPage->intKey ){
/* if we are a left child page */
if( pnParentMinKey ){
/* if we are the left most child page */
if( !pnParentMaxKey ){
if( nMaxKey > *pnParentMinKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent min of %lld)",
nMaxKey, *pnParentMinKey);
}
}else{
if( nMinKey <= *pnParentMinKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent min of %lld)",
nMinKey, *pnParentMinKey);
}
if( nMaxKey > *pnParentMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent max of %lld)",
nMaxKey, *pnParentMaxKey);
}
*pnParentMinKey = nMaxKey;
}
/* else if we're a right child page */
} else if( pnParentMaxKey ){
if( nMinKey <= *pnParentMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent max of %lld)",
nMinKey, *pnParentMaxKey);
}
}
}
/* Check for complete coverage of the page
*/
data = pPage->aData;
hdr = pPage->hdrOffset;
hit = sqlite3PageMalloc( pBt->pageSize );
if( hit==0 ){
pCheck->mallocFailed = 1;
|
| ︙ | ︙ | |||
45042 45043 45044 45045 45046 45047 45048 |
u16 size = 1024;
int j;
if( pc<=usableSize-4 ){
size = cellSizePtr(pPage, &data[pc]);
}
if( (pc+size-1)>=usableSize ){
checkAppendMsg(pCheck, 0,
| | | 45737 45738 45739 45740 45741 45742 45743 45744 45745 45746 45747 45748 45749 45750 45751 |
u16 size = 1024;
int j;
if( pc<=usableSize-4 ){
size = cellSizePtr(pPage, &data[pc]);
}
if( (pc+size-1)>=usableSize ){
checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage);
}else{
for(j=pc+size-1; j>=pc; j--) hit[j]++;
}
}
i = get2byte(&data[hdr+1]);
while( i>0 ){
int size, j;
|
| ︙ | ︙ | |||
45148 45149 45150 45151 45152 45153 45154 |
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
if( aRoot[i]==0 ) continue;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum && aRoot[i]>1 ){
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
}
#endif
| | | 45843 45844 45845 45846 45847 45848 45849 45850 45851 45852 45853 45854 45855 45856 45857 |
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
if( aRoot[i]==0 ) continue;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum && aRoot[i]>1 ){
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
}
#endif
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
}
/* Make sure every page in the file is referenced
*/
for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
#ifdef SQLITE_OMIT_AUTOVACUUM
if( sCheck.anRef[i]==0 ){
|
| ︙ | ︙ | |||
45481 45482 45483 45484 45485 45486 45487 |
pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse));
if( pParse==0 ){
sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory");
rc = SQLITE_NOMEM;
}else{
pParse->db = pDb;
if( sqlite3OpenTempDatabase(pParse) ){
| < > | 46176 46177 46178 46179 46180 46181 46182 46183 46184 46185 46186 46187 46188 46189 46190 46191 46192 46193 |
pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse));
if( pParse==0 ){
sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory");
rc = SQLITE_NOMEM;
}else{
pParse->db = pDb;
if( sqlite3OpenTempDatabase(pParse) ){
sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
sqlite3StackFree(pErrorDb, pParse);
}
if( rc ){
return 0;
}
}
|
| ︙ | ︙ | |||
46327 46328 46329 46330 46331 46332 46333 46334 46335 46336 46337 46338 46339 46340 |
** there are reports that windows throws an expection
** if the floating point value is out of range. (See ticket #2880.)
** Because we do not completely understand the problem, we will
** take the conservative approach and always do range tests
** before attempting the conversion.
*/
static i64 doubleToInt64(double r){
/*
** Many compilers we encounter do not define constants for the
** minimum and maximum 64-bit integers, or they define them
** inconsistently. And many do not understand the "LL" notation.
** So we define our own static constants here using nothing
** larger than a 32-bit integer constant.
*/
| > > > > | 47022 47023 47024 47025 47026 47027 47028 47029 47030 47031 47032 47033 47034 47035 47036 47037 47038 47039 |
** there are reports that windows throws an expection
** if the floating point value is out of range. (See ticket #2880.)
** Because we do not completely understand the problem, we will
** take the conservative approach and always do range tests
** before attempting the conversion.
*/
static i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
/* When floating-point is omitted, double and int64 are the same thing */
return r;
#else
/*
** Many compilers we encounter do not define constants for the
** minimum and maximum 64-bit integers, or they define them
** inconsistently. And many do not understand the "LL" notation.
** So we define our own static constants here using nothing
** larger than a 32-bit integer constant.
*/
|
| ︙ | ︙ | |||
46348 46349 46350 46351 46352 46353 46354 46355 46356 46357 46358 46359 46360 46361 |
** a very large positive number to an integer results in a very large
** negative integer. This makes no sense, but it is what x86 hardware
** does so for compatibility we will do the same in software. */
return minInt;
}else{
return (i64)r;
}
}
/*
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
** If pMem is an integer, then the value is exact. If pMem is
** a floating-point then the value returned is the integer part.
| > | 47047 47048 47049 47050 47051 47052 47053 47054 47055 47056 47057 47058 47059 47060 47061 |
** a very large positive number to an integer results in a very large
** negative integer. This makes no sense, but it is what x86 hardware
** does so for compatibility we will do the same in software. */
return minInt;
}else{
return (i64)r;
}
#endif
}
/*
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
** If pMem is an integer, then the value is exact. If pMem is
** a floating-point then the value returned is the integer part.
|
| ︙ | ︙ | |||
46475 46476 46477 46478 46479 46480 46481 46482 46483 |
MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
| > > > > | < | < < | | > > > | > | 47175 47176 47177 47178 47179 47180 47181 47182 47183 47184 47185 47186 47187 47188 47189 47190 47191 47192 47193 47194 47195 47196 47197 47198 47199 47200 47201 47202 47203 47204 47205 47206 47207 47208 |
MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Invalidate any prior representations.
**
** Every effort is made to force the conversion, even if the input
** is a string that does not look completely like a number. Convert
** as much of the string as we can and ignore the rest.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
int rc;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8);
if( rc ) return rc;
rc = sqlite3VdbeMemNulTerminate(pMem);
if( rc ) return rc;
if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
pMem->r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
sqlite3VdbeIntegerAffinity(pMem);
}
return SQLITE_OK;
}
/*
** Delete any previous value and set the value stored in *pMem to NULL.
*/
|
| ︙ | ︙ | |||
46541 46542 46543 46544 46545 46546 46547 46548 46549 46550 46551 46552 46553 46554 46555 46556 46557 46558 46559 46560 46561 46562 46563 46564 46565 46566 46567 46568 |
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemRelease(pMem);
pMem->u.i = val;
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
}
/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type REAL.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
if( sqlite3IsNaN(val) ){
sqlite3VdbeMemSetNull(pMem);
}else{
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
pMem->flags = MEM_Real;
pMem->type = SQLITE_FLOAT;
}
}
/*
** Delete any previous value and set the value of pMem to be an
** empty boolean index.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){
sqlite3 *db = pMem->db;
| > > | 47246 47247 47248 47249 47250 47251 47252 47253 47254 47255 47256 47257 47258 47259 47260 47261 47262 47263 47264 47265 47266 47267 47268 47269 47270 47271 47272 47273 47274 47275 |
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemRelease(pMem);
pMem->u.i = val;
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type REAL.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
if( sqlite3IsNaN(val) ){
sqlite3VdbeMemSetNull(pMem);
}else{
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
pMem->flags = MEM_Real;
pMem->type = SQLITE_FLOAT;
}
}
#endif
/*
** Delete any previous value and set the value of pMem to be an
** empty boolean index.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){
sqlite3 *db = pMem->db;
|
| ︙ | ︙ | |||
47180 47181 47182 47183 47184 47185 47186 |
}
/*
** Return the SQL associated with a prepared statement
*/
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
| | | 47887 47888 47889 47890 47891 47892 47893 47894 47895 47896 47897 47898 47899 47900 47901 |
}
/*
** Return the SQL associated with a prepared statement
*/
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
return (p && p->isPrepareV2) ? p->zSql : 0;
}
/*
** Swap all content between two VDBE structures.
*/
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
Vdbe tmp, *pTmp;
|
| ︙ | ︙ | |||
47368 47369 47370 47371 47372 47373 47374 47375 47376 47377 47378 47379 47380 47381 |
int j = -1-x;
assert( p->magic==VDBE_MAGIC_INIT );
assert( j>=0 && j<p->nLabel );
if( p->aLabel ){
p->aLabel[j] = p->nOp;
}
}
#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
/*
** The following type and function are used to iterate through all opcodes
** in a Vdbe main program and each of the sub-programs (triggers) it may
** invoke directly or indirectly. It should be used as follows:
| > > > > > > > | 48075 48076 48077 48078 48079 48080 48081 48082 48083 48084 48085 48086 48087 48088 48089 48090 48091 48092 48093 48094 48095 |
int j = -1-x;
assert( p->magic==VDBE_MAGIC_INIT );
assert( j>=0 && j<p->nLabel );
if( p->aLabel ){
p->aLabel[j] = p->nOp;
}
}
/*
** Mark the VDBE as one that can only be run one time.
*/
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){
p->runOnlyOnce = 1;
}
#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
/*
** The following type and function are used to iterate through all opcodes
** in a Vdbe main program and each of the sub-programs (triggers) it may
** invoke directly or indirectly. It should be used as follows:
|
| ︙ | ︙ | |||
48173 48174 48175 48176 48177 48178 48179 | sqlite3 *db = p->db; /* The database connection */ int i; /* Loop counter */ int rc = SQLITE_OK; /* Return code */ Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */ assert( p->explain ); assert( p->magic==VDBE_MAGIC_RUN ); | < | 48887 48888 48889 48890 48891 48892 48893 48894 48895 48896 48897 48898 48899 48900 | sqlite3 *db = p->db; /* The database connection */ int i; /* Loop counter */ int rc = SQLITE_OK; /* Return code */ Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */ assert( p->explain ); assert( p->magic==VDBE_MAGIC_RUN ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); /* Even though this opcode does not use dynamic strings for ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ releaseMemArray(pMem, 8); |
| ︙ | ︙ | |||
48588 48589 48590 48591 48592 48593 48594 |
sqlite3BtreeCloseCursor(pCx->pCursor);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pCx->pModule;
p->inVtabMethod = 1;
| < < | 49301 49302 49303 49304 49305 49306 49307 49308 49309 49310 49311 49312 49313 49314 49315 |
sqlite3BtreeCloseCursor(pCx->pCursor);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pCx->pModule;
p->inVtabMethod = 1;
pModule->xClose(pVtabCursor);
p->inVtabMethod = 0;
}
#endif
}
/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
|
| ︙ | ︙ | |||
48771 48772 48773 48774 48775 48776 48777 |
needXcommit = 1;
if( i!=1 ) nTrans++;
}
}
/* If there are any write-transactions at all, invoke the commit hook */
if( needXcommit && db->xCommitCallback ){
| < < | 49482 49483 49484 49485 49486 49487 49488 49489 49490 49491 49492 49493 49494 49495 49496 |
needXcommit = 1;
if( i!=1 ) nTrans++;
}
}
/* If there are any write-transactions at all, invoke the commit hook */
if( needXcommit && db->xCommitCallback ){
rc = db->xCommitCallback(db->pCommitArg);
if( rc ){
return SQLITE_CONSTRAINT;
}
}
/* The simple case - no more than one database file (not counting the
** TEMP database) has a transaction active. There is no need for the
|
| ︙ | ︙ | |||
49327 49328 49329 49330 49331 49332 49333 | sqlite3 *db; db = p->db; /* If the VM did not run to completion or if it encountered an ** error, then it might not have been halted properly. So halt ** it now. */ | < < > | 50036 50037 50038 50039 50040 50041 50042 50043 50044 50045 50046 50047 50048 50049 50050 50051 50052 50053 50054 50055 50056 50057 50058 50059 50060 50061 50062 50063 50064 50065 50066 50067 50068 50069 50070 |
sqlite3 *db;
db = p->db;
/* If the VM did not run to completion or if it encountered an
** error, then it might not have been halted properly. So halt
** it now.
*/
sqlite3VdbeHalt(p);
/* If the VDBE has be run even partially, then transfer the error code
** and error message from the VDBE into the main database structure. But
** if the VDBE has just been set to run but has not actually executed any
** instructions yet, leave the main database error information unchanged.
*/
if( p->pc>=0 ){
if( p->zErrMsg ){
sqlite3BeginBenignMalloc();
sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT);
sqlite3EndBenignMalloc();
db->errCode = p->rc;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}else if( p->rc ){
sqlite3Error(db, p->rc, 0);
}else{
sqlite3Error(db, SQLITE_OK, 0);
}
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
** to sqlite3_step(). For consistency (since sqlite3_step() was
** called), set the database error in this case as well.
*/
sqlite3Error(db, p->rc, 0);
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
|
| ︙ | ︙ | |||
49450 49451 49452 49453 49454 49455 49456 49457 49458 49459 49460 49461 49462 49463 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); p->magic = VDBE_MAGIC_DEAD; sqlite3DbFree(db, p->pFree); sqlite3DbFree(db, p); } /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error ** prevents us from positioning the cursor to its correct position. | > | 50158 50159 50160 50161 50162 50163 50164 50165 50166 50167 50168 50169 50170 50171 50172 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); p->magic = VDBE_MAGIC_DEAD; sqlite3DbFree(db, p->pFree); p->db = 0; sqlite3DbFree(db, p); } /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error ** prevents us from positioning the cursor to its correct position. |
| ︙ | ︙ | |||
50130 50131 50132 50133 50134 50135 50136 |
assert( sqlite3BtreeCursorIsValid(pCur) );
rc = sqlite3BtreeKeySize(pCur, &nCellKey);
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
/* nCellKey will always be between 0 and 0xffffffff because of the say
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
| | | 50839 50840 50841 50842 50843 50844 50845 50846 50847 50848 50849 50850 50851 50852 50853 |
assert( sqlite3BtreeCursorIsValid(pCur) );
rc = sqlite3BtreeKeySize(pCur, &nCellKey);
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
/* nCellKey will always be between 0 and 0xffffffff because of the say
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
return SQLITE_CORRUPT_BKPT;
}
memset(&m, 0, sizeof(m));
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
if( rc ){
return rc;
}
assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID );
|
| ︙ | ︙ | |||
50256 50257 50258 50259 50260 50261 50262 50263 50264 50265 50266 50267 50268 50269 50270 50271 50272 50273 50274 50275 50276 50277 50278 50279 50280 |
** added or changed.
*/
SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
#endif
/*
** The following routine destroys a virtual machine that is created by
** the sqlite3_compile() routine. The integer returned is an SQLITE_
** success/failure code that describes the result of executing the virtual
** machine.
**
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
#if SQLITE_THREADSAFE
| > > > > > > > > > > > > > > > > > > > > > > | > > > > | 50965 50966 50967 50968 50969 50970 50971 50972 50973 50974 50975 50976 50977 50978 50979 50980 50981 50982 50983 50984 50985 50986 50987 50988 50989 50990 50991 50992 50993 50994 50995 50996 50997 50998 50999 51000 51001 51002 51003 51004 51005 51006 51007 51008 51009 51010 51011 51012 51013 51014 51015 51016 51017 51018 51019 51020 51021 51022 51023 |
** added or changed.
*/
SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
#endif
/*
** Check on a Vdbe to make sure it has not been finalized. Log
** an error and return true if it has been finalized (or is otherwise
** invalid). Return false if it is ok.
*/
static int vdbeSafety(Vdbe *p){
if( p->db==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
return 1;
}else{
return 0;
}
}
static int vdbeSafetyNotNull(Vdbe *p){
if( p==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
return 1;
}else{
return vdbeSafety(p);
}
}
/*
** The following routine destroys a virtual machine that is created by
** the sqlite3_compile() routine. The integer returned is an SQLITE_
** success/failure code that describes the result of executing the virtual
** machine.
**
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex;
#endif
if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
#if SQLITE_THREADSAFE
mutex = v->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
rc = sqlite3VdbeFinalize(v);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(mutex);
}
return rc;
|
| ︙ | ︙ | |||
50521 50522 50523 50524 50525 50526 50527 |
*/
static int sqlite3Step(Vdbe *p){
sqlite3 *db;
int rc;
assert(p);
if( p->magic!=VDBE_MAGIC_RUN ){
| > > | | > < | < < < < < | 51256 51257 51258 51259 51260 51261 51262 51263 51264 51265 51266 51267 51268 51269 51270 51271 51272 51273 51274 51275 51276 51277 51278 51279 51280 51281 51282 51283 51284 51285 51286 |
*/
static int sqlite3Step(Vdbe *p){
sqlite3 *db;
int rc;
assert(p);
if( p->magic!=VDBE_MAGIC_RUN ){
sqlite3_log(SQLITE_MISUSE,
"attempt to step a halted statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
/* Check that malloc() has not failed. If it has, return early. */
db = p->db;
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM;
return SQLITE_NOMEM;
}
if( p->pc<=0 && p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
goto end_of_step;
}
if( p->pc<0 ){
/* If there are no other statements currently running, then
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
if( db->activeVdbeCnt==0 ){
db->u1.isInterrupted = 0;
|
| ︙ | ︙ | |||
50573 50574 50575 50576 50577 50578 50579 |
rc = sqlite3VdbeList(p);
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
rc = sqlite3VdbeExec(p);
}
| < < < < | 51305 51306 51307 51308 51309 51310 51311 51312 51313 51314 51315 51316 51317 51318 |
rc = sqlite3VdbeList(p);
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
rc = sqlite3VdbeExec(p);
}
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){
double rNow;
u64 elapseTime;
|
| ︙ | ︙ | |||
50623 50624 50625 50626 50627 50628 50629 |
/*
** This is the top-level implementation of sqlite3_step(). Call
** sqlite3Step() to do most of the work. If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
| | < | | > > > > > > | | | | | | | | | | | | | | | | | | | | | > | | | | | | | < | 51351 51352 51353 51354 51355 51356 51357 51358 51359 51360 51361 51362 51363 51364 51365 51366 51367 51368 51369 51370 51371 51372 51373 51374 51375 51376 51377 51378 51379 51380 51381 51382 51383 51384 51385 51386 51387 51388 51389 51390 51391 51392 51393 51394 51395 51396 51397 51398 51399 51400 51401 51402 |
/*
** This is the top-level implementation of sqlite3_step(). Call
** sqlite3Step() to do most of the work. If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_OK; /* Result from sqlite3Step() */
int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
int cnt = 0; /* Counter to prevent infinite loop of reprepares */
sqlite3 *db; /* The database connection */
if( vdbeSafetyNotNull(v) ){
return SQLITE_MISUSE_BKPT;
}
db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
v->rc = rc2;
} else {
v->zErrMsg = 0;
v->rc = rc = SQLITE_NOMEM;
}
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
*/
|
| ︙ | ︙ | |||
51125 51126 51127 51128 51129 51130 51131 |
** the mutex is released if any kind of error occurs.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
| > | > > > | | 51858 51859 51860 51861 51862 51863 51864 51865 51866 51867 51868 51869 51870 51871 51872 51873 51874 51875 51876 51877 51878 51879 51880 51881 |
** the mutex is released if any kind of error occurs.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
if( vdbeSafetyNotNull(p) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(p->db->mutex);
sqlite3_log(SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
if( i<1 || i>p->nVar ){
sqlite3Error(p->db, SQLITE_RANGE, 0);
sqlite3_mutex_leave(p->db->mutex);
return SQLITE_RANGE;
}
i--;
|
| ︙ | ︙ | |||
52223 52224 52225 52226 52227 52228 52229 |
**
** After this routine has finished, sqlite3VdbeFinalize() should be
** used to clean up the mess that was left behind.
*/
SQLITE_PRIVATE int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
| | | 52960 52961 52962 52963 52964 52965 52966 52967 52968 52969 52970 52971 52972 52973 52974 |
**
** After this routine has finished, sqlite3VdbeFinalize() should be
** used to clean up the mess that was left behind.
*/
SQLITE_PRIVATE int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
int pc=0; /* The program counter */
Op *aOp = p->aOp; /* Copy of p->aOp */
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */
u8 encoding = ENC(db); /* The database encoding */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
| ︙ | ︙ | |||
52334 52335 52336 52337 52338 52339 52340 |
int i; /* Loop counter */
char *zData; /* Part of the record being decoded */
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
| | | 53071 53072 53073 53074 53075 53076 53077 53078 53079 53080 53081 53082 53083 53084 53085 |
int i; /* Loop counter */
char *zData; /* Part of the record being decoded */
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
u32 szField; /* Number of bytes in the content of a field */
int szHdr; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
Mem *pReg; /* PseudoTable input register */
} am;
struct OP_Affinity_stack_vars {
const char *zAffinity; /* The affinity to be applied */
char cAff; /* A single character of affinity */
|
| ︙ | ︙ | |||
52646 52647 52648 52649 52650 52651 52652 |
char *zTrace;
} cm;
} u;
/* End automatically generated code
********************************************************************/
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
| < | 53383 53384 53385 53386 53387 53388 53389 53390 53391 53392 53393 53394 53395 53396 |
char *zTrace;
} cm;
} u;
/* End automatically generated code
********************************************************************/
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
sqlite3VdbeMutexArrayEnter(p);
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
** sqlite3_column_text16() failed. */
goto no_mem;
}
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
|
| ︙ | ︙ | |||
52731 52732 52733 52734 52735 52736 52737 |
** sqlite3VdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( checkProgress ){
if( db->nProgressOps==nProgressOps ){
int prc;
| < | < | 53467 53468 53469 53470 53471 53472 53473 53474 53475 53476 53477 53478 53479 53480 53481 |
** sqlite3VdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( checkProgress ){
if( db->nProgressOps==nProgressOps ){
int prc;
prc = db->xProgress(db->pProgressArg);
if( prc!=0 ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
}
nProgressOps = 0;
}
nProgressOps++;
|
| ︙ | ︙ | |||
52935 52936 52937 52938 52939 52940 52941 52942 52943 52944 52945 52946 52947 52948 52949 |
break;
}
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
p->pc = pc;
if( pOp->p4.z ){
sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
if( rc==SQLITE_BUSY ){
p->rc = rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
| > > > > > > | 53669 53670 53671 53672 53673 53674 53675 53676 53677 53678 53679 53680 53681 53682 53683 53684 53685 53686 53687 53688 53689 |
break;
}
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
p->pc = pc;
if( pOp->p4.z ){
assert( p->rc!=SQLITE_OK );
sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
}else if( p->rc ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
if( rc==SQLITE_BUSY ){
p->rc = rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
|
| ︙ | ︙ | |||
52969 52970 52971 52972 52973 52974 52975 52976 52977 52978 52979 52980 52981 52982 52983 52984 52985 52986 52987 52988 52989 52990 52991 52992 52993 |
*/
case OP_Int64: { /* out2-prerelease */
assert( pOp->p4.pI64!=0 );
pOut->u.i = *pOp->p4.pI64;
break;
}
/* Opcode: Real * P2 * P4 *
**
** P4 is a pointer to a 64-bit floating point value.
** Write that value into register P2.
*/
case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
pOut->flags = MEM_Real;
assert( !sqlite3IsNaN(*pOp->p4.pReal) );
pOut->r = *pOp->p4.pReal;
break;
}
/* Opcode: String8 * P2 * P4 *
**
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time.
*/
case OP_String8: { /* same as TK_STRING, out2-prerelease */
| > > | 53709 53710 53711 53712 53713 53714 53715 53716 53717 53718 53719 53720 53721 53722 53723 53724 53725 53726 53727 53728 53729 53730 53731 53732 53733 53734 53735 |
*/
case OP_Int64: { /* out2-prerelease */
assert( pOp->p4.pI64!=0 );
pOut->u.i = *pOp->p4.pI64;
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: Real * P2 * P4 *
**
** P4 is a pointer to a 64-bit floating point value.
** Write that value into register P2.
*/
case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
pOut->flags = MEM_Real;
assert( !sqlite3IsNaN(*pOp->p4.pReal) );
pOut->r = *pOp->p4.pReal;
break;
}
#endif
/* Opcode: String8 * P2 * P4 *
**
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time.
*/
case OP_String8: { /* same as TK_STRING, out2-prerelease */
|
| ︙ | ︙ | |||
53390 53391 53392 53393 53394 53395 53396 53397 53398 53399 53400 53401 53402 53403 53404 53405 53406 53407 53408 53409 53410 53411 |
u.af.iB = (i64)u.af.rB;
if( u.af.iA==0 ) goto arithmetic_result_is_null;
if( u.af.iA==-1 ) u.af.iA = 1;
u.af.rB = (double)(u.af.iB % u.af.iA);
break;
}
}
if( sqlite3IsNaN(u.af.rB) ){
goto arithmetic_result_is_null;
}
pOut->r = u.af.rB;
MemSetTypeFlag(pOut, MEM_Real);
if( (u.af.flags & MEM_Real)==0 ){
sqlite3VdbeIntegerAffinity(pOut);
}
}
break;
arithmetic_result_is_null:
sqlite3VdbeMemSetNull(pOut);
break;
}
| > > > > > | 54132 54133 54134 54135 54136 54137 54138 54139 54140 54141 54142 54143 54144 54145 54146 54147 54148 54149 54150 54151 54152 54153 54154 54155 54156 54157 54158 |
u.af.iB = (i64)u.af.rB;
if( u.af.iA==0 ) goto arithmetic_result_is_null;
if( u.af.iA==-1 ) u.af.iA = 1;
u.af.rB = (double)(u.af.iB % u.af.iA);
break;
}
}
#ifdef SQLITE_OMIT_FLOATING_POINT
pOut->u.i = u.af.rB;
MemSetTypeFlag(pOut, MEM_Int);
#else
if( sqlite3IsNaN(u.af.rB) ){
goto arithmetic_result_is_null;
}
pOut->r = u.af.rB;
MemSetTypeFlag(pOut, MEM_Real);
if( (u.af.flags & MEM_Real)==0 ){
sqlite3VdbeIntegerAffinity(pOut);
}
#endif
}
break;
arithmetic_result_is_null:
sqlite3VdbeMemSetNull(pOut);
break;
}
|
| ︙ | ︙ | |||
53490 53491 53492 53493 53494 53495 53496 |
u.ag.ctx.isError = 0;
if( u.ag.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
u.ag.ctx.pColl = pOp[-1].p4.pColl;
}
| < < < < < < < < < | 54237 54238 54239 54240 54241 54242 54243 54244 54245 54246 54247 54248 54249 54250 54251 54252 54253 54254 54255 54256 |
u.ag.ctx.isError = 0;
if( u.ag.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
u.ag.ctx.pColl = pOp[-1].p4.pColl;
}
(*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal);
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
** to return a value. The following call releases any resources
** associated with such a value.
*/
sqlite3VdbeMemRelease(&u.ag.ctx.s);
goto no_mem;
}
/* If any auxiliary data functions have been called by this user function,
** immediately call the destructor for any non-static values.
|
| ︙ | ︙ | |||
53629 53630 53631 53632 53633 53634 53635 53636 53637 53638 53639 53640 53641 53642 53643 53644 53645 53646 53647 53648 53649 53650 53651 53652 53653 53654 53655 53656 53657 53658 |
}
}else{
MemSetTypeFlag(pIn1, MEM_Int);
}
break;
}
/* Opcode: RealAffinity P1 * * * *
**
** If register P1 holds an integer convert it to a real value.
**
** This opcode is used when extracting information from a column that
** has REAL affinity. Such column values may still be stored as
** integers, for space efficiency, but after extraction we want them
** to have only a real value.
*/
case OP_RealAffinity: { /* in1 */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Int ){
sqlite3VdbeMemRealify(pIn1);
}
break;
}
#ifndef SQLITE_OMIT_CAST
/* Opcode: ToText P1 * * * *
**
** Force the value in register P1 to be text.
** If the value is numeric, convert it to a string using the
** equivalent of printf(). Blob values are unchanged and
| > > | 54367 54368 54369 54370 54371 54372 54373 54374 54375 54376 54377 54378 54379 54380 54381 54382 54383 54384 54385 54386 54387 54388 54389 54390 54391 54392 54393 54394 54395 54396 54397 54398 |
}
}else{
MemSetTypeFlag(pIn1, MEM_Int);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: RealAffinity P1 * * * *
**
** If register P1 holds an integer convert it to a real value.
**
** This opcode is used when extracting information from a column that
** has REAL affinity. Such column values may still be stored as
** integers, for space efficiency, but after extraction we want them
** to have only a real value.
*/
case OP_RealAffinity: { /* in1 */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Int ){
sqlite3VdbeMemRealify(pIn1);
}
break;
}
#endif
#ifndef SQLITE_OMIT_CAST
/* Opcode: ToText P1 * * * *
**
** Force the value in register P1 to be text.
** If the value is numeric, convert it to a string using the
** equivalent of printf(). Blob values are unchanged and
|
| ︙ | ︙ | |||
53728 53729 53730 53731 53732 53733 53734 |
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Null)==0 ){
sqlite3VdbeMemIntegerify(pIn1);
}
break;
}
| | | | 54468 54469 54470 54471 54472 54473 54474 54475 54476 54477 54478 54479 54480 54481 54482 54483 54484 54485 54486 54487 54488 54489 54490 54491 54492 54493 54494 54495 54496 54497 54498 54499 |
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Null)==0 ){
sqlite3VdbeMemIntegerify(pIn1);
}
break;
}
#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT)
/* Opcode: ToReal P1 * * * *
**
** Force the value in register P1 to be a floating point number.
** If The value is currently an integer, convert it.
** If the value is text or blob, try to convert it to an integer using the
** equivalent of atoi() and store 0.0 if no such conversion is possible.
**
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_ToReal: { /* same as TK_TO_REAL, in1 */
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Null)==0 ){
sqlite3VdbeMemRealify(pIn1);
}
break;
}
#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
/* Opcode: Lt P1 P2 P3 P4 P5
**
** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
** jump to address P2.
**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
|
| ︙ | ︙ | |||
54167 54168 54169 54170 54171 54172 54173 | int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ u8 *zIdx; /* Index into header */ u8 *zEndHdr; /* Pointer to first byte after the header */ u32 offset; /* Offset into the data */ | | | 54907 54908 54909 54910 54911 54912 54913 54914 54915 54916 54917 54918 54919 54920 54921 | int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ u8 *zIdx; /* Index into header */ u8 *zEndHdr; /* Pointer to first byte after the header */ u32 offset; /* Offset into the data */ u32 szField; /* Number of bytes in the content of a field */ int szHdr; /* Size of the header size field at start of record */ int avail; /* Number of bytes of available data */ Mem *pReg; /* PseudoTable input register */ #endif /* local variables moved into u.am */ u.am.p1 = pOp->p1; |
| ︙ | ︙ | |||
54343 54344 54345 54346 54347 54348 54349 |
u.am.zIdx = (u8 *)&u.am.zData[u.am.szHdr];
/* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[]
** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th
** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning
** of the record to the start of the data for the u.am.i-th column
*/
| < | | > > > > > | | | 55083 55084 55085 55086 55087 55088 55089 55090 55091 55092 55093 55094 55095 55096 55097 55098 55099 55100 55101 55102 55103 55104 55105 55106 55107 55108 55109 55110 55111 55112 55113 55114 55115 55116 55117 55118 55119 55120 55121 55122 55123 55124 55125 55126 55127 |
u.am.zIdx = (u8 *)&u.am.zData[u.am.szHdr];
/* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[]
** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th
** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning
** of the record to the start of the data for the u.am.i-th column
*/
for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
if( u.am.zIdx<u.am.zEndHdr ){
u.am.aOffset[u.am.i] = u.am.offset;
u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]);
u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]);
u.am.offset += u.am.szField;
if( u.am.offset<u.am.szField ){ /* True if u.am.offset overflows */
u.am.zIdx = &u.am.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
break;
}
}else{
/* If u.am.i is less that u.am.nField, then there are less fields in this
** record than SetNumColumns indicated there are columns in the
** table. Set the u.am.offset for any extra columns not present in
** the record to 0. This tells code below to store a NULL
** instead of deserializing a value from the record.
*/
u.am.aOffset[u.am.i] = 0;
}
}
sqlite3VdbeMemRelease(&u.am.sMem);
u.am.sMem.flags = MEM_Null;
/* If we have read more header data than was contained in the header,
** or if the end of the last field appears to be past the end of the
** record, or if the end of the last field appears to be before the end
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
if( (u.am.zIdx > u.am.zEndHdr) || (u.am.offset > u.am.payloadSize)
|| (u.am.zIdx==u.am.zEndHdr && u.am.offset!=u.am.payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
}
/* Get the column information. If u.am.aOffset[u.am.p2] is non-zero, then
** deserialize the value from the record. If u.am.aOffset[u.am.p2] is zero,
|
| ︙ | ︙ | |||
55237 55238 55239 55240 55241 55242 55243 | /* Opcode: OpenPseudo P1 P2 P3 * * ** ** Open a new cursor that points to a fake table that contains a single ** row of data. The content of that one row in the content of memory ** register P2. In other words, cursor P1 becomes an alias for the ** MEM_Blob content contained in register P2. ** | | | 55981 55982 55983 55984 55985 55986 55987 55988 55989 55990 55991 55992 55993 55994 55995 | /* Opcode: OpenPseudo P1 P2 P3 * * ** ** Open a new cursor that points to a fake table that contains a single ** row of data. The content of that one row in the content of memory ** register P2. In other words, cursor P1 becomes an alias for the ** MEM_Blob content contained in register P2. ** ** A pseudo-table created by this opcode is used to hold a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. The OP_Column opcode ** is the only cursor opcode that works with a pseudo-table. ** ** P3 is the number of fields in the records that will be stored by ** the pseudo-table. */ |
| ︙ | ︙ | |||
56189 56190 56191 56192 56193 56194 56195 |
}else if( u.bi.pC->deferredMoveto ){
u.bi.v = u.bi.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( u.bi.pC->pVtabCursor ){
u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab;
u.bi.pModule = u.bi.pVtab->pModule;
assert( u.bi.pModule->xRowid );
| < < | 56933 56934 56935 56936 56937 56938 56939 56940 56941 56942 56943 56944 56945 56946 56947 56948 56949 56950 |
}else if( u.bi.pC->deferredMoveto ){
u.bi.v = u.bi.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( u.bi.pC->pVtabCursor ){
u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab;
u.bi.pModule = u.bi.pVtab->pModule;
assert( u.bi.pModule->xRowid );
rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = u.bi.pVtab->zErrMsg;
u.bi.pVtab->zErrMsg = 0;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( u.bi.pC->pCursor!=0 );
rc = sqlite3VdbeCursorMoveto(u.bi.pC);
if( rc ) goto abort_due_to_error;
if( u.bi.pC->rowidIsValid ){
u.bi.v = u.bi.pC->lastRowid;
|
| ︙ | ︙ | |||
56749 56750 56751 56752 56753 56754 56755 |
sqlite3BtreeEnterAll(db);
if( pOp->p2 || DbHasProperty(db, u.bu.iDb, DB_SchemaLoaded) ){
u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb);
u.bu.initData.db = db;
u.bu.initData.iDb = pOp->p1;
u.bu.initData.pzErrMsg = &p->zErrMsg;
u.bu.zSql = sqlite3MPrintf(db,
| | < < | 57491 57492 57493 57494 57495 57496 57497 57498 57499 57500 57501 57502 57503 57504 57505 57506 57507 57508 57509 57510 57511 57512 57513 57514 57515 57516 57517 |
sqlite3BtreeEnterAll(db);
if( pOp->p2 || DbHasProperty(db, u.bu.iDb, DB_SchemaLoaded) ){
u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb);
u.bu.initData.db = db;
u.bu.initData.iDb = pOp->p1;
u.bu.initData.pzErrMsg = &p->zErrMsg;
u.bu.zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z);
if( u.bu.zSql==0 ){
rc = SQLITE_NOMEM;
}else{
assert( db->init.busy==0 );
db->init.busy = 1;
u.bu.initData.rc = SQLITE_OK;
assert( !db->mallocFailed );
rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0);
if( rc==SQLITE_OK ) rc = u.bu.initData.rc;
sqlite3DbFree(db, u.bu.zSql);
db->init.busy = 0;
}
}
sqlite3BtreeLeaveAll(db);
if( rc==SQLITE_NOMEM ){
goto no_mem;
}
break;
|
| ︙ | ︙ | |||
57349 57350 57351 57352 57353 57354 57355 |
/* Opcode: Vacuum * * * * *
**
** Vacuum the entire database. This opcode will cause other virtual
** machines to be created and run. It may not be called from within
** a transaction.
*/
case OP_Vacuum: {
| < < | 58089 58090 58091 58092 58093 58094 58095 58096 58097 58098 58099 58100 58101 58102 58103 |
/* Opcode: Vacuum * * * * *
**
** Vacuum the entire database. This opcode will cause other virtual
** machines to be created and run. It may not be called from within
** a transaction.
*/
case OP_Vacuum: {
rc = sqlite3RunVacuum(&p->zErrMsg, db);
break;
}
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
/* Opcode: IncrVacuum P1 P2 * * *
**
|
| ︙ | ︙ | |||
57501 57502 57503 57504 57505 57506 57507 | #endif /* local variables moved into u.cf */ u.cf.pCur = 0; u.cf.pVtabCursor = 0; u.cf.pVtab = pOp->p4.pVtab->pVtab; u.cf.pModule = (sqlite3_module *)u.cf.pVtab->pModule; assert(u.cf.pVtab && u.cf.pModule); | < < | 58239 58240 58241 58242 58243 58244 58245 58246 58247 58248 58249 58250 58251 58252 58253 58254 58255 58256 |
#endif /* local variables moved into u.cf */
u.cf.pCur = 0;
u.cf.pVtabCursor = 0;
u.cf.pVtab = pOp->p4.pVtab->pVtab;
u.cf.pModule = (sqlite3_module *)u.cf.pVtab->pModule;
assert(u.cf.pVtab && u.cf.pModule);
rc = u.cf.pModule->xOpen(u.cf.pVtab, &u.cf.pVtabCursor);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = u.cf.pVtab->zErrMsg;
u.cf.pVtab->zErrMsg = 0;
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
u.cf.pVtabCursor->pVtab = u.cf.pVtab;
/* Initialise vdbe cursor object */
u.cf.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
if( u.cf.pCur ){
|
| ︙ | ︙ | |||
57582 57583 57584 57585 57586 57587 57588 |
u.cg.res = 0;
u.cg.apArg = p->apArg;
for(u.cg.i = 0; u.cg.i<u.cg.nArg; u.cg.i++){
u.cg.apArg[u.cg.i] = &u.cg.pArgc[u.cg.i+1];
sqlite3VdbeMemStoreType(u.cg.apArg[u.cg.i]);
}
| < < | 58318 58319 58320 58321 58322 58323 58324 58325 58326 58327 58328 58329 58330 58331 58332 58333 58334 58335 58336 58337 58338 58339 58340 |
u.cg.res = 0;
u.cg.apArg = p->apArg;
for(u.cg.i = 0; u.cg.i<u.cg.nArg; u.cg.i++){
u.cg.apArg[u.cg.i] = &u.cg.pArgc[u.cg.i+1];
sqlite3VdbeMemStoreType(u.cg.apArg[u.cg.i]);
}
p->inVtabMethod = 1;
rc = u.cg.pModule->xFilter(u.cg.pVtabCursor, u.cg.iQuery, pOp->p4.z, u.cg.nArg, u.cg.apArg);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = u.cg.pVtab->zErrMsg;
u.cg.pVtab->zErrMsg = 0;
if( rc==SQLITE_OK ){
u.cg.res = u.cg.pModule->xEof(u.cg.pVtabCursor);
}
if( u.cg.res ){
pc = pOp->p2 - 1;
}
}
u.cg.pCur->nullRow = 0;
|
| ︙ | ︙ | |||
57640 57641 57642 57643 57644 57645 57646 | ** the current contents to u.ch.sContext.s so in case the user-function ** can use the already allocated buffer instead of allocating a ** new one. */ sqlite3VdbeMemMove(&u.ch.sContext.s, u.ch.pDest); MemSetTypeFlag(&u.ch.sContext.s, MEM_Null); | < < < < | 58374 58375 58376 58377 58378 58379 58380 58381 58382 58383 58384 58385 58386 58387 58388 58389 58390 58391 58392 58393 58394 58395 58396 58397 58398 58399 58400 58401 58402 58403 58404 |
** the current contents to u.ch.sContext.s so in case the user-function
** can use the already allocated buffer instead of allocating a
** new one.
*/
sqlite3VdbeMemMove(&u.ch.sContext.s, u.ch.pDest);
MemSetTypeFlag(&u.ch.sContext.s, MEM_Null);
rc = u.ch.pModule->xColumn(pCur->pVtabCursor, &u.ch.sContext, pOp->p2);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = u.ch.pVtab->zErrMsg;
u.ch.pVtab->zErrMsg = 0;
if( u.ch.sContext.isError ){
rc = u.ch.sContext.isError;
}
/* Copy the result of the function to the P3 register. We
** do this regardless of whether or not an error occurred to ensure any
** dynamic allocation in u.ch.sContext.s (a Mem struct) is released.
*/
sqlite3VdbeChangeEncoding(&u.ch.sContext.s, encoding);
sqlite3VdbeMemMove(u.ch.pDest, &u.ch.sContext.s);
REGISTER_TRACE(pOp->p3, u.ch.pDest);
UPDATE_MAX_BLOBSIZE(u.ch.pDest);
if( sqlite3VdbeMemTooBig(u.ch.pDest) ){
goto too_big;
}
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| ︙ | ︙ | |||
57699 57700 57701 57702 57703 57704 57705 | /* Invoke the xNext() method of the module. There is no way for the ** underlying implementation to return an error if one occurs during ** xNext(). Instead, if an error occurs, true is returned (indicating that ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ | < < | 58429 58430 58431 58432 58433 58434 58435 58436 58437 58438 58439 58440 58441 58442 58443 58444 58445 58446 58447 58448 58449 58450 58451 |
/* Invoke the xNext() method of the module. There is no way for the
** underlying implementation to return an error if one occurs during
** xNext(). Instead, if an error occurs, true is returned (indicating that
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
p->inVtabMethod = 1;
rc = u.ci.pModule->xNext(u.ci.pCur->pVtabCursor);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = u.ci.pVtab->zErrMsg;
u.ci.pVtab->zErrMsg = 0;
if( rc==SQLITE_OK ){
u.ci.res = u.ci.pModule->xEof(u.ci.pCur->pVtabCursor);
}
if( !u.ci.res ){
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
break;
}
|
| ︙ | ︙ | |||
57737 57738 57739 57740 57741 57742 57743 | #endif /* local variables moved into u.cj */ u.cj.pVtab = pOp->p4.pVtab->pVtab; u.cj.pName = &aMem[pOp->p1]; assert( u.cj.pVtab->pModule->xRename ); REGISTER_TRACE(pOp->p1, u.cj.pName); assert( u.cj.pName->flags & MEM_Str ); | < < | 58465 58466 58467 58468 58469 58470 58471 58472 58473 58474 58475 58476 58477 58478 58479 58480 58481 58482 | #endif /* local variables moved into u.cj */ u.cj.pVtab = pOp->p4.pVtab->pVtab; u.cj.pName = &aMem[pOp->p1]; assert( u.cj.pVtab->pModule->xRename ); REGISTER_TRACE(pOp->p1, u.cj.pName); assert( u.cj.pName->flags & MEM_Str ); rc = u.cj.pVtab->pModule->xRename(u.cj.pVtab, u.cj.pName->z); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = u.cj.pVtab->zErrMsg; u.cj.pVtab->zErrMsg = 0; break; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VUpdate P1 P2 P3 P4 * |
| ︙ | ︙ | |||
57795 57796 57797 57798 57799 57800 57801 |
u.ck.apArg = p->apArg;
u.ck.pX = &aMem[pOp->p3];
for(u.ck.i=0; u.ck.i<u.ck.nArg; u.ck.i++){
sqlite3VdbeMemStoreType(u.ck.pX);
u.ck.apArg[u.ck.i] = u.ck.pX;
u.ck.pX++;
}
| < < | 58521 58522 58523 58524 58525 58526 58527 58528 58529 58530 58531 58532 58533 58534 58535 58536 58537 58538 |
u.ck.apArg = p->apArg;
u.ck.pX = &aMem[pOp->p3];
for(u.ck.i=0; u.ck.i<u.ck.nArg; u.ck.i++){
sqlite3VdbeMemStoreType(u.ck.pX);
u.ck.apArg[u.ck.i] = u.ck.pX;
u.ck.pX++;
}
rc = u.ck.pModule->xUpdate(u.ck.pVtab, u.ck.nArg, u.ck.apArg, &u.ck.rowid);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = u.ck.pVtab->zErrMsg;
u.ck.pVtab->zErrMsg = 0;
if( rc==SQLITE_OK && pOp->p1 ){
assert( u.ck.nArg>1 && u.ck.apArg[0] && (u.ck.apArg[0]->flags&MEM_Null) );
db->lastRowid = u.ck.rowid;
}
p->nChange++;
}
break;
|
| ︙ | ︙ | |||
57877 57878 57879 57880 57881 57882 57883 57884 57885 57886 57887 57888 57889 57890 |
/*
** The magic Explain opcode are only inserted when explain==2 (which
** is to say when the EXPLAIN QUERY PLAN syntax is used.)
** This opcode records information from the optimizer. It is the
** the same as a no-op. This opcodesnever appears in a real VM program.
*/
default: { /* This is really OP_Noop and OP_Explain */
break;
}
/*****************************************************************************
** The cases of the switch statement above this line should all be indented
** by 6 spaces. But the left-most 6 spaces have been removed to improve the
** readability. From this point on down, the normal indentation rules are
| > | 58601 58602 58603 58604 58605 58606 58607 58608 58609 58610 58611 58612 58613 58614 58615 |
/*
** The magic Explain opcode are only inserted when explain==2 (which
** is to say when the EXPLAIN QUERY PLAN syntax is used.)
** This opcode records information from the optimizer. It is the
** the same as a no-op. This opcodesnever appears in a real VM program.
*/
default: { /* This is really OP_Noop and OP_Explain */
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
break;
}
/*****************************************************************************
** The cases of the switch statement above this line should all be indented
** by 6 spaces. But the left-most 6 spaces have been removed to improve the
** readability. From this point on down, the normal indentation rules are
|
| ︙ | ︙ | |||
57928 57929 57930 57931 57932 57933 57934 57935 57936 57937 57938 57939 57940 57941 | /* If we reach this point, it means that execution is finished with ** an error of some kind. */ vdbe_error_halt: assert( rc ); p->rc = rc; sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the | > > > | 58653 58654 58655 58656 58657 58658 58659 58660 58661 58662 58663 58664 58665 58666 58667 58668 58669 |
/* If we reach this point, it means that execution is finished with
** an error of some kind.
*/
vdbe_error_halt:
assert( rc );
p->rc = rc;
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
pc, p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0);
/* This is the only way out of this procedure. We have to
** release the mutexes on btrees that were acquired at the
|
| ︙ | ︙ | |||
57956 57957 57958 57959 57960 57961 57962 | */ no_mem: db->mallocFailed = 1; sqlite3SetString(&p->zErrMsg, db, "out of memory"); rc = SQLITE_NOMEM; goto vdbe_error_halt; | < < < < < < | 58684 58685 58686 58687 58688 58689 58690 58691 58692 58693 58694 58695 58696 58697 |
*/
no_mem:
db->mallocFailed = 1;
sqlite3SetString(&p->zErrMsg, db, "out of memory");
rc = SQLITE_NOMEM;
goto vdbe_error_halt;
/* Jump to here for any other kind of fatal error. The "rc" variable
** should hold the error number.
*/
abort_due_to_error:
assert( p->zErrMsg==0 );
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc!=SQLITE_IOERR_NOMEM ){
|
| ︙ | ︙ | |||
58081 58082 58083 58084 58085 58086 58087 |
rc = SQLITE_NOMEM;
goto blob_open_out;
}
do {
memset(pParse, 0, sizeof(Parse));
pParse->db = db;
| < < < < < < < < < | 58803 58804 58805 58806 58807 58808 58809 58810 58811 58812 58813 58814 58815 58816 58817 58818 58819 58820 58821 58822 58823 58824 58825 58826 58827 58828 58829 58830 58831 58832 58833 58834 58835 58836 58837 58838 58839 58840 58841 58842 58843 58844 58845 58846 58847 58848 58849 |
rc = SQLITE_NOMEM;
goto blob_open_out;
}
do {
memset(pParse, 0, sizeof(Parse));
pParse->db = db;
sqlite3BtreeEnterAll(db);
pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
if( pTab && IsVirtual(pTab) ){
pTab = 0;
sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
}
#ifndef SQLITE_OMIT_VIEW
if( pTab && pTab->pSelect ){
pTab = 0;
sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable);
}
#endif
if( !pTab ){
if( pParse->zErrMsg ){
sqlite3DbFree(db, zErr);
zErr = pParse->zErrMsg;
pParse->zErrMsg = 0;
}
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
/* Now search pTab for the exact column. */
for(iCol=0; iCol < pTab->nCol; iCol++) {
if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
break;
}
}
if( iCol==pTab->nCol ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
/* If the value is being opened for writing, check that the
** column is not indexed, and that it is not part of a foreign key.
** It is against the rules to open a column to which either of these
|
| ︙ | ︙ | |||
58163 58164 58165 58166 58167 58168 58169 |
}
}
}
if( zFault ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
rc = SQLITE_ERROR;
| < | 58876 58877 58878 58879 58880 58881 58882 58883 58884 58885 58886 58887 58888 58889 |
}
}
}
if( zFault ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
}
v = sqlite3VdbeCreate(db);
if( v ){
|
| ︙ | ︙ | |||
58213 58214 58215 58216 58217 58218 58219 |
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
if( !db->mallocFailed ){
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
}
}
sqlite3BtreeLeaveAll(db);
| < | | 58925 58926 58927 58928 58929 58930 58931 58932 58933 58934 58935 58936 58937 58938 58939 |
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
if( !db->mallocFailed ){
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
}
}
sqlite3BtreeLeaveAll(db);
if( db->mallocFailed ){
goto blob_open_out;
}
sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow);
rc = sqlite3_step((sqlite3_stmt *)v);
if( rc!=SQLITE_ROW ){
nAttempt++;
|
| ︙ | ︙ | |||
58315 58316 58317 58318 58319 58320 58321 |
int (*xCall)(BtCursor*, u32, u32, void*)
){
int rc;
Incrblob *p = (Incrblob *)pBlob;
Vdbe *v;
sqlite3 *db;
| | | 59026 59027 59028 59029 59030 59031 59032 59033 59034 59035 59036 59037 59038 59039 59040 |
int (*xCall)(BtCursor*, u32, u32, void*)
){
int rc;
Incrblob *p = (Incrblob *)pBlob;
Vdbe *v;
sqlite3 *db;
if( p==0 ) return SQLITE_MISUSE_BKPT;
db = p->db;
sqlite3_mutex_enter(db->mutex);
v = (Vdbe*)p->pStmt;
if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){
/* Request is out of range. Return a transient error. */
rc = SQLITE_ERROR;
|
| ︙ | ︙ | |||
59673 59674 59675 59676 59677 59678 59679 59680 59681 59682 59683 59684 59685 59686 59687 59688 59689 59690 59691 |
Parse *pParse, /* Parsing context for error messages */
Select *pSelect, /* The SELECT statement with the ORDER BY clause */
Expr *pE /* The specific ORDER BY term */
){
int i; /* Loop counter */
ExprList *pEList; /* The columns of the result set */
NameContext nc; /* Name context for resolving pE */
assert( sqlite3ExprIsInteger(pE, &i)==0 );
pEList = pSelect->pEList;
/* Resolve all names in the ORDER BY term expression
*/
memset(&nc, 0, sizeof(nc));
nc.pParse = pParse;
nc.pSrcList = pSelect->pSrc;
nc.pEList = pEList;
nc.allowAgg = 1;
nc.nErr = 0;
| > > > > > > | | | < | | 60384 60385 60386 60387 60388 60389 60390 60391 60392 60393 60394 60395 60396 60397 60398 60399 60400 60401 60402 60403 60404 60405 60406 60407 60408 60409 60410 60411 60412 60413 60414 60415 60416 60417 60418 60419 60420 60421 60422 60423 60424 60425 |
Parse *pParse, /* Parsing context for error messages */
Select *pSelect, /* The SELECT statement with the ORDER BY clause */
Expr *pE /* The specific ORDER BY term */
){
int i; /* Loop counter */
ExprList *pEList; /* The columns of the result set */
NameContext nc; /* Name context for resolving pE */
sqlite3 *db; /* Database connection */
int rc; /* Return code from subprocedures */
u8 savedSuppErr; /* Saved value of db->suppressErr */
assert( sqlite3ExprIsInteger(pE, &i)==0 );
pEList = pSelect->pEList;
/* Resolve all names in the ORDER BY term expression
*/
memset(&nc, 0, sizeof(nc));
nc.pParse = pParse;
nc.pSrcList = pSelect->pSrc;
nc.pEList = pEList;
nc.allowAgg = 1;
nc.nErr = 0;
db = pParse->db;
savedSuppErr = db->suppressErr;
db->suppressErr = 1;
rc = sqlite3ResolveExprNames(&nc, pE);
db->suppressErr = savedSuppErr;
if( rc ) return 0;
/* Try to match the ORDER BY expression against an expression
** in the result set. Return an 1-based index of the matching
** result-set entry.
*/
for(i=0; i<pEList->nExpr; i++){
if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
return i+1;
}
}
/* If no match, return 0. */
return 0;
}
|
| ︙ | ︙ | |||
62089 62090 62091 62092 62093 62094 62095 62096 62097 62098 62099 62100 62101 62102 62103 62104 62105 62106 62107 62108 62109 62110 62111 62112 62113 62114 62115 62116 62117 62118 62119 62120 62121 62122 62123 62124 |
char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8);
if( out ){
memcpy(out, in, 8);
}
return out;
}
/*
** Generate an instruction that will put the floating point
** value described by z[0..n-1] into register iMem.
**
** The z[] string will probably not be zero-terminated. But the
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
if( ALWAYS(z!=0) ){
double value;
char *zV;
sqlite3AtoF(z, &value);
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
if( negateFlag ) value = -value;
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
}
}
/*
** Generate an instruction that will put the integer describe by
** text z[0..n-1] into register iMem.
**
** The z[] string will probably not be zero-terminated. But the
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
| > > | > > > > > | 62805 62806 62807 62808 62809 62810 62811 62812 62813 62814 62815 62816 62817 62818 62819 62820 62821 62822 62823 62824 62825 62826 62827 62828 62829 62830 62831 62832 62833 62834 62835 62836 62837 62838 62839 62840 62841 62842 62843 62844 62845 62846 62847 62848 62849 62850 62851 62852 62853 62854 62855 62856 62857 62858 62859 62860 62861 62862 62863 62864 62865 62866 62867 62868 62869 62870 62871 |
char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8);
if( out ){
memcpy(out, in, 8);
}
return out;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Generate an instruction that will put the floating point
** value described by z[0..n-1] into register iMem.
**
** The z[] string will probably not be zero-terminated. But the
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
if( ALWAYS(z!=0) ){
double value;
char *zV;
sqlite3AtoF(z, &value);
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
if( negateFlag ) value = -value;
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
}
}
#endif
/*
** Generate an instruction that will put the integer describe by
** text z[0..n-1] into register iMem.
**
** The z[] string will probably not be zero-terminated. But the
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
Vdbe *v = pParse->pVdbe;
if( pExpr->flags & EP_IntValue ){
int i = pExpr->u.iValue;
if( negFlag ) i = -i;
sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
}else{
const char *z = pExpr->u.zToken;
assert( z!=0 );
if( sqlite3FitsIn64Bits(z, negFlag) ){
i64 value;
char *zV;
sqlite3Atoi64(z, &value);
if( negFlag ) value = -value;
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
}else{
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
#else
codeReal(v, z, negFlag, iMem);
#endif
}
}
}
/*
** Clear a cache entry.
*/
|
| ︙ | ︙ | |||
62521 62522 62523 62524 62525 62526 62527 |
}else{
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
pExpr->iColumn, pExpr->iTable, target);
}
break;
}
case TK_INTEGER: {
| | > > | 63244 63245 63246 63247 63248 63249 63250 63251 63252 63253 63254 63255 63256 63257 63258 63259 63260 63261 63262 63263 63264 63265 63266 63267 |
}else{
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
pExpr->iColumn, pExpr->iTable, target);
}
break;
}
case TK_INTEGER: {
codeInteger(pParse, pExpr, 0, target);
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pExpr->u.zToken, 0, target);
break;
}
#endif
case TK_STRING: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0);
break;
}
case TK_NULL: {
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
| ︙ | ︙ | |||
62698 62699 62700 62701 62702 62703 62704 |
testcase( regFree1==0 );
testcase( regFree2==0 );
break;
}
case TK_UMINUS: {
Expr *pLeft = pExpr->pLeft;
assert( pLeft );
| | > > > < < > | 63423 63424 63425 63426 63427 63428 63429 63430 63431 63432 63433 63434 63435 63436 63437 63438 63439 63440 63441 63442 63443 |
testcase( regFree1==0 );
testcase( regFree2==0 );
break;
}
case TK_UMINUS: {
Expr *pLeft = pExpr->pLeft;
assert( pLeft );
if( pLeft->op==TK_INTEGER ){
codeInteger(pParse, pLeft, 1, target);
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( pLeft->op==TK_FLOAT ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pLeft->u.zToken, 1, target);
#endif
}else{
regFree1 = r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2);
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
testcase( regFree2==0 );
}
|
| ︙ | ︙ | |||
62950 62951 62952 62953 62954 62955 62956 62957 62958 62959 62960 62961 62962 62963 62964 62965 62966 62967 62968 62969 62970 |
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "%s.%s -> $%d",
(pExpr->iTable ? "new" : "old"),
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
target
));
/* If the column has REAL affinity, it may currently be stored as an
** integer. Use OP_RealAffinity to make sure it is really real. */
if( pExpr->iColumn>=0
&& pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
break;
}
/*
** Form A:
** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
| > > | 63677 63678 63679 63680 63681 63682 63683 63684 63685 63686 63687 63688 63689 63690 63691 63692 63693 63694 63695 63696 63697 63698 63699 |
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "%s.%s -> $%d",
(pExpr->iTable ? "new" : "old"),
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
target
));
#ifndef SQLITE_OMIT_FLOATING_POINT
/* If the column has REAL affinity, it may currently be stored as an
** integer. Use OP_RealAffinity to make sure it is really real. */
if( pExpr->iColumn>=0
&& pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
#endif
break;
}
/*
** Form A:
** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
|
| ︙ | ︙ | |||
63622 63623 63624 63625 63626 63627 63628 |
}
}
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2);
}
/*
| | | > > | | | | | | | | | | | | | | | | | | | > > | | 64351 64352 64353 64354 64355 64356 64357 64358 64359 64360 64361 64362 64363 64364 64365 64366 64367 64368 64369 64370 64371 64372 64373 64374 64375 64376 64377 64378 64379 64380 64381 64382 64383 64384 64385 64386 64387 64388 64389 64390 64391 64392 64393 64394 64395 64396 64397 64398 64399 64400 64401 64402 64403 64404 64405 64406 64407 64408 64409 64410 64411 64412 64413 64414 64415 64416 64417 64418 64419 |
}
}
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2);
}
/*
** Do a deep comparison of two expression trees. Return 0 if the two
** expressions are completely identical. Return 1 if they differ only
** by a COLLATE operator at the top level. Return 2 if there are differences
** other than the top-level COLLATE operator.
**
** Sometimes this routine will return 2 even if the two expressions
** really are equivalent. If we cannot prove that the expressions are
** identical, we return 2 just to be safe. So if this routine
** returns 2, then you do not really know for certain if the two
** expressions are the same. But if you get a 0 or 1 return, then you
** can be sure the expressions are the same. In the places where
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
*/
SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
int i;
if( pA==0||pB==0 ){
return pB==pA ? 0 : 2;
}
assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
return 2;
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( pA->op!=pB->op ) return 2;
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
if( pA->x.pList && pB->x.pList ){
if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2;
for(i=0; i<pA->x.pList->nExpr; i++){
Expr *pExprA = pA->x.pList->a[i].pExpr;
Expr *pExprB = pB->x.pList->a[i].pExpr;
if( sqlite3ExprCompare(pExprA, pExprB) ) return 2;
}
}else if( pA->x.pList || pB->x.pList ){
return 2;
}
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
return 2;
}
}else if( pA->op!=TK_COLUMN && pA->u.zToken ){
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){
return 2;
}
}
if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
return 0;
}
/*
** Add a new element to the pAggInfo->aCol[] array. Return the index of
** the new element. Return a negative number if malloc fails.
*/
|
| ︙ | ︙ | |||
63803 63804 63805 63806 63807 63808 63809 |
** to be ignored */
if( pNC->nDepth==0 ){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
| | | 64536 64537 64538 64539 64540 64541 64542 64543 64544 64545 64546 64547 64548 64549 64550 |
** to be ignored */
if( pNC->nDepth==0 ){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
break;
}
}
if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = ENC(pParse->db);
|
| ︙ | ︙ | |||
64424 64425 64426 64427 64428 64429 64430 |
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
if( db->flags&SQLITE_ForeignKeys ){
/* If foreign-key support is enabled, rewrite the CREATE TABLE
** statements corresponding to all child tables of foreign key constraints
** for which the renamed table is the parent table. */
if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
sqlite3NestedParse(pParse,
| | | | 65157 65158 65159 65160 65161 65162 65163 65164 65165 65166 65167 65168 65169 65170 65171 65172 65173 |
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
if( db->flags&SQLITE_ForeignKeys ){
/* If foreign-key support is enabled, rewrite the CREATE TABLE
** statements corresponding to all child tables of foreign key constraints
** for which the renamed table is the parent table. */
if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = sqlite_rename_parent(sql, %Q, %Q) "
"WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
sqlite3DbFree(db, zWhere);
}
}
#endif
/* Modify the sqlite_master table to use the new table name. */
sqlite3NestedParse(pParse,
|
| ︙ | ︙ | |||
65299 65300 65301 65302 65303 65304 65305 |
/* Load new statistics out of the sqlite_stat1 table */
zSql = sqlite3MPrintf(db,
"SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
| < < < < < | 66032 66033 66034 66035 66036 66037 66038 66039 66040 66041 66042 66043 66044 66045 66046 66047 66048 66049 66050 66051 66052 66053 66054 66055 66056 66057 66058 66059 66060 66061 66062 66063 66064 66065 66066 66067 66068 |
/* Load new statistics out of the sqlite_stat1 table */
zSql = sqlite3MPrintf(db,
"SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
sqlite3DbFree(db, zSql);
}
/* Load the statistics from the sqlite_stat2 table. */
#ifdef SQLITE_ENABLE_STAT2
if( rc==SQLITE_OK && !sqlite3FindTable(db, "sqlite_stat2", sInfo.zDatabase) ){
rc = SQLITE_ERROR;
}
if( rc==SQLITE_OK ){
sqlite3_stmt *pStmt = 0;
zSql = sqlite3MPrintf(db,
"SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase);
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
sqlite3DbFree(db, zSql);
}
if( rc==SQLITE_OK ){
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char *zIndex = (char *)sqlite3_column_text(pStmt, 0);
Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
if( pIdx ){
int iSample = sqlite3_column_int(pStmt, 1);
sqlite3 *dbMem = pIdx->pTable->dbMem;
assert( dbMem==db || dbMem==0 );
|
| ︙ | ︙ | |||
65376 65377 65378 65379 65380 65381 65382 |
}
}
}
}
}
}
rc = sqlite3_finalize(pStmt);
| < | 66104 66105 66106 66107 66108 66109 66110 66111 66112 66113 66114 66115 66116 66117 |
}
}
}
}
}
}
rc = sqlite3_finalize(pStmt);
}
}
#endif
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
|
| ︙ | ︙ | |||
65537 65538 65539 65540 65541 65542 65543 65544 65545 |
zErrDyn = sqlite3MPrintf(db,
"attached databases must use the same text encoding as main database");
rc = SQLITE_ERROR;
}
pPager = sqlite3BtreePager(aNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
}
aNew->zName = sqlite3DbStrDup(db, zName);
| > > > > > > | | | 66264 66265 66266 66267 66268 66269 66270 66271 66272 66273 66274 66275 66276 66277 66278 66279 66280 66281 66282 66283 66284 66285 66286 66287 66288 |
zErrDyn = sqlite3MPrintf(db,
"attached databases must use the same text encoding as main database");
rc = SQLITE_ERROR;
}
pPager = sqlite3BtreePager(aNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
sqlite3BtreeSecureDelete(aNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
}
aNew->safety_level = 3;
aNew->zName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && aNew->zName==0 ){
rc = SQLITE_NOMEM;
}
#ifdef SQLITE_HAS_CODEC
if( rc==SQLITE_OK ){
extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
int nKey;
char *zKey;
int t = sqlite3_value_type(argv[2]);
switch( t ){
|
| ︙ | ︙ | |||
65577 65578 65579 65580 65581 65582 65583 |
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
** remove the entry from the db->aDb[] array. i.e. put everything back the way
** we found it.
*/
if( rc==SQLITE_OK ){
| < < | 66310 66311 66312 66313 66314 66315 66316 66317 66318 66319 66320 66321 66322 66323 66324 66325 66326 |
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
** remove the entry from the db->aDb[] array. i.e. put everything back the way
** we found it.
*/
if( rc==SQLITE_OK ){
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrDyn);
sqlite3BtreeLeaveAll(db);
}
if( rc ){
int iDb = db->nDb - 1;
assert( iDb>=2 );
if( db->aDb[iDb].pBt ){
sqlite3BtreeClose(db->aDb[iDb].pBt);
db->aDb[iDb].pBt = 0;
|
| ︙ | ︙ | |||
66383 66384 66385 66386 66387 66388 66389 |
* See ticket [a696379c1f08866] */
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
pParse->nTab, pParse->nMaxArg, pParse->explain,
pParse->isMultiWrite && pParse->mayAbort);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
| | | 67114 67115 67116 67117 67118 67119 67120 67121 67122 67123 67124 67125 67126 67127 67128 |
* See ticket [a696379c1f08866] */
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
pParse->nTab, pParse->nMaxArg, pParse->explain,
pParse->isMultiWrite && pParse->mayAbort);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
}else{
pParse->rc = SQLITE_ERROR;
}
pParse->nTab = 0;
pParse->nMem = 0;
pParse->nSet = 0;
pParse->nVar = 0;
pParse->cookieMask = 0;
|
| ︙ | ︙ | |||
68155 68156 68157 68158 68159 68160 68161 68162 68163 68164 68165 |
int iDb;
if( db->mallocFailed ){
goto exit_drop_table;
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
pTab = sqlite3LocateTable(pParse, isView,
pName->a[0].zName, pName->a[0].zDatabase);
if( pTab==0 ){
| > > < < < | 68886 68887 68888 68889 68890 68891 68892 68893 68894 68895 68896 68897 68898 68899 68900 68901 68902 68903 68904 68905 |
int iDb;
if( db->mallocFailed ){
goto exit_drop_table;
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
pTab = sqlite3LocateTable(pParse, isView,
pName->a[0].zName, pName->a[0].zDatabase);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 && iDb<db->nDb );
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
** it is initialized.
|
| ︙ | ︙ | |||
69583 69584 69585 69586 69587 69588 69589 69590 69591 69592 69593 69594 69595 69596 |
** Make sure the TEMP database is open and available for use. Return
** the number of errors. Leave any error messages in the pParse structure.
*/
SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc;
static const int flags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TEMP_DB;
| > | < > > > > > | < | 70313 70314 70315 70316 70317 70318 70319 70320 70321 70322 70323 70324 70325 70326 70327 70328 70329 70330 70331 70332 70333 70334 70335 70336 70337 70338 70339 70340 70341 70342 70343 70344 70345 70346 70347 70348 |
** Make sure the TEMP database is open and available for use. Return
** the number of errors. Leave any error messages in the pParse structure.
*/
SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc;
Btree *pBt;
static const int flags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TEMP_DB;
rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
"file for storing temporary tables");
pParse->rc = rc;
return 1;
}
db->aDb[1].pBt = pBt;
assert( db->aDb[1].pSchema );
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
db->mallocFailed = 1;
return 1;
}
sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode);
}
return 0;
}
/*
** Generate VDBE code that will verify the schema cookie and start
** a read-transaction for all named database files.
|
| ︙ | ︙ | |||
70337 70338 70339 70340 70341 70342 70343 70344 70345 70346 70347 70348 70349 70350 |
sqlite3HashInit(&p->fkeyHash);
p->enc = SQLITE_UTF8;
}
return p;
}
/************** End of callback.c ********************************************/
/************** Begin file delete.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 71071 71072 71073 71074 71075 71076 71077 71078 71079 71080 71081 71082 71083 71084 71085 71086 71087 71088 71089 71090 71091 71092 71093 71094 71095 71096 71097 71098 71099 71100 71101 71102 71103 71104 71105 71106 71107 71108 71109 71110 71111 71112 71113 71114 71115 71116 71117 71118 71119 71120 71121 71122 71123 71124 71125 71126 71127 71128 71129 71130 71131 71132 71133 71134 71135 71136 71137 71138 71139 71140 71141 71142 71143 71144 71145 71146 71147 71148 71149 71150 71151 71152 71153 71154 71155 71156 71157 71158 71159 71160 71161 71162 71163 71164 71165 71166 71167 71168 71169 71170 71171 71172 71173 71174 71175 71176 71177 71178 71179 71180 71181 71182 71183 71184 71185 71186 71187 71188 71189 71190 71191 71192 71193 71194 71195 71196 71197 71198 71199 71200 71201 71202 71203 71204 71205 71206 71207 71208 71209 71210 71211 71212 71213 71214 71215 71216 71217 71218 71219 71220 71221 71222 71223 71224 71225 71226 71227 71228 71229 71230 71231 71232 71233 71234 71235 71236 71237 71238 71239 71240 71241 71242 71243 71244 71245 71246 71247 71248 71249 71250 71251 71252 71253 71254 71255 71256 71257 71258 71259 71260 71261 71262 71263 71264 71265 71266 71267 71268 71269 71270 71271 71272 71273 71274 71275 71276 71277 71278 71279 71280 71281 71282 71283 71284 71285 71286 71287 71288 71289 71290 71291 71292 71293 71294 71295 71296 71297 71298 71299 71300 71301 71302 71303 71304 71305 71306 71307 71308 71309 71310 71311 71312 71313 71314 71315 71316 71317 71318 71319 71320 71321 71322 71323 71324 71325 71326 71327 71328 71329 71330 71331 71332 71333 71334 71335 71336 71337 71338 71339 71340 71341 71342 71343 71344 71345 71346 71347 71348 71349 71350 71351 71352 71353 71354 71355 71356 71357 71358 71359 71360 71361 71362 71363 71364 71365 71366 71367 71368 71369 71370 71371 71372 71373 71374 71375 71376 71377 71378 71379 71380 71381 71382 71383 71384 71385 71386 71387 71388 71389 71390 71391 71392 71393 71394 71395 71396 71397 71398 71399 71400 71401 71402 71403 71404 71405 71406 71407 71408 71409 71410 71411 71412 71413 71414 71415 71416 71417 71418 71419 71420 71421 71422 71423 71424 71425 71426 71427 71428 71429 71430 71431 71432 71433 71434 71435 71436 71437 71438 71439 71440 71441 71442 71443 71444 71445 71446 71447 71448 71449 71450 71451 71452 71453 71454 71455 71456 71457 71458 71459 71460 71461 71462 71463 71464 71465 71466 71467 71468 71469 71470 71471 |
sqlite3HashInit(&p->fkeyHash);
p->enc = SQLITE_UTF8;
}
return p;
}
/************** End of callback.c ********************************************/
/************** Begin file ctime.c *******************************************/
/*
** 2010 February 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements routines used to report what compile-time options
** SQLite was built with.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
/*
** An array of names of all compile-time options. This array should
** be sorted A-Z.
**
** This array looks large, but in a typical installation actually uses
** only a handful of compile-time options, so most times this array is usually
** rather short and uses little memory space.
*/
static const char * const azCompileOpt[] = {
/* These macros are provided to "stringify" the value of the define
** for those options in which the value is meaningful. */
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
#ifdef SQLITE_32BIT_ROWID
"32BIT_ROWID",
#endif
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
"4_BYTE_ALIGNED_MALLOC",
#endif
#ifdef SQLITE_CASE_SENSITIVE_LIKE
"CASE_SENSITIVE_LIKE",
#endif
#ifdef SQLITE_CHECK_PAGES
"CHECK_PAGES",
#endif
#ifdef SQLITE_COVERAGE_TEST
"COVERAGE_TEST",
#endif
#ifdef SQLITE_DEBUG
"DEBUG",
#endif
#ifdef SQLITE_DEFAULT_LOCKING_MODE
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
#ifdef SQLITE_DISABLE_DIRSYNC
"DISABLE_DIRSYNC",
#endif
#ifdef SQLITE_DISABLE_LFS
"DISABLE_LFS",
#endif
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
"ENABLE_ATOMIC_WRITE",
#endif
#ifdef SQLITE_ENABLE_CEROD
"ENABLE_CEROD",
#endif
#ifdef SQLITE_ENABLE_COLUMN_METADATA
"ENABLE_COLUMN_METADATA",
#endif
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT",
#endif
#ifdef SQLITE_ENABLE_FTS1
"ENABLE_FTS1",
#endif
#ifdef SQLITE_ENABLE_FTS2
"ENABLE_FTS2",
#endif
#ifdef SQLITE_ENABLE_FTS3
"ENABLE_FTS3",
#endif
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
"ENABLE_FTS3_PARENTHESIS",
#endif
#ifdef SQLITE_ENABLE_FTS4
"ENABLE_FTS4",
#endif
#ifdef SQLITE_ENABLE_ICU
"ENABLE_ICU",
#endif
#ifdef SQLITE_ENABLE_IOTRACE
"ENABLE_IOTRACE",
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
"ENABLE_LOAD_EXTENSION",
#endif
#ifdef SQLITE_ENABLE_LOCKING_STYLE
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
"ENABLE_MEMORY_MANAGEMENT",
#endif
#ifdef SQLITE_ENABLE_MEMSYS3
"ENABLE_MEMSYS3",
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
"ENABLE_MEMSYS5",
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
#ifdef SQLITE_ENABLE_RTREE
"ENABLE_RTREE",
#endif
#ifdef SQLITE_ENABLE_STAT2
"ENABLE_STAT2",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
"ENABLE_UNLOCK_NOTIFY",
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
"ENABLE_UPDATE_DELETE_LIMIT",
#endif
#ifdef SQLITE_HAS_CODEC
"HAS_CODEC",
#endif
#ifdef SQLITE_HAVE_ISNAN
"HAVE_ISNAN",
#endif
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
"HOMEGROWN_RECURSIVE_MUTEX",
#endif
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
"IGNORE_AFP_LOCK_ERRORS",
#endif
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
"IGNORE_FLOCK_LOCK_ERRORS",
#endif
#ifdef SQLITE_INT64_TYPE
"INT64_TYPE",
#endif
#ifdef SQLITE_LOCK_TRACE
"LOCK_TRACE",
#endif
#ifdef SQLITE_MEMDEBUG
"MEMDEBUG",
#endif
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
"MIXED_ENDIAN_64BIT_FLOAT",
#endif
#ifdef SQLITE_NO_SYNC
"NO_SYNC",
#endif
#ifdef SQLITE_OMIT_ALTERTABLE
"OMIT_ALTERTABLE",
#endif
#ifdef SQLITE_OMIT_ANALYZE
"OMIT_ANALYZE",
#endif
#ifdef SQLITE_OMIT_ATTACH
"OMIT_ATTACH",
#endif
#ifdef SQLITE_OMIT_AUTHORIZATION
"OMIT_AUTHORIZATION",
#endif
#ifdef SQLITE_OMIT_AUTOINCREMENT
"OMIT_AUTOINCREMENT",
#endif
#ifdef SQLITE_OMIT_AUTOINIT
"OMIT_AUTOINIT",
#endif
#ifdef SQLITE_OMIT_AUTOVACUUM
"OMIT_AUTOVACUUM",
#endif
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
"OMIT_BETWEEN_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_BLOB_LITERAL
"OMIT_BLOB_LITERAL",
#endif
#ifdef SQLITE_OMIT_BTREECOUNT
"OMIT_BTREECOUNT",
#endif
#ifdef SQLITE_OMIT_BUILTIN_TEST
"OMIT_BUILTIN_TEST",
#endif
#ifdef SQLITE_OMIT_CAST
"OMIT_CAST",
#endif
#ifdef SQLITE_OMIT_CHECK
"OMIT_CHECK",
#endif
#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
"OMIT_COMPILEOPTION_DIAGS",
#endif
#ifdef SQLITE_OMIT_COMPLETE
"OMIT_COMPLETE",
#endif
#ifdef SQLITE_OMIT_COMPOUND_SELECT
"OMIT_COMPOUND_SELECT",
#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
"OMIT_DATETIME_FUNCS",
#endif
#ifdef SQLITE_OMIT_DECLTYPE
"OMIT_DECLTYPE",
#endif
#ifdef SQLITE_OMIT_DEPRECATED
"OMIT_DEPRECATED",
#endif
#ifdef SQLITE_OMIT_DISKIO
"OMIT_DISKIO",
#endif
#ifdef SQLITE_OMIT_EXPLAIN
"OMIT_EXPLAIN",
#endif
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
"OMIT_FLAG_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_FLOATING_POINT
"OMIT_FLOATING_POINT",
#endif
#ifdef SQLITE_OMIT_FOREIGN_KEY
"OMIT_FOREIGN_KEY",
#endif
#ifdef SQLITE_OMIT_GET_TABLE
"OMIT_GET_TABLE",
#endif
#ifdef SQLITE_OMIT_GLOBALRECOVER
"OMIT_GLOBALRECOVER",
#endif
#ifdef SQLITE_OMIT_INCRBLOB
"OMIT_INCRBLOB",
#endif
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
"OMIT_INTEGRITY_CHECK",
#endif
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
"OMIT_LIKE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_LOAD_EXTENSION
"OMIT_LOAD_EXTENSION",
#endif
#ifdef SQLITE_OMIT_LOCALTIME
"OMIT_LOCALTIME",
#endif
#ifdef SQLITE_OMIT_LOOKASIDE
"OMIT_LOOKASIDE",
#endif
#ifdef SQLITE_OMIT_MEMORYDB
"OMIT_MEMORYDB",
#endif
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
"OMIT_OR_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
"OMIT_PAGER_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_PRAGMA
"OMIT_PRAGMA",
#endif
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
"OMIT_PROGRESS_CALLBACK",
#endif
#ifdef SQLITE_OMIT_QUICKBALANCE
"OMIT_QUICKBALANCE",
#endif
#ifdef SQLITE_OMIT_REINDEX
"OMIT_REINDEX",
#endif
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
"OMIT_SCHEMA_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
"OMIT_SCHEMA_VERSION_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_SHARED_CACHE
"OMIT_SHARED_CACHE",
#endif
#ifdef SQLITE_OMIT_SUBQUERY
"OMIT_SUBQUERY",
#endif
#ifdef SQLITE_OMIT_TCL_VARIABLE
"OMIT_TCL_VARIABLE",
#endif
#ifdef SQLITE_OMIT_TEMPDB
"OMIT_TEMPDB",
#endif
#ifdef SQLITE_OMIT_TRACE
"OMIT_TRACE",
#endif
#ifdef SQLITE_OMIT_TRIGGER
"OMIT_TRIGGER",
#endif
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
"OMIT_TRUNCATE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_UTF16
"OMIT_UTF16",
#endif
#ifdef SQLITE_OMIT_VACUUM
"OMIT_VACUUM",
#endif
#ifdef SQLITE_OMIT_VIEW
"OMIT_VIEW",
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
"OMIT_VIRTUALTABLE",
#endif
#ifdef SQLITE_OMIT_WSD
"OMIT_WSD",
#endif
#ifdef SQLITE_OMIT_XFER_OPT
"OMIT_XFER_OPT",
#endif
#ifdef SQLITE_PERFORMANCE_TRACE
"PERFORMANCE_TRACE",
#endif
#ifdef SQLITE_PROXY_DEBUG
"PROXY_DEBUG",
#endif
#ifdef SQLITE_SECURE_DELETE
"SECURE_DELETE",
#endif
#ifdef SQLITE_SMALL_STACK
"SMALL_STACK",
#endif
#ifdef SQLITE_SOUNDEX
"SOUNDEX",
#endif
#ifdef SQLITE_TCL
"TCL",
#endif
#ifdef SQLITE_TEMP_STORE
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
#endif
#ifdef SQLITE_TEST
"TEST",
#endif
#ifdef SQLITE_THREADSAFE
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#endif
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
#ifdef SQLITE_ZERO_MALLOC
"ZERO_MALLOC"
#endif
};
/*
** Given the name of a compile-time option, return true if that option
** was used and false if not.
**
** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
** is not required for a match.
*/
SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
int i, n;
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
n = sqlite3Strlen30(zOptName);
/* Since ArraySize(azCompileOpt) is normally in single digits, a
** linear search is adequate. No need for a binary search. */
for(i=0; i<ArraySize(azCompileOpt); i++){
if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0)
&& ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
}
return 0;
}
/*
** Return the N-th compile-time option string. If N is out of range,
** return a NULL pointer.
*/
SQLITE_API const char *sqlite3_compileoption_get(int N){
if( N>=0 && N<ArraySize(azCompileOpt) ){
return azCompileOpt[N];
}
return 0;
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
/************** End of ctime.c ***********************************************/
/************** Begin file delete.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
|
| ︙ | ︙ | |||
71245 71246 71247 71248 71249 71250 71251 |
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
n = sqlite3_value_int(argv[1]);
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
| > > > > > > > > > | | | | > < > | 72366 72367 72368 72369 72370 72371 72372 72373 72374 72375 72376 72377 72378 72379 72380 72381 72382 72383 72384 72385 72386 72387 72388 72389 72390 72391 72392 72393 72394 72395 72396 72397 |
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
n = sqlite3_value_int(argv[1]);
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
/* If Y==0 and X will fit in a 64-bit int,
** handle the rounding directly,
** otherwise use printf.
*/
if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
r = (double)((sqlite_int64)(r+0.5));
}else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
r = -(double)((sqlite_int64)((-r)+0.5));
}else{
zBuf = sqlite3_mprintf("%.*f",n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
}
sqlite3AtoF(zBuf, &r);
sqlite3_free(zBuf);
}
sqlite3_result_double(context, r);
}
#endif
/*
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed and return NULL.
|
| ︙ | ︙ | |||
71414 71415 71416 71417 71418 71419 71420 71421 71422 71423 71424 |
static void last_insert_rowid(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}
/*
| > > > | > > | > | 72545 72546 72547 72548 72549 72550 72551 72552 72553 72554 72555 72556 72557 72558 72559 72560 72561 72562 72563 72564 72565 72566 72567 72568 72569 72570 |
static void last_insert_rowid(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
/* IMP: R-51513-12026 The last_insert_rowid() SQL function is a
** wrapper around the sqlite3_last_insert_rowid() C/C++ interface
** function. */
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}
/*
** Implementation of the changes() SQL function.
**
** IMP: R-62073-11209 The changes() SQL function is a wrapper
** around the sqlite3_changes() C/C++ function and hence follows the same
** rules for counting changes.
*/
static void changes(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
|
| ︙ | ︙ | |||
71442 71443 71444 71445 71446 71447 71448 71449 71450 71451 71452 71453 71454 71455 |
static void total_changes(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int(context, sqlite3_total_changes(db));
}
/*
** A structure defining how to do GLOB-style comparisons.
*/
struct compareInfo {
| > > | 72579 72580 72581 72582 72583 72584 72585 72586 72587 72588 72589 72590 72591 72592 72593 72594 |
static void total_changes(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
/* IMP: R-52756-41993 This function is a wrapper around the
** sqlite3_total_changes() C/C++ interface. */
sqlite3_result_int(context, sqlite3_total_changes(db));
}
/*
** A structure defining how to do GLOB-style comparisons.
*/
struct compareInfo {
|
| ︙ | ︙ | |||
71709 71710 71711 71712 71713 71714 71715 |
*/
static void versionFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
| > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 72848 72849 72850 72851 72852 72853 72854 72855 72856 72857 72858 72859 72860 72861 72862 72863 72864 72865 72866 72867 72868 72869 72870 72871 72872 72873 72874 72875 72876 72877 72878 72879 72880 72881 72882 72883 72884 72885 72886 72887 72888 72889 72890 72891 72892 72893 72894 72895 72896 72897 72898 72899 72900 72901 72902 72903 72904 72905 72906 72907 72908 72909 72910 72911 72912 72913 72914 72915 72916 72917 72918 72919 72920 72921 72922 72923 72924 72925 |
*/
static void versionFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
/* IMP: R-48699-48617 This function is an SQL wrapper around the
** sqlite3_libversion() C-interface. */
sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC);
}
/*
** Implementation of the sqlite_source_id() function. The result is a string
** that identifies the particular version of the source code used to build
** SQLite.
*/
static void sourceidFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
/* IMP: R-24470-31136 This function is an SQL wrapper around the
** sqlite3_sourceid() C interface. */
sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
}
/*
** Implementation of the sqlite_compileoption_used() function.
** The result is an integer that identifies if the compiler option
** was used to build SQLite.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
static void compileoptionusedFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zOptName;
assert( argc==1 );
UNUSED_PARAMETER(argc);
/* IMP: R-xxxx This function is an SQL wrapper around the
** sqlite3_compileoption_used() C interface. */
if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
}
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
/*
** Implementation of the sqlite_compileoption_get() function.
** The result is a string that identifies the compiler options
** used to build SQLite.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
static void compileoptiongetFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int n;
assert( argc==1 );
UNUSED_PARAMETER(argc);
/* IMP: R-xxxx This function is an SQL wrapper around the
** sqlite3_compileoption_get() C interface. */
n = sqlite3_value_int(argv[0]);
sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
|
| ︙ | ︙ | |||
71852 71853 71854 71855 71856 71857 71858 |
UNUSED_PARAMETER(argc);
n = sqlite3_value_int64(argv[0]);
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
}else{
| | | 73038 73039 73040 73041 73042 73043 73044 73045 73046 73047 73048 73049 73050 73051 73052 |
UNUSED_PARAMETER(argc);
n = sqlite3_value_int64(argv[0]);
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
}else{
sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */
}
}
/*
** The replace() function. Three arguments are all strings: call
** them A, B, and C. The result is also a string which is derived
** from A by replacing every occurance of B with C. The match
|
| ︙ | ︙ | |||
72457 72458 72459 72460 72461 72462 72463 72464 72465 72466 72467 72468 72469 72470 |
/* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */
{2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0},
FUNCTION(random, 0, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
FUNCTION(quote, 1, 0, 0, quoteFunc ),
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
FUNCTION(changes, 0, 0, 0, changes ),
FUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(replace, 3, 0, 0, replaceFunc ),
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
#ifdef SQLITE_SOUNDEX
| > > > > | 73643 73644 73645 73646 73647 73648 73649 73650 73651 73652 73653 73654 73655 73656 73657 73658 73659 73660 |
/* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */
{2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0},
FUNCTION(random, 0, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
FUNCTION(quote, 1, 0, 0, quoteFunc ),
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
FUNCTION(changes, 0, 0, 0, changes ),
FUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(replace, 3, 0, 0, replaceFunc ),
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
#ifdef SQLITE_SOUNDEX
|
| ︙ | ︙ | |||
74956 74957 74958 74959 74960 74961 74962 |
case OE_Replace: {
/* If there are DELETE triggers on this table and the
** recursive-triggers flag is set, call GenerateRowDelete() to
** remove the conflicting row from the the table. This will fire
** the triggers and remove both the table and index b-tree entries.
**
** Otherwise, if there are no triggers or the recursive-triggers
| > | | | > > > > > > > > > > > > < > | > | 76146 76147 76148 76149 76150 76151 76152 76153 76154 76155 76156 76157 76158 76159 76160 76161 76162 76163 76164 76165 76166 76167 76168 76169 76170 76171 76172 76173 76174 76175 76176 76177 76178 76179 76180 76181 76182 76183 76184 76185 76186 |
case OE_Replace: {
/* If there are DELETE triggers on this table and the
** recursive-triggers flag is set, call GenerateRowDelete() to
** remove the conflicting row from the the table. This will fire
** the triggers and remove both the table and index b-tree entries.
**
** Otherwise, if there are no triggers or the recursive-triggers
** flag is not set, but the table has one or more indexes, call
** GenerateRowIndexDelete(). This removes the index b-tree entries
** only. The table b-tree entry will be replaced by the new entry
** when it is inserted.
**
** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
** also invoke MultiWrite() to indicate that this VDBE may require
** statement rollback (if the statement is aborted after the delete
** takes place). Earlier versions called sqlite3MultiWrite() regardless,
** but being more selective here allows statements like:
**
** REPLACE INTO t(rowid) VALUES($newrowid)
**
** to run without a statement journal if there are no indexes on the
** table.
*/
Trigger *pTrigger = 0;
if( pParse->db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(
pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
);
}else if( pTab->pIndex ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
}
seenReplace = 1;
break;
}
case OE_Ignore: {
assert( seenReplace==0 );
|
| ︙ | ︙ | |||
75410 75411 75412 75413 75414 75415 75416 |
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
}
if( pSrcIdx==0 ){
return 0; /* pDestIdx has no corresponding index in pSrc */
}
}
#ifndef SQLITE_OMIT_CHECK
| | | 76614 76615 76616 76617 76618 76619 76620 76621 76622 76623 76624 76625 76626 76627 76628 |
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
}
if( pSrcIdx==0 ){
return 0; /* pDestIdx has no corresponding index in pSrc */
}
}
#ifndef SQLITE_OMIT_CHECK
if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
/* If we get this far, it means either:
**
** * We can always do the transfer if the table contains an
|
| ︙ | ︙ | |||
75553 75554 75555 75556 75557 75558 75559 75560 75561 75562 75563 75564 75565 75566 |
int rc = SQLITE_OK; /* Return code */
const char *zLeftover; /* Tail of unprocessed SQL */
sqlite3_stmt *pStmt = 0; /* The current SQL statement */
char **azCols = 0; /* Names of result columns */
int nRetry = 0; /* Number of retry attempts */
int callbackIsInit; /* True if callback data is initialized */
if( zSql==0 ) zSql = "";
sqlite3_mutex_enter(db->mutex);
sqlite3Error(db, SQLITE_OK, 0);
while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
int nCol;
char **azVals = 0;
| > | 76757 76758 76759 76760 76761 76762 76763 76764 76765 76766 76767 76768 76769 76770 76771 |
int rc = SQLITE_OK; /* Return code */
const char *zLeftover; /* Tail of unprocessed SQL */
sqlite3_stmt *pStmt = 0; /* The current SQL statement */
char **azCols = 0; /* Names of result columns */
int nRetry = 0; /* Number of retry attempts */
int callbackIsInit; /* True if callback data is initialized */
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
if( zSql==0 ) zSql = "";
sqlite3_mutex_enter(db->mutex);
sqlite3Error(db, SQLITE_OK, 0);
while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
int nCol;
char **azVals = 0;
|
| ︙ | ︙ | |||
76934 76935 76936 76937 76938 76939 76940 76941 76942 76943 76944 76945 76946 76947 | const char *zDb = 0; /* The database name */ Token *pId; /* Pointer to <id> token */ int iDb; /* Database index for <database> */ sqlite3 *db = pParse->db; Db *pDb; Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); if( v==0 ) return; pParse->nMem = 2; /* Interpret the [database.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); if( iDb<0 ) return; pDb = &db->aDb[iDb]; | > | 78139 78140 78141 78142 78143 78144 78145 78146 78147 78148 78149 78150 78151 78152 78153 | const char *zDb = 0; /* The database name */ Token *pId; /* Pointer to <id> token */ int iDb; /* Database index for <database> */ sqlite3 *db = pParse->db; Db *pDb; Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; /* Interpret the [database.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); if( iDb<0 ) return; pDb = &db->aDb[iDb]; |
| ︙ | ︙ | |||
77065 77066 77067 77068 77069 77070 77071 77072 77073 77074 77075 77076 77077 77078 |
}
if( ALWAYS(pBt) ){
newMax = sqlite3BtreeMaxPageCount(pBt, newMax);
}
returnSingleInt(pParse, "max_page_count", newMax);
}else
/*
** PRAGMA [database.]page_count
**
** Return the number of pages in the specified database.
*/
if( sqlite3StrICmp(zLeft,"page_count")==0 ){
int iReg;
| > > > > > > > > > > > > > > > > > > > > > > > > > | 78271 78272 78273 78274 78275 78276 78277 78278 78279 78280 78281 78282 78283 78284 78285 78286 78287 78288 78289 78290 78291 78292 78293 78294 78295 78296 78297 78298 78299 78300 78301 78302 78303 78304 78305 78306 78307 78308 78309 |
}
if( ALWAYS(pBt) ){
newMax = sqlite3BtreeMaxPageCount(pBt, newMax);
}
returnSingleInt(pParse, "max_page_count", newMax);
}else
/*
** PRAGMA [database.]secure_delete
** PRAGMA [database.]secure_delete=ON/OFF
**
** The first form reports the current setting for the
** secure_delete flag. The second form changes the secure_delete
** flag setting and reports thenew value.
*/
if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
Btree *pBt = pDb->pBt;
int b = -1;
assert( pBt!=0 );
if( zRight ){
b = getBoolean(zRight);
}
if( pId2->n==0 && b>=0 ){
int ii;
for(ii=0; ii<db->nDb; ii++){
sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
}
}
b = sqlite3BtreeSecureDelete(pBt, b);
returnSingleInt(pParse, "secure_delete", b);
}else
/*
** PRAGMA [database.]page_count
**
** Return the number of pages in the specified database.
*/
if( sqlite3StrICmp(zLeft,"page_count")==0 ){
int iReg;
|
| ︙ | ︙ | |||
77983 77984 77985 77986 77987 77988 77989 77990 77991 77992 77993 77994 77995 77996 |
sqlite3VdbeChangeP3(v, addr+1, iCookie);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
}
}else
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
*/
if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
| > > > > > > > > > > > > > > > > > > > > | 79214 79215 79216 79217 79218 79219 79220 79221 79222 79223 79224 79225 79226 79227 79228 79229 79230 79231 79232 79233 79234 79235 79236 79237 79238 79239 79240 79241 79242 79243 79244 79245 79246 79247 |
sqlite3VdbeChangeP3(v, addr+1, iCookie);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
}
}else
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
/*
** PRAGMA compile_options
**
** Return the names of all compile-time options used in this build,
** one option per row.
*/
if( sqlite3StrICmp(zLeft, "compile_options")==0 ){
int i = 0;
const char *zOpt;
sqlite3VdbeSetNumCols(v, 1);
pParse->nMem = 1;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC);
while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
}else
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
*/
if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
|
| ︙ | ︙ | |||
78017 78018 78019 78020 78021 78022 78023 |
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
}else
#endif
| | | 79268 79269 79270 79271 79272 79273 79274 79275 79276 79277 79278 79279 79280 79281 79282 |
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
}else
#endif
#ifdef SQLITE_HAS_CODEC
if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
}else
if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){
sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight));
}else
if( zRight && (sqlite3StrICmp(zLeft, "hexkey")==0 ||
|
| ︙ | ︙ | |||
78040 78041 78042 78043 78044 78045 78046 |
if( (zLeft[3] & 0xf)==0xb ){
sqlite3_key(db, zKey, i/2);
}else{
sqlite3_rekey(db, zKey, i/2);
}
}else
#endif
| | | < < < < < < < < | 79291 79292 79293 79294 79295 79296 79297 79298 79299 79300 79301 79302 79303 79304 79305 79306 79307 79308 79309 79310 79311 79312 79313 79314 79315 79316 79317 79318 79319 79320 79321 79322 |
if( (zLeft[3] & 0xf)==0xb ){
sqlite3_key(db, zKey, i/2);
}else{
sqlite3_rekey(db, zKey, i/2);
}
}else
#endif
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
#ifdef SQLITE_HAS_CODEC
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
sqlite3_activate_see(&zRight[4]);
}
#endif
#ifdef SQLITE_ENABLE_CEROD
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
sqlite3_activate_cerod(&zRight[6]);
}
#endif
}else
#endif
{/* Empty ELSE clause */}
/*
** Reset the safety level, in case the fullfsync flag or synchronous
** setting changed.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
if( db->autoCommit ){
sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
|
| ︙ | ︙ | |||
78278 78279 78280 78281 78282 78283 78284 | azArg[1] = "1"; azArg[2] = zMasterSchema; azArg[3] = 0; initData.db = db; initData.iDb = iDb; initData.rc = SQLITE_OK; initData.pzErrMsg = pzErrMsg; | < < | 79521 79522 79523 79524 79525 79526 79527 79528 79529 79530 79531 79532 79533 79534 79535 |
azArg[1] = "1";
azArg[2] = zMasterSchema;
azArg[3] = 0;
initData.db = db;
initData.iDb = iDb;
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
if( initData.rc ){
rc = initData.rc;
goto error_out;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( ALWAYS(pTab) ){
pTab->tabFlags |= TF_Readonly;
|
| ︙ | ︙ | |||
78401 78402 78403 78404 78405 78406 78407 |
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
{
char *zSql;
zSql = sqlite3MPrintf(db,
| | < < | 79642 79643 79644 79645 79646 79647 79648 79649 79650 79651 79652 79653 79654 79655 79656 79657 79658 79659 79660 79661 79662 79663 79664 79665 79666 79667 79668 79669 |
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
{
char *zSql;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
xAuth = db->xAuth;
db->xAuth = 0;
#endif
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
}
#endif
if( rc==SQLITE_OK ) rc = initData.rc;
sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
sqlite3AnalysisLoad(db, iDb);
}
#endif
}
|
| ︙ | ︙ | |||
78625 78626 78627 78628 78629 78630 78631 |
/* Allocate the parsing context */
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
if( pParse==0 ){
rc = SQLITE_NOMEM;
goto end_prepare;
}
pParse->pReprepare = pReprepare;
| < < < < < | 79864 79865 79866 79867 79868 79869 79870 79871 79872 79873 79874 79875 79876 79877 |
/* Allocate the parsing context */
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
if( pParse==0 ){
rc = SQLITE_NOMEM;
goto end_prepare;
}
pParse->pReprepare = pReprepare;
assert( ppStmt && *ppStmt==0 );
assert( !db->mallocFailed );
assert( sqlite3_mutex_held(db->mutex) );
/* Check to verify that it is possible to get a read lock on all
** database schemas. The inability to get a read lock indicates that
** some other database connection is holding a write-lock, which in
|
| ︙ | ︙ | |||
78665 78666 78667 78668 78669 78670 78671 |
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
assert( sqlite3BtreeHoldsMutex(pBt) );
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, rc, "database schema is locked: %s", zDb);
| < < | 79899 79900 79901 79902 79903 79904 79905 79906 79907 79908 79909 79910 79911 79912 79913 79914 79915 79916 79917 79918 79919 79920 79921 79922 79923 79924 79925 79926 79927 79928 |
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
assert( sqlite3BtreeHoldsMutex(pBt) );
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, rc, "database schema is locked: %s", zDb);
testcase( db->flags & SQLITE_ReadUncommitted );
goto end_prepare;
}
}
}
sqlite3VtabUnlockList(db);
pParse->db = db;
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
testcase( nBytes==mxLen );
testcase( nBytes==mxLen+1 );
if( nBytes>mxLen ){
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
goto end_prepare;
}
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
sqlite3RunParser(pParse, zSqlCopy, &zErrMsg);
sqlite3DbFree(db, zSqlCopy);
|
| ︙ | ︙ | |||
78739 78740 78741 78742 78743 78744 78745 |
for(i=iFirst; i<mx; i++){
sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
azColName[i], SQLITE_STATIC);
}
}
#endif
| < < < < | 79971 79972 79973 79974 79975 79976 79977 79978 79979 79980 79981 79982 79983 79984 |
for(i=iFirst; i<mx; i++){
sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
azColName[i], SQLITE_STATIC);
}
}
#endif
assert( db->init.busy==0 || saveSqlFlag==0 );
if( db->init.busy==0 ){
Vdbe *pVdbe = pParse->pVdbe;
sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
}
if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
sqlite3VdbeFinalize(pParse->pVdbe);
|
| ︙ | ︙ | |||
78790 78791 78792 78793 78794 78795 78796 |
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
int rc;
assert( ppStmt!=0 );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
| | | 80018 80019 80020 80021 80022 80023 80024 80025 80026 80027 80028 80029 80030 80031 80032 |
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
int rc;
assert( ppStmt!=0 );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
if( rc==SQLITE_SCHEMA ){
sqlite3_finalize(*ppStmt);
rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
|
| ︙ | ︙ | |||
78829 78830 78831 78832 78833 78834 78835 |
assert( sqlite3_mutex_held(db->mutex) );
rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
if( rc ){
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
assert( pNew==0 );
| | | 80057 80058 80059 80060 80061 80062 80063 80064 80065 80066 80067 80068 80069 80070 80071 |
assert( sqlite3_mutex_held(db->mutex) );
rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
if( rc ){
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
assert( pNew==0 );
return rc;
}else{
assert( pNew!=0 );
}
sqlite3VdbeSwap((Vdbe*)pNew, p);
sqlite3TransferBindings(pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult((Vdbe*)pNew);
sqlite3VdbeFinalize((Vdbe*)pNew);
|
| ︙ | ︙ | |||
78898 78899 78900 78901 78902 78903 78904 |
char *zSql8;
const char *zTail8 = 0;
int rc = SQLITE_OK;
assert( ppStmt );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
| | | 80126 80127 80128 80129 80130 80131 80132 80133 80134 80135 80136 80137 80138 80139 80140 |
char *zSql8;
const char *zTail8 = 0;
int rc = SQLITE_OK;
assert( ppStmt );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
if( zSql8 ){
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
}
|
| ︙ | ︙ | |||
82286 82287 82288 82289 82290 82291 82292 |
static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Parse *pParse;
int i;
SrcList *pTabList;
struct SrcList_item *pFrom;
assert( p->selFlags & SF_Resolved );
| | | | | | | | | | | | | > | 83514 83515 83516 83517 83518 83519 83520 83521 83522 83523 83524 83525 83526 83527 83528 83529 83530 83531 83532 83533 83534 83535 83536 83537 83538 83539 83540 |
static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Parse *pParse;
int i;
SrcList *pTabList;
struct SrcList_item *pFrom;
assert( p->selFlags & SF_Resolved );
if( (p->selFlags & SF_HasTypeInfo)==0 ){
p->selFlags |= SF_HasTypeInfo;
pParse = pWalker->pParse;
pTabList = p->pSrc;
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab = pFrom->pTab;
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
/* A sub-query in the FROM clause of a SELECT */
Select *pSel = pFrom->pSelect;
assert( pSel );
while( pSel->pPrior ) pSel = pSel->pPrior;
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
}
}
}
return WRC_Continue;
}
#endif
|
| ︙ | ︙ | |||
83569 83570 83571 83572 83573 83574 83575 |
** If sqlite3SrcListLookup() returns 0, indicating the table does not
** exist, the error is caught by the block below.
*/
if( !pTableName || db->mallocFailed ){
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
| > | | 84798 84799 84800 84801 84802 84803 84804 84805 84806 84807 84808 84809 84810 84811 84812 84813 |
** If sqlite3SrcListLookup() returns 0, indicating the table does not
** exist, the error is caught by the block below.
*/
if( !pTableName || db->mallocFailed ){
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( db->init.busy==0 && pName2->n==0 && pTab
&& pTab->pSchema==db->aDb[1].pSchema ){
iDb = 1;
}
/* Ensure the table name matches database name and that the table exists */
if( db->mallocFailed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
|
| ︙ | ︙ | |||
83697 83698 83699 83700 83701 83702 83703 |
** in order to complete the process of building the trigger.
*/
SQLITE_PRIVATE void sqlite3FinishTrigger(
Parse *pParse, /* Parser context */
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
| | | | | | | | | 84927 84928 84929 84930 84931 84932 84933 84934 84935 84936 84937 84938 84939 84940 84941 84942 84943 84944 84945 84946 84947 84948 84949 84950 84951 84952 84953 84954 84955 84956 84957 84958 84959 84960 84961 84962 84963 84964 84965 |
** in order to complete the process of building the trigger.
*/
SQLITE_PRIVATE void sqlite3FinishTrigger(
Parse *pParse, /* Parser context */
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
char *zName; /* Name of trigger */
sqlite3 *db = pParse->db; /* The database */
DbFixer sFix; /* Fixer object */
int iDb; /* Database containing the trigger */
Token nameToken; /* Trigger name for error reporting */
pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
zName = pTrig->zName;
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
pTrig->step_list = pStepList;
while( pStepList ){
pStepList->pTrig = pTrig;
pStepList = pStepList->pNext;
}
nameToken.z = pTrig->zName;
nameToken.n = sqlite3Strlen30(nameToken.z);
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
goto triggerfinish_cleanup;
}
/* if we are not initializing,
** build the sqlite_master entry
*/
if( !db->init.busy ){
Vdbe *v;
char *z;
/* Make an entry in the sqlite_master table */
|
| ︙ | ︙ | |||
85220 85221 85222 85223 85224 85225 85226 85227 85228 85229 | ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* ** Execute zSql on database db. Return an error code. */ | > > > > > > > > > > > > > | > | | | | | | 86450 86451 86452 86453 86454 86455 86456 86457 86458 86459 86460 86461 86462 86463 86464 86465 86466 86467 86468 86469 86470 86471 86472 86473 86474 86475 86476 86477 86478 86479 86480 86481 86482 86483 86484 86485 86486 86487 86488 86489 86490 86491 86492 86493 86494 86495 86496 86497 86498 86499 86500 86501 86502 86503 86504 86505 86506 86507 86508 86509 86510 86511 86512 86513 86514 |
** This file contains code used to implement the VACUUM command.
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
*/
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/*
** Finalize a prepared statement. If there was an error, store the
** text of the error message in *pzErrMsg. Return the result code.
*/
static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
int rc;
rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
if( rc ){
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
}
return rc;
}
/*
** Execute zSql on database db. Return an error code.
*/
static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
sqlite3_stmt *pStmt;
VVA_ONLY( int rc; )
if( !zSql ){
return SQLITE_NOMEM;
}
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
return sqlite3_errcode(db);
}
VVA_ONLY( rc = ) sqlite3_step(pStmt);
assert( rc!=SQLITE_ROW );
return vacuumFinalize(db, pStmt, pzErrMsg);
}
/*
** Execute zSql on database db. The statement returns exactly
** one column. Execute this as SQL on the same database.
*/
static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
sqlite3_stmt *pStmt;
int rc;
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
if( rc!=SQLITE_OK ){
vacuumFinalize(db, pStmt, pzErrMsg);
return rc;
}
}
return vacuumFinalize(db, pStmt, pzErrMsg);
}
/*
** The non-standard VACUUM command is used to clean up the database,
** collapse free space, etc. It is modelled after the VACUUM command
** in PostgreSQL.
**
|
| ︙ | ︙ | |||
85306 85307 85308 85309 85310 85311 85312 | ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_xTrace = db->xTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; | | > > > | > | | 86550 86551 86552 86553 86554 86555 86556 86557 86558 86559 86560 86561 86562 86563 86564 86565 86566 86567 86568 86569 86570 86571 86572 86573 86574 86575 86576 86577 86578 86579 86580 86581 86582 86583 86584 86585 86586 86587 86588 86589 |
** restored before returning. Then set the writable-schema flag, and
** disable CHECK and foreign key constraints. */
saved_flags = db->flags;
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_xTrace = db->xTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
db->xTrace = 0;
pMain = db->aDb[0].pBt;
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
** (possibly synchronous) transaction opened on the main database before
** sqlite3BtreeCopyFile() is called.
**
** An optimisation would be to use a non-journaled pager.
** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
** that actually made the VACUUM run slower. Very little journalling
** actually occurs when doing a vacuum since the vacuum_db is initially
** empty. Only the journal header is written. Apparently it takes more
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
if( sqlite3TempInMemory(db) ){
zSql = "ATTACH ':memory:' AS vacuum_db;";
}else{
zSql = "ATTACH '' AS vacuum_db;";
}
rc = execSql(db, pzErrMsg, zSql);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
pDb = &db->aDb[db->nDb-1];
assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
pTemp = db->aDb[db->nDb-1].pBt;
/* The call to execSql() to attach the temp database has left the file
** locked (as there was more than one active statement when the transaction
|
| ︙ | ︙ | |||
85359 85360 85361 85362 85363 85364 85365 |
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
|| (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
|| NEVER(db->mallocFailed)
){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
| | | | | | | < | | | | 86607 86608 86609 86610 86611 86612 86613 86614 86615 86616 86617 86618 86619 86620 86621 86622 86623 86624 86625 86626 86627 86628 86629 86630 86631 86632 86633 86634 86635 86636 86637 86638 86639 86640 86641 86642 86643 86644 86645 86646 86647 86648 86649 86650 86651 86652 86653 86654 86655 86656 86657 86658 86659 86660 86661 86662 86663 86664 86665 86666 86667 86668 86669 86670 86671 86672 86673 86674 86675 86676 86677 86678 86679 86680 86681 86682 86683 86684 86685 86686 |
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
|| (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
|| NEVER(db->mallocFailed)
){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
if( rc!=SQLITE_OK ){
goto end_of_vacuum;
}
#ifndef SQLITE_OMIT_AUTOVACUUM
sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac :
sqlite3BtreeGetAutoVacuum(pMain));
#endif
/* Begin a transaction */
rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Query the schema of the main database. Create a mirror schema
** in the temporary database.
*/
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
" FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Loop through the tables in the main database. For each, do
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
** the contents to the temporary database.
*/
rc = execExecSql(db, pzErrMsg,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM main.' || quote(name) || ';'"
"FROM main.sqlite_master "
"WHERE type = 'table' AND name!='sqlite_sequence' "
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy over the sequence table
*/
rc = execExecSql(db, pzErrMsg,
"SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db, pzErrMsg,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM main.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy the triggers, views, and virtual tables from the main database
** over to the temporary database. None of these objects has any
** associated storage, so all we have to do is copy their entries
** from the SQLITE_MASTER table.
*/
rc = execSql(db, pzErrMsg,
"INSERT INTO vacuum_db.sqlite_master "
" SELECT type, name, tbl_name, rootpage, sql"
" FROM main.sqlite_master"
" WHERE type='view' OR type='trigger'"
" OR (type='table' AND rootpage=0)"
);
if( rc ) goto end_of_vacuum;
|
| ︙ | ︙ | |||
85637 85638 85639 85640 85641 85642 85643 |
assert( pVTab->nRef>0 );
assert( sqlite3SafetyCheckOk(db) );
pVTab->nRef--;
if( pVTab->nRef==0 ){
sqlite3_vtab *p = pVTab->pVtab;
if( p ){
| < < < | < < < < < < | 86884 86885 86886 86887 86888 86889 86890 86891 86892 86893 86894 86895 86896 86897 86898 |
assert( pVTab->nRef>0 );
assert( sqlite3SafetyCheckOk(db) );
pVTab->nRef--;
if( pVTab->nRef==0 ){
sqlite3_vtab *p = pVTab->pVtab;
if( p ){
p->pModule->xDisconnect(p);
}
sqlite3DbFree(db, pVTab);
}
}
/*
** Table p is a virtual table. This function moves all elements in the
|
| ︙ | ︙ | |||
85982 85983 85984 85985 85986 85987 85988 | pVTable->pMod = pMod; assert( !db->pVTab ); assert( xConstruct ); db->pVTab = pTab; /* Invoke the virtual table constructor */ | < < | 87220 87221 87222 87223 87224 87225 87226 87227 87228 87229 87230 87231 87232 87233 87234 |
pVTable->pMod = pMod;
assert( !db->pVTab );
assert( xConstruct );
db->pVTab = pTab;
/* Invoke the virtual table constructor */
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
if( SQLITE_OK!=rc ){
if( zErr==0 ){
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf(db, "%s", zErr);
|
| ︙ | ︙ | |||
86172 86173 86174 86175 86176 86177 86178 |
char *zErr = 0;
sqlite3_mutex_enter(db->mutex);
pTab = db->pVTab;
if( !pTab ){
sqlite3Error(db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(db->mutex);
| | | 87408 87409 87410 87411 87412 87413 87414 87415 87416 87417 87418 87419 87420 87421 87422 |
char *zErr = 0;
sqlite3_mutex_enter(db->mutex);
pTab = db->pVTab;
if( !pTab ){
sqlite3Error(db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE_BKPT;
}
assert( (pTab->tabFlags & TF_Virtual)!=0 );
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
if( pParse==0 ){
rc = SQLITE_NOMEM;
}else{
|
| ︙ | ︙ | |||
86231 86232 86233 86234 86235 86236 86237 |
int rc = SQLITE_OK;
Table *pTab;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
VTable *p = vtabDisconnectAll(db, pTab);
| < < | 87467 87468 87469 87470 87471 87472 87473 87474 87475 87476 87477 87478 87479 87480 87481 87482 |
int rc = SQLITE_OK;
Table *pTab;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
VTable *p = vtabDisconnectAll(db, pTab);
assert( rc==SQLITE_OK );
rc = p->pMod->pModule->xDestroy(p->pVtab);
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
if( rc==SQLITE_OK ){
assert( pTab->pVTable==p && p->pNext==0 );
p->pVtab = 0;
pTab->pVTable = 0;
sqlite3VtabUnlock(p);
|
| ︙ | ︙ | |||
86286 86287 86288 86289 86290 86291 86292 |
**
** Set *pzErrmsg to point to a buffer that should be released using
** sqlite3DbFree() containing an error message, if one is available.
*/
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
int i;
int rc = SQLITE_OK;
| < < < < < < < | 87520 87521 87522 87523 87524 87525 87526 87527 87528 87529 87530 87531 87532 87533 87534 87535 87536 87537 87538 87539 87540 87541 87542 87543 87544 87545 87546 87547 |
**
** Set *pzErrmsg to point to a buffer that should be released using
** sqlite3DbFree() containing an error message, if one is available.
*/
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
int i;
int rc = SQLITE_OK;
VTable **aVTrans = db->aVTrans;
db->aVTrans = 0;
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
int (*x)(sqlite3_vtab *);
sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
rc = x(pVtab);
sqlite3DbFree(db, *pzErrmsg);
*pzErrmsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
}
}
db->aVTrans = aVTrans;
return rc;
}
/*
** Invoke the xRollback method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
|
| ︙ | ︙ | |||
87129 87130 87131 87132 87133 87134 87135 |
if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ){
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
** be the name of an indexed column with TEXT affinity. */
return 0;
}
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
pColl = sqlite3ExprCollSeq(pParse, pLeft);
| | | 88356 88357 88358 88359 88360 88361 88362 88363 88364 88365 88366 88367 88368 88369 88370 |
if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ){
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
** be the name of an indexed column with TEXT affinity. */
return 0;
}
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
pColl = sqlite3ExprCollSeq(pParse, pLeft);
if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */
if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
/* IMP: R-09003-32046 For the GLOB operator, the column must use the
** default BINARY collating sequence.
** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode
** is enabled then the column must use the default BINARY collating
** sequence, or if case_sensitive_like mode is disabled then the column
|
| ︙ | ︙ | |||
87572 87573 87574 87575 87576 87577 87578 |
int idxTerm /* Index of the term to be analyzed */
){
WhereTerm *pTerm; /* The term to be analyzed */
WhereMaskSet *pMaskSet; /* Set of table index masks */
Expr *pExpr; /* The expression to be analyzed */
Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
Bitmask prereqAll; /* Prerequesites of pExpr */
| | | 88799 88800 88801 88802 88803 88804 88805 88806 88807 88808 88809 88810 88811 88812 88813 |
int idxTerm /* Index of the term to be analyzed */
){
WhereTerm *pTerm; /* The term to be analyzed */
WhereMaskSet *pMaskSet; /* Set of table index masks */
Expr *pExpr; /* The expression to be analyzed */
Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
Bitmask prereqAll; /* Prerequesites of pExpr */
Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
int noCase = 0; /* LIKE/GLOB distinguishes case */
int op; /* Top-level operator. pExpr->op */
Parse *pParse = pWC->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
|
| ︙ | ︙ | |||
87644 87645 87646 87647 87648 87649 87650 |
pDup = pExpr;
pNew = pTerm;
}
exprCommute(pParse, pDup);
pLeft = pDup->pLeft;
pNew->leftCursor = pLeft->iTable;
pNew->u.leftColumn = pLeft->iColumn;
| > | | 88871 88872 88873 88874 88875 88876 88877 88878 88879 88880 88881 88882 88883 88884 88885 88886 |
pDup = pExpr;
pNew = pTerm;
}
exprCommute(pParse, pDup);
pLeft = pDup->pLeft;
pNew->leftCursor = pLeft->iTable;
pNew->u.leftColumn = pLeft->iColumn;
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = operatorMask(pDup->op);
}
}
#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
/* If a term is the BETWEEN operator, create two new virtual terms
|
| ︙ | ︙ | |||
88234 88235 88236 88237 88238 88239 88240 |
** that this is required.
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
int i;
int rc;
| < < | 89462 89463 89464 89465 89466 89467 89468 89469 89470 89471 89472 89473 89474 89475 89476 89477 89478 89479 |
** that this is required.
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
int i;
int rc;
WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(p);
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ){
pParse->db->mallocFailed = 1;
}else if( !pVtab->zErrMsg ){
sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
}else{
|
| ︙ | ︙ | |||
90869 90870 90871 90872 90873 90874 90875 | ** yy_action. Used to detect hash collisions. ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ | | | 92095 92096 92097 92098 92099 92100 92101 92102 92103 92104 92105 92106 92107 92108 92109 |
** yy_action. Used to detect hash collisions.
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
#define YY_ACTTAB_COUNT (1550)
static const YYACTIONTYPE yy_action[] = {
/* 0 */ 313, 49, 556, 46, 147, 172, 628, 598, 55, 55,
/* 10 */ 55, 55, 302, 53, 53, 53, 53, 52, 52, 51,
/* 20 */ 51, 51, 50, 238, 603, 66, 624, 623, 604, 598,
/* 30 */ 591, 585, 48, 53, 53, 53, 53, 52, 52, 51,
/* 40 */ 51, 51, 50, 238, 51, 51, 51, 50, 238, 56,
/* 50 */ 57, 47, 583, 582, 584, 584, 54, 54, 55, 55,
|
| ︙ | ︙ | |||
91019 91020 91021 91022 91023 91024 91025 | /* 1410 */ 386, 536, 329, 411, 602, 83, 414, 518, 280, 411, /* 1420 */ 513, 414, 594, 594, 594, 602, 82, 517, 414, 311, /* 1430 */ 602, 81, 411, 514, 414, 512, 131, 602, 70, 229, /* 1440 */ 228, 227, 494, 602, 17, 411, 488, 414, 259, 346, /* 1450 */ 249, 389, 487, 486, 314, 164, 602, 79, 310, 240, /* 1460 */ 414, 373, 480, 163, 262, 371, 414, 162, 369, 602, /* 1470 */ 78, 212, 478, 26, 477, 602, 9, 161, 467, 363, | | | | | | | | | 92245 92246 92247 92248 92249 92250 92251 92252 92253 92254 92255 92256 92257 92258 92259 92260 92261 92262 92263 92264 92265 |
/* 1410 */ 386, 536, 329, 411, 602, 83, 414, 518, 280, 411,
/* 1420 */ 513, 414, 594, 594, 594, 602, 82, 517, 414, 311,
/* 1430 */ 602, 81, 411, 514, 414, 512, 131, 602, 70, 229,
/* 1440 */ 228, 227, 494, 602, 17, 411, 488, 414, 259, 346,
/* 1450 */ 249, 389, 487, 486, 314, 164, 602, 79, 310, 240,
/* 1460 */ 414, 373, 480, 163, 262, 371, 414, 162, 369, 602,
/* 1470 */ 78, 212, 478, 26, 477, 602, 9, 161, 467, 363,
/* 1480 */ 141, 122, 339, 187, 119, 457, 348, 347, 117, 116,
/* 1490 */ 115, 112, 114, 448, 182, 22, 320, 433, 432, 431,
/* 1500 */ 19, 428, 610, 597, 574, 193, 572, 63, 298, 404,
/* 1510 */ 555, 552, 290, 281, 510, 460, 498, 499, 495, 447,
/* 1520 */ 356, 497, 256, 380, 306, 570, 5, 250, 345, 238,
/* 1530 */ 299, 550, 527, 490, 508, 525, 502, 401, 501, 963,
/* 1540 */ 211, 963, 483, 963, 963, 963, 963, 963, 963, 370,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 19, 222, 223, 224, 225, 24, 1, 26, 77, 78,
/* 10 */ 79, 80, 15, 82, 83, 84, 85, 86, 87, 88,
/* 20 */ 89, 90, 91, 92, 113, 22, 26, 27, 117, 26,
/* 30 */ 49, 50, 81, 82, 83, 84, 85, 86, 87, 88,
/* 40 */ 89, 90, 91, 92, 88, 89, 90, 91, 92, 68,
|
| ︙ | ︙ | |||
91176 91177 91178 91179 91180 91181 91182 | /* 1410 */ 104, 211, 47, 150, 174, 175, 165, 176, 176, 150, /* 1420 */ 103, 165, 129, 130, 131, 174, 175, 184, 165, 179, /* 1430 */ 174, 175, 150, 178, 165, 176, 22, 174, 175, 230, /* 1440 */ 92, 230, 184, 174, 175, 150, 176, 165, 105, 106, /* 1450 */ 107, 150, 176, 176, 111, 156, 174, 175, 179, 116, /* 1460 */ 165, 18, 157, 156, 238, 157, 165, 156, 45, 174, /* 1470 */ 175, 157, 157, 135, 239, 174, 175, 156, 189, 157, | | | | | | | | | | | | | | | | | | | | | 92402 92403 92404 92405 92406 92407 92408 92409 92410 92411 92412 92413 92414 92415 92416 92417 92418 92419 92420 92421 92422 92423 92424 92425 92426 92427 92428 92429 92430 92431 92432 92433 92434 92435 92436 92437 92438 92439 92440 92441 92442 92443 92444 92445 92446 92447 92448 92449 92450 92451 92452 92453 92454 92455 92456 92457 92458 92459 92460 92461 92462 92463 92464 92465 92466 92467 92468 92469 92470 92471 92472 92473 92474 92475 92476 92477 92478 92479 92480 92481 92482 92483 92484 92485 92486 92487 92488 92489 92490 92491 92492 92493 92494 92495 92496 92497 92498 92499 92500 92501 92502 |
/* 1410 */ 104, 211, 47, 150, 174, 175, 165, 176, 176, 150,
/* 1420 */ 103, 165, 129, 130, 131, 174, 175, 184, 165, 179,
/* 1430 */ 174, 175, 150, 178, 165, 176, 22, 174, 175, 230,
/* 1440 */ 92, 230, 184, 174, 175, 150, 176, 165, 105, 106,
/* 1450 */ 107, 150, 176, 176, 111, 156, 174, 175, 179, 116,
/* 1460 */ 165, 18, 157, 156, 238, 157, 165, 156, 45, 174,
/* 1470 */ 175, 157, 157, 135, 239, 174, 175, 156, 189, 157,
/* 1480 */ 68, 189, 139, 219, 22, 199, 157, 18, 192, 192,
/* 1490 */ 192, 189, 192, 199, 219, 243, 157, 40, 157, 157,
/* 1500 */ 243, 38, 153, 166, 233, 196, 233, 246, 198, 228,
/* 1510 */ 177, 177, 209, 177, 182, 199, 166, 177, 166, 199,
/* 1520 */ 242, 177, 242, 178, 148, 166, 196, 209, 209, 92,
/* 1530 */ 195, 208, 174, 186, 183, 174, 183, 191, 183, 253,
/* 1540 */ 236, 253, 186, 253, 253, 253, 253, 253, 253, 237,
};
#define YY_SHIFT_USE_DFLT (-90)
#define YY_SHIFT_COUNT (418)
#define YY_SHIFT_MIN (-89)
#define YY_SHIFT_MAX (1469)
static const short yy_shift_ofst[] = {
/* 0 */ 993, 1114, 1343, 1114, 1213, 1213, 90, 90, 0, -19,
/* 10 */ 1213, 1213, 1213, 1213, 1213, 352, 517, 721, 1091, 1213,
/* 20 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
/* 30 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
/* 40 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1236, 1213, 1213,
/* 50 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
/* 60 */ 1213, -49, 199, 517, 517, 913, 913, 382, 1177, 55,
/* 70 */ 647, 573, 499, 425, 351, 277, 203, 129, 795, 795,
/* 80 */ 795, 795, 795, 795, 795, 795, 795, 795, 795, 795,
/* 90 */ 795, 795, 795, 795, 795, 795, 869, 795, 943, 1017,
/* 100 */ 1017, -69, -69, -69, -69, -1, -1, 58, 138, -44,
/* 110 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517,
/* 120 */ 517, 517, 517, 517, 517, 517, 202, 579, 517, 517,
/* 130 */ 517, 517, 517, 382, 885, 1437, -90, -90, -90, 1293,
/* 140 */ 73, 272, 272, 309, 311, 297, 282, 216, 602, 538,
/* 150 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517,
/* 160 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517,
/* 170 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517,
/* 180 */ 517, 517, 505, 231, 231, 231, 706, 64, 1177, 1177,
/* 190 */ 1177, -90, -90, -90, 136, 168, 168, 12, 496, 496,
/* 200 */ 496, 506, 423, 512, 370, 349, 335, 149, 149, 149,
/* 210 */ 149, 604, 516, 149, 149, 508, 3, 299, 677, 871,
/* 220 */ 613, 613, 879, 871, 879, 144, 382, 226, 382, 226,
/* 230 */ 564, 226, 613, 226, 226, 404, 625, 625, 382, 426,
/* 240 */ -89, 801, 1463, 1244, 1244, 1457, 1457, 1244, 1462, 1412,
/* 250 */ 1188, 1469, 1469, 1469, 1469, 1244, 1188, 1462, 1412, 1412,
/* 260 */ 1244, 1443, 1338, 1423, 1244, 1244, 1443, 1244, 1443, 1244,
/* 270 */ 1443, 1414, 1306, 1306, 1306, 1365, 1348, 1348, 1414, 1306,
/* 280 */ 1317, 1306, 1365, 1306, 1306, 1267, 1268, 1267, 1268, 1267,
/* 290 */ 1268, 1244, 1244, 1216, 1214, 1215, 1192, 1173, 1188, 1177,
/* 300 */ 1260, 1253, 1253, 1248, 1248, 1248, 1248, -90, -90, -90,
/* 310 */ -90, -90, -90, 939, 102, 614, 84, 133, 14, 837,
/* 320 */ 396, 829, 825, 796, 757, 751, 650, 357, 244, 107,
/* 330 */ 54, 305, 278, 1207, 1203, 1183, 1063, 1179, 1137, 1166,
/* 340 */ 1172, 1170, 1064, 1152, 1046, 1057, 1034, 1126, 1041, 1129,
/* 350 */ 1142, 1031, 1120, 1012, 1056, 1048, 1018, 1098, 1086, 1001,
/* 360 */ 1097, 1076, 1058, 971, 936, 1026, 1052, 1025, 1013, 1027,
/* 370 */ 967, 1044, 1032, 1050, 945, 949, 1028, 995, 1024, 1021,
/* 380 */ 963, 981, 928, 953, 951, 870, 876, 897, 838, 720,
/* 390 */ 828, 794, 820, 498, 642, 783, 657, 729, 642, 557,
/* 400 */ 507, 509, 497, 470, 478, 449, 294, 228, 443, 23,
/* 410 */ 152, 123, 68, -20, -42, 57, 39, -3, 5,
};
#define YY_REDUCE_USE_DFLT (-222)
#define YY_REDUCE_COUNT (312)
#define YY_REDUCE_MIN (-221)
#define YY_REDUCE_MAX (1376)
static const short yy_reduce_ofst[] = {
/* 0 */ 310, 994, 1134, 221, 169, 157, 89, 18, 83, 301,
/* 10 */ 377, 316, 312, 16, 295, 238, 249, 391, 1301, 1295,
/* 20 */ 1282, 1269, 1263, 1256, 1251, 1240, 1234, 1228, 1221, 1208,
/* 30 */ 1109, 1103, 1077, 1054, 1022, 1016, 911, 908, 890, 888,
/* 40 */ 874, 816, 800, 760, 742, 739, 726, 684, 672, 665,
/* 50 */ 652, 612, 610, 594, 591, 578, 530, 528, 526, 524,
/* 60 */ -72, -221, 399, 469, 445, 438, 143, 222, 359, 523,
/* 70 */ 523, 523, 523, 523, 523, 523, 523, 523, 523, 523,
/* 80 */ 523, 523, 523, 523, 523, 523, 523, 523, 523, 523,
/* 90 */ 523, 523, 523, 523, 523, 523, 523, 523, 523, 523,
/* 100 */ 523, 523, 523, 523, 523, 523, 523, 307, 523, 523,
/* 110 */ 1110, 678, 1033, 965, 962, 891, 814, 813, 744, 771,
/* 120 */ 691, 607, 522, 743, 686, 740, 328, 418, 670, 666,
/* 130 */ 596, 527, 529, 583, 523, 523, 523, 523, 523, 593,
/* 140 */ 823, 738, 712, 892, 1199, 1185, 1176, 1171, 673, 673,
/* 150 */ 1168, 1167, 1162, 1159, 1148, 1145, 1139, 1117, 1111, 1107,
/* 160 */ 1084, 1066, 1049, 1011, 1010, 1006, 1002, 999, 998, 973,
/* 170 */ 972, 970, 966, 964, 895, 894, 892, 833, 822, 762,
/* 180 */ 761, 229, 811, 804, 803, 389, 688, 808, 807, 737,
/* 190 */ 460, 464, 572, 584, 1356, 1361, 1358, 1347, 1355, 1353,
/* 200 */ 1351, 1323, 1335, 1346, 1335, 1335, 1335, 1335, 1335, 1335,
/* 210 */ 1335, 1312, 1304, 1335, 1335, 1323, 1359, 1330, 1376, 1320,
/* 220 */ 1319, 1318, 1280, 1316, 1278, 1345, 1352, 1344, 1350, 1340,
/* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1273, 1271, 1337, 1310,
/* 240 */ 1309, 1349, 1261, 1342, 1341, 1257, 1252, 1339, 1275, 1302,
/* 250 */ 1294, 1300, 1298, 1297, 1296, 1329, 1286, 1264, 1292, 1289,
/* 260 */ 1322, 1321, 1235, 1226, 1315, 1314, 1311, 1308, 1307, 1305,
/* 270 */ 1299, 1279, 1277, 1276, 1270, 1258, 1211, 1209, 1250, 1259,
/* 280 */ 1255, 1242, 1243, 1241, 1201, 1200, 1184, 1186, 1182, 1178,
/* 290 */ 1165, 1206, 1204, 1113, 1135, 1095, 1124, 1105, 1102, 1096,
/* 300 */ 1112, 1140, 1136, 1121, 1116, 1115, 1089, 985, 961, 987,
/* 310 */ 1061, 1038, 1053,
};
|
| ︙ | ︙ | |||
94756 94757 94758 94759 94760 94761 94762 94763 94764 94765 94766 94767 94768 94769 |
}
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc));
}
assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
*pzErrMsg = pParse->zErrMsg;
pParse->zErrMsg = 0;
nErr++;
}
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
sqlite3VdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
}
| > | 95982 95983 95984 95985 95986 95987 95988 95989 95990 95991 95992 95993 95994 95995 95996 |
}
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc));
}
assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
*pzErrMsg = pParse->zErrMsg;
sqlite3_log(pParse->rc, "%s", *pzErrMsg);
pParse->zErrMsg = 0;
nErr++;
}
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
sqlite3VdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
}
|
| ︙ | ︙ | |||
95434 95435 95436 95437 95438 95439 95440 |
*/
SQLITE_API int sqlite3_config(int op, ...){
va_list ap;
int rc = SQLITE_OK;
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
** the SQLite library is in use. */
| | | 96661 96662 96663 96664 96665 96666 96667 96668 96669 96670 96671 96672 96673 96674 96675 |
*/
SQLITE_API int sqlite3_config(int op, ...){
va_list ap;
int rc = SQLITE_OK;
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
** the SQLite library is in use. */
if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;
va_start(ap, op);
switch( op ){
/* Mutex configuration options are only available in a threadsafe
** compile.
*/
|
| ︙ | ︙ | |||
95555 95556 95557 95558 95559 95560 95561 95562 95563 95564 95565 95566 95567 95568 |
#endif
case SQLITE_CONFIG_LOOKASIDE: {
sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
default: {
rc = SQLITE_ERROR;
break;
}
}
va_end(ap);
| > > > > > > > > > > > > > > > | 96782 96783 96784 96785 96786 96787 96788 96789 96790 96791 96792 96793 96794 96795 96796 96797 96798 96799 96800 96801 96802 96803 96804 96805 96806 96807 96808 96809 96810 |
#endif
case SQLITE_CONFIG_LOOKASIDE: {
sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
/* Record a pointer to the logger funcction and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
*/
case SQLITE_CONFIG_LOG: {
/* MSVC is picky about pulling func ptrs from va lists.
** http://support.microsoft.com/kb/47961
** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
*/
typedef void(*LOGFUNC_t)(void*,int,const char*);
sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
break;
}
default: {
rc = SQLITE_ERROR;
break;
}
}
va_end(ap);
|
| ︙ | ︙ | |||
95768 95769 95770 95771 95772 95773 95774 |
HashElem *i;
int j;
if( !db ){
return SQLITE_OK;
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
| | | 97010 97011 97012 97013 97014 97015 97016 97017 97018 97019 97020 97021 97022 97023 97024 |
HashElem *i;
int j;
if( !db ){
return SQLITE_OK;
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
sqlite3ResetInternalSchema(db, 0);
/* If a transaction is open, the ResetInternalSchema() call above
** will not have called the xDisconnect() method on any virtual
|
| ︙ | ︙ | |||
96115 96116 96117 96118 96119 96120 96121 |
assert( sqlite3_mutex_held(db->mutex) );
if( zFunctionName==0 ||
(xFunc && (xFinal || xStep)) ||
(!xFunc && (xFinal && !xStep)) ||
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
| | | 97357 97358 97359 97360 97361 97362 97363 97364 97365 97366 97367 97368 97369 97370 97371 |
assert( sqlite3_mutex_held(db->mutex) );
if( zFunctionName==0 ||
(xFunc && (xFinal || xStep)) ||
(!xFunc && (xFinal && !xStep)) ||
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
return SQLITE_MISUSE_BKPT;
}
#ifndef SQLITE_OMIT_UTF16
/* If SQLITE_UTF16 is specified as the encoding type, transform this
** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
**
|
| ︙ | ︙ | |||
96446 96447 96448 96449 96450 96451 96452 |
*/
SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){
const char *z;
if( !db ){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
| | | 97688 97689 97690 97691 97692 97693 97694 97695 97696 97697 97698 97699 97700 97701 97702 |
*/
SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){
const char *z;
if( !db ){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
return sqlite3ErrStr(SQLITE_MISUSE_BKPT);
}
sqlite3_mutex_enter(db->mutex);
if( db->mallocFailed ){
z = sqlite3ErrStr(SQLITE_NOMEM);
}else{
z = (char*)sqlite3_value_text(db->pErr);
assert( !db->mallocFailed );
|
| ︙ | ︙ | |||
96515 96516 96517 96518 96519 96520 96521 |
/*
** Return the most recent error code generated by an SQLite routine. If NULL is
** passed to this function, we assume a malloc() failed during sqlite3_open().
*/
SQLITE_API int sqlite3_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
| | | | 97757 97758 97759 97760 97761 97762 97763 97764 97765 97766 97767 97768 97769 97770 97771 97772 97773 97774 97775 97776 97777 97778 97779 97780 |
/*
** Return the most recent error code generated by an SQLite routine. If NULL is
** passed to this function, we assume a malloc() failed during sqlite3_open().
*/
SQLITE_API int sqlite3_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
if( !db || db->mallocFailed ){
return SQLITE_NOMEM;
}
return db->errCode & db->errMask;
}
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
if( !db || db->mallocFailed ){
return SQLITE_NOMEM;
}
return db->errCode;
}
|
| ︙ | ︙ | |||
96562 96563 96564 96565 96566 96567 96568 |
enc2 = enc;
testcase( enc2==SQLITE_UTF16 );
testcase( enc2==SQLITE_UTF16_ALIGNED );
if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){
enc2 = SQLITE_UTF16NATIVE;
}
if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
| | | 97804 97805 97806 97807 97808 97809 97810 97811 97812 97813 97814 97815 97816 97817 97818 |
enc2 = enc;
testcase( enc2==SQLITE_UTF16 );
testcase( enc2==SQLITE_UTF16_ALIGNED );
if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){
enc2 = SQLITE_UTF16NATIVE;
}
if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
return SQLITE_MISUSE_BKPT;
}
/* Check if this call is removing or replacing an existing collation
** sequence. If so, and there are active VMs, return busy. If there
** are no active VMs, invalidate any pre-compiled statements.
*/
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
|
| ︙ | ︙ | |||
97106 97107 97108 97109 97110 97111 97112 |
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
}
| < | > > > | > > > | | > > > > > > > > > > > > > | | 98348 98349 98350 98351 98352 98353 98354 98355 98356 98357 98358 98359 98360 98361 98362 98363 98364 98365 98366 98367 98368 98369 98370 98371 98372 98373 98374 98375 98376 98377 98378 98379 98380 98381 98382 98383 98384 98385 98386 98387 98388 98389 |
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
}
/*
** The following routines are subtitutes for constants SQLITE_CORRUPT,
** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error
** constants. They server two purposes:
**
** 1. Serve as a convenient place to set a breakpoint in a debugger
** to detect when version error conditions occurs.
**
** 2. Invoke sqlite3_log() to provide the source code location where
** a low-level error is first detected.
*/
SQLITE_PRIVATE int sqlite3CorruptError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_CORRUPT,
"database corruption found by source line %d", lineno);
return SQLITE_CORRUPT;
}
SQLITE_PRIVATE int sqlite3MisuseError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_MISUSE, "misuse detected by source line %d", lineno);
return SQLITE_MISUSE;
}
SQLITE_PRIVATE int sqlite3CantopenError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_CANTOPEN, "cannot open file at source line %d", lineno);
return SQLITE_CANTOPEN;
}
#ifndef SQLITE_OMIT_DEPRECATED
/*
** This is a convenience routine that makes sure that all thread-specific
** data for this thread has been deallocated.
**
** SQLite no longer uses thread-specific data so this routine is now a
|
| ︙ | ︙ | |||
97159 97160 97161 97162 97163 97164 97165 | char const *zCollSeq = 0; int notnull = 0; int primarykey = 0; int autoinc = 0; /* Ensure the database schema has been loaded */ sqlite3_mutex_enter(db->mutex); | < | 98419 98420 98421 98422 98423 98424 98425 98426 98427 98428 98429 98430 98431 98432 |
char const *zCollSeq = 0;
int notnull = 0;
int primarykey = 0;
int autoinc = 0;
/* Ensure the database schema has been loaded */
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrMsg);
if( SQLITE_OK!=rc ){
goto error_out;
}
/* Locate the table in question */
|
| ︙ | ︙ | |||
97218 97219 97220 97221 97222 97223 97224 |
}
if( !zCollSeq ){
zCollSeq = "BINARY";
}
error_out:
sqlite3BtreeLeaveAll(db);
| < | 98477 98478 98479 98480 98481 98482 98483 98484 98485 98486 98487 98488 98489 98490 |
}
if( !zCollSeq ){
zCollSeq = "BINARY";
}
error_out:
sqlite3BtreeLeaveAll(db);
/* Whether the function call succeeded or failed, set the output parameters
** to whatever their local counterparts contain. If an error did occur,
** this has the effect of zeroing all output parameters.
*/
if( pzDataType ) *pzDataType = zDataType;
if( pzCollSeq ) *pzCollSeq = zCollSeq;
|
| ︙ | ︙ | |||
97857 97858 97859 97860 97861 97862 97863 | ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ | < < < | 99115 99116 99117 99118 99119 99120 99121 99122 99123 99124 99125 99126 99127 99128 | ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ /* The full-text index is stored in a series of b+tree (-like) ** structures called segments which map terms to doclists. The ** structures are like b+trees in layout, but are constructed from the ** bottom up in optimal fashion and are not updatable. Since trees ** are built from the bottom up, things will be described from the ** bottom up. ** |
| ︙ | ︙ | |||
97882 97883 97884 97885 97886 97887 97888 | ** B = 1xxxxxxx 7 bits of data and one flag bit ** ** 7 bits - A ** 14 bits - BA ** 21 bits - BBA ** and so on. ** | | > > > > > > > > > | > > > > > < < < < < | | | > > > > > > > > > > > > > > | 99137 99138 99139 99140 99141 99142 99143 99144 99145 99146 99147 99148 99149 99150 99151 99152 99153 99154 99155 99156 99157 99158 99159 99160 99161 99162 99163 99164 99165 99166 99167 99168 99169 99170 99171 99172 99173 99174 99175 99176 99177 99178 99179 99180 99181 99182 99183 99184 99185 99186 99187 99188 99189 99190 99191 99192 99193 99194 99195 99196 99197 99198 99199 99200 99201 99202 99203 99204 99205 99206 99207 99208 |
** B = 1xxxxxxx 7 bits of data and one flag bit
**
** 7 bits - A
** 14 bits - BA
** 21 bits - BBA
** and so on.
**
** This is similar in concept to how sqlite encodes "varints" but
** the encoding is not the same. SQLite varints are big-endian
** are are limited to 9 bytes in length whereas FTS3 varints are
** little-endian and can be upt to 10 bytes in length (in theory).
**
** Example encodings:
**
** 1: 0x01
** 127: 0x7f
** 128: 0x81 0x00
**
**
**** Document lists ****
** A doclist (document list) holds a docid-sorted list of hits for a
** given term. Doclists hold docids, and can optionally associate
** token positions and offsets with docids. A position is the index
** of a word within the document. The first word of the document has
** a position of 0.
**
** FTS3 used to optionally store character offsets using a compile-time
** option. But that functionality is no longer supported.
**
** A DL_POSITIONS_OFFSETS doclist is stored like this:
**
** array {
** varint docid;
** array { (position list for column 0)
** varint position; (delta from previous position plus POS_BASE)
** }
** array {
** varint POS_COLUMN; (marks start of position list for new column)
** varint column; (index of new column)
** array {
** varint position; (delta from previous position plus POS_BASE)
** }
** }
** varint POS_END; (marks end of positions for this document.
** }
**
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory. A "position" is an index of a token in the token stream
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
** in the same logical place as the position element, and act as sentinals
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
** The positions numbers are not stored literally but rather as two more
** the difference from the prior position, or the just the position plus
** 2 for the first position. Example:
**
** label: A B C D E F G H I J K
** value: 123 5 9 1 1 14 35 0 234 72 0
**
** The 123 value is the first docid. For column zero in this document
** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1
** at D signals the start of a new column; the 1 at E indicates that the
** new column is column number 1. There are two positions at 12 and 45
** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The
** 234 at I is the next docid. It has one position 72 (72-2) and then
** terminates with the 0 at K.
**
** A DL_POSITIONS doclist omits the startOffset and endOffset
** information. A DL_DOCIDS doclist omits both the position and
** offset information, becoming an array of varint-encoded docids.
**
** On-disk data is stored as type DL_DEFAULT, so we don't serialize
** the type. Due to how deletion is implemented in the segmentation
|
| ︙ | ︙ | |||
98490 98491 98492 98493 98494 98495 98496 | int nColumn; /* number of named columns in virtual table */ char **azColumn; /* column names. malloced */ sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ /* Precompiled statements used by the implementation. Each of these ** statements is run and reset within a single virtual table API call. */ | | > > | 99768 99769 99770 99771 99772 99773 99774 99775 99776 99777 99778 99779 99780 99781 99782 99783 99784 99785 99786 99787 99788 99789 99790 99791 99792 99793 99794 99795 99796 99797 | int nColumn; /* number of named columns in virtual table */ char **azColumn; /* column names. malloced */ sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ /* Precompiled statements used by the implementation. Each of these ** statements is run and reset within a single virtual table API call. */ sqlite3_stmt *aStmt[25]; /* Pointer to string containing the SQL: ** ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? ** ORDER BY blockid" */ char *zSelectLeaves; int nLeavesStmt; /* Valid statements in aLeavesStmt */ int nLeavesTotal; /* Total number of prepared leaves stmts */ int nLeavesAlloc; /* Allocated size of aLeavesStmt */ sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ int nNodeSize; /* Soft limit for node size */ u8 bHasContent; /* True if %_content table exists */ u8 bHasDocsize; /* True if %_docsize table exists */ /* The following hash table is used to buffer pending index updates during ** transactions. Variable nPendingData estimates the memory size of the ** pending data, including hash table overhead, but not malloc overhead. ** When nPendingData exceeds nMaxPendingData, the buffer is flushed ** automatically. Variable iPrevDocid is the docid of the most recently ** inserted record. |
| ︙ | ︙ | |||
98534 98535 98536 98537 98538 98539 98540 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ Fts3Expr *pExpr; /* Parsed MATCH query string */ sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ char *pNextId; /* Pointer into the body of aDoclist */ char *aDoclist; /* List of docids for full-text queries */ int nDoclist; /* Size of buffer at aDoclist */ | | | | 99814 99815 99816 99817 99818 99819 99820 99821 99822 99823 99824 99825 99826 99827 99828 99829 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ Fts3Expr *pExpr; /* Parsed MATCH query string */ sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ char *pNextId; /* Pointer into the body of aDoclist */ char *aDoclist; /* List of docids for full-text queries */ int nDoclist; /* Size of buffer at aDoclist */ int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ u32 *aMatchinfo; /* Information about most recent match */ }; /* ** The Fts3Cursor.eSearch member is always set to one of the following. ** Actualy, Fts3Cursor.eSearch can be greater than or equal to ** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index ** of the column to be searched. For example, in |
| ︙ | ︙ | |||
98641 98642 98643 98644 98645 98646 98647 98648 98649 98650 98651 98652 98653 98654 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *); SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, int (*)(Fts3Table *, void *, char *, int, char *, int), void * ); SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 #define FTS3_SEGMENT_PREFIX 0x00000008 | > > | 99921 99922 99923 99924 99925 99926 99927 99928 99929 99930 99931 99932 99933 99934 99935 99936 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *); SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, int (*)(Fts3Table *, void *, char *, int, char *, int), void * ); SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*); SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*); /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 #define FTS3_SEGMENT_PREFIX 0x00000008 |
| ︙ | ︙ | |||
98665 98666 98667 98668 98669 98670 98671 98672 98673 98674 98675 98676 98677 98678 98679 98680 98681 | SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int); SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *); /* fts3_tokenizer.c */ SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, sqlite3_tokenizer **, const char **, char ** ); /* fts3_snippet.c */ SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); | > | < < < | 99947 99948 99949 99950 99951 99952 99953 99954 99955 99956 99957 99958 99959 99960 99961 99962 99963 99964 99965 99966 99967 99968 99969 99970 99971 99972 | SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int); SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *); SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int); /* fts3_tokenizer.c */ SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, sqlite3_tokenizer **, const char **, char ** ); /* fts3_snippet.c */ SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, const char *, const char *, int, int ); SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *); /* fts3_expr.c */ SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, char **, int, int, const char *, int, Fts3Expr ** |
| ︙ | ︙ | |||
98798 98799 98800 98801 98802 98803 98804 98805 98806 98807 98808 98809 98810 98811 98812 98813 98814 98815 98816 98817 |
z[iOut++] = z[iIn++];
}
}
z[iOut] = '\0';
}
}
static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
sqlite3_int64 iVal;
*pp += sqlite3Fts3GetVarint(*pp, &iVal);
*pVal += iVal;
}
static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){
if( *pp>=pEnd ){
*pp = 0;
}else{
fts3GetDeltaVarint(pp, pVal);
}
}
| > > > > > > > > > > > | 100078 100079 100080 100081 100082 100083 100084 100085 100086 100087 100088 100089 100090 100091 100092 100093 100094 100095 100096 100097 100098 100099 100100 100101 100102 100103 100104 100105 100106 100107 100108 |
z[iOut++] = z[iIn++];
}
}
z[iOut] = '\0';
}
}
/*
** Read a single varint from the doclist at *pp and advance *pp to point
** to the next element of the varlist. Add the value of the varint
** to *pVal.
*/
static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
sqlite3_int64 iVal;
*pp += sqlite3Fts3GetVarint(*pp, &iVal);
*pVal += iVal;
}
/*
** As long as *pp has not reached its end (pEnd), then do the same
** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
** But if we have reached the end of the varint, just set *pp=0 and
** leave *pVal unchanged.
*/
static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){
if( *pp>=pEnd ){
*pp = 0;
}else{
fts3GetDeltaVarint(pp, pVal);
}
}
|
| ︙ | ︙ | |||
98837 98838 98839 98840 98841 98842 98843 98844 98845 98846 98847 98848 |
/* Invoke the tokenizer destructor to free the tokenizer. */
p->pTokenizer->pModule->xDestroy(p->pTokenizer);
sqlite3_free(p);
return SQLITE_OK;
}
/*
** The xDestroy() virtual table method.
*/
static int fts3DestroyMethod(sqlite3_vtab *pVtab){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | < | | | | < | < < < < < < < < < | 100128 100129 100130 100131 100132 100133 100134 100135 100136 100137 100138 100139 100140 100141 100142 100143 100144 100145 100146 100147 100148 100149 100150 100151 100152 100153 100154 100155 100156 100157 100158 100159 100160 100161 100162 100163 100164 100165 100166 100167 100168 100169 100170 100171 100172 100173 100174 100175 100176 100177 100178 100179 100180 100181 100182 100183 |
/* Invoke the tokenizer destructor to free the tokenizer. */
p->pTokenizer->pModule->xDestroy(p->pTokenizer);
sqlite3_free(p);
return SQLITE_OK;
}
/*
** Construct one or more SQL statements from the format string given
** and then evaluate those statements. The success code is writting
** into *pRc.
**
** If *pRc is initially non-zero then this routine is a no-op.
*/
void fts3DbExec(
int *pRc, /* Success code */
sqlite3 *db, /* Database in which to run SQL */
const char *zFormat, /* Format string for SQL */
... /* Arguments to the format string */
){
va_list ap;
char *zSql;
if( *pRc ) return;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zSql==0 ){
*pRc = SQLITE_NOMEM;
}else{
*pRc = sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
}
/*
** The xDestroy() virtual table method.
*/
static int fts3DestroyMethod(sqlite3_vtab *pVtab){
int rc = SQLITE_OK; /* Return code */
Fts3Table *p = (Fts3Table *)pVtab;
sqlite3 *db = p->db;
/* Drop the shadow tables */
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", p->zDb, p->zName);
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", p->zDb,p->zName);
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", p->zDb, p->zName);
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", p->zDb, p->zName);
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", p->zDb, p->zName);
/* If everything has worked, invoke fts3DisconnectMethod() to free the
** memory associated with the Fts3Table structure and return SQLITE_OK.
** Otherwise, return an SQLite error code.
*/
return (rc==SQLITE_OK ? fts3DisconnectMethod(pVtab) : rc);
}
|
| ︙ | ︙ | |||
98910 98911 98912 98913 98914 98915 98916 |
/*
** Create the backing store tables (%_content, %_segments and %_segdir)
** required by the FTS3 table passed as the only argument. This is done
** as part of the vtab xCreate() method.
*/
static int fts3CreateTables(Fts3Table *p){
| | | > | | | | | > | < > | > > > > > > | > > > | > > > > > > > > > | < < < < | < < | > > > > > | < > > > > > > | > > > | 100218 100219 100220 100221 100222 100223 100224 100225 100226 100227 100228 100229 100230 100231 100232 100233 100234 100235 100236 100237 100238 100239 100240 100241 100242 100243 100244 100245 100246 100247 100248 100249 100250 100251 100252 100253 100254 100255 100256 100257 100258 100259 100260 100261 100262 100263 100264 100265 100266 100267 100268 100269 100270 100271 100272 100273 100274 100275 100276 100277 100278 100279 100280 100281 100282 100283 100284 100285 100286 100287 100288 100289 100290 100291 100292 100293 100294 100295 100296 100297 100298 |
/*
** Create the backing store tables (%_content, %_segments and %_segdir)
** required by the FTS3 table passed as the only argument. This is done
** as part of the vtab xCreate() method.
*/
static int fts3CreateTables(Fts3Table *p){
int rc = SQLITE_OK; /* Return code */
int i; /* Iterator variable */
char *zContentCols; /* Columns of %_content table */
sqlite3 *db = p->db; /* The database connection */
/* Create a list of user columns for the content table */
if( p->bHasContent ){
zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
for(i=0; zContentCols && i<p->nColumn; i++){
char *z = p->azColumn[i];
zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
}
if( zContentCols==0 ) rc = SQLITE_NOMEM;
/* Create the content table */
fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_content'(%s)",
p->zDb, p->zName, zContentCols
);
sqlite3_free(zContentCols);
}
/* Create other tables */
fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",
p->zDb, p->zName
);
fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_segdir'("
"level INTEGER,"
"idx INTEGER,"
"start_block INTEGER,"
"leaves_end_block INTEGER,"
"end_block INTEGER,"
"root BLOB,"
"PRIMARY KEY(level, idx)"
");",
p->zDb, p->zName
);
if( p->bHasDocsize ){
fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
p->zDb, p->zName
);
fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);",
p->zDb, p->zName
);
}
return rc;
}
/*
** Determine if a table currently exists in the database.
*/
static void fts3TableExists(
int *pRc, /* Success code */
sqlite3 *db, /* The database connection to test */
const char *zDb, /* ATTACHed database within the connection */
const char *zName, /* Name of the FTS3 table */
const char *zSuffix, /* Shadow table extension */
u8 *pResult /* Write results here */
){
int rc = SQLITE_OK;
if( *pRc ) return;
fts3DbExec(&rc, db, "SELECT 1 FROM %Q.'%q%s'", zDb, zName, zSuffix);
*pResult = (rc==SQLITE_OK) ? 1 : 0;
if( rc!=SQLITE_ERROR ) *pRc = rc;
}
/*
** This function is the implementation of both the xConnect and xCreate
** methods of the FTS3 virtual table.
**
** The argv[] array contains the following:
|
| ︙ | ︙ | |||
99068 99069 99070 99071 99072 99073 99074 99075 |
p->azColumn[0] = "content";
}
/* If this is an xCreate call, create the underlying tables in the
** database. TODO: For xConnect(), it could verify that said tables exist.
*/
if( isCreate ){
rc = fts3CreateTables(p);
| > > > | > > > | 100403 100404 100405 100406 100407 100408 100409 100410 100411 100412 100413 100414 100415 100416 100417 100418 100419 100420 100421 100422 100423 100424 100425 |
p->azColumn[0] = "content";
}
/* If this is an xCreate call, create the underlying tables in the
** database. TODO: For xConnect(), it could verify that said tables exist.
*/
if( isCreate ){
p->bHasContent = 1;
p->bHasDocsize = argv[0][3]=='4';
rc = fts3CreateTables(p);
}else{
rc = SQLITE_OK;
fts3TableExists(&rc, db, argv[1], argv[2], "_content", &p->bHasContent);
fts3TableExists(&rc, db, argv[1], argv[2], "_docsize", &p->bHasDocsize);
}
if( rc!=SQLITE_OK ) goto fts3_init_out;
rc = fts3DeclareVtab(p);
if( rc!=SQLITE_OK ) goto fts3_init_out;
*ppVTab = &p->base;
fts3_init_out:
|
| ︙ | ︙ | |||
99191 99192 99193 99194 99195 99196 99197 |
*ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
if( !pCsr ){
return SQLITE_NOMEM;
}
memset(pCsr, 0, sizeof(Fts3Cursor));
return SQLITE_OK;
}
| < < < < < < | 100532 100533 100534 100535 100536 100537 100538 100539 100540 100541 100542 100543 100544 100545 |
*ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
if( !pCsr ){
return SQLITE_NOMEM;
}
memset(pCsr, 0, sizeof(Fts3Cursor));
return SQLITE_OK;
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fulltextClose(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
| ︙ | ︙ | |||
99253 99254 99255 99256 99257 99258 99259 |
}
}else if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
pCsr->isEof = 1;
}else{
sqlite3_reset(pCsr->pStmt);
fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
pCsr->isRequireSeek = 1;
| | | 100588 100589 100590 100591 100592 100593 100594 100595 100596 100597 100598 100599 100600 100601 100602 |
}
}else if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
pCsr->isEof = 1;
}else{
sqlite3_reset(pCsr->pStmt);
fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
}
return rc;
}
/*
** The buffer pointed to by argument zNode (size nNode bytes) contains the
|
| ︙ | ︙ | |||
100118 100119 100120 100121 100122 100123 100124 100125 100126 100127 100128 100129 100130 100131 |
*paOut = pOut;
*pnOut = nOut;
}else{
sqlite3_free(pOut);
}
return rc;
}
/*
** Evaluate the full-text expression pExpr against fts3 table pTab. Store
** the resulting doclist in *paOut and *pnOut.
*/
static int evalFts3Expr(
Fts3Table *p, /* Virtual table handle */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 101453 101454 101455 101456 101457 101458 101459 101460 101461 101462 101463 101464 101465 101466 101467 101468 101469 101470 101471 101472 101473 101474 101475 101476 101477 101478 101479 101480 101481 101482 101483 101484 101485 101486 101487 101488 101489 101490 101491 101492 101493 101494 101495 101496 101497 101498 101499 101500 101501 101502 101503 101504 101505 101506 101507 101508 101509 101510 101511 101512 101513 101514 101515 101516 101517 101518 101519 101520 101521 101522 101523 101524 101525 101526 101527 101528 101529 101530 101531 101532 101533 101534 |
*paOut = pOut;
*pnOut = nOut;
}else{
sqlite3_free(pOut);
}
return rc;
}
static int fts3NearMerge(
int mergetype, /* MERGE_POS_NEAR or MERGE_NEAR */
int nNear, /* Parameter to NEAR operator */
int nTokenLeft, /* Number of tokens in LHS phrase arg */
char *aLeft, /* Doclist for LHS (incl. positions) */
int nLeft, /* Size of LHS doclist in bytes */
int nTokenRight, /* As nTokenLeft */
char *aRight, /* As aLeft */
int nRight, /* As nRight */
char **paOut, /* OUT: Results of merge (malloced) */
int *pnOut /* OUT: Sized of output buffer */
){
char *aOut;
int rc;
assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR );
aOut = sqlite3_malloc(nLeft+nRight+1);
if( aOut==0 ){
rc = SQLITE_NOMEM;
}else{
rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft,
aOut, pnOut, aLeft, nLeft, aRight, nRight
);
if( rc!=SQLITE_OK ){
sqlite3_free(aOut);
aOut = 0;
}
}
*paOut = aOut;
return rc;
}
SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){
int rc;
if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){
sqlite3_free(pLeft->aDoclist);
sqlite3_free(pRight->aDoclist);
pRight->aDoclist = 0;
pLeft->aDoclist = 0;
rc = SQLITE_OK;
}else{
char *aOut;
int nOut;
rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
&aOut, &nOut
);
if( rc!=SQLITE_OK ) return rc;
sqlite3_free(pRight->aDoclist);
pRight->aDoclist = aOut;
pRight->nDoclist = nOut;
rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
&aOut, &nOut
);
sqlite3_free(pLeft->aDoclist);
pLeft->aDoclist = aOut;
pLeft->nDoclist = nOut;
}
return rc;
}
/*
** Evaluate the full-text expression pExpr against fts3 table pTab. Store
** the resulting doclist in *paOut and *pnOut.
*/
static int evalFts3Expr(
Fts3Table *p, /* Virtual table handle */
|
| ︙ | ︙ | |||
100163 100164 100165 100166 100167 100168 100169 |
|| pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
);
switch( pExpr->eType ){
case FTSQUERY_NEAR: {
Fts3Expr *pLeft;
Fts3Expr *pRight;
int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR;
| < < < | | < < | > < < < < < | 101566 101567 101568 101569 101570 101571 101572 101573 101574 101575 101576 101577 101578 101579 101580 101581 101582 101583 101584 101585 101586 101587 101588 101589 101590 101591 101592 101593 101594 101595 101596 |
|| pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
);
switch( pExpr->eType ){
case FTSQUERY_NEAR: {
Fts3Expr *pLeft;
Fts3Expr *pRight;
int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR;
if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){
mergetype = MERGE_POS_NEAR;
}
pLeft = pExpr->pLeft;
while( pLeft->eType==FTSQUERY_NEAR ){
pLeft=pLeft->pRight;
}
pRight = pExpr->pRight;
assert( pRight->eType==FTSQUERY_PHRASE );
assert( pLeft->eType==FTSQUERY_PHRASE );
rc = fts3NearMerge(mergetype, pExpr->nNear,
pLeft->pPhrase->nToken, aLeft, nLeft,
pRight->pPhrase->nToken, aRight, nRight,
paOut, pnOut
);
sqlite3_free(aLeft);
break;
}
case FTSQUERY_OR: {
/* Allocate a buffer for the output. The maximum size is the
** sum of the sizes of the two input buffers. The +1 term is
|
| ︙ | ︙ | |||
100439 100440 100441 100442 100443 100444 100445 |
*/
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *pTab, Fts3Expr *pExpr){
return evalFts3Expr(pTab, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
}
/*
** After ExprLoadDoclist() (see above) has been called, this function is
| | | 101833 101834 101835 101836 101837 101838 101839 101840 101841 101842 101843 101844 101845 101846 101847 |
*/
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *pTab, Fts3Expr *pExpr){
return evalFts3Expr(pTab, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
}
/*
** After ExprLoadDoclist() (see above) has been called, this function is
** used to iterate/search through the position lists that make up the doclist
** stored in pExpr->aDoclist.
*/
SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
Fts3Expr *pExpr, /* Access this expressions doclist */
sqlite3_int64 iDocid, /* Docid associated with requested pos-list */
int iCol /* Column of requested pos-list */
){
|
| ︙ | ︙ | |||
100474 100475 100476 100477 100478 100479 100480 |
}
while( iThis<iCol ){
fts3ColumnlistCopy(0, &pCsr);
if( *pCsr==0x00 ) return 0;
pCsr++;
pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis);
}
| | | 101868 101869 101870 101871 101872 101873 101874 101875 101876 101877 101878 101879 101880 101881 101882 |
}
while( iThis<iCol ){
fts3ColumnlistCopy(0, &pCsr);
if( *pCsr==0x00 ) return 0;
pCsr++;
pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis);
}
if( iCol==iThis && (*pCsr&0xFE) ) return pCsr;
}
return 0;
}
}
}
return 0;
|
| ︙ | ︙ | |||
100526 100527 100528 100529 100530 100531 100532 |
int nVal, /* Size of apVal[] array */
sqlite3_value **apVal /* Array of arguments */
){
Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
const char *zStart = "<b>";
const char *zEnd = "</b>";
const char *zEllipsis = "<b>...</b>";
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 101920 101921 101922 101923 101924 101925 101926 101927 101928 101929 101930 101931 101932 101933 101934 101935 |
int nVal, /* Size of apVal[] array */
sqlite3_value **apVal /* Array of arguments */
){
Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
const char *zStart = "<b>";
const char *zEnd = "</b>";
const char *zEllipsis = "<b>...</b>";
int iCol = -1;
int nToken = 15; /* Default number of tokens in snippet */
/* There must be at least one argument passed to this function (otherwise
** the non-overloaded version would have been called instead of this one).
*/
assert( nVal>=1 );
if( nVal>6 ){
|
| ︙ | ︙ | |||
100588 100589 100590 100591 100592 100593 100594 |
case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
}
if( !zEllipsis || !zEnd || !zStart ){
sqlite3_result_error_nomem(pContext);
}else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
| | | 101945 101946 101947 101948 101949 101950 101951 101952 101953 101954 101955 101956 101957 101958 101959 |
case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
}
if( !zEllipsis || !zEnd || !zStart ){
sqlite3_result_error_nomem(pContext);
}else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
}
}
/*
** Implementation of the offsets() function for FTS3
*/
static void fts3OffsetsFunc(
|
| ︙ | ︙ | |||
100689 100690 100691 100692 100693 100694 100695 |
void **ppArg /* Unused */
){
struct Overloaded {
const char *zName;
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aOverload[] = {
{ "snippet", fts3SnippetFunc },
| < | 102046 102047 102048 102049 102050 102051 102052 102053 102054 102055 102056 102057 102058 102059 |
void **ppArg /* Unused */
){
struct Overloaded {
const char *zName;
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aOverload[] = {
{ "snippet", fts3SnippetFunc },
{ "offsets", fts3OffsetsFunc },
{ "optimize", fts3OptimizeFunc },
{ "matchinfo", fts3MatchinfoFunc },
};
int i; /* Iterator variable */
UNUSED_PARAMETER(pVtab);
|
| ︙ | ︙ | |||
100718 100719 100720 100721 100722 100723 100724 |
/*
** Implementation of FTS3 xRename method. Rename an fts3 table.
*/
static int fts3RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
| | | | | > > | < < | > > > > > | > > > | | < < < > > > > > > > > | 102074 102075 102076 102077 102078 102079 102080 102081 102082 102083 102084 102085 102086 102087 102088 102089 102090 102091 102092 102093 102094 102095 102096 102097 102098 102099 102100 102101 102102 102103 102104 102105 102106 102107 102108 102109 102110 102111 102112 102113 102114 102115 102116 |
/*
** Implementation of FTS3 xRename method. Rename an fts3 table.
*/
static int fts3RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
Fts3Table *p = (Fts3Table *)pVtab;
sqlite3 *db; /* Database connection */
int rc; /* Return Code */
db = p->db;
rc = SQLITE_OK;
fts3DbExec(&rc, db,
"ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';",
p->zDb, p->zName, zName
);
if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
if( p->bHasDocsize ){
fts3DbExec(&rc, db,
"ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';",
p->zDb, p->zName, zName
);
fts3DbExec(&rc, db,
"ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';",
p->zDb, p->zName, zName
);
}
fts3DbExec(&rc, db,
"ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';",
p->zDb, p->zName, zName
);
fts3DbExec(&rc, db,
"ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
p->zDb, p->zName, zName
);
return rc;
}
static const sqlite3_module fts3Module = {
/* iVersion */ 0,
/* xCreate */ fts3CreateMethod,
/* xConnect */ fts3ConnectMethod,
|
| ︙ | ︙ | |||
100839 100840 100841 100842 100843 100844 100845 | /* Create the virtual table wrapper around the hash-table and overload ** the two scalar functions. If this is successful, register the ** module with sqlite. */ if( SQLITE_OK==rc && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) | < | > > > > > > | 102208 102209 102210 102211 102212 102213 102214 102215 102216 102217 102218 102219 102220 102221 102222 102223 102224 102225 102226 102227 102228 102229 102230 102231 102232 102233 102234 |
/* Create the virtual table wrapper around the hash-table and overload
** the two scalar functions. If this is successful, register the
** module with sqlite.
*/
if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
){
rc = sqlite3_create_module_v2(
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
);
if( rc==SQLITE_OK ){
rc = sqlite3_create_module_v2(
db, "fts4", &fts3Module, (void *)pHash, 0
);
}
return rc;
}
/* An error has occurred. Delete the hash table and return the error code. */
assert( rc!=SQLITE_OK );
if( pHash ){
sqlite3Fts3HashClear(pHash);
sqlite3_free(pHash);
|
| ︙ | ︙ | |||
102776 102777 102778 102779 102780 102781 102782 102783 |
while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
c->iOffset++;
}
if( c->iOffset>iStartOffset ){
int n = c->iOffset-iStartOffset;
if( n>c->nAllocated ){
c->nAllocated = n+20;
| > | | > | 104150 104151 104152 104153 104154 104155 104156 104157 104158 104159 104160 104161 104162 104163 104164 104165 104166 104167 104168 |
while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
c->iOffset++;
}
if( c->iOffset>iStartOffset ){
int n = c->iOffset-iStartOffset;
if( n>c->nAllocated ){
char *pNew;
c->nAllocated = n+20;
pNew = sqlite3_realloc(c->zToken, c->nAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->zToken = pNew;
}
porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
*pzToken = c->zToken;
*piStartOffset = iStartOffset;
*piEndOffset = c->iOffset;
*piPosition = c->iToken++;
return SQLITE_OK;
|
| ︙ | ︙ | |||
103489 103490 103491 103492 103493 103494 103495 103496 |
while( c->iOffset<c->nBytes && !simpleDelim(t, p[c->iOffset]) ){
c->iOffset++;
}
if( c->iOffset>iStartOffset ){
int i, n = c->iOffset-iStartOffset;
if( n>c->nTokenAllocated ){
c->nTokenAllocated = n+20;
| > | | > | 104865 104866 104867 104868 104869 104870 104871 104872 104873 104874 104875 104876 104877 104878 104879 104880 104881 104882 104883 |
while( c->iOffset<c->nBytes && !simpleDelim(t, p[c->iOffset]) ){
c->iOffset++;
}
if( c->iOffset>iStartOffset ){
int i, n = c->iOffset-iStartOffset;
if( n>c->nTokenAllocated ){
char *pNew;
c->nTokenAllocated = n+20;
pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->pToken = pNew;
}
for(i=0; i<n; i++){
/* TODO(shess) This needs expansion to handle UTF-8
** case-insensitivity.
*/
unsigned char ch = p[iStartOffset+i];
c->pToken[i] = (char)(ch<0x80 ? tolower(ch) : ch);
|
| ︙ | ︙ | |||
103675 103676 103677 103678 103679 103680 103681 | ** Valid values for the second argument to fts3SqlStmt(). */ #define SQL_DELETE_CONTENT 0 #define SQL_IS_EMPTY 1 #define SQL_DELETE_ALL_CONTENT 2 #define SQL_DELETE_ALL_SEGMENTS 3 #define SQL_DELETE_ALL_SEGDIR 4 | > > | | | | | | | | | | | | | > > > > > | 105053 105054 105055 105056 105057 105058 105059 105060 105061 105062 105063 105064 105065 105066 105067 105068 105069 105070 105071 105072 105073 105074 105075 105076 105077 105078 105079 105080 105081 105082 105083 105084 105085 105086 | ** Valid values for the second argument to fts3SqlStmt(). */ #define SQL_DELETE_CONTENT 0 #define SQL_IS_EMPTY 1 #define SQL_DELETE_ALL_CONTENT 2 #define SQL_DELETE_ALL_SEGMENTS 3 #define SQL_DELETE_ALL_SEGDIR 4 #define SQL_DELETE_ALL_DOCSIZE 5 #define SQL_DELETE_ALL_STAT 6 #define SQL_SELECT_CONTENT_BY_ROWID 7 #define SQL_NEXT_SEGMENT_INDEX 8 #define SQL_INSERT_SEGMENTS 9 #define SQL_NEXT_SEGMENTS_ID 10 #define SQL_INSERT_SEGDIR 11 #define SQL_SELECT_LEVEL 12 #define SQL_SELECT_ALL_LEVEL 13 #define SQL_SELECT_LEVEL_COUNT 14 #define SQL_SELECT_SEGDIR_COUNT_MAX 15 #define SQL_DELETE_SEGDIR_BY_LEVEL 16 #define SQL_DELETE_SEGMENTS_RANGE 17 #define SQL_CONTENT_INSERT 18 #define SQL_GET_BLOCK 19 #define SQL_DELETE_DOCSIZE 20 #define SQL_REPLACE_DOCSIZE 21 #define SQL_SELECT_DOCSIZE 22 #define SQL_SELECT_DOCTOTAL 23 #define SQL_REPLACE_DOCTOTAL 24 /* ** This function is used to obtain an SQLite prepared statement handle ** for the statement identified by the second argument. If successful, ** *pp is set to the requested statement handle and SQLITE_OK returned. ** Otherwise, an SQLite error code is returned and *pp is set to 0. ** |
| ︙ | ︙ | |||
103712 103713 103714 103715 103716 103717 103718 |
){
const char *azSql[] = {
/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?",
/* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)",
/* 2 */ "DELETE FROM %Q.'%q_content'",
/* 3 */ "DELETE FROM %Q.'%q_segments'",
/* 4 */ "DELETE FROM %Q.'%q_segdir'",
| > > | | | | | | | | | | | | | > > > > > | 105097 105098 105099 105100 105101 105102 105103 105104 105105 105106 105107 105108 105109 105110 105111 105112 105113 105114 105115 105116 105117 105118 105119 105120 105121 105122 105123 105124 105125 105126 105127 105128 105129 105130 105131 105132 105133 105134 105135 105136 |
){
const char *azSql[] = {
/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?",
/* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)",
/* 2 */ "DELETE FROM %Q.'%q_content'",
/* 3 */ "DELETE FROM %Q.'%q_segments'",
/* 4 */ "DELETE FROM %Q.'%q_segdir'",
/* 5 */ "DELETE FROM %Q.'%q_docsize'",
/* 6 */ "DELETE FROM %Q.'%q_stat'",
/* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?",
/* 8 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?",
/* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
/* 10 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'",
/* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
/* Return segments in order from oldest to newest.*/
/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC",
/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
/* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'",
/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%z)",
/* 19 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?",
/* 20 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
/* 21 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
/* 22 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
/* 23 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
/* 24 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
};
int rc = SQLITE_OK;
sqlite3_stmt *pStmt;
assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
|
| ︙ | ︙ | |||
103787 103788 103789 103790 103791 103792 103793 | ** Similar to fts3SqlStmt(). Except, after binding the parameters in ** array apVal[] to the SQL statement identified by eStmt, the statement ** is executed. ** ** Returns SQLITE_OK if the statement is successfully executed, or an ** SQLite error code otherwise. */ | > > > > | > > > | | | 105179 105180 105181 105182 105183 105184 105185 105186 105187 105188 105189 105190 105191 105192 105193 105194 105195 105196 105197 105198 105199 105200 105201 105202 105203 105204 105205 105206 105207 |
** Similar to fts3SqlStmt(). Except, after binding the parameters in
** array apVal[] to the SQL statement identified by eStmt, the statement
** is executed.
**
** Returns SQLITE_OK if the statement is successfully executed, or an
** SQLite error code otherwise.
*/
static void fts3SqlExec(
int *pRC, /* Result code */
Fts3Table *p, /* The FTS3 table */
int eStmt, /* Index of statement to evaluate */
sqlite3_value **apVal /* Parameters to bind */
){
sqlite3_stmt *pStmt;
int rc;
if( *pRC ) return;
rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
}
*pRC = rc;
}
/*
** Read a single block from the %_segments table. If the specified block
** does not exist, return SQLITE_CORRUPT. If some other error (malloc, IO
** etc.) occurs, return the appropriate SQLite error code.
|
| ︙ | ︙ | |||
103974 103975 103976 103977 103978 103979 103980 | /* ** Tokenize the nul-terminated string zText and add all tokens to the ** pending-terms hash-table. The docid used is that currently stored in ** p->iPrevDocid, and the column is specified by argument iCol. ** ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. */ | | > > > > > > | 105373 105374 105375 105376 105377 105378 105379 105380 105381 105382 105383 105384 105385 105386 105387 105388 105389 105390 105391 105392 105393 105394 105395 105396 105397 |
/*
** Tokenize the nul-terminated string zText and add all tokens to the
** pending-terms hash-table. The docid used is that currently stored in
** p->iPrevDocid, and the column is specified by argument iCol.
**
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
*/
static int fts3PendingTermsAdd(
Fts3Table *p, /* FTS table into which text will be inserted */
const char *zText, /* Text of document to be inseted */
int iCol, /* Column number into which text is inserted */
u32 *pnWord /* OUT: Number of tokens inserted */
){
int rc;
int iStart;
int iEnd;
int iPos;
int nWord = 0;
char const *zToken;
int nToken;
sqlite3_tokenizer *pTokenizer = p->pTokenizer;
sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
sqlite3_tokenizer_cursor *pCsr;
|
| ︙ | ︙ | |||
104002 104003 104004 104005 104006 104007 104008 104009 104010 104011 104012 104013 104014 104015 |
pCsr->pTokenizer = pTokenizer;
xNext = pModule->xNext;
while( SQLITE_OK==rc
&& SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
){
PendingList *pList;
/* Positions cannot be negative; we use -1 as a terminator internally.
** Tokens must have a non-zero length.
*/
if( iPos<0 || !zToken || nToken<=0 ){
rc = SQLITE_ERROR;
break;
| > > | 105407 105408 105409 105410 105411 105412 105413 105414 105415 105416 105417 105418 105419 105420 105421 105422 |
pCsr->pTokenizer = pTokenizer;
xNext = pModule->xNext;
while( SQLITE_OK==rc
&& SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
){
PendingList *pList;
if( iPos>=nWord ) nWord = iPos+1;
/* Positions cannot be negative; we use -1 as a terminator internally.
** Tokens must have a non-zero length.
*/
if( iPos<0 || !zToken || nToken<=0 ){
rc = SQLITE_ERROR;
break;
|
| ︙ | ︙ | |||
104031 104032 104033 104034 104035 104036 104037 104038 104039 104040 104041 104042 104043 104044 |
}
if( rc==SQLITE_OK ){
p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
}
}
pModule->xClose(pCsr);
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
/*
** Calling this function indicates that subsequent calls to
** fts3PendingTermsAdd() are to add term/position-list pairs for the
** contents of the document with docid iDocid.
| > | 105438 105439 105440 105441 105442 105443 105444 105445 105446 105447 105448 105449 105450 105451 105452 |
}
if( rc==SQLITE_OK ){
p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
}
}
pModule->xClose(pCsr);
*pnWord = nWord;
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
/*
** Calling this function indicates that subsequent calls to
** fts3PendingTermsAdd() are to add term/position-list pairs for the
** contents of the document with docid iDocid.
|
| ︙ | ︙ | |||
104071 104072 104073 104074 104075 104076 104077 | ** This function is called by the xUpdate() method as part of an INSERT ** operation. It adds entries for each term in the new record to the ** pendingTerms hash table. ** ** Argument apVal is the same as the similarly named argument passed to ** fts3InsertData(). Parameter iDocid is the docid of the new row. */ | | | | 105479 105480 105481 105482 105483 105484 105485 105486 105487 105488 105489 105490 105491 105492 105493 105494 105495 105496 105497 105498 |
** This function is called by the xUpdate() method as part of an INSERT
** operation. It adds entries for each term in the new record to the
** pendingTerms hash table.
**
** Argument apVal is the same as the similarly named argument passed to
** fts3InsertData(). Parameter iDocid is the docid of the new row.
*/
static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
int i; /* Iterator variable */
for(i=2; i<p->nColumn+2; i++){
const char *zText = (const char *)sqlite3_value_text(apVal[i]);
if( zText ){
int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
if( rc!=SQLITE_OK ){
return rc;
}
}
}
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
104157 104158 104159 104160 104161 104162 104163 |
/*
** Remove all data from the FTS3 table. Clear the hash table containing
** pending terms.
*/
static int fts3DeleteAll(Fts3Table *p){
| | | < | < < | > > > | > > > > > > | > | | | 105565 105566 105567 105568 105569 105570 105571 105572 105573 105574 105575 105576 105577 105578 105579 105580 105581 105582 105583 105584 105585 105586 105587 105588 105589 105590 105591 105592 105593 105594 105595 105596 105597 105598 105599 105600 105601 105602 105603 105604 105605 105606 105607 105608 105609 105610 105611 105612 105613 105614 105615 105616 105617 105618 105619 105620 105621 105622 105623 105624 105625 105626 105627 105628 |
/*
** Remove all data from the FTS3 table. Clear the hash table containing
** pending terms.
*/
static int fts3DeleteAll(Fts3Table *p){
int rc = SQLITE_OK; /* Return code */
/* Discard the contents of the pending-terms hash table. */
sqlite3Fts3PendingTermsClear(p);
/* Delete everything from the %_content, %_segments and %_segdir tables. */
fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0);
fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0);
fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
if( p->bHasDocsize ){
fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0);
fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
}
return rc;
}
/*
** The first element in the apVal[] array is assumed to contain the docid
** (an integer) of a row about to be deleted. Remove all terms from the
** full-text index.
*/
static void fts3DeleteTerms(
int *pRC, /* Result code */
Fts3Table *p, /* The FTS table to delete from */
sqlite3_value **apVal, /* apVal[] contains the docid to be deleted */
u32 *aSz /* Sizes of deleted document written here */
){
int rc;
sqlite3_stmt *pSelect;
if( *pRC ) return;
rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal);
if( rc==SQLITE_OK ){
if( SQLITE_ROW==sqlite3_step(pSelect) ){
int i;
for(i=1; i<=p->nColumn; i++){
const char *zText = (const char *)sqlite3_column_text(pSelect, i);
rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]);
if( rc!=SQLITE_OK ){
sqlite3_reset(pSelect);
*pRC = rc;
return;
}
}
}
rc = sqlite3_reset(pSelect);
}else{
sqlite3_reset(pSelect);
}
*pRC = rc;
}
/*
** Forward declaration to account for the circular dependency between
** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
*/
static int fts3SegmentMerge(Fts3Table *, int);
|
| ︙ | ︙ | |||
105319 105320 105321 105322 105323 105324 105325 |
rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_BY_LEVEL, &pDelete, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int(pDelete, 1, iLevel);
sqlite3_step(pDelete);
rc = sqlite3_reset(pDelete);
}
}else{
| | | 106734 106735 106736 106737 106738 106739 106740 106741 106742 106743 106744 106745 106746 106747 106748 |
rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_BY_LEVEL, &pDelete, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int(pDelete, 1, iLevel);
sqlite3_step(pDelete);
rc = sqlite3_reset(pDelete);
}
}else{
fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
}
return rc;
}
/*
** When this function is called, buffer *ppList (size *pnList bytes) contains
|
| ︙ | ︙ | |||
105746 105747 105748 105749 105750 105751 105752 105753 105754 105755 105756 105757 105758 105759 |
sqlite3Fts3SegReaderFree(p, pReader);
if( rc==SQLITE_OK ){
sqlite3Fts3PendingTermsClear(p);
}
return rc;
}
/*
** Handle a 'special' INSERT of the form:
**
** "INSERT INTO tbl(tbl) VALUES(<expr>)"
**
** Argument pVal contains the result of <expr>. Currently the only
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 107161 107162 107163 107164 107165 107166 107167 107168 107169 107170 107171 107172 107173 107174 107175 107176 107177 107178 107179 107180 107181 107182 107183 107184 107185 107186 107187 107188 107189 107190 107191 107192 107193 107194 107195 107196 107197 107198 107199 107200 107201 107202 107203 107204 107205 107206 107207 107208 107209 107210 107211 107212 107213 107214 107215 107216 107217 107218 107219 107220 107221 107222 107223 107224 107225 107226 107227 107228 107229 107230 107231 107232 107233 107234 107235 107236 107237 107238 107239 107240 107241 107242 107243 107244 107245 107246 107247 107248 107249 107250 107251 107252 107253 107254 107255 107256 107257 107258 107259 107260 107261 107262 107263 107264 107265 107266 107267 107268 107269 107270 107271 107272 107273 107274 107275 107276 107277 107278 107279 107280 107281 107282 107283 107284 107285 107286 107287 107288 107289 107290 107291 107292 107293 107294 107295 107296 107297 107298 107299 107300 107301 107302 107303 107304 107305 107306 107307 107308 107309 107310 107311 107312 107313 107314 107315 107316 107317 107318 107319 107320 107321 107322 107323 107324 107325 107326 107327 107328 107329 107330 107331 107332 107333 107334 107335 107336 107337 107338 107339 107340 107341 107342 107343 107344 107345 107346 107347 107348 107349 107350 107351 107352 107353 107354 107355 107356 107357 107358 107359 107360 107361 107362 107363 107364 107365 107366 107367 107368 107369 107370 107371 107372 107373 107374 107375 107376 107377 107378 107379 |
sqlite3Fts3SegReaderFree(p, pReader);
if( rc==SQLITE_OK ){
sqlite3Fts3PendingTermsClear(p);
}
return rc;
}
/*
** Encode N integers as varints into a blob.
*/
static void fts3EncodeIntArray(
int N, /* The number of integers to encode */
u32 *a, /* The integer values */
char *zBuf, /* Write the BLOB here */
int *pNBuf /* Write number of bytes if zBuf[] used here */
){
int i, j;
for(i=j=0; i<N; i++){
j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]);
}
*pNBuf = j;
}
/*
** Decode a blob of varints into N integers
*/
static void fts3DecodeIntArray(
int N, /* The number of integers to decode */
u32 *a, /* Write the integer values */
const char *zBuf, /* The BLOB containing the varints */
int nBuf /* size of the BLOB */
){
int i, j;
UNUSED_PARAMETER(nBuf);
for(i=j=0; i<N; i++){
sqlite3_int64 x;
j += sqlite3Fts3GetVarint(&zBuf[j], &x);
assert(j<=nBuf);
a[i] = (u32)(x & 0xffffffff);
}
}
/*
** Fill in the document size auxiliary information for the matchinfo
** structure. The auxiliary information is:
**
** N Total number of documents in the full-text index
** a0 Average length of column 0 over the whole index
** n0 Length of column 0 on the matching row
** ...
** aM Average length of column M over the whole index
** nM Length of column M on the matching row
**
** The fts3MatchinfoDocsizeLocal() routine fills in the nX values.
** The fts3MatchinfoDocsizeGlobal() routine fills in N and the aX values.
*/
SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor *pCur, u32 *a){
const char *pBlob; /* The BLOB holding %_docsize info */
int nBlob; /* Size of the BLOB */
sqlite3_stmt *pStmt; /* Statement for reading and writing */
int i, j; /* Loop counters */
sqlite3_int64 x; /* Varint value */
int rc; /* Result code from subfunctions */
Fts3Table *p; /* The FTS table */
p = (Fts3Table*)pCur->base.pVtab;
rc = fts3SqlStmt(p, SQL_SELECT_DOCSIZE, &pStmt, 0);
if( rc ){
return rc;
}
sqlite3_bind_int64(pStmt, 1, pCur->iPrevId);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
nBlob = sqlite3_column_bytes(pStmt, 0);
pBlob = (const char*)sqlite3_column_blob(pStmt, 0);
for(i=j=0; i<p->nColumn && j<nBlob; i++){
j = sqlite3Fts3GetVarint(&pBlob[j], &x);
a[2+i*2] = (u32)(x & 0xffffffff);
}
}
sqlite3_reset(pStmt);
return SQLITE_OK;
}
SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor *pCur, u32 *a){
const char *pBlob; /* The BLOB holding %_stat info */
int nBlob; /* Size of the BLOB */
sqlite3_stmt *pStmt; /* Statement for reading and writing */
int i, j; /* Loop counters */
sqlite3_int64 x; /* Varint value */
int nDoc; /* Number of documents */
int rc; /* Result code from subfunctions */
Fts3Table *p; /* The FTS table */
p = (Fts3Table*)pCur->base.pVtab;
rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
if( rc ){
return rc;
}
if( sqlite3_step(pStmt)==SQLITE_ROW ){
nBlob = sqlite3_column_bytes(pStmt, 0);
pBlob = (const char*)sqlite3_column_blob(pStmt, 0);
j = sqlite3Fts3GetVarint(pBlob, &x);
a[0] = nDoc = (u32)(x & 0xffffffff);
for(i=0; i<p->nColumn && j<nBlob; i++){
j = sqlite3Fts3GetVarint(&pBlob[j], &x);
a[1+i*2] = ((u32)(x & 0xffffffff) + nDoc/2)/nDoc;
}
}
sqlite3_reset(pStmt);
return SQLITE_OK;
}
/*
** Insert the sizes (in tokens) for each column of the document
** with docid equal to p->iPrevDocid. The sizes are encoded as
** a blob of varints.
*/
static void fts3InsertDocsize(
int *pRC, /* Result code */
Fts3Table *p, /* Table into which to insert */
u32 *aSz /* Sizes of each column */
){
char *pBlob; /* The BLOB encoding of the document size */
int nBlob; /* Number of bytes in the BLOB */
sqlite3_stmt *pStmt; /* Statement used to insert the encoding */
int rc; /* Result code from subfunctions */
if( *pRC ) return;
pBlob = sqlite3_malloc( 10*p->nColumn );
if( pBlob==0 ){
*pRC = SQLITE_NOMEM;
return;
}
fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob);
rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0);
if( rc ){
sqlite3_free(pBlob);
*pRC = rc;
return;
}
sqlite3_bind_int64(pStmt, 1, p->iPrevDocid);
sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free);
sqlite3_step(pStmt);
*pRC = sqlite3_reset(pStmt);
}
/*
** Update the 0 record of the %_stat table so that it holds a blob
** which contains the document count followed by the cumulative
** document sizes for all columns.
*/
static void fts3UpdateDocTotals(
int *pRC, /* The result code */
Fts3Table *p, /* Table being updated */
u32 *aSzIns, /* Size increases */
u32 *aSzDel, /* Size decreases */
int nChng /* Change in the number of documents */
){
char *pBlob; /* Storage for BLOB written into %_stat */
int nBlob; /* Size of BLOB written into %_stat */
u32 *a; /* Array of integers that becomes the BLOB */
sqlite3_stmt *pStmt; /* Statement for reading and writing */
int i; /* Loop counter */
int rc; /* Result code from subfunctions */
if( *pRC ) return;
a = sqlite3_malloc( (sizeof(u32)+10)*(p->nColumn+1) );
if( a==0 ){
*pRC = SQLITE_NOMEM;
return;
}
pBlob = (char*)&a[p->nColumn+1];
rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
if( rc ){
sqlite3_free(a);
*pRC = rc;
return;
}
if( sqlite3_step(pStmt)==SQLITE_ROW ){
fts3DecodeIntArray(p->nColumn+1, a,
sqlite3_column_blob(pStmt, 0),
sqlite3_column_bytes(pStmt, 0));
}else{
memset(a, 0, sizeof(u32)*(p->nColumn+1) );
}
sqlite3_reset(pStmt);
if( nChng<0 && a[0]<(u32)(-nChng) ){
a[0] = 0;
}else{
a[0] += nChng;
}
for(i=0; i<p->nColumn; i++){
u32 x = a[i+1];
if( x+aSzIns[i] < aSzDel[i] ){
x = 0;
}else{
x = x + aSzIns[i] - aSzDel[i];
}
a[i+1] = x;
}
fts3EncodeIntArray(p->nColumn+1, a, pBlob, &nBlob);
rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0);
if( rc ){
sqlite3_free(a);
*pRC = rc;
return;
}
sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
sqlite3_step(pStmt);
*pRC = sqlite3_reset(pStmt);
sqlite3_free(a);
}
/*
** Handle a 'special' INSERT of the form:
**
** "INSERT INTO tbl(tbl) VALUES(<expr>)"
**
** Argument pVal contains the result of <expr>. Currently the only
|
| ︙ | ︙ | |||
105798 105799 105800 105801 105802 105803 105804 105805 105806 105807 105808 105809 105810 105811 105812 105813 105814 105815 105816 105817 105818 105819 105820 105821 |
sqlite3_value **apVal, /* Array of arguments */
sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
){
Fts3Table *p = (Fts3Table *)pVtab;
int rc = SQLITE_OK; /* Return Code */
int isRemove = 0; /* True for an UPDATE or DELETE */
sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
/* If this is a DELETE or UPDATE operation, remove the old record. */
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
int isEmpty;
rc = fts3IsEmpty(p, apVal, &isEmpty);
if( rc==SQLITE_OK ){
if( isEmpty ){
/* Deleting this row means the whole table is empty. In this case
** delete the contents of all three tables and throw away any
** data in the pendingTerms hash table.
*/
rc = fts3DeleteAll(p);
}else{
isRemove = 1;
iRemove = sqlite3_value_int64(apVal[0]);
rc = fts3PendingTermsDocid(p, iRemove);
| > > > > > > > > > < | < | < > > > > | > > > > > > > > > | 107418 107419 107420 107421 107422 107423 107424 107425 107426 107427 107428 107429 107430 107431 107432 107433 107434 107435 107436 107437 107438 107439 107440 107441 107442 107443 107444 107445 107446 107447 107448 107449 107450 107451 107452 107453 107454 107455 107456 107457 107458 107459 107460 107461 107462 107463 107464 107465 107466 107467 107468 107469 107470 107471 107472 107473 107474 107475 107476 107477 107478 107479 107480 107481 107482 107483 107484 107485 107486 107487 107488 107489 107490 |
sqlite3_value **apVal, /* Array of arguments */
sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
){
Fts3Table *p = (Fts3Table *)pVtab;
int rc = SQLITE_OK; /* Return Code */
int isRemove = 0; /* True for an UPDATE or DELETE */
sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
u32 *aSzIns; /* Sizes of inserted documents */
u32 *aSzDel; /* Sizes of deleted documents */
int nChng = 0; /* Net change in number of documents */
/* Allocate space to hold the change in document sizes */
aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*p->nColumn*2 );
if( aSzIns==0 ) return SQLITE_NOMEM;
aSzDel = &aSzIns[p->nColumn];
memset(aSzIns, 0, sizeof(aSzIns[0])*p->nColumn*2);
/* If this is a DELETE or UPDATE operation, remove the old record. */
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
int isEmpty;
rc = fts3IsEmpty(p, apVal, &isEmpty);
if( rc==SQLITE_OK ){
if( isEmpty ){
/* Deleting this row means the whole table is empty. In this case
** delete the contents of all three tables and throw away any
** data in the pendingTerms hash table.
*/
rc = fts3DeleteAll(p);
}else{
isRemove = 1;
iRemove = sqlite3_value_int64(apVal[0]);
rc = fts3PendingTermsDocid(p, iRemove);
fts3DeleteTerms(&rc, p, apVal, aSzDel);
fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal);
if( p->bHasDocsize ){
fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal);
nChng--;
}
}
}
}else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){
sqlite3_free(aSzIns);
return fts3SpecialInsert(p, apVal[p->nColumn+2]);
}
/* If this is an INSERT or UPDATE operation, insert the new record. */
if( nArg>1 && rc==SQLITE_OK ){
rc = fts3InsertData(p, apVal, pRowid);
if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
rc = fts3PendingTermsDocid(p, *pRowid);
}
if( rc==SQLITE_OK ){
rc = fts3InsertTerms(p, apVal, aSzIns);
}
if( p->bHasDocsize ){
nChng++;
fts3InsertDocsize(&rc, p, aSzIns);
}
}
if( p->bHasDocsize ){
fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
}
sqlite3_free(aSzIns);
return rc;
}
/*
** Flush any data in the pending-terms hash table to disk. If successful,
** merge all segments in the database (including the new segment, if
** there was any data to flush) into a single segment.
|
| ︙ | ︙ | |||
105884 105885 105886 105887 105888 105889 105890 | ** ****************************************************************************** */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) | < > | < > > > > > > > > > > > > > > > | > | > | > > > | | > > > > > > > | > | > > > > | > > > > > > | > > > | | | > > > > > > > | | | < < < < < < < < < < < < < < < < < < < | | < < < < < < < < | < < < < < < < < < | < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < | < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > | > | | | > | | > > > > > | | > > > | | > | > > > > > | | < < < | | > > > > > | > > > > > > > > > > > > > > > > | > | | < | > > > > > > > > > > | > > > > | | | > > > | > | < < < | | | < < < | < | | < < | < | < < < | < < < < | < < < < < < | > > > > | > > > > > | > > > > > > | > > > > > > | > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | | | > > > > > > > > | | | > > | > > > > > | > > > > > | > > > > > | | | | < > | > | | | > > > > > < > | > | | | < < < < < < < | < | < < < < | < < < < | < < | < | < < | < < < < | < | > | | > < | | | > | < < | < < < < < | | > | < < < < < | | < < < | > > | | | < < | > | < < > | < > > | < < < < < < > > > > > | | < < < < | < < < < < | | | > > < | | < | > | | > | < < | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > | | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | < > > > | < | | > > > | > | > > > > | < > | > > | < < < | < > < | < < | < | | > > | | | | | | < < | < < < < | | | > | > > > > | < > > | < < > | < < | > > > | > > | > > > > > > > > > > > < < < < < | > > | < < < < < | < > | < | < < < < < | < < < < < < < < < < | < < < | > | > > > > > | > > | | | < > > > > > > < > | > | > | > | | | > > > > > < > > > > > | | < < | | > > > | < < | | | > > | | | > > > | | > < < < < | < | | > > > > | > > > | > | | > | > > > > > > > > > > > | > > > > | > | > > > > > > > > | > > > > > > > > > > > > > > | > > > > > > > > > > | > | > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > | 107523 107524 107525 107526 107527 107528 107529 107530 107531 107532 107533 107534 107535 107536 107537 107538 107539 107540 107541 107542 107543 107544 107545 107546 107547 107548 107549 107550 107551 107552 107553 107554 107555 107556 107557 107558 107559 107560 107561 107562 107563 107564 107565 107566 107567 107568 107569 107570 107571 107572 107573 107574 107575 107576 107577 107578 107579 107580 107581 107582 107583 107584 107585 107586 107587 107588 107589 107590 107591 107592 107593 107594 107595 107596 107597 107598 107599 107600 107601 107602 107603 107604 107605 107606 107607 107608 107609 107610 107611 107612 107613 107614 107615 107616 107617 107618 107619 107620 107621 107622 107623 107624 107625 107626 107627 107628 107629 107630 107631 107632 107633 107634 107635 107636 107637 107638 107639 107640 107641 107642 107643 107644 107645 107646 107647 107648 107649 107650 107651 107652 107653 107654 107655 107656 107657 107658 107659 107660 107661 107662 107663 107664 107665 107666 107667 107668 107669 107670 107671 107672 107673 107674 107675 107676 107677 107678 107679 107680 107681 107682 107683 107684 107685 107686 107687 107688 107689 107690 107691 107692 107693 107694 107695 107696 107697 107698 107699 107700 107701 107702 107703 107704 107705 107706 107707 107708 107709 107710 107711 107712 107713 107714 107715 107716 107717 107718 107719 107720 107721 107722 107723 107724 107725 107726 107727 107728 107729 107730 107731 107732 107733 107734 107735 107736 107737 107738 107739 107740 107741 107742 107743 107744 107745 107746 107747 107748 107749 107750 107751 107752 107753 107754 107755 107756 107757 107758 107759 107760 107761 107762 107763 107764 107765 107766 107767 107768 107769 107770 107771 107772 107773 107774 107775 107776 107777 107778 107779 107780 107781 107782 107783 107784 107785 107786 107787 107788 107789 107790 107791 107792 107793 107794 107795 107796 107797 107798 107799 107800 107801 107802 107803 107804 107805 107806 107807 107808 107809 107810 107811 107812 107813 107814 107815 107816 107817 107818 107819 107820 107821 107822 107823 107824 107825 107826 107827 107828 107829 107830 107831 107832 107833 107834 107835 107836 107837 107838 107839 107840 107841 107842 107843 107844 107845 107846 107847 107848 107849 107850 107851 107852 107853 107854 107855 107856 107857 107858 107859 107860 107861 107862 107863 107864 107865 107866 107867 107868 107869 107870 107871 107872 107873 107874 107875 107876 107877 107878 107879 107880 107881 107882 107883 107884 107885 107886 107887 107888 107889 107890 107891 107892 107893 107894 107895 107896 107897 107898 107899 107900 107901 107902 107903 107904 107905 107906 107907 107908 107909 107910 107911 107912 107913 107914 107915 107916 107917 107918 107919 107920 107921 107922 107923 107924 107925 107926 107927 107928 107929 107930 107931 107932 107933 107934 107935 107936 107937 107938 107939 107940 107941 107942 107943 107944 107945 107946 107947 107948 107949 107950 107951 107952 107953 107954 107955 107956 107957 107958 107959 107960 107961 107962 107963 107964 107965 107966 107967 107968 107969 107970 107971 107972 107973 107974 107975 107976 107977 107978 107979 107980 107981 107982 107983 107984 107985 107986 107987 107988 107989 107990 107991 107992 107993 107994 107995 107996 107997 107998 107999 108000 108001 108002 108003 108004 108005 108006 108007 108008 108009 108010 108011 108012 108013 108014 108015 108016 108017 108018 108019 108020 108021 108022 108023 108024 108025 108026 108027 108028 108029 108030 108031 108032 108033 108034 108035 108036 108037 108038 108039 108040 108041 108042 108043 108044 108045 108046 108047 108048 108049 108050 108051 108052 108053 108054 108055 108056 108057 108058 108059 108060 108061 108062 108063 108064 108065 108066 108067 108068 108069 108070 108071 108072 108073 108074 108075 108076 108077 108078 108079 108080 108081 108082 108083 108084 108085 108086 108087 108088 108089 108090 108091 108092 108093 108094 108095 108096 108097 108098 108099 108100 108101 108102 108103 108104 108105 108106 108107 108108 108109 108110 108111 108112 108113 108114 108115 108116 108117 108118 108119 108120 108121 108122 108123 108124 108125 108126 108127 108128 108129 108130 108131 108132 108133 108134 108135 108136 108137 108138 108139 108140 108141 108142 108143 108144 108145 108146 108147 108148 108149 108150 108151 108152 108153 108154 108155 108156 108157 108158 108159 108160 108161 108162 108163 108164 108165 108166 108167 108168 108169 108170 108171 108172 108173 108174 108175 108176 108177 108178 108179 108180 108181 108182 108183 108184 108185 108186 108187 108188 108189 108190 108191 108192 108193 108194 108195 108196 108197 108198 108199 108200 108201 108202 108203 108204 108205 108206 108207 108208 108209 108210 108211 108212 108213 108214 108215 108216 108217 108218 108219 108220 108221 108222 108223 108224 108225 108226 108227 108228 108229 108230 108231 108232 108233 108234 108235 108236 108237 108238 108239 108240 108241 108242 108243 108244 108245 108246 108247 108248 108249 108250 108251 108252 108253 108254 108255 108256 108257 108258 108259 108260 108261 108262 108263 108264 108265 108266 108267 108268 108269 108270 108271 108272 108273 108274 108275 108276 108277 108278 108279 108280 108281 108282 108283 108284 108285 108286 108287 108288 108289 108290 108291 108292 108293 108294 108295 108296 108297 108298 108299 108300 108301 108302 108303 108304 108305 108306 108307 108308 108309 108310 108311 108312 108313 108314 108315 108316 108317 108318 108319 108320 108321 108322 108323 108324 108325 108326 108327 108328 108329 108330 108331 108332 108333 108334 108335 108336 108337 108338 108339 108340 108341 108342 108343 108344 108345 108346 108347 108348 108349 108350 108351 108352 108353 108354 108355 108356 108357 108358 108359 108360 108361 108362 108363 108364 108365 108366 108367 108368 108369 108370 108371 108372 108373 108374 108375 108376 108377 108378 108379 108380 108381 108382 108383 108384 108385 108386 108387 108388 108389 108390 108391 108392 108393 108394 108395 108396 108397 108398 108399 108400 108401 108402 108403 108404 108405 108406 108407 108408 108409 108410 108411 108412 108413 108414 108415 108416 108417 108418 108419 108420 108421 108422 108423 108424 108425 108426 108427 108428 108429 108430 108431 108432 108433 108434 108435 108436 108437 108438 108439 108440 108441 108442 108443 108444 108445 108446 108447 108448 108449 108450 108451 108452 108453 108454 108455 108456 108457 108458 108459 108460 108461 108462 108463 108464 108465 108466 108467 108468 108469 108470 108471 108472 108473 108474 108475 108476 108477 108478 108479 108480 108481 108482 108483 108484 108485 108486 108487 108488 108489 108490 108491 108492 108493 108494 108495 108496 108497 108498 108499 108500 108501 108502 108503 108504 108505 108506 108507 108508 108509 108510 108511 108512 108513 108514 108515 108516 108517 108518 108519 108520 108521 108522 108523 108524 108525 108526 108527 108528 108529 108530 108531 108532 108533 108534 108535 108536 108537 108538 108539 108540 108541 108542 108543 108544 108545 108546 108547 108548 108549 108550 108551 108552 108553 108554 108555 108556 108557 108558 108559 108560 108561 108562 108563 108564 108565 108566 108567 108568 108569 108570 108571 108572 108573 108574 108575 108576 108577 108578 108579 108580 108581 108582 108583 108584 108585 108586 108587 108588 108589 108590 108591 108592 108593 108594 108595 108596 108597 108598 108599 108600 108601 108602 108603 108604 108605 108606 108607 108608 108609 108610 108611 108612 108613 108614 108615 108616 108617 108618 108619 108620 108621 108622 108623 108624 108625 108626 108627 108628 108629 108630 108631 108632 108633 108634 108635 108636 108637 108638 108639 108640 108641 108642 108643 108644 108645 108646 108647 108648 108649 108650 108651 108652 108653 108654 108655 108656 108657 108658 108659 108660 108661 108662 108663 108664 108665 108666 108667 108668 108669 108670 108671 108672 108673 108674 108675 108676 108677 108678 108679 108680 108681 108682 108683 108684 108685 108686 108687 108688 108689 108690 108691 108692 108693 108694 108695 108696 108697 108698 108699 108700 108701 108702 108703 108704 108705 108706 108707 108708 108709 108710 108711 108712 108713 108714 108715 |
**
******************************************************************************
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/*
** Used as an fts3ExprIterate() context when loading phrase doclists to
** Fts3Expr.aDoclist[]/nDoclist.
*/
typedef struct LoadDoclistCtx LoadDoclistCtx;
struct LoadDoclistCtx {
Fts3Table *pTab; /* FTS3 Table */
int nPhrase; /* Number of phrases seen so far */
int nToken; /* Number of tokens seen so far */
};
/*
** The following types are used as part of the implementation of the
** fts3BestSnippet() routine.
*/
typedef struct SnippetIter SnippetIter;
typedef struct SnippetPhrase SnippetPhrase;
typedef struct SnippetFragment SnippetFragment;
struct SnippetIter {
Fts3Cursor *pCsr; /* Cursor snippet is being generated from */
int iCol; /* Extract snippet from this column */
int nSnippet; /* Requested snippet length (in tokens) */
int nPhrase; /* Number of phrases in query */
SnippetPhrase *aPhrase; /* Array of size nPhrase */
int iCurrent; /* First token of current snippet */
};
struct SnippetPhrase {
int nToken; /* Number of tokens in phrase */
char *pList; /* Pointer to start of phrase position list */
int iHead; /* Next value in position list */
char *pHead; /* Position list data following iHead */
int iTail; /* Next value in trailing position list */
char *pTail; /* Position list data following iTail */
};
struct SnippetFragment {
int iCol; /* Column snippet is extracted from */
int iPos; /* Index of first token in snippet */
u64 covered; /* Mask of query phrases covered */
u64 hlmask; /* Mask of snippet terms to highlight */
};
/*
** This type is used as an fts3ExprIterate() context object while
** accumulating the data returned by the matchinfo() function.
*/
typedef struct MatchInfo MatchInfo;
struct MatchInfo {
Fts3Cursor *pCursor; /* FTS3 Cursor */
int nCol; /* Number of columns in table */
u32 *aMatchinfo; /* Pre-allocated buffer */
};
/*
** 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.
*/
typedef struct StrBuffer StrBuffer;
struct StrBuffer {
char *z; /* Pointer to buffer containing string */
int n; /* Length of z in bytes (excl. nul-term) */
int nAlloc; /* Allocated size of buffer z in bytes */
};
/*
** This function is used to help iterate through a position-list. A position
** list is a list of unique integers, sorted from smallest to largest. Each
** element of the list is represented by an FTS3 varint that takes the value
** of the difference between the current element and the previous one plus
** two. For example, to store the position-list:
**
** 4 9 113
**
** the three varints:
**
** 6 7 106
**
** are encoded.
**
** When this function is called, *pp points to the start of an element of
** the list. *piPos contains the value of the previous entry in the list.
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
static void fts3GetDeltaPosition(char **pp, int *piPos){
int iVal;
*pp += sqlite3Fts3GetVarint32(*pp, &iVal);
*piPos += (iVal-2);
}
/*
** Helper function for fts3ExprIterate() (see below).
*/
static int fts3ExprIterate2(
Fts3Expr *pExpr, /* Expression to iterate phrases of */
int *piPhrase, /* Pointer to phrase counter */
int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
void *pCtx /* Second argument to pass to callback */
){
int rc; /* Return code */
int eType = pExpr->eType; /* Type of expression node pExpr */
if( eType!=FTSQUERY_PHRASE ){
assert( pExpr->pLeft && pExpr->pRight );
rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx);
if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){
rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx);
}
}else{
rc = x(pExpr, *piPhrase, pCtx);
(*piPhrase)++;
}
return rc;
}
/*
** Iterate through all phrase nodes in an FTS3 query, except those that
** are part of a sub-tree that is the right-hand-side of a NOT operator.
** For each phrase node found, the supplied callback function is invoked.
**
** If the callback function returns anything other than SQLITE_OK,
** the iteration is abandoned and the error code returned immediately.
** Otherwise, SQLITE_OK is returned after a callback has been made for
** all eligible phrase nodes.
*/
static int fts3ExprIterate(
Fts3Expr *pExpr, /* Expression to iterate phrases of */
int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
void *pCtx /* Second argument to pass to callback */
){
int iPhrase = 0; /* Variable used as the phrase counter */
return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
}
/*
** The argument to this function is always a phrase node. Its doclist
** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes
** to the left of this one in the query tree have already been loaded.
**
** If this phrase node is part of a series of phrase nodes joined by
** NEAR operators (and is not the left-most of said series), then elements are
** removed from the phrases doclist consistent with the NEAR restriction. If
** required, elements may be removed from the doclists of phrases to the
** left of this one that are part of the same series of NEAR operator
** connected phrases.
**
** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
*/
static int fts3ExprNearTrim(Fts3Expr *pExpr){
int rc = SQLITE_OK;
Fts3Expr *pParent = pExpr->pParent;
assert( pExpr->eType==FTSQUERY_PHRASE );
while( rc==SQLITE_OK
&& pParent
&& pParent->eType==FTSQUERY_NEAR
&& pParent->pRight==pExpr
){
/* This expression (pExpr) is the right-hand-side of a NEAR operator.
** Find the expression to the left of the same operator.
*/
int nNear = pParent->nNear;
Fts3Expr *pLeft = pParent->pLeft;
if( pLeft->eType!=FTSQUERY_PHRASE ){
assert( pLeft->eType==FTSQUERY_NEAR );
assert( pLeft->pRight->eType==FTSQUERY_PHRASE );
pLeft = pLeft->pRight;
}
rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear);
pExpr = pLeft;
pParent = pExpr->pParent;
}
return rc;
}
/*
** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** fts3ExprLoadDoclists().
*/
static int fts3ExprLoadDoclistsCb1(Fts3Expr *pExpr, int iPhrase, void *ctx){
int rc = SQLITE_OK;
LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
UNUSED_PARAMETER(iPhrase);
p->nPhrase++;
p->nToken += pExpr->pPhrase->nToken;
if( pExpr->isLoaded==0 ){
rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr);
pExpr->isLoaded = 1;
if( rc==SQLITE_OK ){
rc = fts3ExprNearTrim(pExpr);
}
}
return rc;
}
/*
** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** fts3ExprLoadDoclists().
*/
static int fts3ExprLoadDoclistsCb2(Fts3Expr *pExpr, int iPhrase, void *ctx){
UNUSED_PARAMETER(iPhrase);
UNUSED_PARAMETER(ctx);
if( pExpr->aDoclist ){
pExpr->pCurrent = pExpr->aDoclist;
pExpr->iCurrent = 0;
pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent, &pExpr->iCurrent);
}
return SQLITE_OK;
}
/*
** Load the doclists for each phrase in the query associated with FTS3 cursor
** pCsr.
**
** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable
** phrases in the expression (all phrases except those directly or
** indirectly descended from the right-hand-side of a NOT operator). If
** pnToken is not NULL, then it is set to the number of tokens in all
** matchable phrases of the expression.
*/
static int fts3ExprLoadDoclists(
Fts3Cursor *pCsr, /* Fts3 cursor for current query */
int *pnPhrase, /* OUT: Number of phrases in query */
int *pnToken /* OUT: Number of tokens in query */
){
int rc; /* Return Code */
LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */
sCtx.pTab = (Fts3Table *)pCsr->base.pVtab;
rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb1, (void *)&sCtx);
if( rc==SQLITE_OK ){
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb2, 0);
}
if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
if( pnToken ) *pnToken = sCtx.nToken;
return rc;
}
/*
** Advance the position list iterator specified by the first two
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
char *pIter = *ppIter;
if( pIter ){
int iIter = *piIter;
while( iIter<iNext ){
if( 0==(*pIter & 0xFE) ){
iIter = -1;
pIter = 0;
break;
}
fts3GetDeltaPosition(&pIter, &iIter);
}
*piIter = iIter;
*ppIter = pIter;
}
}
/*
** Advance the snippet iterator to the next candidate snippet.
*/
static int fts3SnippetNextCandidate(SnippetIter *pIter){
int i; /* Loop counter */
if( pIter->iCurrent<0 ){
/* The SnippetIter object has just been initialized. The first snippet
** candidate always starts at offset 0 (even if this candidate has a
** score of 0.0).
*/
pIter->iCurrent = 0;
/* Advance the 'head' iterator of each phrase to the first offset that
** is greater than or equal to (iNext+nSnippet).
*/
for(i=0; i<pIter->nPhrase; i++){
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet);
}
}else{
int iStart;
int iEnd = 0x7FFFFFFF;
for(i=0; i<pIter->nPhrase; i++){
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
if( pPhrase->pHead && pPhrase->iHead<iEnd ){
iEnd = pPhrase->iHead;
}
}
if( iEnd==0x7FFFFFFF ){
return 1;
}
pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1;
for(i=0; i<pIter->nPhrase; i++){
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1);
fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart);
}
}
return 0;
}
/*
** Retrieve information about the current candidate snippet of snippet
** iterator pIter.
*/
static void fts3SnippetDetails(
SnippetIter *pIter, /* Snippet iterator */
u64 mCovered, /* Bitmask of phrases already covered */
int *piToken, /* OUT: First token of proposed snippet */
int *piScore, /* OUT: "Score" for this snippet */
u64 *pmCover, /* OUT: Bitmask of phrases covered */
u64 *pmHighlight /* OUT: Bitmask of terms to highlight */
){
int iStart = pIter->iCurrent; /* First token of snippet */
int iScore = 0; /* Score of this snippet */
int i; /* Loop counter */
u64 mCover = 0; /* Mask of phrases covered by this snippet */
u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */
for(i=0; i<pIter->nPhrase; i++){
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
if( pPhrase->pTail ){
char *pCsr = pPhrase->pTail;
int iCsr = pPhrase->iTail;
while( iCsr<(iStart+pIter->nSnippet) ){
int j;
u64 mPhrase = (u64)1 << i;
u64 mPos = (u64)1 << (iCsr - iStart);
assert( iCsr>=iStart );
if( (mCover|mCovered)&mPhrase ){
iScore++;
}else{
iScore += 1000;
}
mCover |= mPhrase;
for(j=0; j<pPhrase->nToken; j++){
mHighlight |= (mPos>>j);
}
if( 0==(*pCsr & 0x0FE) ) break;
fts3GetDeltaPosition(&pCsr, &iCsr);
}
}
}
/* Set the output variables before returning. */
*piToken = iStart;
*piScore = iScore;
*pmCover = mCover;
*pmHighlight = mHighlight;
}
/*
** This function is an fts3ExprIterate() callback used by fts3BestSnippet().
** Each invocation populates an element of the SnippetIter.aPhrase[] array.
*/
static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
SnippetIter *p = (SnippetIter *)ctx;
SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
char *pCsr;
pPhrase->nToken = pExpr->pPhrase->nToken;
pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol);
if( pCsr ){
int iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
pPhrase->pHead = pCsr;
pPhrase->pTail = pCsr;
pPhrase->iHead = iFirst;
pPhrase->iTail = iFirst;
}else{
assert( pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 );
}
return SQLITE_OK;
}
/*
** Select the fragment of text consisting of nFragment contiguous tokens
** from column iCol that represent the "best" snippet. The best snippet
** is the snippet with the highest score, where scores are calculated
** by adding:
**
** (a) +1 point for each occurence of a matchable phrase in the snippet.
**
** (b) +1000 points for the first occurence of each matchable phrase in
** the snippet for which the corresponding mCovered bit is not set.
**
** The selected snippet parameters are stored in structure *pFragment before
** returning. The score of the selected snippet is stored in *piScore
** before returning.
*/
static int fts3BestSnippet(
int nSnippet, /* Desired snippet length */
Fts3Cursor *pCsr, /* Cursor to create snippet for */
int iCol, /* Index of column to create snippet from */
u64 mCovered, /* Mask of phrases already covered */
u64 *pmSeen, /* IN/OUT: Mask of phrases seen */
SnippetFragment *pFragment, /* OUT: Best snippet found */
int *piScore /* OUT: Score of snippet pFragment */
){
int rc; /* Return Code */
int nList; /* Number of phrases in expression */
SnippetIter sIter; /* Iterates through snippet candidates */
int nByte; /* Number of bytes of space to allocate */
int iBestScore = -1; /* Best snippet score found so far */
int i; /* Loop counter */
memset(&sIter, 0, sizeof(sIter));
/* Iterate through the phrases in the expression to count them. The same
** callback makes sure the doclists are loaded for each phrase.
*/
rc = fts3ExprLoadDoclists(pCsr, &nList, 0);
if( rc!=SQLITE_OK ){
return rc;
}
/* Now that it is known how many phrases there are, allocate and zero
** the required space using malloc().
*/
nByte = sizeof(SnippetPhrase) * nList;
sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
if( !sIter.aPhrase ){
return SQLITE_NOMEM;
}
memset(sIter.aPhrase, 0, nByte);
/* Initialize the contents of the SnippetIter object. Then iterate through
** the set of phrases in the expression to populate the aPhrase[] array.
*/
sIter.pCsr = pCsr;
sIter.iCol = iCol;
sIter.nSnippet = nSnippet;
sIter.nPhrase = nList;
sIter.iCurrent = -1;
(void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter);
/* Set the *pmSeen output variable. */
for(i=0; i<nList; i++){
if( sIter.aPhrase[i].pHead ){
*pmSeen |= (u64)1 << i;
}
}
/* Loop through all candidate snippets. Store the best snippet in
** *pFragment. Store its associated 'score' in iBestScore.
*/
pFragment->iCol = iCol;
while( !fts3SnippetNextCandidate(&sIter) ){
int iPos;
int iScore;
u64 mCover;
u64 mHighlight;
fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight);
assert( iScore>=0 );
if( iScore>iBestScore ){
pFragment->iPos = iPos;
pFragment->hlmask = mHighlight;
pFragment->covered = mCover;
iBestScore = iScore;
}
}
sqlite3_free(sIter.aPhrase);
*piScore = iBestScore;
return SQLITE_OK;
}
/*
** Append a string to the string-buffer passed as the first argument.
**
** If nAppend is negative, then the length of the string zAppend is
** determined using strlen().
*/
static int fts3StringAppend(
StrBuffer *pStr, /* Buffer to append to */
const char *zAppend, /* Pointer to data to append to buffer */
int nAppend /* Size of zAppend in bytes (or -1) */
){
if( nAppend<0 ){
nAppend = (int)strlen(zAppend);
}
/* If there is insufficient space allocated at StrBuffer.z, use realloc()
** to grow the buffer until so that it is big enough to accomadate the
** appended data.
*/
if( pStr->n+nAppend+1>=pStr->nAlloc ){
int nAlloc = pStr->nAlloc+nAppend+100;
char *zNew = sqlite3_realloc(pStr->z, nAlloc);
if( !zNew ){
return SQLITE_NOMEM;
}
pStr->z = zNew;
pStr->nAlloc = nAlloc;
}
/* Append the data to the string buffer. */
memcpy(&pStr->z[pStr->n], zAppend, nAppend);
pStr->n += nAppend;
pStr->z[pStr->n] = '\0';
return SQLITE_OK;
}
/*
** The fts3BestSnippet() function often selects snippets that end with a
** query term. That is, the final term of the snippet is always a term
** that requires highlighting. For example, if 'X' is a highlighted term
** and '.' is a non-highlighted term, BestSnippet() may select:
**
** ........X.....X
**
** This function "shifts" the beginning of the snippet forward in the
** document so that there are approximately the same number of
** non-highlighted terms to the right of the final highlighted term as there
** are to the left of the first highlighted term. For example, to this:
**
** ....X.....X....
**
** This is done as part of extracting the snippet text, not when selecting
** the snippet. Snippet selection is done based on doclists only, so there
** is no way for fts3BestSnippet() to know whether or not the document
** actually contains terms that follow the final highlighted term.
*/
int fts3SnippetShift(
Fts3Table *pTab, /* FTS3 table snippet comes from */
int nSnippet, /* Number of tokens desired for snippet */
const char *zDoc, /* Document text to extract snippet from */
int nDoc, /* Size of buffer zDoc in bytes */
int *piPos, /* IN/OUT: First token of snippet */
u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
){
u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */
if( hlmask ){
int nLeft; /* Tokens to the left of first highlight */
int nRight; /* Tokens to the right of last highlight */
int nDesired; /* Ideal number of tokens to shift forward */
for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
nDesired = (nLeft-nRight)/2;
/* Ideally, the start of the snippet should be pushed forward in the
** document nDesired tokens. This block checks if there are actually
** nDesired tokens to the right of the snippet. If so, *piPos and
** *pHlMask are updated to shift the snippet nDesired tokens to the
** right. Otherwise, the snippet is shifted by the number of tokens
** available.
*/
if( nDesired>0 ){
int nShift; /* Number of tokens to shift snippet by */
int iCurrent = 0; /* Token counter */
int rc; /* Return Code */
sqlite3_tokenizer_module *pMod;
sqlite3_tokenizer_cursor *pC;
pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
/* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
** or more tokens in zDoc/nDoc.
*/
rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
if( rc!=SQLITE_OK ){
return rc;
}
pC->pTokenizer = pTab->pTokenizer;
while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
}
pMod->xClose(pC);
if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; }
nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet;
assert( nShift<=nDesired );
if( nShift>0 ){
*piPos += nShift;
*pHlmask = hlmask >> nShift;
}
}
}
return SQLITE_OK;
}
/*
** Extract the snippet text for fragment pFragment from cursor pCsr and
** append it to string buffer pOut.
*/
static int fts3SnippetText(
Fts3Cursor *pCsr, /* FTS3 Cursor */
SnippetFragment *pFragment, /* Snippet to extract */
int iFragment, /* Fragment number */
int isLast, /* True for final fragment in snippet */
int nSnippet, /* Number of tokens in extracted snippet */
const char *zOpen, /* String inserted before highlighted term */
const char *zClose, /* String inserted after highlighted term */
const char *zEllipsis, /* String inserted between snippets */
StrBuffer *pOut /* Write output here */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc; /* Return code */
const char *zDoc; /* Document text to extract snippet from */
int nDoc; /* Size of zDoc in bytes */
int iCurrent = 0; /* Current token number of document */
int iEnd = 0; /* Byte offset of end of current token */
int isShiftDone = 0; /* True after snippet is shifted */
int iPos = pFragment->iPos; /* First token of snippet */
u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */
int iCol = pFragment->iCol+1; /* Query column to extract text from */
sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */
const char *ZDUMMY; /* Dummy argument used with tokenizer */
int DUMMY1; /* Dummy argument used with tokenizer */
zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
if( zDoc==0 ){
if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){
return SQLITE_NOMEM;
}
return SQLITE_OK;
}
nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
/* Open a token cursor on the document. */
pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
if( rc!=SQLITE_OK ){
return rc;
}
pC->pTokenizer = pTab->pTokenizer;
while( rc==SQLITE_OK ){
int iBegin; /* Offset in zDoc of start of token */
int iFin; /* Offset in zDoc of end of token */
int isHighlight; /* True for highlighted terms */
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
/* Special case - the last token of the snippet is also the last token
** of the column. Append any punctuation that occurred between the end
** of the previous token and the end of the document to the output.
** Then break out of the loop. */
rc = fts3StringAppend(pOut, &zDoc[iEnd], -1);
}
break;
}
if( iCurrent<iPos ){ continue; }
if( !isShiftDone ){
int n = nDoc - iBegin;
rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask);
isShiftDone = 1;
/* Now that the shift has been done, check if the initial "..." are
** required. They are required if (a) this is not the first fragment,
** or (b) this fragment does not begin at position 0 of its column.
*/
if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){
rc = fts3StringAppend(pOut, zEllipsis, -1);
}
if( rc!=SQLITE_OK || iCurrent<iPos ) continue;
}
if( iCurrent>=(iPos+nSnippet) ){
if( isLast ){
rc = fts3StringAppend(pOut, zEllipsis, -1);
}
break;
}
/* Set isHighlight to true if this term should be highlighted. */
isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0;
if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd);
if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1);
if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin);
if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1);
iEnd = iFin;
}
pMod->xClose(pC);
return rc;
}
/*
** This function is used to count the entries in a column-list (a
** delta-encoded list of term offsets within a single column of a single
** row). When this function is called, *ppCollist should point to the
** beginning of the first varint in the column-list (the varint that
** contains the position of the first matching term in the column data).
** Before returning, *ppCollist is set to point to the first byte after
** the last varint in the column-list (either the 0x00 signifying the end
** of the position-list, or the 0x01 that precedes the column number of
** the next column in the position-list).
**
** The number of elements in the column-list is returned.
*/
static int fts3ColumnlistCount(char **ppCollist){
char *pEnd = *ppCollist;
char c = 0;
int nEntry = 0;
/* A column-list is terminated by either a 0x01 or 0x00. */
while( 0xFE & (*pEnd | c) ){
c = *pEnd++ & 0x80;
if( !c ) nEntry++;
}
*ppCollist = pEnd;
return nEntry;
}
static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){
char *pCsr = *pp;
while( *pCsr ){
int nHit;
sqlite3_int64 iCol = 0;
if( *pCsr==0x01 ){
pCsr++;
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
}
nHit = fts3ColumnlistCount(&pCsr);
assert( nHit>0 );
if( isGlobal ){
aOut[iCol*3+1]++;
}
aOut[iCol*3] += nHit;
}
pCsr++;
*pp = pCsr;
}
/*
** fts3ExprIterate() callback used to collect the "global" matchinfo stats
** for a single query. The "global" stats are those elements of the matchinfo
** array that are constant for all rows returned by the current query.
*/
static int fts3ExprGlobalMatchinfoCb(
Fts3Expr *pExpr, /* Phrase expression node */
int iPhrase, /* Phrase number (numbered from zero) */
void *pCtx /* Pointer to MatchInfo structure */
){
MatchInfo *p = (MatchInfo *)pCtx;
char *pCsr;
char *pEnd;
const int iStart = 2 + (iPhrase * p->nCol * 3) + 1;
assert( pExpr->isLoaded );
/* Fill in the global hit count matrix row for this phrase. */
pCsr = pExpr->aDoclist;
pEnd = &pExpr->aDoclist[pExpr->nDoclist];
while( pCsr<pEnd ){
while( *pCsr++ & 0x80 ); /* Skip past docid. */
fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 1);
}
return SQLITE_OK;
}
/*
** fts3ExprIterate() callback used to collect the "local" matchinfo stats
** for a single query. The "local" stats are those elements of the matchinfo
** array that are different for each row returned by the query.
*/
static int fts3ExprLocalMatchinfoCb(
Fts3Expr *pExpr, /* Phrase expression node */
int iPhrase, /* Phrase number */
void *pCtx /* Pointer to MatchInfo structure */
){
MatchInfo *p = (MatchInfo *)pCtx;
if( pExpr->aDoclist ){
char *pCsr;
int iStart = 2 + (iPhrase * p->nCol * 3);
int i;
for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1);
if( pCsr ){
fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
}
}
return SQLITE_OK;
}
/*
** Populate pCsr->aMatchinfo[] with data for the current row. The
** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32).
*/
static int fts3GetMatchinfo(Fts3Cursor *pCsr){
MatchInfo sInfo;
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc = SQLITE_OK;
sInfo.pCursor = pCsr;
sInfo.nCol = pTab->nColumn;
if( pCsr->aMatchinfo==0 ){
/* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the
** matchinfo function has been called for this query. In this case
** allocate the array used to accumulate the matchinfo data and
** initialize those elements that are constant for every row.
*/
int nPhrase; /* Number of phrases */
int nMatchinfo; /* Number of u32 elements in match-info */
/* Load doclists for each phrase in the query. */
rc = fts3ExprLoadDoclists(pCsr, &nPhrase, 0);
if( rc!=SQLITE_OK ){
return rc;
}
nMatchinfo = 2 + 3*sInfo.nCol*nPhrase;
if( pTab->bHasDocsize ){
nMatchinfo += 1 + 2*pTab->nColumn;
}
sInfo.aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo);
if( !sInfo.aMatchinfo ){
return SQLITE_NOMEM;
}
memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo);
/* First element of match-info is the number of phrases in the query */
sInfo.aMatchinfo[0] = nPhrase;
sInfo.aMatchinfo[1] = sInfo.nCol;
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo);
if( pTab->bHasDocsize ){
int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1];
rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]);
}
pCsr->aMatchinfo = sInfo.aMatchinfo;
pCsr->isMatchinfoNeeded = 1;
}
sInfo.aMatchinfo = pCsr->aMatchinfo;
if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo);
if( pTab->bHasDocsize ){
int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1];
rc = sqlite3Fts3MatchinfoDocsizeLocal(pCsr, &sInfo.aMatchinfo[ofst]);
}
pCsr->isMatchinfoNeeded = 0;
}
return SQLITE_OK;
}
/*
** Implementation of snippet() function.
*/
SQLITE_PRIVATE void sqlite3Fts3Snippet(
sqlite3_context *pCtx, /* SQLite function call context */
Fts3Cursor *pCsr, /* Cursor object */
const char *zStart, /* Snippet start text - "<b>" */
const char *zEnd, /* Snippet end text - "</b>" */
const char *zEllipsis, /* Snippet ellipsis text - "<b>...</b>" */
int iCol, /* Extract snippet from this column */
int nToken /* Approximate number of tokens in snippet */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc = SQLITE_OK;
int i;
StrBuffer res = {0, 0, 0};
/* The returned text includes up to four fragments of text extracted from
** the data in the current row. The first iteration of the for(...) loop
** below attempts to locate a single fragment of text nToken tokens in
** size that contains at least one instance of all phrases in the query
** expression that appear in the current row. If such a fragment of text
** cannot be found, the second iteration of the loop attempts to locate
** a pair of fragments, and so on.
*/
int nSnippet = 0; /* Number of fragments in this snippet */
SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */
int nFToken = -1; /* Number of tokens in each fragment */
if( !pCsr->pExpr ){
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
return;
}
for(nSnippet=1; 1; nSnippet++){
int iSnip; /* Loop counter 0..nSnippet-1 */
u64 mCovered = 0; /* Bitmask of phrases covered by snippet */
u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */
if( nToken>=0 ){
nFToken = (nToken+nSnippet-1) / nSnippet;
}else{
nFToken = -1 * nToken;
}
for(iSnip=0; iSnip<nSnippet; iSnip++){
int iBestScore = -1; /* Best score of columns checked so far */
int iRead; /* Used to iterate through columns */
SnippetFragment *pFragment = &aSnippet[iSnip];
memset(pFragment, 0, sizeof(*pFragment));
/* Loop through all columns of the table being considered for snippets.
** If the iCol argument to this function was negative, this means all
** columns of the FTS3 table. Otherwise, only column iCol is considered.
*/
for(iRead=0; iRead<pTab->nColumn; iRead++){
SnippetFragment sF;
int iS;
if( iCol>=0 && iRead!=iCol ) continue;
/* Find the best snippet of nFToken tokens in column iRead. */
rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS);
if( rc!=SQLITE_OK ){
goto snippet_out;
}
if( iS>iBestScore ){
*pFragment = sF;
iBestScore = iS;
}
}
mCovered |= pFragment->covered;
}
/* If all query phrases seen by fts3BestSnippet() are present in at least
** one of the nSnippet snippet fragments, break out of the loop.
*/
assert( (mCovered&mSeen)==mCovered );
if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break;
}
assert( nFToken>0 );
for(i=0; i<nSnippet && rc==SQLITE_OK; i++){
rc = fts3SnippetText(pCsr, &aSnippet[i],
i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res
);
}
snippet_out:
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
sqlite3_free(res.z);
}else{
sqlite3_result_text(pCtx, res.z, -1, sqlite3_free);
}
}
typedef struct TermOffset TermOffset;
typedef struct TermOffsetCtx TermOffsetCtx;
struct TermOffset {
char *pList; /* Position-list */
int iPos; /* Position just read from pList */
int iOff; /* Offset of this term from read positions */
};
struct TermOffsetCtx {
int iCol; /* Column of table to populate aTerm for */
int iTerm;
sqlite3_int64 iDocid;
TermOffset *aTerm;
};
/*
** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets().
*/
static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
TermOffsetCtx *p = (TermOffsetCtx *)ctx;
int nTerm; /* Number of tokens in phrase */
int iTerm; /* For looping through nTerm phrase terms */
char *pList; /* Pointer to position list for phrase */
int iPos = 0; /* First position in position-list */
UNUSED_PARAMETER(iPhrase);
pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol);
nTerm = pExpr->pPhrase->nToken;
if( pList ){
fts3GetDeltaPosition(&pList, &iPos);
assert( iPos>=0 );
}
for(iTerm=0; iTerm<nTerm; iTerm++){
TermOffset *pT = &p->aTerm[p->iTerm++];
pT->iOff = nTerm-iTerm-1;
pT->pList = pList;
pT->iPos = iPos;
}
return SQLITE_OK;
}
/*
** Implementation of offsets() function.
*/
SQLITE_PRIVATE void sqlite3Fts3Offsets(
sqlite3_context *pCtx, /* SQLite function call context */
Fts3Cursor *pCsr /* Cursor object */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
const char *ZDUMMY; /* Dummy argument used with xNext() */
int NDUMMY; /* Dummy argument used with xNext() */
int rc; /* Return Code */
int nToken; /* Number of tokens in query */
int iCol; /* Column currently being processed */
StrBuffer res = {0, 0, 0}; /* Result string */
TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */
if( !pCsr->pExpr ){
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
return;
}
memset(&sCtx, 0, sizeof(sCtx));
assert( pCsr->isRequireSeek==0 );
/* Count the number of terms in the query */
rc = fts3ExprLoadDoclists(pCsr, 0, &nToken);
if( rc!=SQLITE_OK ) goto offsets_out;
/* Allocate the array of TermOffset iterators. */
sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
if( 0==sCtx.aTerm ){
rc = SQLITE_NOMEM;
goto offsets_out;
}
sCtx.iDocid = pCsr->iPrevId;
/* Loop through the table columns, appending offset information to
** string-buffer res for each column.
*/
for(iCol=0; iCol<pTab->nColumn; iCol++){
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
int iStart;
int iEnd;
int iCurrent;
const char *zDoc;
int nDoc;
/* Initialize the contents of sCtx.aTerm[] for column iCol. There is
** no way that this operation can fail, so the return code from
** fts3ExprIterate() can be discarded.
*/
sCtx.iCol = iCol;
sCtx.iTerm = 0;
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx);
/* Retreive the text stored in column iCol. If an SQL NULL is stored
** in column iCol, jump immediately to the next iteration of the loop.
** If an OOM occurs while retrieving the data (this can happen if SQLite
** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
** to the caller.
*/
zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1);
nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
if( zDoc==0 ){
if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){
continue;
}
rc = SQLITE_NOMEM;
goto offsets_out;
}
/* Initialize a tokenizer iterator to iterate through column iCol. */
rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
if( rc!=SQLITE_OK ) goto offsets_out;
pC->pTokenizer = pTab->pTokenizer;
rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
while( rc==SQLITE_OK ){
int i; /* Used to loop through terms */
int iMinPos = 0x7FFFFFFF; /* Position of next token */
TermOffset *pTerm = 0; /* TermOffset associated with next token */
for(i=0; i<nToken; i++){
TermOffset *pT = &sCtx.aTerm[i];
if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){
iMinPos = pT->iPos-pT->iOff;
pTerm = pT;
}
}
if( !pTerm ){
/* All offsets for this column have been gathered. */
break;
}else{
assert( iCurrent<=iMinPos );
if( 0==(0xFE&*pTerm->pList) ){
pTerm->pList = 0;
}else{
fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
}
while( rc==SQLITE_OK && iCurrent<iMinPos ){
rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
}
if( rc==SQLITE_OK ){
char aBuffer[64];
sqlite3_snprintf(sizeof(aBuffer), aBuffer,
"%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
);
rc = fts3StringAppend(&res, aBuffer, -1);
}
}
}
if( rc==SQLITE_DONE ){
rc = SQLITE_CORRUPT;
}
pMod->xClose(pC);
if( rc!=SQLITE_OK ) goto offsets_out;
}
offsets_out:
sqlite3_free(sCtx.aTerm);
assert( rc!=SQLITE_DONE );
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
sqlite3_free(res.z);
}else{
sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free);
}
return;
}
/*
** Implementation of matchinfo() function.
*/
SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc;
if( !pCsr->pExpr ){
sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
return;
}
rc = fts3GetMatchinfo(pCsr);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pContext, rc);
}else{
Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*3);
if( pTab->bHasDocsize ){
n += sizeof(u32)*(1 + 2*pTab->nColumn);
}
sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT);
}
}
#endif
/************** End of fts3_snippet.c ****************************************/
|
| ︙ | ︙ | |||
107632 107633 107634 107635 107636 107637 107638 107639 107640 107641 107642 107643 107644 107645 |
pNode->isDirty = 0;
pNode->pNext = 0;
sqlite3_bind_int64(pRtree->pReadNode, 1, iNode);
rc = sqlite3_step(pRtree->pReadNode);
if( rc==SQLITE_ROW ){
const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
nodeReference(pParent);
}else{
sqlite3_free(pNode);
pNode = 0;
}
| > | 109131 109132 109133 109134 109135 109136 109137 109138 109139 109140 109141 109142 109143 109144 109145 |
pNode->isDirty = 0;
pNode->pNext = 0;
sqlite3_bind_int64(pRtree->pReadNode, 1, iNode);
rc = sqlite3_step(pRtree->pReadNode);
if( rc==SQLITE_ROW ){
const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize );
memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
nodeReference(pParent);
}else{
sqlite3_free(pNode);
pNode = 0;
}
|
| ︙ | ︙ | |||
109828 109829 109830 109831 109832 109833 109834 |
sqlite3_free(zSql);
}
return rc;
}
/*
| | > | | | | | | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > | | > > > > > > > | < | < < < < < < < < < < < < | < < < < < < | < < | < > | | | | | | | | | | | | | | | | | | | | | | > | 111328 111329 111330 111331 111332 111333 111334 111335 111336 111337 111338 111339 111340 111341 111342 111343 111344 111345 111346 111347 111348 111349 111350 111351 111352 111353 111354 111355 111356 111357 111358 111359 111360 111361 111362 111363 111364 111365 111366 111367 111368 111369 111370 111371 111372 111373 111374 111375 111376 111377 111378 111379 111380 111381 111382 111383 111384 111385 111386 111387 111388 111389 111390 111391 111392 111393 111394 111395 111396 111397 111398 111399 111400 111401 111402 111403 111404 111405 111406 111407 111408 111409 111410 111411 111412 111413 111414 111415 111416 111417 111418 111419 111420 111421 111422 111423 111424 111425 111426 111427 111428 111429 111430 111431 111432 111433 111434 111435 111436 111437 111438 111439 111440 111441 111442 111443 111444 111445 111446 111447 111448 111449 111450 111451 111452 111453 111454 111455 111456 111457 111458 111459 111460 111461 111462 111463 111464 111465 111466 111467 111468 111469 111470 111471 111472 111473 111474 111475 111476 111477 111478 111479 111480 111481 111482 111483 111484 111485 111486 111487 111488 111489 111490 111491 |
sqlite3_free(zSql);
}
return rc;
}
/*
** The second argument to this function contains the text of an SQL statement
** that returns a single integer value. The statement is compiled and executed
** using database connection db. If successful, the integer value returned
** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error
** code is returned and the value of *piVal after returning is not defined.
*/
static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
int rc = SQLITE_NOMEM;
if( zSql ){
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
if( SQLITE_ROW==sqlite3_step(pStmt) ){
*piVal = sqlite3_column_int(pStmt, 0);
}
rc = sqlite3_finalize(pStmt);
}
}
return rc;
}
/*
** This function is called from within the xConnect() or xCreate() method to
** determine the node-size used by the rtree table being created or connected
** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned.
** Otherwise, an SQLite error code is returned.
**
** If this function is being called as part of an xConnect(), then the rtree
** table already exists. In this case the node-size is determined by inspecting
** the root node of the tree.
**
** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
** This ensures that each node is stored on a single database page. If the
** database page-size is so large that more than RTREE_MAXCELLS entries
** would fit in a single node, use a smaller node-size.
*/
static int getNodeSize(
sqlite3 *db, /* Database handle */
Rtree *pRtree, /* Rtree handle */
int isCreate /* True for xCreate, false for xConnect */
){
int rc;
char *zSql;
if( isCreate ){
int iPageSize;
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
rc = getIntFromStmt(db, zSql, &iPageSize);
if( rc==SQLITE_OK ){
pRtree->iNodeSize = iPageSize-64;
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
}
}
}else{
zSql = sqlite3_mprintf(
"SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
pRtree->zDb, pRtree->zName
);
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
}
sqlite3_free(zSql);
return rc;
}
/*
** This function is the implementation of both the xConnect and xCreate
** methods of the r-tree virtual table.
**
** argv[0] -> module name
** argv[1] -> database name
** argv[2] -> table name
** argv[...] -> column names...
*/
static int rtreeInit(
sqlite3 *db, /* Database connection */
void *pAux, /* One of the RTREE_COORD_* constants */
int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */
sqlite3_vtab **ppVtab, /* OUT: New virtual table */
char **pzErr, /* OUT: Error message, if any */
int isCreate /* True for xCreate, false for xConnect */
){
int rc = SQLITE_OK;
Rtree *pRtree;
int nDb; /* Length of string argv[1] */
int nName; /* Length of string argv[2] */
int eCoordType = (int)pAux;
const char *aErrMsg[] = {
0, /* 0 */
"Wrong number of columns for an rtree table", /* 1 */
"Too few columns for an rtree table", /* 2 */
"Too many columns for an rtree table" /* 3 */
};
int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
if( aErrMsg[iErr] ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
return SQLITE_ERROR;
}
/* Allocate the sqlite3_vtab structure */
nDb = strlen(argv[1]);
nName = strlen(argv[2]);
pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
if( !pRtree ){
return SQLITE_NOMEM;
}
memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
pRtree->nBusy = 1;
pRtree->base.pModule = &rtreeModule;
pRtree->zDb = (char *)&pRtree[1];
pRtree->zName = &pRtree->zDb[nDb+1];
pRtree->nDim = (argc-4)/2;
pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
pRtree->eCoordType = eCoordType;
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
/* Figure out the node size to use. */
rc = getNodeSize(db, pRtree, isCreate);
/* Create/Connect to the underlying relational database schema. If
** that is successful, call sqlite3_declare_vtab() to configure
** the r-tree table schema.
*/
if( rc==SQLITE_OK ){
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else{
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
char *zTmp;
int ii;
for(ii=4; zSql && ii<argc; ii++){
zTmp = zSql;
zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
sqlite3_free(zTmp);
}
if( zSql ){
zTmp = zSql;
zSql = sqlite3_mprintf("%s);", zTmp);
sqlite3_free(zTmp);
}
if( !zSql ){
rc = SQLITE_NOMEM;
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
sqlite3_free(zSql);
}
}
if( rc==SQLITE_OK ){
*ppVtab = (sqlite3_vtab *)pRtree;
}else{
rtreeRelease(pRtree);
}
|
| ︙ | ︙ |
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
103 104 105 106 107 108 109 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.6.23" #define SQLITE_VERSION_NUMBER 3006023 #define SQLITE_SOURCE_ID "2010-03-04 17:58:45 5e472896e02eed05c6c0886a48acd0bdc7a38731" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ** but are associated with the library instead of the header file. ^(Cautious ** programmers might include assert() statements in their application to ** verify that values returned by these interfaces match the macros in ** the header, and thus insure that the application is |
| ︙ | ︙ | |||
131 132 133 134 135 136 137 | ** ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] ** macro. ^The sqlite3_libversion() function returns a pointer to the ** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | ** ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] ** macro. ^The sqlite3_libversion() function returns a pointer to the ** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the ** [SQLITE_SOURCE_ID] C preprocessor macro. ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; SQLITE_API const char *sqlite3_libversion(void); SQLITE_API const char *sqlite3_sourceid(void); SQLITE_API int sqlite3_libversion_number(void); #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics ** ** ^The sqlite3_compileoption_used() function returns 0 or 1 ** indicating whether the specified option was defined at ** compile time. ^The SQLITE_ prefix may be omitted from the ** option name passed to sqlite3_compileoption_used(). ** ** ^The sqlite3_compileoption_get() function allows interating ** over the list of options that were defined at compile time by ** returning the N-th compile time option string. ^If N is out of range, ** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ ** prefix is omitted from any strings returned by ** sqlite3_compileoption_get(). ** ** ^Support for the diagnostic functions sqlite3_compileoption_used() ** and sqlite3_compileoption_get() may be omitted by specifing the ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. ** ** See also: SQL functions [sqlite_compileoption_used()] and ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ SQLITE_API int sqlite3_compileoption_used(const char *zOptName); SQLITE_API const char *sqlite3_compileoption_get(int N); #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ /* ** CAPI3REF: Test To See If The Library Is Threadsafe ** ** ^The sqlite3_threadsafe() function returns zero if and only if ** SQLite was compiled mutexing code omitted due to the ** [SQLITE_THREADSAFE] compile-time option being set to 0. ** |
| ︙ | ︙ | |||
433 434 435 436 437 438 439 440 441 442 443 444 445 446 | ** [sqlite3_vfs] object. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ | > | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | ** [sqlite3_vfs] object. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ |
| ︙ | ︙ | |||
914 915 916 917 918 919 920 | SQLITE_API int sqlite3_initialize(void); SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library | < | 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | SQLITE_API int sqlite3_initialize(void); SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** ** The sqlite3_config() interface is used to make global configuration ** changes to SQLite in order to tune SQLite to the specific needs of ** the application. The default configuration is recommended for most ** applications and so this routine is usually not necessary. It is ** provided to support rare applications with unusual needs. ** |
| ︙ | ︙ | |||
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 | #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ #define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ /* ** CAPI3REF: Configuration Options ** EXPERIMENTAL ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. | > | 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 | #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ #define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ /* ** CAPI3REF: Configuration Options ** EXPERIMENTAL ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. |
| ︙ | ︙ | |||
3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 | ); SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); /* ** Specify the key for an encrypted database. This routine should be ** called right after sqlite3_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ | > | 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 | ); SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); #if SQLITE_HAS_CODEC /* ** Specify the key for an encrypted database. This routine should be ** called right after sqlite3_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ |
| ︙ | ︙ | |||
3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 | ** of SQLite. */ SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); /* ** CAPI3REF: Suspend Execution For A Short Time ** ** ^The sqlite3_sleep() function causes the current thread to suspend execution ** for at least a number of milliseconds specified in its parameter. ** ** ^If the operating system does not support sleep requests with | > > > > > > > > > > > > > > > > > > > | 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 | ** of SQLite. */ SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); /* ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif #ifdef SQLITE_ENABLE_CEROD /* ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif /* ** CAPI3REF: Suspend Execution For A Short Time ** ** ^The sqlite3_sleep() function causes the current thread to suspend execution ** for at least a number of milliseconds specified in its parameter. ** ** ^If the operating system does not support sleep requests with |
| ︙ | ︙ | |||
5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 | ** ^The [sqlite3_strnicmp()] API allows applications and extensions to ** compare the contents of two buffers containing UTF-8 strings in a ** case-indendent fashion, using the same definition of case independence ** that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif | > > > > > > > > > > > > > > > > > > > > > > > > | 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 | ** ^The [sqlite3_strnicmp()] API allows applications and extensions to ** compare the contents of two buffers containing UTF-8 strings in a ** case-indendent fashion, using the same definition of case independence ** that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: Error Logging Interface ** EXPERIMENTAL ** ** ^The [sqlite3_log()] interface writes a message into the error log ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are ** passed through to [sqlite3_vmprintf()] to generate the final output string. ** ** The sqlite3_log() interface is intended for use by extensions such as ** virtual tables, collating functions, and SQL functions. While there is ** nothing to prevent an application from calling sqlite3_log(), doing so ** is considered bad form. ** ** The zFormat string must not be NULL. ** ** To avoid deadlocks and other threading problems, the sqlite3_log() routine ** will not use dynamically allocated memory. The log message is stored in ** a fixed-length buffer on the stack. If the log message is longer than ** a few hundred characters, it will be truncated to the length of the ** buffer. */ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif |
Changes to src/url.c.
| ︙ | ︙ | |||
308 309 310 311 312 313 314 |
}
/*
** Prompt the user for the password for g.urlUser. Store the result
** in g.urlPasswd.
*/
void url_prompt_for_password(void){
| > | | | | | | > > > > | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
}
/*
** Prompt the user for the password for g.urlUser. Store the result
** in g.urlPasswd.
*/
void url_prompt_for_password(void){
if( isatty(fileno(stdin)) ){
char *zPrompt = mprintf("password for %s: ", g.urlUser);
Blob x;
prompt_for_password(zPrompt, &x, 0);
free(zPrompt);
g.urlPasswd = mprintf("%b", &x);
blob_reset(&x);
}else{
fossil_fatal("missing or incorrect password for user \"%s\"",
g.urlUser);
}
}
|
Changes to src/wikiformat.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** Copyright (c) 2007 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public ** License version 2 as published by the Free Software Foundation. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** Copyright (c) 2007 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public ** License version 2 as published by the Free Software Foundation. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public ** License along with this library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com |
| ︙ | ︙ | |||
148 149 150 151 152 153 154 | /* ** Allowed markup. ** ** Except for MARKUP_INVALID, this must all be in alphabetical order ** and in numerical sequence. The first markup type must be zero. | | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /* ** Allowed markup. ** ** Except for MARKUP_INVALID, this must all be in alphabetical order ** and in numerical sequence. The first markup type must be zero. ** The value for MARKUP_XYZ must correspond to the <xyz> entry ** in aAllowedMarkup[]. */ #define MARKUP_INVALID 0 #define MARKUP_A 1 #define MARKUP_ADDRESS 2 #define MARKUP_B 3 #define MARKUP_BIG 4 |
| ︙ | ︙ | |||
256 257 258 259 260 261 262 |
AMSK_COLOR|AMSK_FACE|AMSK_SIZE },
{ "h1", MARKUP_H1, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h2", MARKUP_H2, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h3", MARKUP_H3, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h4", MARKUP_H4, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h5", MARKUP_H5, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h6", MARKUP_H6, MUTYPE_BLOCK, AMSK_ALIGN },
| | | | | | | | | | | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
AMSK_COLOR|AMSK_FACE|AMSK_SIZE },
{ "h1", MARKUP_H1, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h2", MARKUP_H2, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h3", MARKUP_H3, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h4", MARKUP_H4, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h5", MARKUP_H5, MUTYPE_BLOCK, AMSK_ALIGN },
{ "h6", MARKUP_H6, MUTYPE_BLOCK, AMSK_ALIGN },
{ "hr", MARKUP_HR, MUTYPE_SINGLE,
AMSK_ALIGN|AMSK_COLOR|AMSK_SIZE|AMSK_WIDTH },
{ "i", MARKUP_I, MUTYPE_FONT, 0 },
{ "img", MARKUP_IMG, MUTYPE_SINGLE,
AMSK_ALIGN|AMSK_ALT|AMSK_BORDER|AMSK_HEIGHT|
AMSK_HSPACE|AMSK_SRC|AMSK_VSPACE|AMSK_WIDTH },
{ "kbd", MARKUP_KBD, MUTYPE_FONT, 0 },
{ "li", MARKUP_LI, MUTYPE_LI,
AMSK_TYPE|AMSK_VALUE },
{ "nobr", MARKUP_NOBR, MUTYPE_FONT, 0 },
{ "nowiki", MARKUP_NOWIKI, MUTYPE_SPECIAL, 0 },
{ "ol", MARKUP_OL, MUTYPE_LIST,
AMSK_START|AMSK_TYPE|AMSK_COMPACT },
{ "p", MARKUP_P, MUTYPE_BLOCK, AMSK_ALIGN },
{ "pre", MARKUP_PRE, MUTYPE_BLOCK, 0 },
{ "s", MARKUP_S, MUTYPE_FONT, 0 },
{ "samp", MARKUP_SAMP, MUTYPE_FONT, 0 },
{ "small", MARKUP_SMALL, MUTYPE_FONT, 0 },
{ "strike", MARKUP_STRIKE, MUTYPE_FONT, 0 },
{ "strong", MARKUP_STRONG, MUTYPE_FONT, 0 },
{ "sub", MARKUP_SUB, MUTYPE_FONT, 0 },
{ "sup", MARKUP_SUP, MUTYPE_FONT, 0 },
{ "table", MARKUP_TABLE, MUTYPE_TABLE,
AMSK_ALIGN|AMSK_BGCOLOR|AMSK_BORDER|AMSK_CELLPADDING|
AMSK_CELLSPACING|AMSK_HSPACE|AMSK_VSPACE },
{ "td", MARKUP_TD, MUTYPE_TD,
AMSK_ALIGN|AMSK_BGCOLOR|AMSK_COLSPAN|
AMSK_ROWSPAN|AMSK_VALIGN },
{ "th", MARKUP_TH, MUTYPE_TD,
AMSK_ALIGN|AMSK_BGCOLOR|AMSK_COLSPAN|
AMSK_ROWSPAN|AMSK_VALIGN },
{ "tr", MARKUP_TR, MUTYPE_TR,
AMSK_ALIGN|AMSK_BGCOLOR||AMSK_VALIGN },
{ "tt", MARKUP_TT, MUTYPE_FONT, 0 },
{ "u", MARKUP_U, MUTYPE_FONT, 0 },
{ "ul", MARKUP_UL, MUTYPE_LIST,
AMSK_TYPE|AMSK_COMPACT },
{ "var", MARKUP_VAR, MUTYPE_FONT, 0 },
{ "verbatim", MARKUP_VERBATIM, MUTYPE_SPECIAL, AMSK_ID|AMSK_TYPE },
};
/*
** Use binary search to locate a tag in the aMarkup[] table.
*/
static int findTag(const char *z){
int i, c, first, last;
|
| ︙ | ︙ | |||
434 435 436 437 438 439 440 |
int n = 0;
int c;
while( (c = z[0])!=0 && c!='<' && c!='&' &&
(useWiki==0 || (c!='[' && c!='\n')) ){
n++;
z++;
}
| | | 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
int n = 0;
int c;
while( (c = z[0])!=0 && c!='<' && c!='&' &&
(useWiki==0 || (c!='[' && c!='\n')) ){
n++;
z++;
}
return n;
}
/*
** Return true if z[] begins with an HTML character element.
*/
static int isElement(const char *z){
int i;
|
| ︙ | ︙ | |||
548 549 550 551 552 553 554 |
}else{
return 0;
}
}
/*
** Get the next wiki token.
| | | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
}else{
return 0;
}
}
/*
** Get the next wiki token.
**
** z points to the start of a token. Return the number of
** characters in that token. Write the token type into *pTokenType.
*/
static int nextWikiToken(const char *z, Renderer *p, int *pTokenType){
int n;
if( z[0]=='<' ){
n = markupLength(z);
|
| ︙ | ︙ | |||
614 615 616 617 618 619 620 | } *pTokenType = TOKEN_TEXT; return 1 + textLength(z+1, p->state & ALLOW_WIKI); } /* ** Parse only Wiki links, return everything else as TOKEN_RAW. | | | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
}
*pTokenType = TOKEN_TEXT;
return 1 + textLength(z+1, p->state & ALLOW_WIKI);
}
/*
** Parse only Wiki links, return everything else as TOKEN_RAW.
**
** z points to the start of a token. Return the number of
** characters in that token. Write the token type into *pTokenType.
*/
static int nextRawToken(const char *z, Renderer *p, int *pTokenType){
int n;
if( z[0]=='[' && (n = linkLength(z))>0 ){
|
| ︙ | ︙ | |||
650 651 652 653 654 655 656 | } aAttr[10]; }; /* ** z[] is an HTML markup element - something that begins with '<'. ** Parse this element into the p structure. ** | | | | | 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 |
} aAttr[10];
};
/*
** z[] is an HTML markup element - something that begins with '<'.
** Parse this element into the p structure.
**
** The content of z[] might be modified by converting characters
** to lowercase and by inserting some "\000" characters.
*/
static void parseMarkup(ParsedMarkup *p, char *z){
int i, j, c;
int iACode;
char *zValue;
int seen = 0;
char zTag[100];
if( z[1]=='/' ){
p->endTag = 1;
i = 2;
}else{
p->endTag = 0;
i = 1;
}
j = 0;
while( isalnum(z[i]) ){
if( j<sizeof(zTag)-1 ) zTag[j++] = tolower(z[i]);
i++;
}
zTag[j] = 0;
p->iCode = findTag(zTag);
p->iType = aMarkup[p->iCode].iType;
p->nAttr = 0;
while( isspace(z[i]) ){ i++; }
while( p->nAttr<8 && isalpha(z[i]) ){
int attrOk; /* True to preserver attribute. False to ignore it */
j = 0;
while( isalnum(z[i]) ){
if( j<sizeof(zTag)-1 ) zTag[j++] = tolower(z[i]);
i++;
}
zTag[j] = 0;
p->aAttr[p->nAttr].iACode = iACode = findAttr(zTag);
attrOk = iACode!=0 && (seen & aAttribute[iACode].iMask)==0;
while( isspace(z[i]) ){ z++; }
|
| ︙ | ︙ | |||
823 824 825 826 827 828 829 |
while( p->nStack>i ){
popStack(p);
}
}
/*
** Attempt to find a find a tag of type iTag with id zId. Return -1
| | | 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 |
while( p->nStack>i ){
popStack(p);
}
}
/*
** Attempt to find a find a tag of type iTag with id zId. Return -1
** if not found. If found, return its stack level.
*/
static int findTagWithId(Renderer *p, int iTag, const char *zId){
int i;
assert( zId!=0 );
for(i=p->nStack-1; i>=0; i--){
if( p->aStack[i].iCode!=iTag ) continue;
if( p->aStack[i].zId==0 ) continue;
|
| ︙ | ︙ | |||
913 914 915 916 917 918 919 |
n = strlen(zTarget);
memcpy(zLower, zTarget, n+1);
canonical16(zLower, n+1);
memcpy(zUpper, zLower, n+1);
zUpper[n-1]++;
if( once ){
const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
| | | 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 |
n = strlen(zTarget);
memcpy(zLower, zTarget, n+1);
canonical16(zLower, n+1);
memcpy(zUpper, zLower, n+1);
zUpper[n-1]++;
if( once ){
const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
db_static_prepare(&q,
"SELECT %s FROM ticket "
" WHERE tkt_uuid>=:lwr AND tkt_uuid<:upr",
zClosedExpr
);
once = 0;
}
db_bind_text(&q, ":lwr", zLower);
|
| ︙ | ︙ | |||
956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 |
** [./relpath]
**
** [WikiPageName]
**
** [0123456789abcdef]
**
** [#fragment]
*/
static void openHyperlink(
Renderer *p, /* Rendering context */
const char *zTarget, /* Hyperlink traget; text within [...] */
char *zClose, /* Write hyperlink closing text here */
int nClose /* Bytes available in zClose[] */
){
const char *zTerm = "</a>";
assert( nClose>=20 );
| > > | | | 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 |
** [./relpath]
**
** [WikiPageName]
**
** [0123456789abcdef]
**
** [#fragment]
**
** [2010-02-27 07:13]
*/
static void openHyperlink(
Renderer *p, /* Rendering context */
const char *zTarget, /* Hyperlink traget; text within [...] */
char *zClose, /* Write hyperlink closing text here */
int nClose /* Bytes available in zClose[] */
){
const char *zTerm = "</a>";
assert( nClose>=20 );
if( strncmp(zTarget, "http:", 5)==0
|| strncmp(zTarget, "https:", 6)==0
|| strncmp(zTarget, "ftp:", 4)==0
|| strncmp(zTarget, "mailto:", 7)==0
){
blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
/* zTerm = "⟾</a>"; // doesn't work on windows */
}else if( zTarget[0]=='/' ){
if( 1 /* g.okHistory */ ){
blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zBaseURL, zTarget);
|
| ︙ | ︙ | |||
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 |
}else{
zTerm = "";
}
}
}else if( g.okHistory ){
blob_appendf(p->pOut, "<a href=\"%s/info/%s\">", g.zBaseURL, zTarget);
}
}else if( wiki_name_is_wellformed((const unsigned char *)zTarget) ){
blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zBaseURL, zTarget);
}else{
blob_appendf(p->pOut, "[bad-link: %h]", zTarget);
zTerm = "";
}
assert( strlen(zTerm)<nClose );
| > > > | 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 |
}else{
zTerm = "";
}
}
}else if( g.okHistory ){
blob_appendf(p->pOut, "<a href=\"%s/info/%s\">", g.zBaseURL, zTarget);
}
}else if( strlen(zTarget)>=10 && isdigit(zTarget[0]) && zTarget[4]=='-'
&& db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zBaseURL, zTarget);
}else if( wiki_name_is_wellformed((const unsigned char *)zTarget) ){
blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zBaseURL, zTarget);
}else{
blob_appendf(p->pOut, "[bad-link: %h]", zTarget);
zTerm = "";
}
assert( strlen(zTerm)<nClose );
|
| ︙ | ︙ | |||
1211 1212 1213 1214 1215 1216 1217 |
case TOKEN_MARKUP: {
const char *zId;
int iDiv;
parseMarkup(&markup, z);
/* Markup of the form </div id=ID> where there is a matching
** ID somewhere on the stack. Exit the verbatim if were are in
| | | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 |
case TOKEN_MARKUP: {
const char *zId;
int iDiv;
parseMarkup(&markup, z);
/* Markup of the form </div id=ID> where there is a matching
** ID somewhere on the stack. Exit the verbatim if were are in
** it. Pop the stack up to the matching <div>. Discard the
** </div>
*/
if( markup.iCode==MARKUP_DIV && markup.endTag &&
(zId = markupId(&markup))!=0 &&
(iDiv = findTagWithId(p, MARKUP_DIV, zId))>=0
){
if( p->inVerbatim ){
|
| ︙ | ︙ | |||
1235 1236 1237 1238 1239 1240 1241 |
}
assert( p->nStack==iDiv+1 );
p->nStack--;
}else
/* If within <verbatim id=ID> ignore everything other than
** </verbatim id=ID> and the </dev id=ID2> above.
| | | 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 |
}
assert( p->nStack==iDiv+1 );
p->nStack--;
}else
/* If within <verbatim id=ID> ignore everything other than
** </verbatim id=ID> and the </dev id=ID2> above.
*/
if( p->inVerbatim ){
if( endVerbatim(p, &markup) ){
p->inVerbatim = 0;
p->state = p->preVerbState;
blob_append(p->pOut, "</pre>", 6);
}else{
unparseMarkup(&markup);
|
| ︙ | ︙ | |||
1293 1294 1295 1296 1297 1298 1299 |
if( markup.iCode==MARKUP_DIV ){
pushStackWithId(p, markup.iCode, markupId(&markup),
(p->state & ALLOW_WIKI)!=0);
}else
/* Enter <verbatim> processing. With verbatim enabled, all other
** markup other than the corresponding end-tag with the same ID is
| | | < < | < > > > > > > > > > > | | 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 |
if( markup.iCode==MARKUP_DIV ){
pushStackWithId(p, markup.iCode, markupId(&markup),
(p->state & ALLOW_WIKI)!=0);
}else
/* Enter <verbatim> processing. With verbatim enabled, all other
** markup other than the corresponding end-tag with the same ID is
** ignored.
*/
if( markup.iCode==MARKUP_VERBATIM ){
int vAttrIdx, vAttrDidAppend=0;
p->zVerbatimId = 0;
p->inVerbatim = 1;
p->preVerbState = p->state;
p->state &= ~ALLOW_WIKI;
for (vAttrIdx = 0; vAttrIdx < markup.nAttr; vAttrIdx++){
if( markup.aAttr[vAttrIdx].iACode == ATTR_ID ){
p->zVerbatimId = markup.aAttr[0].zValue;
}else if( markup.aAttr[vAttrIdx].iACode == ATTR_TYPE ){
blob_appendf(p->pOut, "<pre name='code' class='%s'>",
markup.aAttr[vAttrIdx].zValue);
vAttrDidAppend=1;
}
}
if( !vAttrDidAppend )
blob_append(p->pOut, "<pre class='verbatim'>",-1);
p->wantAutoParagraph = 0;
}else
if( markup.iType==MUTYPE_LI ){
if( backupToType(p, MUTYPE_LIST)==0 ){
pushStack(p, MARKUP_UL);
blob_append(p->pOut, "<ul>", 4);
}
|
| ︙ | ︙ | |||
1366 1367 1368 1369 1370 1371 1372 |
** initialized. The output is merely appended to pOut.
** If pOut is NULL, then the output is appended to the CGI
** reply.
*/
void wiki_convert(Blob *pIn, Blob *pOut, int flags){
char *z;
Renderer renderer;
| | | 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 |
** initialized. The output is merely appended to pOut.
** If pOut is NULL, then the output is appended to the CGI
** reply.
*/
void wiki_convert(Blob *pIn, Blob *pOut, int flags){
char *z;
Renderer renderer;
memset(&renderer, 0, sizeof(renderer));
renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH;
if( flags & WIKI_NOBLOCK ){
renderer.state |= INLINE_MARKUP_ONLY;
}
if( flags & WIKI_INLINE ){
renderer.wantAutoParagraph = 0;
|
| ︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 | blob_write_to_file(&out, "-"); } /* ** Search for a <title>...</title> at the beginning of a wiki page. ** Return true (nonzero) if a title is found. Return zero if there is ** not title. | | | 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 |
blob_write_to_file(&out, "-");
}
/*
** Search for a <title>...</title> at the beginning of a wiki page.
** Return true (nonzero) if a title is found. Return zero if there is
** not title.
**
** If a title is found, initialize the pTitle blob to be the content
** of the title and initialize pTail to be the text that follows the
** title.
*/
int wiki_find_title(Blob *pIn, Blob *pTitle, Blob *pTail){
char *z;
int i;
|
| ︙ | ︙ |