1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-
+
-
+
|
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.7.4. By combining all the individual C code files into this
** version 3.7.3. 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% or more are commonly seen when SQLite is compiled as a single
** 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
** programs, you need this file and the "sqlite3.h" header file that defines
** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy embedded within
** the text of this file. Search for "Begin file sqlite3.h" to find the start
|
︙ | | |
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
|
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
|
-
-
-
+
+
+
|
** 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.7.4"
#define SQLITE_VERSION_NUMBER 3007004
#define SQLITE_SOURCE_ID "2010-11-16 23:10:26 fd5b2f23dd5111d2f0934dd828bae36b755024c1"
#define SQLITE_VERSION "3.7.3"
#define SQLITE_VERSION_NUMBER 3007003
#define SQLITE_SOURCE_ID "2010-10-07 13:29:13 e55ada89246d4cc5f476891c70572dc7c1c3643e"
/*
** 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
|
︙ | | |
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
|
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
**
** ^This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
*/
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
**
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
** the [prepared statement] X is guaranteed to leave the database file
** unmodified. ^If the sqlite3_stmt_readonly(X) interface returns false (zero)
** then evaluating the statement might change the database file, but this
** is not guaranteed as the write operation might be conditional and the
** condition might not be met. ^If X is a NULL pointer then
** sqlite3_stmt_readonly(X) returns true. If X is a non-NULL pointer but
** is not a pointer to a valid, unfinalized prepared statement, then the
** behavior is undefined and probably harmful.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Dynamically Typed Value Object
** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
**
** SQLite uses the sqlite3_value object to represent all values
** that can be stored in a database table. SQLite uses dynamic typing
** for the values it stores. ^Values stored in sqlite3_value objects
|
︙ | | |
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
|
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
|
-
+
-
-
-
|
** number of bytes in the parameter. To be clear: the value is the
** number of <u>bytes</u> in the value, not the number of characters.)^
** ^If the fourth parameter is negative, the length of the string is
** the number of bytes up to the first zero terminator.
**
** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it. ^The destructor is called
** string after SQLite has finished with it. ^If the fifth argument is
** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
**
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
|
︙ | | |
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
|
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
|
-
+
-
-
-
+
+
-
-
-
-
-
+
+
+
|
** aggregate. ^A scalar SQL function requires an implementation of the xFunc
** callback only; NULL pointers must be passed as the xStep and xFinal
** parameters. ^An aggregate SQL function requires an implementation of xStep
** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing
** SQL function or aggregate, pass NULL poiners for all three function
** callbacks.
**
** ^(If the tenth parameter to sqlite3_create_function_v2() is not NULL,
** ^If the tenth parameter to sqlite3_create_function_v2() is not NULL,
** then it is destructor for the application data pointer.
** The destructor is invoked when the function is deleted, either by being
** overloaded or when the database connection closes.)^
** then it is invoked when the function is deleted, either by being
** overloaded or when the database connection closes.
** ^The destructor is also invoked if the call to
** sqlite3_create_function_v2() fails.
** ^When the destructor callback of the tenth parameter is invoked, it
** is passed a single argument which is a copy of the application data
** pointer which was the fifth parameter to sqlite3_create_function_v2().
** ^When the destructure callback of the tenth parameter is invoked, it
** is passed a single argument which is a copy of the pointer which was
** the fifth parameter to sqlite3_create_function_v2().
**
** ^It is permitted to register multiple implementations of the same
** functions with the same name but with either differing numbers of
** arguments or differing preferred text encodings. ^SQLite will use
** the implementation that most closely matches the way in which the
** SQL function is used. ^A function implementation with a non-negative
** nArg parameter is a better match than a function implementation with
|
︙ | | |
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
|
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
|
-
-
-
-
-
-
-
-
-
|
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
** with the addition that the xDestroy callback is invoked on pArg when
** the collating function is deleted.
** ^Collating functions are deleted when they are overridden by later
** calls to the collation creation functions or when the
** [database connection] is closed using [sqlite3_close()].
**
** ^The xDestroy callback is <u>not</u> called if the
** sqlite3_create_collation_v2() function fails. Applications that invoke
** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
** check the return code and dispose of the application data pointer
** themselves rather than expecting SQLite to deal with it for them.
** This is different from every other SQLite interface. The inconsistency
** is unfortunate but cannot be changed without breaking backwards
** compatibility.
**
** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
*/
SQLITE_API int sqlite3_create_collation(
sqlite3*,
const char *zName,
int eTextRep,
void *pArg,
|
︙ | | |
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
|
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
|
-
+
-
-
|
** parameter is an arbitrary client data pointer that is passed through
** into the [xCreate] and [xConnect] methods of the virtual table module
** when a new virtual table is be being created or reinitialized.
**
** ^The sqlite3_create_module_v2() interface has a fifth parameter which
** is a pointer to a destructor for the pClientData. ^SQLite will
** invoke the destructor function (if it is not NULL) when SQLite
** no longer needs the pClientData pointer. ^The destructor will also
** no longer needs the pClientData pointer. ^The sqlite3_create_module()
** be invoked if the call to sqlite3_create_module_v2() fails.
** ^The sqlite3_create_module()
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
*/
SQLITE_API int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
|
︙ | | |
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
|
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
const char *zTable,
const char *zColumn,
sqlite3_int64 iRow,
int flags,
sqlite3_blob **ppBlob
);
/*
** CAPI3REF: Move a BLOB Handle to a New Row
**
** ^This function is used to move an existing blob handle so that it points
** to a different row of the same database table. ^The new row is identified
** by the rowid value passed as the second argument. Only the row can be
** changed. ^The database, table and column on which the blob handle is open
** remain the same. Moving an existing blob handle to a new row can be
** faster than closing the existing handle and opening a new one.
**
** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
** it must exist and there must be either a blob or text value stored in
** the nominated column.)^ ^If the new row is not present in the table, or if
** it does not contain a blob or text value, or if another error occurs, an
** SQLite error code is returned and the blob handle is considered aborted.
** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or
** [sqlite3_blob_reopen()] on an aborted blob handle immediately return
** SQLITE_ABORT.
**
** ^This function sets the database handle error code and message.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
/*
** CAPI3REF: Close A BLOB Handle
**
** ^Closes an open [BLOB handle].
**
** ^Closing a BLOB shall cause the current transaction to commit
** if there are no other BLOBs, no pending prepared statements, and the
|
︙ | | |
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
|
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
|
-
-
-
|
u8 notIndexed; /* True if there is a NOT INDEXED clause */
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
char *zIndex; /* Identifier from "INDEXED BY <zIndex>" clause */
Index *pIndex; /* Index structure corresponding to zIndex, if any */
#ifndef SQLITE_OMIT_EXPLAIN
int iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
#endif
} a[1]; /* One entry for each identifier on the list */
};
/*
** Permitted values of the SrcList.a.jointype field
*/
#define JT_INNER 0x0001 /* Any kind of inner or cross join */
|
︙ | | |
9978
9979
9980
9981
9982
9983
9984
9985
9986
9987
9988
9989
9990
9991
9992
|
9920
9921
9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
|
-
|
** pTerm is only used when wsFlags&WHERE_MULTI_OR is true. And pVtabIdx
** is only used when wsFlags&WHERE_VIRTUALTABLE is true. It is never the
** case that more than one of these conditions is true.
*/
struct WherePlan {
u32 wsFlags; /* WHERE_* flags that describe the strategy */
u32 nEq; /* Number of == constraints */
double nRow; /* Estimated number of rows (for EQP) */
union {
Index *pIdx; /* Index when WHERE_INDEXED is true */
struct WhereTerm *pTerm; /* WHERE clause term for OR-search */
sqlite3_index_info *pVtabIdx; /* Virtual table index to use */
} u;
};
|
︙ | | |
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
|
10004
10005
10006
10007
10008
10009
10010
10011
10012
10013
10014
10015
10016
10017
|
-
|
SrcList *pTabList; /* List of tables in the join */
int iTop; /* The very beginning of the WHERE loop */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
int nLevel; /* Number of nested loop */
struct WhereClause *pWC; /* Decomposition of the WHERE clause */
double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
double nRowOut; /* Estimated number of output rows */
WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
/*
** A NameContext defines a context in which to resolve table and column
** names. The context consists of a list of tables (the pSrcList) field and
** a list of named expression (pEList). The named expression list may
|
︙ | | |
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153
|
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
|
-
|
Select *pPrior; /* Prior select in a compound select statement */
Select *pNext; /* Next select to the left in a compound */
Select *pRightmost; /* Right-most select in a compound select statement */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
Expr *pOffset; /* OFFSET expression. NULL means not used. */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
double nSelectRow; /* Estimated number of result rows */
};
/*
** Allowed values for Select.selFlags. The "SF" prefix stands for
** "Select Flag".
*/
#define SF_Distinct 0x0001 /* Output should be DISTINCT */
|
︙ | | |
10335
10336
10337
10338
10339
10340
10341
10342
10343
10344
10345
10346
10347
10348
10349
10350
10351
10352
10353
|
10274
10275
10276
10277
10278
10279
10280
10281
10282
10283
10284
10285
10286
10287
|
-
-
-
-
-
|
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
int nVtabLock; /* Number of virtual tables to lock */
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
int nHeight; /* Expression tree height of current sub-select */
Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
#ifndef SQLITE_OMIT_EXPLAIN
int iSelectId;
int iNextSelectId;
#endif
};
#ifdef SQLITE_OMIT_VIRTUALTABLE
#define IN_DECLARE_VTAB 0
#else
#define IN_DECLARE_VTAB (pParse->declareVtab)
#endif
|
︙ | | |
27375
27376
27377
27378
27379
27380
27381
27382
27383
27384
27385
27386
27387
27388
27389
27390
27391
27392
27393
27394
27395
27396
27397
27398
27399
27400
27401
27402
27403
27404
27405
27406
|
27309
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320
27321
27322
27323
27324
27325
|
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
|
){
int rc = SQLITE_OK; /* Return Code */
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
char zDb[MAX_PATHNAME+1]; /* Database file path */
int nDb; /* Number of valid bytes in zDb */
struct stat sStat; /* Output of stat() on database file */
/* zPath is a path to a WAL or journal file. The following block derives
** the path to the associated database file from zPath. This block handles
** the following naming conventions:
**
** "<path to db>-journal"
** "<path to db>-wal"
** "<path to db>-journal-NNNN"
** "<path to db>-wal-NNNN"
**
** where NNNN is a 4 digit decimal number. The NNNN naming schemes are
** used by the test_multiplex.c module.
*/
nDb = sqlite3Strlen30(zPath) - 1;
nDb = sqlite3Strlen30(zPath) - ((flags & SQLITE_OPEN_WAL) ? 4 : 8);
while( nDb>0 && zPath[nDb]!='l' ) nDb--;
nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7);
memcpy(zDb, zPath, nDb);
zDb[nDb] = '\0';
if( 0==stat(zDb, &sStat) ){
*pMode = sStat.st_mode & 0777;
}else{
rc = SQLITE_IOERR_FSTAT;
}
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
*pMode = 0600;
|
︙ | | |
34598
34599
34600
34601
34602
34603
34604
34605
34606
34607
34608
34609
34610
34611
34612
34613
34614
34615
34616
34617
34618
34619
34620
34621
34622
34623
|
34517
34518
34519
34520
34521
34522
34523
34524
34525
34526
34527
34528
34529
34530
34531
34532
34533
34534
34535
34536
34537
34538
34539
34540
34541
|
-
-
+
|
# define sqlite3WalUndo(x,y,z) 0
# define sqlite3WalSavepoint(y,z)
# define sqlite3WalSavepointUndo(y,z) 0
# define sqlite3WalFrames(u,v,w,x,y,z) 0
# define sqlite3WalCheckpoint(u,v,w,x) 0
# define sqlite3WalCallback(z) 0
# define sqlite3WalExclusiveMode(y,z) 0
# define sqlite3WalHeapMemory(z) 0
#else
#define WAL_SAVEPOINT_NDATA 4
/* Connection to a write-ahead log (WAL) file.
** There is one object of this type for each pager.
*/
typedef struct Wal Wal;
/* Open and close a connection to a write-ahead log. */
SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, Wal**);
SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
/* Used by readers to open (lock) and close (unlock) a snapshot. A
** snapshot is like a read-transaction. It is the state of the database
** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
** preserves the current state even if the other threads or processes
** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
|
︙ | | |
34666
34667
34668
34669
34670
34671
34672
34673
34674
34675
34676
34677
34678
34679
34680
34681
34682
34683
34684
34685
|
34584
34585
34586
34587
34588
34589
34590
34591
34592
34593
34594
34595
34596
34597
|
-
-
-
-
-
-
|
SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal);
/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
** by the pager layer on the database file.
*/
SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
/* Return true if the argument is non-NULL and the WAL module is using
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
** WAL module is using shared-memory, return false.
*/
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* _WAL_H_ */
/************** End of wal.h *************************************************/
/************** Continuing where we left off in pager.c **********************/
|
︙ | | |
35582
35583
35584
35585
35586
35587
35588
35589
35590
35591
35592
35593
35594
35595
35596
35597
35598
|
35494
35495
35496
35497
35498
35499
35500
35501
35502
35503
35504
35505
35506
35507
35508
|
-
-
|
assert( pPager->errCode!=SQLITE_OK );
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
break;
}
return 1;
}
#endif /* ifndef NDEBUG */
#ifdef SQLITE_DEBUG
/*
** Return a pointer to a human readable string in a static buffer
** containing the state of the Pager object passed as an argument. This
** is intended to be used within debuggers. For example, as an alternative
** to "print *pPager" in gdb:
**
** (gdb) printf "%s", print_pager_state(pPager)
|
︙ | | |
35708
35709
35710
35711
35712
35713
35714
35715
35716
35717
35718
35719
35720
35721
35722
|
35618
35619
35620
35621
35622
35623
35624
35625
35626
35627
35628
35629
35630
35631
35632
|
-
+
|
** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
** called, do not modify it. See the comment above the #define of
** UNKNOWN_LOCK for an explanation of this.
*/
static int pagerUnlockDb(Pager *pPager, int eLock){
int rc = SQLITE_OK;
assert( !pPager->exclusiveMode || pPager->eLock==eLock );
assert( !pPager->exclusiveMode );
assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
if( isOpen(pPager->fd) ){
assert( pPager->eLock>=eLock );
rc = sqlite3OsUnlock(pPager->fd, eLock);
if( pPager->eLock!=UNKNOWN_LOCK ){
pPager->eLock = (u8)eLock;
|
︙ | | |
39182
39183
39184
39185
39186
39187
39188
39189
39190
39191
39192
39193
39194
39195
39196
|
39092
39093
39094
39095
39096
39097
39098
39099
39100
39101
39102
39103
39104
39105
39106
|
-
+
|
*/
rc = pagerPagecount(pPager, &nPage);
if( rc==SQLITE_OK ){
if( nPage==0 ){
sqlite3BeginBenignMalloc();
if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
sqlite3OsDelete(pVfs, pPager->zJournal, 0);
if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
pagerUnlockDb(pPager, SHARED_LOCK);
}
sqlite3EndBenignMalloc();
}else{
/* The journal file exists and no other connection has a reserved
** or greater lock on the database file. Now check that there is
** at least one non-zero bytes at the start of the journal file.
** If there is, then we consider this journal to be hot. If not,
|
︙ | | |
41008
41009
41010
41011
41012
41013
41014
41015
41016
41017
41018
41019
41020
41021
41022
41023
|
40918
40919
40920
40921
40922
40923
40924
40925
40926
40927
40928
40929
40930
40931
40932
|
-
-
+
|
*/
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
assert( eMode==PAGER_LOCKINGMODE_QUERY
|| eMode==PAGER_LOCKINGMODE_NORMAL
|| eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
assert( PAGER_LOCKINGMODE_QUERY<0 );
assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
if( eMode>=0 && !pPager->tempFile ){
pPager->exclusiveMode = (u8)eMode;
}
return (int)pPager->exclusiveMode;
}
/*
** Set the journal-mode for this pager. Parameter eMode must be one of:
|
︙ | | |
41196
41197
41198
41199
41200
41201
41202
41203
41204
41205
41206
41207
41208
41209
41210
41211
41212
41213
41214
41215
41216
41217
41218
41219
41220
41221
41222
41223
41224
41225
41226
41227
41228
41229
41230
41231
41232
41233
41234
41235
41236
41237
41238
41239
41240
41241
41242
41243
41244
41245
41246
41247
41248
41249
41250
41251
41252
41253
41254
41255
41256
41257
41258
41259
41260
41261
41262
41263
|
41105
41106
41107
41108
41109
41110
41111
41112
41113
41114
41115
41116
41117
41118
41119
41120
|
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
/*
** Return true if the underlying VFS for the given pager supports the
** primitives necessary for write-ahead logging.
*/
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
return pMethods->iVersion>=2 && pMethods->xShmMap!=0;
}
/*
** Attempt to take an exclusive lock on the database file. If a PENDING lock
** is obtained instead, immediately release it.
*/
static int pagerExclusiveLock(Pager *pPager){
int rc; /* Return code */
assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){
/* If the attempt to grab the pending lock failed, release the
** exclusive lock that may have been obtained instead. */
pagerUnlockDb(pPager, SHARED_LOCK);
}
return rc;
}
/*
** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
** exclusive-locking mode when this function is called, take an EXCLUSIVE
** lock on the database file and use heap-memory to store the wal-index
** in. Otherwise, use the normal shared-memory.
*/
static int pagerOpenWal(Pager *pPager){
int rc = SQLITE_OK;
assert( pPager->pWal==0 && pPager->tempFile==0 );
assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK || pPager->noReadlock);
/* If the pager is already in exclusive-mode, the WAL module will use
** heap-memory for the wal-index instead of the VFS shared-memory
** implementation. Take the exclusive lock now, before opening the WAL
** file, to make sure this is safe.
*/
if( pPager->exclusiveMode ){
rc = pagerExclusiveLock(pPager);
}
/* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), return an error code.
*/
if( rc==SQLITE_OK ){
rc = sqlite3WalOpen(pPager->pVfs,
pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
);
}
return rc;
}
/*
** The caller must be holding a SHARED lock on the database file to call
** this function.
**
** If the pager passed as the first argument is open on a real database
** file (not a temp file or an in-memory database), and the WAL file
|
︙ | | |
41284
41285
41286
41287
41288
41289
41290
41291
41292
41293
41294
41295
41296
41297
41298
|
41141
41142
41143
41144
41145
41146
41147
41148
41149
41150
41151
41152
41153
41154
41155
41156
41157
41158
41159
|
+
+
+
+
-
+
|
if( !pPager->tempFile && !pPager->pWal ){
if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
/* Close any rollback journal previously open */
sqlite3OsClose(pPager->jfd);
/* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), unlock the database file and
** return an error code.
*/
rc = pagerOpenWal(pPager);
rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal);
if( rc==SQLITE_OK ){
pPager->journalMode = PAGER_JOURNALMODE_WAL;
pPager->eState = PAGER_OPEN;
}
}else{
*pbOpen = 1;
}
|
︙ | | |
41323
41324
41325
41326
41327
41328
41329
41330
41331
41332
41333
41334
41335
41336
41337
41338
41339
41340
41341
41342
41343
41344
41345
41346
41347
41348
41349
41350
41351
|
41184
41185
41186
41187
41188
41189
41190
41191
41192
41193
41194
41195
41196
41197
41198
41199
41200
41201
41202
41203
41204
41205
41206
41207
41208
41209
41210
41211
41212
41213
41214
41215
41216
41217
|
+
-
+
-
+
-
-
+
+
+
+
+
+
|
rc = pagerLockDb(pPager, SHARED_LOCK);
if( rc==SQLITE_OK ){
rc = sqlite3OsAccess(
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
);
}
if( rc==SQLITE_OK && logexists ){
rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
rc = pagerOpenWal(pPager);
pPager->zWal, &pPager->pWal);
}
}
/* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
** the database file, the log and log-summary files will be deleted.
*/
if( rc==SQLITE_OK && pPager->pWal ){
rc = pagerExclusiveLock(pPager);
rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
if( rc==SQLITE_OK ){
rc = sqlite3WalClose(pPager->pWal,
(pPager->noSync ? 0 : pPager->sync_flags),
pPager->pageSize, (u8*)pPager->pTmpSpace
(pPager->noSync ? 0 : pPager->sync_flags),
pPager->pageSize, (u8*)pPager->pTmpSpace
);
pPager->pWal = 0;
}else{
/* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock
** that we did get back to SHARED. */
pagerUnlockDb(pPager, SQLITE_LOCK_SHARED);
}
}
return rc;
}
#ifdef SQLITE_HAS_CODEC
/*
|
︙ | | |
41793
41794
41795
41796
41797
41798
41799
41800
41801
41802
41803
41804
41805
41806
41807
41808
41809
41810
41811
41812
41813
|
41659
41660
41661
41662
41663
41664
41665
41666
41667
41668
41669
41670
41671
41672
|
-
-
-
-
-
-
-
|
const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
#ifdef SQLITE_DEBUG
u8 lockError; /* True if a locking error has occurred */
#endif
};
/*
** Candidate values for Wal.exclusiveMode.
*/
#define WAL_NORMAL_MODE 0
#define WAL_EXCLUSIVE_MODE 1
#define WAL_HEAPMEMORY_MODE 2
/*
** Each page of the wal-index mapping contains a hash-table made up of
** an array of HASHTABLE_NSLOT elements of the following type.
*/
typedef u16 ht_slot;
/*
|
︙ | | |
41886
41887
41888
41889
41890
41891
41892
41893
41894
41895
41896
41897
41898
41899
41900
41901
41902
41903
41904
41905
41906
41907
|
41745
41746
41747
41748
41749
41750
41751
41752
41753
41754
41755
41756
41757
41758
41759
41760
41761
|
-
-
-
-
-
-
-
+
+
+
-
|
sizeof(u32*)*(iPage+1-pWal->nWiData));
pWal->apWiData = apNew;
pWal->nWiData = iPage+1;
}
/* Request a pointer to the required page from the VFS */
if( pWal->apWiData[iPage]==0 ){
if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
}else{
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
}
}
*ppPage = pWal->apWiData[iPage];
assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
return rc;
}
|
︙ | | |
41976
41977
41978
41979
41980
41981
41982
41983
41984
41985
41986
41987
41988
41989
41990
41991
41992
41993
41994
41995
41996
41997
41998
41999
42000
42001
42002
42003
42004
42005
42006
42007
42008
42009
42010
|
41830
41831
41832
41833
41834
41835
41836
41837
41838
41839
41840
41841
41842
41843
41844
41845
41846
41847
41848
41849
41850
41851
41852
41853
41854
41855
41856
41857
41858
|
-
-
-
-
-
-
-
+
|
}while( aData<aEnd );
}
aOut[0] = s1;
aOut[1] = s2;
}
static void walShmBarrier(Wal *pWal){
if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
sqlite3OsShmBarrier(pWal->pDbFd);
}
}
/*
** Write the header information in pWal->hdr into the wal-index.
**
** The checksum on pWal->hdr is updated before it is written.
*/
static void walIndexWriteHdr(Wal *pWal){
volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
const int nCksum = offsetof(WalIndexHdr, aCksum);
assert( pWal->writeLock );
pWal->hdr.isInit = 1;
pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr));
walShmBarrier(pWal);
sqlite3OsShmBarrier(pWal->pDbFd);
memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr));
}
/*
** This function encodes a single frame header and writes it to a buffer
** supplied by the caller. A frame-header is made up of a series of
** 4-byte big-endian integers, as follows:
|
︙ | | |
42568
42569
42570
42571
42572
42573
42574
42575
42576
42577
42578
42579
42580
42581
42582
42583
42584
42585
42586
42587
42588
42589
42590
|
42416
42417
42418
42419
42420
42421
42422
42423
42424
42425
42426
42427
42428
42429
42430
|
-
-
-
-
-
-
-
-
+
-
|
return rc;
}
/*
** Close an open wal-index.
*/
static void walIndexClose(Wal *pWal, int isDelete){
if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
int i;
for(i=0; i<pWal->nWiData; i++){
sqlite3_free((void *)pWal->apWiData[i]);
pWal->apWiData[i] = 0;
}
}else{
sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
}
}
/*
** Open a connection to the WAL file zWalName. The database file must
** already be opened on connection pDbFd. The buffer that zWalName points
** to must remain valid for the lifetime of the returned Wal* handle.
**
|
︙ | | |
42598
42599
42600
42601
42602
42603
42604
42605
42606
42607
42608
42609
42610
42611
42612
|
42438
42439
42440
42441
42442
42443
42444
42445
42446
42447
42448
42449
42450
42451
|
-
|
** *ppWal is set to point to a new WAL handle. If an error occurs,
** an SQLite error code is returned and *ppWal is left unmodified.
*/
SQLITE_PRIVATE int sqlite3WalOpen(
sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
sqlite3_file *pDbFd, /* The open database file */
const char *zWalName, /* Name of the WAL file */
int bNoShm, /* True to run in heap-memory mode */
Wal **ppWal /* OUT: Allocated Wal handle */
){
int rc; /* Return Code */
Wal *pRet; /* Object to allocate and return */
int flags; /* Flags passed to OsOpen() */
assert( zWalName && zWalName[0] );
|
︙ | | |
42632
42633
42634
42635
42636
42637
42638
42639
42640
42641
42642
42643
42644
42645
42646
|
42471
42472
42473
42474
42475
42476
42477
42478
42479
42480
42481
42482
42483
42484
|
-
|
}
pRet->pVfs = pVfs;
pRet->pWalFd = (sqlite3_file *)&pRet[1];
pRet->pDbFd = pDbFd;
pRet->readLock = -1;
pRet->zWalName = zWalName;
pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
/* Open file handle on the write-ahead log file. */
flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
pRet->readOnly = 1;
}
|
︙ | | |
43066
43067
43068
43069
43070
43071
43072
43073
43074
43075
43076
43077
43078
43079
43080
43081
43082
|
42904
42905
42906
42907
42908
42909
42910
42911
42912
42913
42914
42915
42916
42917
42918
|
-
-
+
-
|
** the database. In this case checkpoint the database and unlink both
** the wal and wal-index files.
**
** The EXCLUSIVE lock is not released before returning.
*/
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
if( rc==SQLITE_OK ){
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
pWal->exclusiveMode = 1;
}
rc = sqlite3WalCheckpoint(pWal, sync_flags, nBuf, zBuf);
if( rc==SQLITE_OK ){
isDelete = 1;
}
}
walIndexClose(pWal, isDelete);
|
︙ | | |
43124
43125
43126
43127
43128
43129
43130
43131
43132
43133
43134
43135
43136
43137
43138
|
42960
42961
42962
42963
42964
42965
42966
42967
42968
42969
42970
42971
42972
42973
42974
|
-
+
|
** There are two copies of the header at the beginning of the wal-index.
** When reading, read [0] first then [1]. Writes are in the reverse order.
** Memory barriers are used to prevent the compiler or the hardware from
** reordering the reads and writes.
*/
aHdr = walIndexHdr(pWal);
memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
walShmBarrier(pWal);
sqlite3OsShmBarrier(pWal->pDbFd);
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
return 1; /* Dirty read */
}
if( h1.isInit==0 ){
return 1; /* Malformed header - probably all zeros */
|
︙ | | |
43325
43326
43327
43328
43329
43330
43331
43332
43333
43334
43335
43336
43337
43338
43339
|
43161
43162
43163
43164
43165
43166
43167
43168
43169
43170
43171
43172
43173
43174
43175
|
-
+
|
pInfo = walCkptInfo(pWal);
if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
/* The WAL has been completely backfilled (or it is empty).
** and can be safely ignored.
*/
rc = walLockShared(pWal, WAL_READ_LOCK(0));
walShmBarrier(pWal);
sqlite3OsShmBarrier(pWal->pDbFd);
if( rc==SQLITE_OK ){
if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
/* It is not safe to allow the reader to continue here if frames
** may have been appended to the log before READ_LOCK(0) was obtained.
** When holding READ_LOCK(0), the reader ignores the entire log file,
** which implies that the database file contains a trustworthy
** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from
|
︙ | | |
43419
43420
43421
43422
43423
43424
43425
43426
43427
43428
43429
43430
43431
43432
43433
|
43255
43256
43257
43258
43259
43260
43261
43262
43263
43264
43265
43266
43267
43268
43269
|
-
+
|
**
** This does not guarantee that the copy of the wal-index header is up to
** date before proceeding. That would not be possible without somehow
** blocking writers. It only guarantees that a dangerous checkpoint or
** log-wrap (either of which would require an exclusive lock on
** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
*/
walShmBarrier(pWal);
sqlite3OsShmBarrier(pWal->pDbFd);
if( pInfo->aReadMark[mxI]!=mxReadMark
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
){
walUnlockShared(pWal, WAL_READ_LOCK(mxI));
return WAL_RETRY;
}else{
assert( mxReadMark<=pWal->hdr.mxFrame );
|
︙ | | |
44062
44063
44064
44065
44066
44067
44068
44069
44070
44071
44072
44073
44074
44075
44076
44077
44078
44079
44080
44081
44082
44083
|
43898
43899
43900
43901
43902
43903
43904
43905
43906
43907
43908
43909
43910
43911
43912
43913
43914
43915
43916
43917
43918
|
-
+
-
|
** locking_mode=EXCLUSIVE. This means that the pWal->readLock must
** be released. Return 1 if the transition is made and 0 if the
** WAL is already in exclusive-locking mode - meaning that this
** routine is a no-op. The pager must already hold the exclusive lock
** on the main database file before invoking this operation.
**
** If op is negative, then do a dry-run of the op==1 case but do
** not actually change anything. The pager uses this to see if it
** not actually change anything. The pager uses this to see if it
** should acquire the database exclusive lock prior to invoking
** the op==1 case.
*/
SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
int rc;
assert( pWal->writeLock==0 );
assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
/* pWal->readLock is usually set, but might be -1 if there was a
** prior error while attempting to acquire are read-lock. This cannot
** happen if the connection is actually in exclusive mode (as no xShmLock
** locks are taken in this case). Nor should the pager attempt to
** upgrade to exclusive-mode following such an error.
*/
|
︙ | | |
44103
44104
44105
44106
44107
44108
44109
44110
44111
44112
44113
44114
44115
44116
44117
44118
44119
44120
44121
44122
44123
44124
44125
|
43938
43939
43940
43941
43942
43943
43944
43945
43946
43947
43948
43949
43950
43951
|
-
-
-
-
-
-
-
-
-
|
rc = 1;
}else{
rc = pWal->exclusiveMode==0;
}
return rc;
}
/*
** Return true if the argument is non-NULL and the WAL module is using
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
** WAL module is using shared-memory, return false.
*/
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
}
#endif /* #ifndef SQLITE_OMIT_WAL */
/************** End of wal.c *************************************************/
/************** Begin file btmutex.c *****************************************/
/*
** 2007 August 27
**
|
︙ | | |
48291
48292
48293
48294
48295
48296
48297
48298
48299
48300
48301
48302
48303
48304
48305
48306
48307
48308
48309
48310
48311
48312
48313
48314
48315
|
48117
48118
48119
48120
48121
48122
48123
48124
48125
48126
48127
48128
48129
48130
48131
48132
48133
48134
48135
48136
48137
48138
48139
48140
|
+
-
-
|
** the rollback journal (which causes the transaction to commit) and
** drop locks.
**
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
*/
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p){
BtShared *pBt = p->pBt;
if( p->inTrans==TRANS_NONE ) return SQLITE_OK;
sqlite3BtreeEnter(p);
btreeIntegrity(p);
/* If the handle has a write-transaction open, commit the shared-btrees
** transaction and set the shared state to TRANS_READ.
*/
if( p->inTrans==TRANS_WRITE ){
int rc;
BtShared *pBt = p->pBt;
assert( pBt->inTransaction==TRANS_WRITE );
assert( pBt->nTransaction>0 );
rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
if( rc!=SQLITE_OK ){
sqlite3BtreeLeave(p);
return rc;
}
|
︙ | | |
53220
53221
53222
53223
53224
53225
53226
53227
53228
53229
53230
53231
53232
53233
53234
|
53045
53046
53047
53048
53049
53050
53051
53052
53053
53054
53055
53056
53057
53058
53059
53060
|
+
-
+
|
** (stored in BtCursor.aOverflow[]) is allocated and used by function
** accessPayload() (the worker function for sqlite3BtreeData() and
** sqlite3BtreePutData()).
*/
SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert(!pCur->isIncrblobHandle);
invalidateOverflowCache(pCur);
assert(!pCur->aOverflow);
pCur->isIncrblobHandle = 1;
}
#endif
/*
** Set both the "read version" (single byte at byte offset 18) and
** "write version" (single byte at byte offset 19) fields in the database
|
︙ | | |
56253
56254
56255
56256
56257
56258
56259
56260
56261
56262
56263
56264
56265
56266
56267
56268
56269
56270
|
56079
56080
56081
56082
56083
56084
56085
56086
56087
56088
56089
56090
56091
56092
56093
56094
56095
56096
56097
56098
|
+
-
-
-
-
+
+
+
+
+
|
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p2; /* P2 */
pMem->type = SQLITE_INTEGER;
pMem++;
if( p->explain==1 ){
pMem->flags = MEM_Int;
pMem->u.i = pOp->p3; /* P3 */
pMem->type = SQLITE_INTEGER;
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p3; /* P3 */
pMem->type = SQLITE_INTEGER;
pMem++;
}
if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
z = displayP4(pOp, pMem->z, 32);
|
︙ | | |
56301
56302
56303
56304
56305
56306
56307
56308
56309
56310
56311
56312
56313
56314
56315
|
56129
56130
56131
56132
56133
56134
56135
56136
56137
56138
56139
56140
56141
56142
56143
|
-
+
|
#endif
{
pMem->flags = MEM_Null; /* Comment */
pMem->type = SQLITE_NULL;
}
}
p->nResColumn = 8 - 4*(p->explain-1);
p->nResColumn = 8 - 5*(p->explain-1);
p->rc = SQLITE_OK;
rc = SQLITE_ROW;
}
return rc;
}
#endif /* SQLITE_OMIT_EXPLAIN */
|
︙ | | |
59248
59249
59250
59251
59252
59253
59254
59255
59256
59257
59258
59259
59260
59261
59262
59263
|
59076
59077
59078
59079
59080
59081
59082
59083
59084
59085
59086
59087
59088
59089
|
-
-
|
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
sqlite3Error(p->db, rc, 0);
rc = sqlite3ApiExit(p->db, rc);
}
sqlite3_mutex_leave(p->db->mutex);
}else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
xDel((void*)zData);
}
return rc;
}
/*
** Bind a blob value to an SQL statement variable.
|
︙ | | |
59492
59493
59494
59495
59496
59497
59498
59499
59500
59501
59502
59503
59504
59505
59506
59507
59508
59509
59510
59511
59512
59513
|
59318
59319
59320
59321
59322
59323
59324
59325
59326
59327
59328
59329
59330
59331
|
-
-
-
-
-
-
-
-
|
** the first argument to the sqlite3_prepare() that was used to create
** the statement in the first place.
*/
SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->db : 0;
}
/*
** Return true if the prepared statement is guaranteed to not modify the
** database.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}
/*
** Return a pointer to the next prepared statement after pStmt associated
** with database connection pDb. If pStmt is NULL, return the first
** prepared statement for the database connection. Return NULL if there
** are no more.
*/
SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
|
︙ | | |
66251
66252
66253
66254
66255
66256
66257
66258
66259
66260
66261
66262
66263
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
66289
66290
66291
66292
66293
66294
66295
66296
66297
66298
66299
66300
66301
66302
66303
66304
66305
66306
66307
66308
66309
66310
66311
66312
66313
66314
66315
66316
66317
66318
66319
66320
66321
66322
66323
66324
66325
66326
66327
66328
66329
66330
66331
66332
66333
66334
66335
66336
66337
66338
66339
66340
|
66069
66070
66071
66072
66073
66074
66075
66076
66077
66078
66079
66080
66081
66082
66083
66084
66085
66086
66087
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
** Valid sqlite3_blob* handles point to Incrblob structures.
*/
typedef struct Incrblob Incrblob;
struct Incrblob {
int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
int nByte; /* Size of open blob, in bytes */
int iOffset; /* Byte offset of blob in cursor data */
int iCol; /* Table column this handle is open on */
BtCursor *pCsr; /* Cursor pointing at blob row */
sqlite3_stmt *pStmt; /* Statement holding cursor open */
sqlite3 *db; /* The associated database */
};
/*
** This function is used by both blob_open() and blob_reopen(). It seeks
** the b-tree cursor associated with blob handle p to point to row iRow.
** If successful, SQLITE_OK is returned and subsequent calls to
** sqlite3_blob_read() or sqlite3_blob_write() access the specified row.
**
** If an error occurs, or if the specified row does not exist or does not
** contain a value of type TEXT or BLOB in the column nominated when the
** blob handle was opened, then an error code is returned and *pzErr may
** be set to point to a buffer containing an error message. It is the
** responsibility of the caller to free the error message buffer using
** sqlite3DbFree().
**
** If an error does occur, then the b-tree cursor is closed. All subsequent
** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
** immediately return SQLITE_ABORT.
*/
static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
int rc; /* Error code */
char *zErr = 0; /* Error message */
Vdbe *v = (Vdbe *)p->pStmt;
/* Set the value of the SQL statements only variable to integer iRow.
** This is done directly instead of using sqlite3_bind_int64() to avoid
** triggering asserts related to mutexes.
*/
assert( v->aVar[0].flags&MEM_Int );
v->aVar[0].u.i = iRow;
rc = sqlite3_step(p->pStmt);
if( rc==SQLITE_ROW ){
u32 type = v->apCsr[0]->aType[p->iCol];
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
);
rc = SQLITE_ERROR;
sqlite3_finalize(p->pStmt);
p->pStmt = 0;
}else{
p->iOffset = v->apCsr[0]->aOffset[p->iCol];
p->nByte = sqlite3VdbeSerialTypeLen(type);
p->pCsr = v->apCsr[0]->pCursor;
sqlite3BtreeEnterCursor(p->pCsr);
sqlite3BtreeCacheOverflow(p->pCsr);
sqlite3BtreeLeaveCursor(p->pCsr);
}
}
if( rc==SQLITE_ROW ){
rc = SQLITE_OK;
}else if( p->pStmt ){
rc = sqlite3_finalize(p->pStmt);
p->pStmt = 0;
if( rc==SQLITE_OK ){
zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow);
rc = SQLITE_ERROR;
}else{
zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db));
}
}
assert( rc!=SQLITE_OK || zErr==0 );
assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE );
*pzErr = zErr;
return rc;
}
/*
** Open a blob handle.
*/
SQLITE_API int sqlite3_blob_open(
sqlite3* db, /* The database connection */
const char *zDb, /* The attached database containing the blob */
const char *zTable, /* The table containing the blob */
|
︙ | | |
66367
66368
66369
66370
66371
66372
66373
66374
66375
66376
66377
66378
66379
66380
66381
66382
66383
66384
66385
66386
66387
66388
66389
66390
66391
66392
66393
66394
66395
66396
66397
66398
66399
66400
66401
66402
66403
66404
66405
66406
66407
66408
66409
|
66114
66115
66116
66117
66118
66119
66120
66121
66122
66123
66124
66125
66126
66127
66128
66129
66130
66131
66132
66133
66134
66135
66136
66137
66138
66139
66140
66141
66142
66143
66144
66145
66146
66147
66148
66149
66150
|
-
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
+
+
-
-
+
+
-
-
|
{OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */
/* One of the following two instructions is replaced by an OP_Noop. */
{OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */
{OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */
{OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */
{OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */
{OP_NotExists, 0, 9, 1}, /* 6: Seek the cursor */
{OP_Column, 0, 0, 1}, /* 7 */
{OP_ResultRow, 1, 0, 0}, /* 8 */
{OP_Goto, 0, 5, 0}, /* 9 */
{OP_Close, 0, 0, 0}, /* 10 */
{OP_Halt, 0, 0, 0}, /* 11 */
{OP_Close, 0, 0, 0}, /* 9 */
{OP_Halt, 0, 0, 0}, /* 10 */
};
Vdbe *v = 0;
int rc = SQLITE_OK;
char *zErr = 0;
Table *pTab;
Parse *pParse = 0;
Parse *pParse;
Incrblob *pBlob = 0;
flags = !!flags; /* flags = (flags ? 1 : 0); */
*ppBlob = 0;
sqlite3_mutex_enter(db->mutex);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
if( !pBlob ) goto blob_open_out;
pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
if( pParse==0 ){
rc = SQLITE_NOMEM;
if( !pParse ) goto blob_open_out;
goto blob_open_out;
}
do {
memset(pParse, 0, sizeof(Parse));
pParse->db = db;
sqlite3DbFree(db, zErr);
zErr = 0;
sqlite3BtreeEnterAll(db);
pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
if( pTab && IsVirtual(pTab) ){
pTab = 0;
sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
}
|
︙ | | |
66421
66422
66423
66424
66425
66426
66427
66428
66429
66430
66431
66432
66433
66434
66435
|
66162
66163
66164
66165
66166
66167
66168
66169
66170
66171
66172
66173
66174
66175
66176
|
-
+
|
}
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
/* Now search pTab for the exact column. */
for(iCol=0; iCol<pTab->nCol; iCol++) {
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);
|
︙ | | |
66475
66476
66477
66478
66479
66480
66481
66482
66483
66484
66485
66486
66487
66488
66489
66490
66491
66492
66493
66494
66495
66496
|
66216
66217
66218
66219
66220
66221
66222
66223
66224
66225
66226
66227
66228
66229
66230
66231
66232
66233
66234
|
-
+
-
-
+
-
-
-
+
|
zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
}
pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db);
v = sqlite3VdbeCreate(db);
assert( pBlob->pStmt || db->mallocFailed );
if( pBlob->pStmt ){
if( v ){
Vdbe *v = (Vdbe *)pBlob->pStmt;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
flags = !!flags; /* flags = (flags ? 1 : 0); */
/* Configure the OP_Transaction */
sqlite3VdbeChangeP1(v, 0, iDb);
sqlite3VdbeChangeP2(v, 0, flags);
/* Configure the OP_VerifyCookie */
sqlite3VdbeChangeP1(v, 1, iDb);
|
︙ | | |
66525
66526
66527
66528
66529
66530
66531
66532
66533
66534
66535
66536
66537
66538
66539
66540
66541
66542
66543
66544
66545
66546
66547
66548
66549
66550
66551
66552
66553
66554
66555
66556
66557
|
66263
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
66289
66290
66291
66292
66293
66294
66295
66296
66297
66298
66299
66300
66301
66302
66303
66304
66305
66306
66307
66308
66309
66310
66311
66312
66313
66314
66315
66316
66317
66318
66319
66320
66321
66322
66323
66324
66325
66326
66327
66328
66329
66330
66331
66332
66333
66334
66335
|
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+
+
+
-
+
|
sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
if( !db->mallocFailed ){
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
}
}
pBlob->flags = flags;
pBlob->iCol = iCol;
pBlob->db = db;
sqlite3BtreeLeaveAll(db);
if( db->mallocFailed ){
goto blob_open_out;
}
sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
rc = blobSeekToRow(pBlob, iRow, &zErr);
} while( (++nAttempt)<5 && rc==SQLITE_SCHEMA );
sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow);
rc = sqlite3_step((sqlite3_stmt *)v);
if( rc!=SQLITE_ROW ){
nAttempt++;
rc = sqlite3_finalize((sqlite3_stmt *)v);
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, sqlite3_errmsg(db));
v = 0;
}
} while( nAttempt<5 && rc==SQLITE_SCHEMA );
if( rc==SQLITE_ROW ){
/* The row-record has been opened successfully. Check that the
** column in question contains text or a blob. If it contains
** text, it is up to the caller to get the encoding right.
*/
Incrblob *pBlob;
u32 type = v->apCsr[0]->aType[iCol];
if( type<12 ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
);
rc = SQLITE_ERROR;
blob_open_out:
if( rc==SQLITE_OK && db->mallocFailed==0 ){
goto blob_open_out;
}
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
if( db->mallocFailed ){
sqlite3DbFree(db, pBlob);
goto blob_open_out;
}
pBlob->flags = flags;
pBlob->pCsr = v->apCsr[0]->pCursor;
sqlite3BtreeEnterCursor(pBlob->pCsr);
sqlite3BtreeCacheOverflow(pBlob->pCsr);
sqlite3BtreeLeaveCursor(pBlob->pCsr);
pBlob->pStmt = (sqlite3_stmt *)v;
pBlob->iOffset = v->apCsr[0]->aOffset[iCol];
pBlob->nByte = sqlite3VdbeSerialTypeLen(type);
pBlob->db = db;
*ppBlob = (sqlite3_blob *)pBlob;
rc = SQLITE_OK;
}else{
}else if( rc==SQLITE_OK ){
if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
sqlite3DbFree(db, pBlob);
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "no such rowid: %lld", iRow);
rc = SQLITE_ERROR;
}
blob_open_out:
if( v && (rc!=SQLITE_OK || db->mallocFailed) ){
sqlite3VdbeFinalize(v);
}
sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3Error(db, rc, zErr);
sqlite3DbFree(db, zErr);
sqlite3StackFree(db, pParse);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
|
︙ | | |
66596
66597
66598
66599
66600
66601
66602
66603
66604
66605
66606
66607
66608
66609
66610
|
66374
66375
66376
66377
66378
66379
66380
66381
66382
66383
66384
66385
66386
66387
66388
|
-
+
|
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;
sqlite3Error(db, SQLITE_ERROR, 0);
}else if( v==0 ){
} else if( v==0 ){
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
rc = SQLITE_ABORT;
}else{
/* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
** returned, clean-up the statement handle.
|
︙ | | |
66647
66648
66649
66650
66651
66652
66653
66654
66655
66656
66657
66658
66659
66660
66661
66662
66663
66664
66665
66666
66667
66668
66669
66670
66671
66672
66673
66674
66675
66676
66677
66678
66679
66680
66681
66682
66683
66684
66685
66686
66687
66688
66689
66690
66691
66692
66693
66694
66695
66696
66697
66698
66699
|
66425
66426
66427
66428
66429
66430
66431
66432
66433
66434
66435
66436
66437
66438
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
** so no mutex is required for access.
*/
SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
Incrblob *p = (Incrblob *)pBlob;
return p ? p->nByte : 0;
}
/*
** Move an existing blob handle to point to a different row of the same
** database table.
**
** If an error occurs, or if the specified row does not exist or does not
** contain a blob or text value, then an error code is returned and the
** database handle error code and message set. If this happens, then all
** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
** immediately return SQLITE_ABORT.
*/
SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
int rc;
Incrblob *p = (Incrblob *)pBlob;
sqlite3 *db;
if( p==0 ) return SQLITE_MISUSE_BKPT;
db = p->db;
sqlite3_mutex_enter(db->mutex);
if( p->pStmt==0 ){
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
rc = SQLITE_ABORT;
}else{
char *zErr;
rc = blobSeekToRow(p, iRow, &zErr);
if( rc!=SQLITE_OK ){
sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
}
assert( rc!=SQLITE_SCHEMA );
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
/************** End of vdbeblob.c ********************************************/
/************** Begin file journal.c *****************************************/
/*
** 2007 August 22
**
|
︙ | | |
69016
69017
69018
69019
69020
69021
69022
69023
69024
69025
69026
69027
69028
69029
69030
69031
69032
|
68755
68756
68757
68758
68759
68760
68761
68762
68763
68764
68765
68766
68767
68768
|
-
-
-
|
int op, /* Expression opcode */
Expr *pLeft, /* Left operand */
Expr *pRight, /* Right operand */
const Token *pToken /* Argument token */
){
Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
if( p ) {
sqlite3ExprCheckHeight(pParse, p->nHeight);
}
return p;
}
/*
** Join two expressions using an AND operator. If either expression is
** NULL, then just return the other expression.
*/
|
︙ | | |
70132
70133
70134
70135
70136
70137
70138
70139
70140
70141
70142
70143
70144
70145
70146
70147
70148
70149
70150
70151
70152
70153
70154
70155
|
69868
69869
69870
69871
69872
69873
69874
69875
69876
69877
69878
69879
69880
69881
|
-
-
-
-
-
-
-
-
-
-
|
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
int mem = ++pParse->nMem;
sqlite3VdbeAddOp1(v, OP_If, mem);
testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
assert( testAddr>0 || pParse->db->mallocFailed );
}
#ifndef SQLITE_OMIT_EXPLAIN
if( pParse->explain==2 ){
char *zMsg = sqlite3MPrintf(
pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr?"":"CORRELATED ",
pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
);
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
}
#endif
switch( pExpr->op ){
case TK_IN: {
char affinity; /* Affinity of the LHS of the IN */
KeyInfo keyInfo; /* Keyinfo for the generated table */
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
|
︙ | | |
84328
84329
84330
84331
84332
84333
84334
84335
84336
84337
84338
84339
84340
84341
84342
84343
84344
84345
84346
84347
84348
84349
84350
84351
84352
84353
84354
84355
84356
84357
84358
84359
84360
84361
84362
|
84054
84055
84056
84057
84058
84059
84060
84061
84062
84063
84064
84065
84066
84067
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
int (*limit)(sqlite3*,int,int);
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
const char *(*sql)(sqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(sqlite3_backup*);
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
int (*backup_pagecount)(sqlite3_backup*);
int (*backup_remaining)(sqlite3_backup*);
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*),void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
void (*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
};
/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
|
︙ | | |
84528
84529
84530
84531
84532
84533
84534
84535
84536
84537
84538
84539
84540
84541
84542
84543
84544
84545
84546
84547
84548
84549
84550
84551
84552
84553
84554
84555
84556
84557
84558
84559
84560
84561
84562
|
84233
84234
84235
84236
84237
84238
84239
84240
84241
84242
84243
84244
84245
84246
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
#define sqlite3_randomness sqlite3_api->randomness
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
#define sqlite3_limit sqlite3_api->limit
#define sqlite3_next_stmt sqlite3_api->next_stmt
#define sqlite3_sql sqlite3_api->sql
#define sqlite3_status sqlite3_api->status
#define sqlite3_backup_finish sqlite3_api->backup_finish
#define sqlite3_backup_init sqlite3_api->backup_init
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
#define sqlite3_backup_step sqlite3_api->backup_step
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
#define sqlite3_db_config sqlite3_api->db_config
#define sqlite3_db_mutex sqlite3_api->db_mutex
#define sqlite3_db_status sqlite3_api->db_status
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
#define sqlite3_log sqlite3_api->log
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid sqlite3_api->sourceid
#define sqlite3_stmt_status sqlite3_api->stmt_status
#define sqlite3_strnicmp sqlite3_api->strnicmp
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
#endif /* _SQLITE3EXT_H_ */
|
︙ | | |
84866
84867
84868
84869
84870
84871
84872
84873
84874
84875
84876
84877
84878
84879
84880
84881
84882
84883
84884
84885
84886
84887
84888
84889
84890
84891
84892
84893
84894
84895
84896
84897
84898
84899
84900
84901
84902
84903
84904
84905
84906
84907
84908
84909
84910
84911
84912
84913
84914
84915
84916
84917
84918
84919
|
84550
84551
84552
84553
84554
84555
84556
84557
84558
84559
84560
84561
84562
84563
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
** Added for 3.6.0
*/
sqlite3_extended_result_codes,
sqlite3_limit,
sqlite3_next_stmt,
sqlite3_sql,
sqlite3_status,
/*
** Added for 3.7.4
*/
sqlite3_backup_finish,
sqlite3_backup_init,
sqlite3_backup_pagecount,
sqlite3_backup_remaining,
sqlite3_backup_step,
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
sqlite3_compileoption_get,
sqlite3_compileoption_used,
#else
0,
0,
#endif
sqlite3_create_function_v2,
sqlite3_db_config,
sqlite3_db_mutex,
sqlite3_db_status,
sqlite3_extended_errcode,
sqlite3_log,
sqlite3_soft_heap_limit64,
sqlite3_sourceid,
sqlite3_stmt_status,
sqlite3_strnicmp,
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
sqlite3_unlock_notify,
#else
0,
#endif
#ifndef SQLITE_OMIT_WAL
sqlite3_wal_autocheckpoint,
sqlite3_wal_checkpoint,
sqlite3_wal_hook,
#else
0,
0,
0,
#endif
};
/*
** Attempt to load an SQLite extension library contained in the file
** zFile. The entry point is zProc. zProc may be 0 in which case a
** default entry point name (sqlite3_extension_init) is used. Use
** of the default name is recommended.
|
︙ | | |
87330
87331
87332
87333
87334
87335
87336
87337
87338
87339
87340
87341
87342
87343
87344
87345
87346
87347
87348
87349
87350
|
86974
86975
86976
86977
86978
86979
86980
86981
86982
86983
86984
86985
86986
86987
86988
86989
86990
86991
86992
86993
86994
|
-
+
-
+
-
+
|
}
rc = pParse->rc;
#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){
static const char * const azColName[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
"selectid", "order", "from", "detail"
"order", "from", "detail"
};
int iFirst, mx;
if( pParse->explain==2 ){
sqlite3VdbeSetNumCols(pParse->pVdbe, 4);
sqlite3VdbeSetNumCols(pParse->pVdbe, 3);
iFirst = 8;
mx = 12;
mx = 11;
}else{
sqlite3VdbeSetNumCols(pParse->pVdbe, 8);
iFirst = 0;
mx = 8;
}
for(i=iFirst; i<mx; i++){
sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
|
︙ | | |
88335
88336
88337
88338
88339
88340
88341
88342
88343
88344
88345
88346
88347
88348
88349
88350
88351
88352
88353
88354
88355
88356
88357
88358
88359
88360
88361
88362
88363
88364
88365
88366
88367
88368
88369
88370
88371
88372
88373
88374
88375
88376
88377
88378
88379
88380
88381
88382
88383
88384
88385
88386
88387
88388
88389
88390
88391
88392
88393
88394
88395
88396
88397
88398
88399
88400
88401
88402
88403
88404
88405
88406
88407
88408
88409
88410
88411
88412
88413
88414
88415
88416
88417
88418
88419
88420
88421
88422
88423
88424
88425
88426
88427
88428
88429
88430
|
87979
87980
87981
87982
87983
87984
87985
87986
87987
87988
87989
87990
87991
87992
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
pInfo->aColl[i] = pColl;
pInfo->aSortOrder[i] = pItem->sortOrder;
}
}
return pInfo;
}
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Name of the connection operator, used for error messages.
*/
static const char *selectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
case TK_INTERSECT: z = "INTERSECT"; break;
case TK_EXCEPT: z = "EXCEPT"; break;
default: z = "UNION"; break;
}
return z;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
#ifndef SQLITE_OMIT_EXPLAIN
/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of the form:
**
** "USE TEMP B-TREE FOR xxx"
**
** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
** is determined by the zUsage argument.
*/
static void explainTempTable(Parse *pParse, const char *zUsage){
if( pParse->explain==2 ){
Vdbe *v = pParse->pVdbe;
char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage);
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
}
}
/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of one of the two forms:
**
** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
**
** where iSub1 and iSub2 are the integers passed as the corresponding
** function parameters, and op is the text representation of the parameter
** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT,
** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is
** false, or the second form if it is true.
*/
static void explainComposite(
Parse *pParse, /* Parse context */
int op, /* One of TK_UNION, TK_EXCEPT etc. */
int iSub1, /* Subquery id 1 */
int iSub2, /* Subquery id 2 */
int bUseTmp /* True if a temp table was used */
){
assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL );
if( pParse->explain==2 ){
Vdbe *v = pParse->pVdbe;
char *zMsg = sqlite3MPrintf(
pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)
);
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
}
}
/*
** Assign expression b to lvalue a. A second, no-op, version of this macro
** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
** in sqlite3Select() to assign values to structure member variables that
** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
** code with #ifndef directives.
*/
# define explainSetInteger(a, b) a = b
#else
/* No-op versions of the explainXXX() functions and macros. */
# define explainTempTable(y,z)
# define explainComposite(v,w,x,y,z)
# define explainSetInteger(y,z)
#endif
/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter. After the loop is terminated
** we need to run the sorter and output the results. The following
** routine generates the code needed to do that.
*/
|
︙ | | |
88764
88765
88766
88767
88768
88769
88770
88771
88772
88773
88774
88775
88776
88777
|
88326
88327
88328
88329
88330
88331
88332
88333
88334
88335
88336
88337
88338
88339
88340
88341
88342
88343
88344
88345
88346
88347
88348
88349
88350
88351
88352
88353
88354
88355
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
sqlite3VdbeSetColName(v, i, COLNAME_NAME,
sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
}
}
generateColumnTypes(pParse, pTabList, pEList);
}
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Name of the connection operator, used for error messages.
*/
static const char *selectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
case TK_INTERSECT: z = "INTERSECT"; break;
case TK_EXCEPT: z = "EXCEPT"; break;
default: z = "UNION"; break;
}
return z;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
** Given a an expression list (which is really the list of expressions
** that form the result set of a SELECT statement) compute appropriate
** column names for a table that would hold the expression list.
**
** All column names will be unique.
**
|
︙ | | |
88926
88927
88928
88929
88930
88931
88932
88933
88934
88935
88936
88937
88938
88939
88940
|
88504
88505
88506
88507
88508
88509
88510
88511
88512
88513
88514
88515
88516
88517
|
-
|
return 0;
}
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
** is disabled */
assert( db->lookaside.bEnabled==0 );
pTab->nRef = 1;
pTab->zName = 0;
pTab->nRowEst = 1000000;
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(db, pTab);
return 0;
}
|
︙ | | |
88997
88998
88999
89000
89001
89002
89003
89004
89005
89006
89007
89008
89009
89010
89011
89012
|
88574
88575
88576
88577
88578
88579
88580
88581
88582
88583
88584
88585
88586
88587
|
-
-
|
v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return; /* VDBE should have already been allocated */
if( sqlite3ExprIsInteger(p->pLimit, &n) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
}else{
if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
}
}else{
sqlite3ExprCode(pParse, p->pLimit, iLimit);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
VdbeComment((v, "LIMIT counter"));
sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
}
|
︙ | | |
89099
89100
89101
89102
89103
89104
89105
89106
89107
89108
89109
89110
89111
89112
89113
89114
89115
89116
|
88674
88675
88676
88677
88678
88679
88680
88681
88682
88683
88684
88685
88686
88687
|
-
-
-
-
|
){
int rc = SQLITE_OK; /* Success code from a subroutine */
Select *pPrior; /* Another SELECT immediately to our left */
Vdbe *v; /* Generate code to this VDBE */
SelectDest dest; /* Alternative data destination */
Select *pDelete = 0; /* Chain of simple selects to delete */
sqlite3 *db; /* Database connection */
#ifndef SQLITE_OMIT_EXPLAIN
int iSub1; /* EQP id of left-hand query */
int iSub2; /* EQP id of right-hand query */
#endif
/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
*/
assert( p && p->pPrior ); /* Calling function guarantees this much */
db = pParse->db;
pPrior = p->pPrior;
|
︙ | | |
89160
89161
89162
89163
89164
89165
89166
89167
89168
89169
89170
89171
89172
89173
89174
89175
89176
89177
89178
89179
89180
89181
89182
89183
89184
89185
89186
89187
89188
89189
89190
89191
89192
89193
89194
89195
89196
89197
89198
89199
89200
89201
89202
89203
|
88731
88732
88733
88734
88735
88736
88737
88738
88739
88740
88741
88742
88743
88744
88745
88746
88747
88748
88749
88750
88751
88752
88753
88754
88755
88756
88757
88758
88759
88760
88761
88762
88763
88764
|
-
-
-
-
-
-
-
-
-
-
|
}
/* Generate code for the left and right SELECT statements.
*/
switch( p->op ){
case TK_ALL: {
int addr = 0;
int nLimit;
assert( !pPrior->pLimit );
pPrior->pLimit = p->pLimit;
pPrior->pOffset = p->pOffset;
explainSetInteger(iSub1, pParse->iNextSelectId);
rc = sqlite3Select(pParse, pPrior, &dest);
p->pLimit = 0;
p->pOffset = 0;
if( rc ){
goto multi_select_end;
}
p->pPrior = 0;
p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset;
if( p->iLimit ){
addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
VdbeComment((v, "Jump ahead if LIMIT reached"));
}
explainSetInteger(iSub2, pParse->iNextSelectId);
rc = sqlite3Select(pParse, p, &dest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->nSelectRow += pPrior->nSelectRow;
if( pPrior->pLimit
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
&& p->nSelectRow > (double)nLimit
){
p->nSelectRow = (double)nLimit;
}
if( addr ){
sqlite3VdbeJumpHere(v, addr);
}
break;
}
case TK_EXCEPT:
case TK_UNION: {
|
︙ | | |
89233
89234
89235
89236
89237
89238
89239
89240
89241
89242
89243
89244
89245
89246
89247
89248
89249
89250
89251
89252
89253
89254
89255
89256
89257
89258
89259
89260
89261
89262
89263
89264
89265
89266
89267
89268
89269
89270
89271
89272
89273
89274
89275
89276
|
88794
88795
88796
88797
88798
88799
88800
88801
88802
88803
88804
88805
88806
88807
88808
88809
88810
88811
88812
88813
88814
88815
88816
88817
88818
88819
88820
88821
88822
88823
88824
88825
88826
88827
88828
88829
88830
88831
88832
88833
88834
|
-
-
-
|
assert( p->pEList );
}
/* Code the SELECT statements to our left
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
explainSetInteger(iSub1, pParse->iNextSelectId);
rc = sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
}
/* Code the current SELECT statement
*/
if( p->op==TK_EXCEPT ){
op = SRT_Except;
}else{
assert( p->op==TK_UNION );
op = SRT_Union;
}
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
uniondest.eDest = op;
explainSetInteger(iSub2, pParse->iNextSelectId);
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
/* Query flattening in sqlite3Select() might refill p->pOrderBy.
** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
sqlite3ExprListDelete(db, p->pOrderBy);
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
p->iLimit = 0;
p->iOffset = 0;
/* Convert the data in the temporary table into whatever form
|
︙ | | |
89320
89321
89322
89323
89324
89325
89326
89327
89328
89329
89330
89331
89332
89333
89334
89335
89336
89337
89338
89339
89340
89341
89342
89343
89344
89345
89346
89347
89348
89349
89350
89351
89352
89353
89354
89355
89356
|
88878
88879
88880
88881
88882
88883
88884
88885
88886
88887
88888
88889
88890
88891
88892
88893
88894
88895
88896
88897
88898
88899
88900
88901
88902
88903
88904
88905
88906
88907
88908
88909
88910
88911
|
-
-
-
|
p->addrOpenEphm[0] = addr;
p->pRightmost->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
explainSetInteger(iSub1, pParse->iNextSelectId);
rc = sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
}
/* Code the current SELECT into temporary table "tab2"
*/
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
assert( p->addrOpenEphm[1] == -1 );
p->addrOpenEphm[1] = addr;
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
intersectdest.iParm = tab2;
explainSetInteger(iSub2, pParse->iNextSelectId);
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
/* Generate code to take the intersection of the two temporary
** tables.
*/
|
︙ | | |
89375
89376
89377
89378
89379
89380
89381
89382
89383
89384
89385
89386
89387
89388
89389
89390
|
88930
88931
88932
88933
88934
88935
88936
88937
88938
88939
88940
88941
88942
88943
|
-
-
|
sqlite3VdbeResolveLabel(v, iBreak);
sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
break;
}
}
explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL);
/* Compute collating sequences used by
** temporary tables needed to implement the compound select.
** Attach the KeyInfo structure to all temporary tables.
**
** This section is run by the right-most SELECT statement only.
** SELECT statements to the left always skip this part. The right-most
** SELECT might also skip this part if it has no ORDER BY clause and
|
︙ | | |
89720
89721
89722
89723
89724
89725
89726
89727
89728
89729
89730
89731
89732
89733
89734
89735
89736
89737
|
89273
89274
89275
89276
89277
89278
89279
89280
89281
89282
89283
89284
89285
89286
|
-
-
-
-
|
int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
KeyInfo *pKeyMerge; /* Comparison information for merging rows */
sqlite3 *db; /* Database connection */
ExprList *pOrderBy; /* The ORDER BY clause */
int nOrderBy; /* Number of terms in the ORDER BY clause */
int *aPermute; /* Mapping from ORDER BY terms to result set columns */
#ifndef SQLITE_OMIT_EXPLAIN
int iSub1; /* EQP id of left-hand query */
int iSub2; /* EQP id of right-hand query */
#endif
assert( p->pOrderBy!=0 );
assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */
db = pParse->db;
v = pParse->pVdbe;
assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */
labelEnd = sqlite3VdbeMakeLabel(v);
|
︙ | | |
89877
89878
89879
89880
89881
89882
89883
89884
89885
89886
89887
89888
89889
89890
89891
89892
89893
89894
89895
89896
89897
89898
89899
89900
89901
89902
89903
89904
89905
89906
|
89426
89427
89428
89429
89430
89431
89432
89433
89434
89435
89436
89437
89438
89439
89440
89441
89442
89443
89444
89445
89446
89447
89448
89449
89450
89451
89452
89453
|
-
-
|
/* Generate a coroutine to evaluate the SELECT statement to the
** left of the compound operator - the "A" select.
*/
VdbeNoopComment((v, "Begin coroutine for left SELECT"));
pPrior->iLimit = regLimitA;
explainSetInteger(iSub1, pParse->iNextSelectId);
sqlite3Select(pParse, pPrior, &destA);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
VdbeNoopComment((v, "End coroutine for left SELECT"));
/* Generate a coroutine to evaluate the SELECT statement on
** the right - the "B" select
*/
addrSelectB = sqlite3VdbeCurrentAddr(v);
VdbeNoopComment((v, "Begin coroutine for right SELECT"));
savedLimit = p->iLimit;
savedOffset = p->iOffset;
p->iLimit = regLimitB;
p->iOffset = 0;
explainSetInteger(iSub2, pParse->iNextSelectId);
sqlite3Select(pParse, p, &destB);
p->iLimit = savedLimit;
p->iOffset = savedOffset;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
VdbeNoopComment((v, "End coroutine for right SELECT"));
|
︙ | | |
89929
89930
89931
89932
89933
89934
89935
89936
89937
89938
89939
89940
89941
89942
89943
89944
89945
89946
89947
89948
89949
89950
89951
|
89476
89477
89478
89479
89480
89481
89482
89483
89484
89485
89486
89487
89488
89489
89490
89491
89492
89493
89494
89495
89496
|
-
-
|
if( op==TK_EXCEPT || op==TK_INTERSECT ){
addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
}else{
addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
p->nSelectRow += pPrior->nSelectRow;
}
/* Generate a subroutine to run when the results from select B
** are exhausted and only data in select A remains.
*/
if( op==TK_INTERSECT ){
addrEofB = addrEofA;
if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
}else{
VdbeNoopComment((v, "eof-B subroutine"));
addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB);
}
|
︙ | | |
90025
90026
90027
90028
90029
90030
90031
90032
90033
90034
90035
90036
90037
90038
90039
|
89570
89571
89572
89573
89574
89575
89576
89577
89578
89579
89580
89581
89582
89583
|
-
|
if( p->pPrior ){
sqlite3SelectDelete(db, p->pPrior);
}
p->pPrior = pPrior;
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
explainComposite(pParse, p->op, iSub1, iSub2, 0);
return SQLITE_OK;
}
#endif
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* Forward Declarations */
static void substExprList(sqlite3*, ExprList*, int, ExprList*);
|
︙ | | |
90759
90760
90761
90762
90763
90764
90765
90766
90767
90768
90769
90770
90771
90772
90773
|
90303
90304
90305
90306
90307
90308
90309
90310
90311
90312
90313
90314
90315
90316
|
-
|
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
pTab->nRef = 1;
pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
while( pSel->pPrior ){ pSel = pSel->pPrior; }
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
pTab->iPKey = -1;
pTab->nRowEst = 1000000;
pTab->tabFlags |= TF_Ephemeral;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
|
︙ | | |
91253
91254
91255
91256
91257
91258
91259
91260
91261
91262
91263
91264
91265
91266
91267
91268
91269
91270
91271
|
90796
90797
90798
90799
90800
90801
90802
90803
90804
90805
90806
90807
90808
90809
|
-
-
-
-
-
|
int distinct; /* Table to use for the distinct set */
int rc = 1; /* Value to return from this function */
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
sqlite3 *db; /* The database connection */
#ifndef SQLITE_OMIT_EXPLAIN
int iRestoreSelectId = pParse->iSelectId;
pParse->iSelectId = pParse->iNextSelectId++;
#endif
db = pParse->db;
if( p==0 || db->mallocFailed || pParse->nErr ){
return 1;
}
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
|
︙ | | |
91329
91330
91331
91332
91333
91334
91335
91336
91337
91338
91339
91340
91341
91342
91343
91344
91345
91346
|
90867
90868
90869
90870
90871
90872
90873
90874
90875
90876
90877
90878
90879
90880
90881
90882
|
-
-
|
isAgg = 1;
p->selFlags |= SF_Aggregate;
}
i = -1;
}else{
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
assert( pItem->isPopulated==0 );
explainSetInteger(pItem->iSelectId, pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->isPopulated = 1;
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
}
if( /*pParse->nErr ||*/ db->mallocFailed ){
goto select_end;
}
pParse->nHeight -= sqlite3SelectExprHeight(p);
pTabList = p->pSrc;
if( !IgnorableOrderby(pDest) ){
|
︙ | | |
91366
91367
91368
91369
91370
91371
91372
91373
91374
91375
91376
91377
91378
91379
91380
91381
91382
91383
91384
91385
91386
91387
91388
91389
91390
91391
91392
91393
91394
91395
91396
|
90902
90903
90904
90905
90906
90907
90908
90909
90910
90911
90912
90913
90914
90915
90916
90917
90918
90919
90920
90921
90922
90923
90924
90925
90926
90927
90928
90929
90930
90931
|
-
+
-
+
-
-
+
|
pLoop->pRightmost = p;
pLoop->pNext = pRight;
pRight = pLoop;
}
mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
if( mxSelect && cnt>mxSelect ){
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
goto select_end;
return 1;
}
}
rc = multiSelect(pParse, p, pDest);
return multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
return rc;
}
#endif
/* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
** GROUP BY might use an index, DISTINCT never does.
*/
assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
p->selFlags &= ~SF_Distinct;
isDistinct = 0;
}
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then disable the ORDER BY clause since the GROUP BY
** will cause elements to come out in the correct order. This is
** an optimization - the correct answer should result regardless.
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
|
︙ | | |
91425
91426
91427
91428
91429
91430
91431
91432
91433
91434
91435
91436
91437
91438
91439
91440
91441
91442
91443
91444
91445
91446
91447
91448
91449
91450
91451
91452
91453
91454
91455
91456
91457
91458
91459
91460
91461
91462
91463
|
90960
90961
90962
90963
90964
90965
90966
90967
90968
90969
90970
90971
90972
90973
90974
90975
90976
90977
90978
90979
90980
90981
90982
90983
90984
90985
90986
90987
90988
90989
90990
90991
90992
90993
90994
90995
90996
|
-
-
+
-
|
if( pDest->eDest==SRT_EphemTab ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr);
}
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
p->nSelectRow = (double)LARGEST_INT64;
computeLimitRegisters(pParse, p, iEnd);
/* Open a virtual index to use for the distinct set.
*/
if( p->selFlags & SF_Distinct ){
if( isDistinct ){
KeyInfo *pKeyInfo;
assert( isAgg || pGroupBy );
distinct = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
(char*)pKeyInfo, P4_KEYINFO_HANDOFF);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
}else{
distinct = -1;
}
/* Aggregate and non-aggregate queries are handled differently */
if( !isAgg && pGroupBy==0 ){
/* This case is for non-aggregate queries
** Begin the database scan
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
if( pWInfo==0 ) goto select_end;
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
** into an OP_Noop.
*/
if( addrSortIndex>=0 && pOrderBy==0 ){
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
|
︙ | | |
91494
91495
91496
91497
91498
91499
91500
91501
91502
91503
91504
91505
91506
91507
91508
91509
91510
|
91027
91028
91029
91030
91031
91032
91033
91034
91035
91036
91037
91038
91039
91040
|
-
-
-
|
for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
pItem->iAlias = 0;
}
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
pItem->iAlias = 0;
}
if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
}else{
p->nSelectRow = (double)1;
}
/* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
|
︙ | | |
91593
91594
91595
91596
91597
91598
91599
91600
91601
91602
91603
91604
91605
91606
91607
91608
91609
|
91123
91124
91125
91126
91127
91128
91129
91130
91131
91132
91133
91134
91135
91136
|
-
-
-
|
** in sorted order
*/
int regBase;
int regRecord;
int nCol;
int nGroupBy;
explainTempTable(pParse,
isDistinct && !(p->selFlags&SF_Distinct)?"DISTINCT":"GROUP BY");
groupBySort = 1;
nGroupBy = pGroupBy->nExpr;
nCol = nGroupBy + 1;
j = nGroupBy+1;
for(i=0; i<sAggInfo.nColumn; i++){
if( sAggInfo.aCol[i].iSorterColumn>=j ){
nCol++;
|
︙ | | |
91857
91858
91859
91860
91861
91862
91863
91864
91865
91866
91867
91868
91869
91870
91871
91872
91873
91874
91875
91876
91877
91878
91879
91880
91881
91882
91883
91884
91885
91886
91887
91888
91889
91890
91891
91892
91893
91894
91895
91896
|
91384
91385
91386
91387
91388
91389
91390
91391
91392
91393
91394
91395
91396
91397
91398
91399
91400
91401
91402
91403
91404
91405
91406
91407
91408
91409
91410
91411
91412
91413
91414
91415
91416
91417
|
-
-
-
-
-
-
|
pDest, addrEnd, addrEnd);
sqlite3ExprListDelete(db, pDel);
}
sqlite3VdbeResolveLabel(v, addrEnd);
} /* endif aggregate query */
if( distinct>=0 ){
explainTempTable(pParse, "DISTINCT");
}
/* If there is an ORDER BY clause, then we need to sort the results
** and send them to the callback one by one.
*/
if( pOrderBy ){
explainTempTable(pParse, "ORDER BY");
generateSortTail(pParse, p, v, pEList->nExpr, pDest);
}
/* Jump here to skip this query
*/
sqlite3VdbeResolveLabel(v, iEnd);
/* The SELECT was successfully coded. Set the return code to 0
** to indicate no errors.
*/
rc = 0;
/* Control jumps to here if an error is encountered above, or upon
** successful coding of the SELECT.
*/
select_end:
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
/* Identify column names if results of the SELECT are to be output.
*/
if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
generateColumnNames(pParse, pTabList, pEList);
}
|
︙ | | |
94972
94973
94974
94975
94976
94977
94978
94979
94980
94981
94982
94983
94984
94985
94986
|
94493
94494
94495
94496
94497
94498
94499
94500
94501
94502
94503
94504
94505
94506
94507
|
-
+
|
pTab->aCol = pParse->pNewTable->aCol;
pTab->nCol = pParse->pNewTable->nCol;
pParse->pNewTable->nCol = 0;
pParse->pNewTable->aCol = 0;
}
db->pVTab = 0;
}else{
sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
sqlite3Error(db, SQLITE_ERROR, zErr);
sqlite3DbFree(db, zErr);
rc = SQLITE_ERROR;
}
pParse->declareVtab = 0;
if( pParse->pVdbe ){
sqlite3VdbeFinalize(pParse->pVdbe);
|
︙ | | |
95434
95435
95436
95437
95438
95439
95440
95441
95442
95443
95444
95445
95446
95447
|
94955
94956
94957
94958
94959
94960
94961
94962
94963
94964
94965
94966
94967
94968
94969
|
+
|
/*
** A WhereCost object records a lookup strategy and the estimated
** cost of pursuing that strategy.
*/
struct WhereCost {
WherePlan plan; /* The lookup strategy */
double rCost; /* Overall cost of pursuing this search strategy */
double nRow; /* Estimated number of output rows */
Bitmask used; /* Bitmask of cursors used by this plan */
};
/*
** Bitmasks for the operators that indices are able to exploit. An
** OR-ed combination of these values can be used when searching for
** terms in the where clause.
|
︙ | | |
95476
95477
95478
95479
95480
95481
95482
95483
95484
95485
95486
95487
95488
95489
95490
95491
95492
95493
95494
|
94998
94999
95000
95001
95002
95003
95004
95005
95006
95007
95008
95009
95010
95011
95012
95013
95014
95015
|
-
+
-
|
#define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */
#define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */
#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
#define WHERE_NOT_FULLSCAN 0x000f3000 /* Does not do a full table scan */
#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
#define WHERE_IDX_ONLY 0x00800000 /* Use index only - omit table */
#define WHERE_ORDERBY 0x01000000 /* Output will appear in correct order */
#define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
#define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
|
︙ | | |
96823
96824
96825
96826
96827
96828
96829
96830
96831
96832
96833
96834
96835
96836
96837
96838
96839
|
96344
96345
96346
96347
96348
96349
96350
96351
96352
96353
96354
96355
96356
96357
96358
96359
|
-
+
-
-
+
|
){
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */
WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
WhereTerm *pTerm; /* A single term of the WHERE clause */
/* No OR-clause optimization allowed if the INDEXED BY or NOT INDEXED clauses
/* No OR-clause optimization allowed if the NOT INDEXED clause is used */
** are used */
if( pSrc->notIndexed || pSrc->pIndex!=0 ){
if( pSrc->notIndexed ){
return;
}
/* Search the WHERE clause terms for a usable WO_OR term. */
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( pTerm->eOperator==WO_OR
&& ((pTerm->prereqAll & ~maskSrc) & notReady)==0
|
︙ | | |
96863
96864
96865
96866
96867
96868
96869
96870
96871
96872
96873
96874
96875
96876
96877
96878
96879
96880
96881
96882
96883
96884
96885
96886
96887
96888
96889
96890
96891
96892
96893
96894
96895
96896
96897
|
96383
96384
96385
96386
96387
96388
96389
96390
96391
96392
96393
96394
96395
96396
96397
96398
96399
96400
96401
96402
96403
96404
96405
96406
96407
96408
96409
96410
96411
96412
96413
96414
96415
96416
96417
|
-
+
+
-
|
tempWC.a = pOrTerm;
tempWC.nTerm = 1;
bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
}else{
continue;
}
rTotal += sTermCost.rCost;
nRow += sTermCost.plan.nRow;
nRow += sTermCost.nRow;
used |= sTermCost.used;
if( rTotal>=pCost->rCost ) break;
}
/* If there is an ORDER BY clause, increase the scan cost to account
** for the cost of the sort. */
if( pOrderBy!=0 ){
WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
rTotal, rTotal+nRow*estLog(nRow)));
rTotal += nRow*estLog(nRow);
}
/* If the cost of scanning using this OR term for optimization is
** less than the current cost stored in pCost, replace the contents
** of pCost. */
WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
if( rTotal<pCost->rCost ){
pCost->rCost = rTotal;
pCost->nRow = nRow;
pCost->used = used;
pCost->plan.nRow = nRow;
pCost->plan.wsFlags = flags;
pCost->plan.u.pTerm = pTerm;
}
}
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
}
|
︙ | | |
96967
96968
96969
96970
96971
96972
96973
96974
96975
96976
96977
96978
96979
96980
96981
|
96487
96488
96489
96490
96491
96492
96493
96494
96495
96496
96497
96498
96499
96500
96501
|
-
+
|
/* Search for any equality comparison term */
pWCEnd = &pWC->a[pWC->nTerm];
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
WHERETRACE(("auto-index reduces cost from %.2f to %.2f\n",
pCost->rCost, costTempIdx));
pCost->rCost = costTempIdx;
pCost->plan.nRow = logN + 1;
pCost->nRow = logN + 1;
pCost->plan.wsFlags = WHERE_TEMP_INDEX;
pCost->used = pTerm->prereqRight;
break;
}
}
}
#else
|
︙ | | |
98040
98041
98042
98043
98044
98045
98046
98047
98048
98049
98050
98051
98052
98053
98054
98055
98056
98057
98058
|
97560
97561
97562
97563
97564
97565
97566
97567
97568
97569
97570
97571
97572
97573
97574
97575
97576
97577
97578
|
-
+
+
-
|
notReady, nRow, cost, used
));
/* If this index is the best we have seen so far, then record this
** index and its cost in the pCost structure.
*/
if( (!pIdx || wsFlags)
&& (cost<pCost->rCost || (cost<=pCost->rCost && nRow<pCost->plan.nRow))
&& (cost<pCost->rCost || (cost<=pCost->rCost && nRow<pCost->nRow))
){
pCost->rCost = cost;
pCost->nRow = nRow;
pCost->used = used;
pCost->plan.nRow = nRow;
pCost->plan.wsFlags = (wsFlags&wsFlagMask);
pCost->plan.nEq = nEq;
pCost->plan.u.pIdx = pIdx;
}
/* If there was an INDEXED BY clause, then only that one index is
** considered. */
|
︙ | | |
98372
98373
98374
98375
98376
98377
98378
98379
98380
98381
98382
98383
98384
98385
98386
98387
98388
98389
98390
98391
98392
98393
98394
98395
98396
98397
98398
98399
98400
98401
98402
98403
98404
98405
98406
98407
98408
98409
98410
98411
98412
98413
98414
98415
98416
98417
98418
98419
98420
98421
98422
98423
98424
98425
98426
98427
98428
98429
98430
98431
98432
98433
98434
98435
98436
98437
98438
98439
98440
98441
98442
98443
98444
98445
98446
98447
98448
98449
98450
98451
98452
98453
98454
98455
98456
98457
98458
98459
98460
98461
98462
98463
98464
98465
98466
98467
98468
98469
98470
98471
98472
98473
98474
98475
98476
98477
98478
98479
98480
98481
98482
98483
98484
98485
98486
98487
98488
98489
98490
98491
98492
98493
98494
98495
98496
98497
98498
98499
98500
98501
98502
98503
98504
98505
98506
98507
98508
98509
98510
98511
98512
98513
98514
98515
98516
98517
98518
98519
98520
98521
98522
98523
98524
98525
98526
98527
98528
98529
98530
98531
98532
98533
98534
98535
98536
98537
98538
98539
98540
|
97892
97893
97894
97895
97896
97897
97898
97899
97900
97901
97902
97903
97904
97905
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
}
}
}
}
*pzAff = zAff;
return regBase;
}
#ifndef SQLITE_OMIT_EXPLAIN
/*
** This routine is a helper for explainIndexRange() below
**
** pStr holds the text of an expression that we are building up one term
** at a time. This routine adds a new term to the end of the expression.
** Terms are separated by AND so add the "AND" text for second and subsequent
** terms only.
*/
static void explainAppendTerm(
StrAccum *pStr, /* The text expression being built */
int iTerm, /* Index of this term. First is zero */
const char *zColumn, /* Name of the column */
const char *zOp /* Name of the operator */
){
if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5);
sqlite3StrAccumAppend(pStr, zColumn, -1);
sqlite3StrAccumAppend(pStr, zOp, 1);
sqlite3StrAccumAppend(pStr, "?", 1);
}
/*
** Argument pLevel describes a strategy for scanning table pTab. This
** function returns a pointer to a string buffer containing a description
** of the subset of table rows scanned by the strategy in the form of an
** SQL expression. Or, if all rows are scanned, NULL is returned.
**
** For example, if the query:
**
** SELECT * FROM t1 WHERE a=1 AND b>2;
**
** is run and there is an index on (a, b), then this function returns a
** string similar to:
**
** "a=? AND b>?"
**
** The returned pointer points to memory obtained from sqlite3DbMalloc().
** It is the responsibility of the caller to free the buffer when it is
** no longer required.
*/
static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
WherePlan *pPlan = &pLevel->plan;
Index *pIndex = pPlan->u.pIdx;
int nEq = pPlan->nEq;
int i, j;
Column *aCol = pTab->aCol;
int *aiColumn = pIndex->aiColumn;
StrAccum txt;
if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
return 0;
}
sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
txt.db = db;
sqlite3StrAccumAppend(&txt, " (", 2);
for(i=0; i<nEq; i++){
explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "=");
}
j = i;
if( pPlan->wsFlags&WHERE_BTM_LIMIT ){
explainAppendTerm(&txt, i++, aCol[aiColumn[j]].zName, ">");
}
if( pPlan->wsFlags&WHERE_TOP_LIMIT ){
explainAppendTerm(&txt, i, aCol[aiColumn[j]].zName, "<");
}
sqlite3StrAccumAppend(&txt, ")", 1);
return sqlite3StrAccumFinish(&txt);
}
/*
** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single
** record is added to the output to describe the table scan strategy in
** pLevel.
*/
static void explainOneScan(
Parse *pParse, /* Parse context */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
int iLevel, /* Value for "level" column of output */
int iFrom, /* Value for "from" column of output */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
if( pParse->explain==2 ){
u32 flags = pLevel->plan.wsFlags;
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
char *zMsg; /* Text to add to EQP output */
sqlite3_int64 nRow; /* Expected number of rows visited by scan */
int iId = pParse->iSelectId; /* Select id (left-most output column) */
int isSearch; /* True for a SEARCH. False for SCAN. */
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
isSearch = (pLevel->plan.nEq>0)
|| (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
if( pItem->pSelect ){
zMsg = sqlite3MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId);
}else{
zMsg = sqlite3MAppendf(db, zMsg, "%s TABLE %s", zMsg, pItem->zName);
}
if( pItem->zAlias ){
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
if( (flags & WHERE_INDEXED)!=0 ){
char *zWhere = explainIndexRange(db, pLevel, pItem->pTab);
zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
((flags & WHERE_IDX_ONLY)?"COVERING ":""),
((flags & WHERE_TEMP_INDEX)?"":" "),
((flags & WHERE_TEMP_INDEX)?"": pLevel->plan.u.pIdx->zName),
zWhere
);
sqlite3DbFree(db, zWhere);
}else if( flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
if( flags&WHERE_ROWID_EQ ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
}else if( flags&WHERE_BTM_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>?)", zMsg);
}else if( flags&WHERE_TOP_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid<?)", zMsg);
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
pVtabIdx->idxNum, pVtabIdx->idxStr);
}
#endif
if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
testcase( wctrlFlags & WHERE_ORDERBY_MIN );
nRow = 1;
}else{
nRow = (sqlite3_int64)pLevel->plan.nRow;
}
zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
}
}
#else
# define explainOneScan(u,v,w,x,y,z)
#endif /* SQLITE_OMIT_EXPLAIN */
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
static Bitmask codeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
|
︙ | | |
98935
98936
98937
98938
98939
98940
98941
98942
98943
98944
98945
98946
98947
98948
98949
|
98300
98301
98302
98303
98304
98305
98306
98307
98308
98309
98310
98311
98312
98313
98314
|
-
+
|
/* If there are inequality constraints, check that the value
** of the table column that the inequality contrains is not NULL.
** If it is, jump to the next iteration of the loop.
*/
r1 = sqlite3GetTempReg(pParse);
testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT );
testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT );
if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
if( pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
}
sqlite3ReleaseTempReg(pParse, r1);
/* Seek the table cursor, if required */
disableTerm(pLevel, pRangeStart);
|
︙ | | |
99069
99070
99071
99072
99073
99074
99075
99076
99077
99078
99079
99080
99081
99082
99083
99084
99085
|
98434
98435
98436
98437
98438
98439
98440
98441
98442
98443
98444
98445
98446
98447
|
-
-
-
|
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
/* Loop through table entries that match term pOrTerm. */
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
if( pSubWInfo ){
explainOneScan(
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
);
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
regRowid);
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
|
︙ | | |
99467
99468
99469
99470
99471
99472
99473
99474
99475
99476
99477
99478
99479
99480
99481
|
98829
98830
98831
98832
98833
98834
98835
98836
98837
98838
98839
98840
98841
98842
|
-
|
Bitmask m; /* Bitmask value for j or bestJ */
int isOptimal; /* Iterator for optimal/non-optimal search */
int nUnconstrained; /* Number tables without INDEXED BY */
Bitmask notIndexed; /* Mask of tables that cannot use an index */
memset(&bestPlan, 0, sizeof(bestPlan));
bestPlan.rCost = SQLITE_BIG_DBL;
WHERETRACE(("*** Begin search for loop %d ***\n", i));
/* Loop through the remaining entries in the FROM clause to find the
** next nested loop. The loop tests all FROM clause entries
** either once or twice.
**
** The first test is always performed if there are two or more entries
** remaining and never performed if there is only one FROM clause entry
|
︙ | | |
99532
99533
99534
99535
99536
99537
99538
99539
99540
99541
99542
99543
99544
99545
99546
99547
|
98893
98894
98895
98896
98897
98898
98899
98900
98901
98902
98903
98904
98905
98906
|
-
-
|
if( j==iFrom ) iFrom++;
continue;
}
mask = (isOptimal ? m : notReady);
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
if( pTabItem->pIndex==0 ) nUnconstrained++;
WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
j, isOptimal));
assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTabItem->pTab) ){
sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
&sCost, pp);
}else
|
︙ | | |
99584
99585
99586
99587
99588
99589
99590
99591
99592
99593
99594
99595
99596
99597
99598
99599
99600
99601
99602
99603
99604
99605
99606
99607
99608
99609
99610
99611
99612
99613
99614
99615
99616
99617
99618
99619
99620
99621
99622
99623
99624
99625
99626
99627
99628
99629
99630
99631
|
98943
98944
98945
98946
98947
98948
98949
98950
98951
98952
98953
98954
98955
98956
98957
98958
98959
98960
98961
98962
98963
98964
98965
98966
98967
98968
98969
98970
98971
98972
98973
98974
98975
98976
98977
98978
98979
98980
98981
98982
98983
98984
98985
|
-
+
-
-
-
-
+
+
-
+
-
-
+
-
-
+
-
|
*/
if( (sCost.used¬Ready)==0 /* (1) */
&& (bestJ<0 || (notIndexed&m)!=0 /* (2) */
|| (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
&& (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */
|| NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
&& (bestJ<0 || sCost.rCost<bestPlan.rCost /* (4) */
|| (sCost.rCost<=bestPlan.rCost
|| (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow))
&& sCost.plan.nRow<bestPlan.plan.nRow))
){
WHERETRACE(("=== table %d is best so far"
" with cost=%g and nRow=%g\n",
j, sCost.rCost, sCost.plan.nRow));
WHERETRACE(("... best so far with cost=%g and nRow=%g\n",
sCost.rCost, sCost.nRow));
bestPlan = sCost;
bestJ = j;
}
if( doNotReorder ) break;
}
}
assert( bestJ>=0 );
assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
WHERETRACE(("*** Optimizer selects table %d for loop %d"
WHERETRACE(("*** Optimizer selects table %d for loop %d\n", bestJ,
" with cost=%g and nRow=%g\n",
bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
pLevel-pWInfo->a));
if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
*ppOrderBy = 0;
}
andFlags &= bestPlan.plan.wsFlags;
pLevel->plan = bestPlan.plan;
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
pLevel->iIdxCur = pParse->nTab++;
}else{
pLevel->iIdxCur = -1;
}
notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
pLevel->iFrom = (u8)bestJ;
if( bestPlan.plan.nRow>=(double)1 ){
pParse->nQueryLoop *= bestPlan.plan.nRow;
if( bestPlan.nRow>=(double)1 ) pParse->nQueryLoop *= bestPlan.nRow;
}
/* Check that if the table scanned by this loop iteration had an
** INDEXED BY clause attached to it, that the named index is being
** used for the scan. If not, then query compilation has failed.
** Return an error.
*/
pIdx = pTabList->a[bestJ].pIndex;
|
︙ | | |
99665
99666
99667
99668
99669
99670
99671
99672
99673
99674
99675
99676
99677
99678
99679
99680
99681
99682
99683
99684
99685
99686
99687
|
99019
99020
99021
99022
99023
99024
99025
99026
99027
99028
99029
99030
99031
99032
99033
99034
99035
99036
99037
99038
99039
99040
99041
99042
99043
99044
99045
99046
99047
99048
99049
99050
99051
99052
99053
99054
99055
99056
99057
99058
99059
99060
99061
99062
99063
99064
99065
99066
99067
99068
99069
99070
|
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
|
}
/* Open all tables in the pTabList and any indices selected for
** searching those tables.
*/
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
notReady = ~(Bitmask)0;
pWInfo->nRowOut = (double)1;
for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
#ifndef SQLITE_OMIT_EXPLAIN
if( pParse->explain==2 ){
char *zMsg;
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
zMsg = sqlite3MPrintf(db, "TABLE %s", pItem->zName);
if( pItem->zAlias ){
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s WITH AUTOMATIC INDEX", zMsg);
}else if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s",
zMsg, pLevel->plan.u.pIdx->zName);
}else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
zMsg = sqlite3MAppendf(db, zMsg, "%s VIA MULTI-INDEX UNION", zMsg);
}else if( pLevel->plan.wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
pVtabIdx->idxNum, pVtabIdx->idxStr);
}
#endif
if( pLevel->plan.wsFlags & WHERE_ORDERBY ){
zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg);
}
sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC);
}
#endif /* SQLITE_OMIT_EXPLAIN */
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
pLevel->iTabCur = pTabItem->iCursor;
pWInfo->nRowOut *= pLevel->plan.nRow;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
/* Do nothing */
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
︙ | | |
99729
99730
99731
99732
99733
99734
99735
99736
99737
99738
99739
99740
99741
99742
99743
99744
99745
99746
|
99112
99113
99114
99115
99116
99117
99118
99119
99120
99121
99122
99123
99124
99125
99126
99127
|
-
-
-
+
|
/* Generate the code to do the search. Each iteration of the for
** loop below generates code for a single nested loop of the VM
** program.
*/
notReady = ~(Bitmask)0;
for(i=0; i<nTabList; i++){
WhereLevel *pLevel = &pWInfo->a[i];
explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
pWInfo->iContinue = pLevel->addrCont;
pWInfo->iContinue = pWInfo->a[i].addrCont;
}
#ifdef SQLITE_TEST /* For testing and debugging use only */
/* Record in the query plan information about the current table
** and the index used to access it (if any). If the table itself
** is not used, its name is just '{}'. If no index is used
** the index is listed as "{}". If the primary key is used the
|
︙ | | |
106134
106135
106136
106137
106138
106139
106140
106141
106142
106143
106144
106145
106146
106147
106148
106149
106150
106151
106152
106153
|
105515
105516
105517
105518
105519
105520
105521
105522
105523
105524
105525
105526
105527
105528
105529
105530
105531
105532
105533
105534
105535
|
-
-
-
-
-
-
+
+
+
+
+
+
+
|
p->xCmp = 0;
}
}
}
}
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1);
if( pColl==0 ) return SQLITE_NOMEM;
pColl->xCmp = xCompare;
pColl->pUser = pCtx;
pColl->xDel = xDel;
pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED));
pColl->type = collType;
if( pColl ){
pColl->xCmp = xCompare;
pColl->pUser = pCtx;
pColl->xDel = xDel;
pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED));
pColl->type = collType;
}
sqlite3Error(db, SQLITE_OK, 0);
return SQLITE_OK;
}
/*
** This array defines hard upper bounds on limit values. The
|
︙ | | |
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
|
107489
107490
107491
107492
107493
107494
107495
107496
107497
107498
107499
107500
107501
107502
107503
107504
107505
107506
107507
107508
107509
107510
107511
107512
107513
107514
107515
107516
107517
107518
107519
107520
107521
107522
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
|
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
|
** amalgamation.
*/
#ifndef SQLITE_AMALGAMATION
/*
** Macros indicating that conditional expressions are always true or
** false.
*/
#ifdef SQLITE_COVERAGE_TEST
# define ALWAYS(x) (1)
# define NEVER(X) (0)
#else
# define ALWAYS(x) (x)
# define NEVER(X) (x)
#endif
/*
** Internal types used by SQLite.
*/
typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
typedef short int i16; /* 2-byte (or larger) signed integer */
typedef unsigned int u32; /* 4-byte unsigned integer */
typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
/*
** Macro used to suppress compiler warnings for unused parameters.
*/
#define UNUSED_PARAMETER(x) (void)(x)
#endif
typedef struct Fts3Table Fts3Table;
typedef struct Fts3Cursor Fts3Cursor;
typedef struct Fts3Expr Fts3Expr;
typedef struct Fts3Phrase Fts3Phrase;
typedef struct Fts3PhraseToken Fts3PhraseToken;
typedef struct Fts3SegFilter Fts3SegFilter;
typedef struct Fts3DeferredToken Fts3DeferredToken;
typedef struct Fts3SegReader Fts3SegReader;
typedef struct Fts3SegReaderArray Fts3SegReaderArray;
typedef struct Fts3SegFilter Fts3SegFilter;
/*
** A connection to a fulltext index is an instance of the following
** structure. The xCreate and xConnect methods create an instance
** of this structure and xDestroy and xDisconnect free that instance.
** All other methods receive a pointer to the structure as one of their
** arguments.
*/
struct Fts3Table {
sqlite3_vtab base; /* Base class used by SQLite core */
sqlite3 *db; /* The database connection */
const char *zDb; /* logical database name */
const char *zName; /* virtual table name */
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[24];
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 bHasStat; /* True if %_stat table exists */
u8 bHasContent; /* True if %_content table exists */
u8 bHasDocsize; /* True if %_docsize table exists */
int nPgsz; /* Page size for host database */
char *zSegmentsTbl; /* Name of %_segments table */
sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
/* 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.
|
︙ | | |
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
|
107572
107573
107574
107575
107576
107577
107578
107579
107580
107581
107582
107583
107584
107585
107586
107587
107588
107589
107590
107591
107592
107593
|
-
-
-
-
-
-
-
|
struct Fts3Cursor {
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
i16 eSearch; /* Search strategy (see below) */
u8 isEof; /* True if at End Of Results */
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 */
Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
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 */
int eEvalmode; /* An FTS3_EVAL_XX constant */
int nRowAvg; /* Average size of database rows, in pages */
};
#define FTS3_EVAL_FILTER 0
#define FTS3_EVAL_NEXT 1
#define FTS3_EVAL_MATCHINFO 2
/*
** 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
**
** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
|
︙ | | |
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
|
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
|
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
|
#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
/*
** A "phrase" is a sequence of one or more tokens that must match in
** sequence. A single token is the base case and the most common case.
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
** nToken will be the number of tokens in the string.
** For a sequence of tokens contained in "...", nToken will be the number
** of tokens in the string.
**
** The nDocMatch and nMatch variables contain data that may be used by the
** matchinfo() function. They are populated when the full-text index is
** queried for hits on the phrase. If one or more tokens in the phrase
** are deferred, the nDocMatch and nMatch variables are populated based
** on the assumption that the
*/
struct Fts3PhraseToken {
char *z; /* Text of the token */
int n; /* Number of bytes in buffer z */
int isPrefix; /* True if token ends with a "*" character */
int bFulltext; /* True if full-text index was used */
Fts3SegReaderArray *pArray; /* Segment-reader for this token */
Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
};
struct Fts3Phrase {
/* Variables populated by fts3_expr.c when parsing a MATCH expression */
int nToken; /* Number of tokens in the phrase */
int iColumn; /* Index of column this phrase must match */
int isNot; /* Phrase prefixed by unary not (-) operator */
struct PhraseToken {
char *z; /* Text of the token */
int n; /* Number of bytes in buffer pointed to by z */
int isPrefix; /* True if token ends in with a "*" character */
Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
} aToken[1]; /* One entry for each token in the phrase */
};
/*
** A tree of these objects forms the RHS of a MATCH operator.
**
** If Fts3Expr.eType is either FTSQUERY_NEAR or FTSQUERY_PHRASE and isLoaded
** is true, then aDoclist points to a malloced buffer, size nDoclist bytes,
|
︙ | | |
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
|
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
|
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
|
#define FTSQUERY_NEAR 1
#define FTSQUERY_NOT 2
#define FTSQUERY_AND 3
#define FTSQUERY_OR 4
#define FTSQUERY_PHRASE 5
/* fts3_init.c */
SQLITE_PRIVATE int sqlite3Fts3DeleteVtab(int, sqlite3_vtab *);
SQLITE_PRIVATE int sqlite3Fts3InitVtab(int, sqlite3*, void*, int, const char*const*,
sqlite3_vtab **, char **);
/* fts3_write.c */
SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *);
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64,
sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**);
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 sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *);
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*);
SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*);
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *);
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
/* 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
|
︙ | | |
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
|
107709
107710
107711
107712
107713
107714
107715
107716
107717
107718
107719
107720
107721
107722
107723
107724
107725
107726
107727
107728
107729
107730
107731
|
-
+
-
-
-
+
+
-
|
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
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(Fts3Cursor *, Fts3Expr *);
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *);
SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
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 **, char **
SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash,
const char *, sqlite3_tokenizer **, const char **, char **
);
SQLITE_PRIVATE int sqlite3Fts3IsIdChar(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 *);
|
︙ | | |
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
|
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
|
-
+
+
+
-
+
+
-
+
|
** The xDisconnect() virtual table method.
*/
static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table *)pVtab;
int i;
assert( p->nPendingData==0 );
assert( p->pSegments==0 );
/* Free any prepared statements held */
for(i=0; i<SizeofArray(p->aStmt); i++){
sqlite3_finalize(p->aStmt[i]);
}
for(i=0; i<p->nLeavesStmt; i++){
sqlite3_finalize(p->aLeavesStmt[i]);
}
sqlite3_free(p->zSegmentsTbl);
sqlite3_free(p->zSelectLeaves);
sqlite3_free(p->aLeavesStmt);
/* 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 written
** 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.
*/
static void fts3DbExec(
int *pRc, /* Success code */
sqlite3 *db, /* Database in which to run SQL */
|
︙ | | |
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
|
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
|
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
|
}
/*
** Invoke sqlite3_declare_vtab() to declare the schema for the FTS3 table
** passed as the first argument. This is done as part of the xConnect()
** and xCreate() methods.
**
** If *pRc is non-zero when this function is called, it is a no-op.
** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
** before returning.
*/
static void fts3DeclareVtab(int *pRc, Fts3Table *p){
static int fts3DeclareVtab(Fts3Table *p){
if( *pRc==SQLITE_OK ){
int i; /* Iterator variable */
int rc; /* Return code */
char *zSql; /* SQL statement passed to declare_vtab() */
char *zCols; /* List of user defined columns */
int i; /* Iterator variable */
int rc; /* Return code */
char *zSql; /* SQL statement passed to declare_vtab() */
char *zCols; /* List of user defined columns */
/* Create a list of user columns for the virtual table */
zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
for(i=1; zCols && i<p->nColumn; i++){
zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
}
/* Create a list of user columns for the virtual table */
zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
for(i=1; zCols && i<p->nColumn; i++){
zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
}
/* Create the whole "CREATE TABLE" statement to pass to SQLite */
zSql = sqlite3_mprintf(
"CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN)", zCols, p->zName
);
if( !zCols || !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_declare_vtab(p->db, zSql);
}
/* Create the whole "CREATE TABLE" statement to pass to SQLite */
zSql = sqlite3_mprintf(
"CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN)", zCols, p->zName
);
if( !zCols || !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_declare_vtab(p->db, zSql);
}
sqlite3_free(zSql);
sqlite3_free(zCols);
*pRc = rc;
sqlite3_free(zSql);
sqlite3_free(zCols);
return rc;
}
}
/*
** 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.
**
** If the p->bHasDocsize boolean is true (indicating that this is an
** FTS4 table, not an FTS3 table) then also create the %_docsize and
** %_stat tables required by FTS4.
*/
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;
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 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'("
|
︙ | | |
108672
108673
108674
108675
108676
108677
108678
108679
108680
108681
108682
108683
108684
108685
108686
108687
|
108027
108028
108029
108030
108031
108032
108033
108034
108035
108036
108037
108038
108039
108040
|
-
-
|
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
);
}
if( p->bHasStat ){
fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);",
p->zDb, p->zName
);
}
return rc;
}
|
︙ | | |
108718
108719
108720
108721
108722
108723
108724
108725
108726
108727
108728
108729
108730
108731
108732
108733
108734
108735
108736
108737
108738
108739
108740
108741
108742
108743
108744
108745
108746
108747
108748
108749
108750
108751
108752
108753
108754
108755
108756
108757
108758
108759
108760
108761
108762
108763
108764
108765
108766
108767
108768
108769
108770
108771
108772
108773
108774
108775
108776
108777
108778
108779
108780
108781
108782
108783
108784
108785
108786
108787
108788
108789
108790
108791
|
108071
108072
108073
108074
108075
108076
108077
108078
108079
108080
108081
108082
108083
108084
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
);
rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0);
sqlite3_free(zSql);
*pResult = (u8)(res & 0xff);
if( rc!=SQLITE_ABORT ) *pRc = rc;
}
/*
** Store the current database page-size in bytes in p->nPgsz.
**
** If *pRc is non-zero when this function is called, it is a no-op.
** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
** before returning.
*/
static void fts3DatabasePageSize(int *pRc, Fts3Table *p){
if( *pRc==SQLITE_OK ){
int rc; /* Return code */
char *zSql; /* SQL text "PRAGMA %Q.page_size" */
sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb);
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
p->nPgsz = sqlite3_column_int(pStmt, 0);
rc = sqlite3_finalize(pStmt);
}
}
assert( p->nPgsz>0 || rc!=SQLITE_OK );
sqlite3_free(zSql);
*pRc = rc;
}
}
/*
** "Special" FTS4 arguments are column specifications of the following form:
**
** <key> = <value>
**
** There may not be whitespace surrounding the "=" character. The <value>
** term may be quoted, but the <key> may not.
*/
static int fts3IsSpecialColumn(
const char *z,
int *pnKey,
char **pzValue
){
char *zValue;
const char *zCsr = z;
while( *zCsr!='=' ){
if( *zCsr=='\0' ) return 0;
zCsr++;
}
*pnKey = zCsr-z;
zValue = sqlite3_mprintf("%s", &zCsr[1]);
if( zValue ){
sqlite3Fts3Dequote(zValue);
}
*pzValue = zValue;
return 1;
}
/*
** This function is the implementation of both the xConnect and xCreate
** methods of the FTS3 virtual table.
**
** The argv[] array contains the following:
**
** argv[0] -> module name ("fts3" or "fts4")
|
︙ | | |
108799
108800
108801
108802
108803
108804
108805
108806
108807
108808
108809
108810
108811
108812
108813
108814
108815
108816
108817
108818
108819
108820
108821
108822
108823
108824
108825
108826
108827
108828
108829
108830
108831
108832
108833
108834
108835
108836
108837
108838
108839
108840
108841
108842
108843
108844
108845
108846
108847
108848
108849
108850
108851
108852
108853
108854
108855
108856
108857
108858
108859
108860
108861
108862
108863
108864
108865
108866
108867
108868
108869
108870
108871
108872
108873
108874
108875
108876
108877
108878
108879
108880
108881
108882
108883
108884
108885
108886
108887
108888
108889
108890
108891
108892
108893
108894
108895
108896
108897
108898
108899
108900
108901
108902
108903
108904
108905
108906
108907
108908
108909
108910
108911
108912
108913
108914
108915
108916
108917
108918
108919
108920
108921
108922
108923
108924
108925
108926
108927
108928
108929
108930
108931
108932
108933
108934
108935
108936
108937
108938
108939
108940
108941
108942
108943
108944
108945
108946
108947
108948
108949
108950
108951
108952
108953
108954
108955
108956
108957
108958
108959
108960
108961
108962
108963
108964
108965
108966
108967
108968
108969
108970
108971
108972
108973
108974
108975
108976
108977
108978
|
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
|
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
-
-
+
-
+
-
-
+
-
-
|
void *pAux, /* Hash table containing tokenizers */
int argc, /* Number of elements in argv array */
const char * const *argv, /* xCreate/xConnect argument array */
sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
char **pzErr /* Write any error message here */
){
Fts3Hash *pHash = (Fts3Hash *)pAux;
Fts3Table *p = 0; /* Pointer to allocated vtab */
int rc = SQLITE_OK; /* Return code */
Fts3Table *p; /* Pointer to allocated vtab */
int rc; /* Return code */
int i; /* Iterator variable */
int nByte; /* Size of allocation used for *p */
int iCol; /* Column index */
int nString = 0; /* Bytes required to hold all column names */
int nCol = 0; /* Number of columns in the FTS table */
char *zCsr; /* Space for holding column names */
int nDb; /* Bytes required to hold database name */
int nName; /* Bytes required to hold table name */
int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
int bNoDocsize = 0; /* True to omit %_docsize table */
const char *zTokenizer = 0; /* Name of tokenizer to use */
const char **aCol; /* Array of column names */
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
assert( strlen(argv[0])==4 );
assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
|| (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
);
nDb = (int)strlen(argv[1]) + 1;
nName = (int)strlen(argv[2]) + 1;
aCol = (const char **)sqlite3_malloc(sizeof(const char *) * (argc-2) );
if( !aCol ) return SQLITE_NOMEM;
memset(aCol, 0, sizeof(const char *) * (argc-2));
/* Loop through all of the arguments passed by the user to the FTS3/4
** module (i.e. all the column names and special arguments). This loop
** does the following:
**
** + Figures out the number of columns the FTSX table will have, and
** the number of bytes of space that must be allocated to store copies
** of the column names.
**
** + If there is a tokenizer specification included in the arguments,
** initializes the tokenizer pTokenizer.
*/
for(i=3; rc==SQLITE_OK && i<argc; i++){
for(i=3; i<argc; i++){
char const *z = argv[i];
int nKey;
char *zVal;
/* Check if this is a tokenizer specification */
if( !pTokenizer
&& strlen(z)>8
&& 0==sqlite3_strnicmp(z, "tokenize", 8)
&& 0==sqlite3Fts3IsIdChar(z[8])
){
rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
rc = sqlite3Fts3InitTokenizer(pHash, z, &pTokenizer, &zTokenizer, pzErr);
}
/* Check if it is an FTS4 special argument. */
else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){
if( !zVal ){
rc = SQLITE_NOMEM;
if( rc!=SQLITE_OK ){
goto fts3_init_out;
}
if( nKey==9 && 0==sqlite3_strnicmp(z, "matchinfo", 9) ){
if( strlen(zVal)==4 && 0==sqlite3_strnicmp(zVal, "fts3", 4) ){
bNoDocsize = 1;
}else{
*pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
rc = SQLITE_ERROR;
}
return rc;
}
}else{
*pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
rc = SQLITE_ERROR;
}
sqlite3_free(zVal);
}
if( z!=zTokenizer ){
/* Otherwise, the argument is a column name. */
else {
nString += (int)(strlen(z) + 1);
aCol[nCol++] = z;
}
}
if( rc!=SQLITE_OK ) goto fts3_init_out;
if( nCol==0 ){
assert( nString==0 );
aCol[0] = "content";
nString = 8;
nCol = 1;
nCol = argc - 3 - (zTokenizer!=0);
}
if( pTokenizer==0 ){
rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
if( rc!=SQLITE_OK ) goto fts3_init_out;
}
assert( pTokenizer );
if( zTokenizer==0 ){
rc = sqlite3Fts3InitTokenizer(pHash, 0, &pTokenizer, 0, pzErr);
if( rc!=SQLITE_OK ){
return rc;
}
assert( pTokenizer );
}
if( nCol==0 ){
nCol = 1;
}
/* Allocate and populate the Fts3Table structure. */
nByte = sizeof(Fts3Table) + /* Fts3Table */
nCol * sizeof(char *) + /* azColumn */
nName + /* zName */
nDb + /* zDb */
nString; /* Space for azColumn strings */
p = (Fts3Table*)sqlite3_malloc(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
goto fts3_init_out;
}
memset(p, 0, nByte);
p->db = db;
p->nColumn = nCol;
p->nPendingData = 0;
p->azColumn = (char **)&p[1];
p->pTokenizer = pTokenizer;
p->nNodeSize = 1000;
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
p->bHasDocsize = (isFts4 && bNoDocsize==0);
p->bHasStat = isFts4;
zCsr = (char *)&p->azColumn[nCol];
fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1);
/* Fill in the zName and zDb fields of the vtab structure. */
zCsr = (char *)&p->azColumn[nCol];
p->zName = zCsr;
memcpy(zCsr, argv[2], nName);
zCsr += nName;
p->zDb = zCsr;
memcpy(zCsr, argv[1], nDb);
zCsr += nDb;
/* Fill in the azColumn array */
for(iCol=0; iCol<nCol; iCol++){
char *z;
int n;
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
memcpy(zCsr, z, n);
zCsr[n] = '\0';
sqlite3Fts3Dequote(zCsr);
p->azColumn[iCol] = zCsr;
zCsr += n+1;
assert( zCsr <= &((char *)p)[nByte] );
iCol = 0;
for(i=3; i<argc; i++){
if( argv[i]!=zTokenizer ){
char *z;
int n;
z = (char *)sqlite3Fts3NextToken(argv[i], &n);
memcpy(zCsr, z, n);
zCsr[n] = '\0';
sqlite3Fts3Dequote(zCsr);
p->azColumn[iCol++] = zCsr;
zCsr += n+1;
assert( zCsr <= &((char *)p)[nByte] );
}
}
if( iCol==0 ){
assert( nCol==1 );
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;
/* Figure out the page-size for the database. This is required in order to
** estimate the cost of loading large doclists from the database (see
** function sqlite3Fts3SegReaderCost() for details).
*/
fts3DatabasePageSize(&rc, p);
rc = fts3DeclareVtab(p);
if( rc!=SQLITE_OK ) goto fts3_init_out;
/* Declare the table schema to SQLite. */
fts3DeclareVtab(&rc, p);
*ppVTab = &p->base;
fts3_init_out:
assert( p || (pTokenizer && rc!=SQLITE_OK) );
sqlite3_free(aCol);
if( rc!=SQLITE_OK ){
if( p ){
fts3DisconnectMethod((sqlite3_vtab *)p);
}else if( pTokenizer ){
}else{
pTokenizer->pModule->xDestroy(pTokenizer);
}
}else{
*ppVTab = &p->base;
}
return rc;
}
/*
** The xConnect() and xCreate() methods for the virtual table. All the
** work is done in function fts3InitVtab().
|
︙ | | |
109076
109077
109078
109079
109080
109081
109082
109083
109084
109085
109086
109087
109088
109089
109090
109091
109092
109093
109094
109095
|
108321
108322
108323
108324
108325
108326
108327
108328
108329
108330
108331
108332
108333
108334
108335
108336
108337
108338
|
-
+
-
-
|
return SQLITE_OK;
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
static int fulltextClose(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_finalize(pCsr->pStmt);
sqlite3Fts3ExprFree(pCsr->pExpr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3_free(pCsr->aMatchinfo);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
|
︙ | | |
109120
109121
109122
109123
109124
109125
109126
109127
109128
109129
109130
109131
109132
109133
109134
109135
109136
109137
109138
109139
109140
109141
109142
109143
109144
109145
109146
109147
109148
109149
109150
109151
109152
109153
109154
109155
109156
109157
109158
109159
109160
109161
109162
109163
109164
109165
109166
109167
109168
109169
109170
109171
109172
109173
109174
109175
109176
109177
109178
109179
109180
109181
109182
109183
109184
109185
109186
109187
109188
109189
109190
109191
109192
109193
109194
109195
109196
109197
109198
109199
109200
109201
109202
109203
109204
109205
109206
109207
109208
109209
109210
109211
109212
109213
109214
109215
109216
109217
109218
109219
109220
109221
109222
109223
109224
109225
109226
109227
109228
109229
109230
109231
109232
109233
109234
109235
109236
109237
109238
109239
109240
109241
109242
109243
109244
109245
109246
109247
109248
109249
109250
109251
109252
109253
109254
109255
109256
109257
109258
109259
109260
109261
109262
109263
109264
109265
109266
109267
109268
109269
109270
109271
109272
109273
109274
109275
109276
109277
109278
109279
109280
109281
109282
109283
109284
109285
109286
109287
109288
109289
109290
109291
109292
109293
109294
109295
109296
109297
109298
109299
109300
109301
109302
109303
109304
109305
109306
109307
109308
109309
|
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
|
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
-
+
-
-
-
+
+
+
+
+
-
+
+
+
+
+
-
+
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
|
}
}else{
return SQLITE_OK;
}
}
/*
** This function is used to process a single interior node when searching
** a b-tree for a term or term prefix. The node data is passed to this
** function via the zNode/nNode parameters. The term to search for is
** passed in zTerm/nTerm.
** Advance the cursor to the next row in the %_content table that
** matches the search criteria. For a MATCH search, this will be
** the next row that matches. For a full-table scan, this will be
** simply the next row in the %_content table. For a docid lookup,
**
** If piFirst is not NULL, then this function sets *piFirst to the blockid
** of the child node that heads the sub-tree that may contain the term.
**
** If piLast is not NULL, then *piLast is set to the right-most child node
** that heads a sub-tree that may contain a term for which zTerm/nTerm is
** a prefix.
** this routine simply sets the EOF flag.
**
** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
** even if we reach end-of-file. The fts3EofMethod() will be called
** subsequently to determine whether or not an EOF was hit.
*/
static int fts3ScanInteriorNode(
static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
Fts3Table *p, /* Virtual table handle */
const char *zTerm, /* Term to select leaves for */
int nTerm, /* Size of term zTerm in bytes */
const char *zNode, /* Buffer containing segment interior node */
int nNode, /* Size of buffer at zNode */
sqlite3_int64 *piFirst, /* OUT: Selected child node */
sqlite3_int64 *piLast /* OUT: Selected child node */
){
int rc = SQLITE_OK; /* Return code */
const char *zCsr = zNode; /* Cursor to iterate through node */
const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
char *zBuffer = 0; /* Buffer to load terms into */
int nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
sqlite3_int64 iChild; /* Block id of child node to descend to */
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
/* Skip over the 'height' varint that occurs at the start of every
** interior node. Then load the blockid of the left-child of the b-tree
** node into variable iChild.
**
** Even if the data structure on disk is corrupted, this (reading two
** varints from the buffer) does not risk an overread. If zNode is a
** root node, then the buffer comes from a SELECT statement. SQLite does
** not make this guarantee explicitly, but in practice there are always
** either more than 20 bytes of allocated space following the nNode bytes of
** contents, or two zero bytes. Or, if the node is read from the %_segments
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
if( zCsr>=zEnd ){
return SQLITE_CORRUPT;
}
if( pCsr->aDoclist==0 ){
while( zCsr<zEnd && (piFirst || piLast) ){
int cmp; /* memcmp() result */
int nSuffix; /* Size of term suffix */
int nPrefix = 0; /* Size of term prefix */
int nBuffer; /* Total term size */
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
/* Load the next term on the node into zBuffer. Use realloc() to expand
** the size of zBuffer if required. */
if( !isFirstTerm ){
zCsr += sqlite3Fts3GetVarint32(zCsr, &nPrefix);
}
isFirstTerm = 0;
zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
pCsr->isEof = 1;
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
rc = SQLITE_CORRUPT;
rc = sqlite3_reset(pCsr->pStmt);
goto finish_scan;
}
if( nPrefix+nSuffix>nAlloc ){
char *zNew;
nAlloc = (nPrefix+nSuffix) * 2;
zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
if( !zNew ){
rc = SQLITE_NOMEM;
goto finish_scan;
}
zBuffer = zNew;
}
memcpy(&zBuffer[nPrefix], zCsr, nSuffix);
nBuffer = nPrefix + nSuffix;
zCsr += nSuffix;
}else if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
/* Compare the term we are searching for with the term just loaded from
** the interior node. If the specified term is greater than or equal
** to the term from the interior node, then all terms on the sub-tree
** headed by node iChild are smaller than zTerm. No need to search
** iChild.
**
** If the interior node term is larger than the specified term, then
** the tree headed by iChild may contain the specified term.
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
*piFirst = iChild;
piFirst = 0;
}
pCsr->isEof = 1;
}else{
sqlite3_reset(pCsr->pStmt);
if( piLast && cmp<0 ){
*piLast = iChild;
piLast = 0;
}
fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
iChild++;
};
if( piFirst ) *piFirst = iChild;
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
if( piLast ) *piLast = iChild;
}
finish_scan:
sqlite3_free(zBuffer);
return rc;
}
/*
** The buffer pointed to by argument zNode (size nNode bytes) contains an
** interior node of a b-tree segment. The zTerm buffer (size nTerm bytes)
** contains a term. This function searches the sub-tree headed by the zNode
** node for the range of leaf nodes that may contain the specified term
** or terms for which the specified term is a prefix.
**
** The buffer pointed to by argument zNode (size nNode bytes) contains the
** root node of a b-tree segment. The segment is guaranteed to be at least
** one level high (i.e. the root node is not also a leaf). If successful,
** this function locates the leaf node of the segment that may contain the
** term specified by arguments zTerm and nTerm and writes its block number
** to *piLeaf.
** If piLeaf is not NULL, then *piLeaf is set to the blockid of the
** left-most leaf node in the tree that may contain the specified term.
** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the
** right-most leaf node that may contain a term for which the specified
** term is a prefix.
**
** It is possible that the range of returned leaf nodes does not contain
** It is possible that the returned leaf node does not contain the specified
** the specified term or any terms for which it is a prefix. However, if the
** segment does contain any such terms, they are stored within the identified
** range. Because this function only inspects interior segment nodes (and
** never loads leaf nodes into memory), it is not possible to be sure.
** term. However, if the segment does contain said term, it is stored on
** the identified leaf node. Because this function only inspects interior
** segment nodes (and never loads leaf nodes into memory), it is not possible
** to be sure.
**
** If an error occurs, an error code other than SQLITE_OK is returned.
*/
static int fts3SelectLeaf(
Fts3Table *p, /* Virtual table handle */
const char *zTerm, /* Term to select leaves for */
int nTerm, /* Size of term zTerm in bytes */
const char *zNode, /* Buffer containing segment interior node */
int nNode, /* Size of buffer at zNode */
sqlite3_int64 *piLeaf, /* Selected leaf node */
sqlite3_int64 *piLeaf /* Selected leaf node */
sqlite3_int64 *piLeaf2 /* Selected leaf node */
){
int rc; /* Return code */
int iHeight; /* Height of this node in tree */
int rc = SQLITE_OK; /* Return code */
const char *zCsr = zNode; /* Cursor to iterate through node */
const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
char *zBuffer = 0; /* Buffer to load terms into */
int nAlloc = 0; /* Size of allocated buffer */
assert( piLeaf || piLeaf2 );
while( 1 ){
int isFirstTerm = 1; /* True when processing first term on page */
int iHeight; /* Height of this node in tree */
sqlite3_int64 iChild; /* Block id of child node to descend to */
int nBlock; /* Size of child node in bytes */
sqlite3Fts3GetVarint32(zNode, &iHeight);
zCsr += sqlite3Fts3GetVarint32(zCsr, &iHeight);
rc = fts3ScanInteriorNode(p, zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
if( rc==SQLITE_OK && iHeight>1 ){
char *zBlob = 0; /* Blob read from %_segments table */
int nBlob; /* Size of zBlob in bytes */
if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob);
if( rc==SQLITE_OK ){
while( zCsr<zEnd ){
int cmp; /* memcmp() result */
int nSuffix; /* Size of term suffix */
int nPrefix = 0; /* Size of term prefix */
int nBuffer; /* Total term size */
/* Load the next term on the node into zBuffer */
if( !isFirstTerm ){
zCsr += sqlite3Fts3GetVarint32(zCsr, &nPrefix);
}
isFirstTerm = 0;
zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
if( nPrefix+nSuffix>nAlloc ){
char *zNew;
nAlloc = (nPrefix+nSuffix) * 2;
zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
if( !zNew ){
sqlite3_free(zBuffer);
return SQLITE_NOMEM;
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
}
}
sqlite3_free(zBlob);
piLeaf = 0;
zBlob = 0;
}
if( rc==SQLITE_OK ){
zBuffer = zNew;
}
memcpy(&zBuffer[nPrefix], zCsr, nSuffix);
nBuffer = nPrefix + nSuffix;
zCsr += nSuffix;
/* Compare the term we are searching for with the term just loaded from
** the interior node. If the specified term is greater than or equal
** to the term from the interior node, then all terms on the sub-tree
** headed by node iChild are smaller than zTerm. No need to search
** iChild.
**
** If the interior node term is larger than the specified term, then
** the tree headed by iChild may contain the specified term.
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( cmp<0 || (cmp==0 && nBuffer>nTerm) ) break;
rc = sqlite3Fts3ReadBlock(p, piLeaf ? *piLeaf : *piLeaf2, &zBlob, &nBlob);
}
if( rc==SQLITE_OK ){
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
iChild++;
};
/* If (iHeight==1), the children of this interior node are leaves. The
** specified term may be present on leaf node iChild.
*/
if( iHeight==1 ){
*piLeaf = iChild;
break;
}
sqlite3_free(zBlob);
}
/* Descend to interior node iChild. */
rc = sqlite3Fts3ReadBlock(p, iChild, &zCsr, &nBlock);
if( rc!=SQLITE_OK ) break;
zEnd = &zCsr[nBlock];
}
sqlite3_free(zBuffer);
return rc;
}
/*
** This function is used to create delta-encoded serialized lists of FTS3
** varints. Each call to this function appends a single varint to a list.
*/
|
︙ | | |
109527
109528
109529
109530
109531
109532
109533
109534
109535
109536
109537
109538
109539
109540
109541
109542
109543
109544
109545
109546
109547
109548
109549
109550
109551
109552
109553
109554
109555
109556
109557
109558
109559
109560
109561
109562
109563
109564
109565
109566
109567
109568
109569
109570
109571
109572
109573
109574
109575
109576
109577
109578
|
108718
108719
108720
108721
108722
108723
108724
108725
108726
108727
108728
108729
108730
108731
108732
108733
108734
108735
108736
108737
108738
108739
108740
108741
108742
108743
108744
108745
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
-
-
-
-
|
*pp = p;
*pp1 = p1 + 1;
*pp2 = p2 + 1;
}
/*
** nToken==1 searches for adjacent positions.
**
** This function is used to merge two position lists into one. When it is
** called, *pp1 and *pp2 must both point to position lists. A position-list is
** the part of a doclist that follows each document id. For example, if a row
** contains:
**
** 'a b c'|'x y z'|'a b b a'
**
** Then the position list for this row for token 'b' would consist of:
**
** 0x02 0x01 0x02 0x03 0x03 0x00
**
** When this function returns, both *pp1 and *pp2 are left pointing to the
** byte following the 0x00 terminator of their respective position lists.
**
** If isSaveLeft is 0, an entry is added to the output position list for
** each position in *pp2 for which there exists one or more positions in
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
** when the *pp1 token appears before the *pp2 token, but not more than nToken
** slots before it.
*/
static int fts3PoslistPhraseMerge(
char **pp, /* IN/OUT: Preallocated output buffer */
char **pp, /* Output buffer */
int nToken, /* Maximum difference in token positions */
int isSaveLeft, /* Save the left position */
int isExact, /* If *pp1 is exactly nTokens before *pp2 */
char **pp1, /* IN/OUT: Left input list */
char **pp2 /* IN/OUT: Right input list */
char **pp1, /* Left input list */
char **pp2 /* Right input list */
){
char *p = (pp ? *pp : 0);
char *p1 = *pp1;
char *p2 = *pp2;
int iCol1 = 0;
int iCol2 = 0;
/* Never set both isSaveLeft and isExact for the same invocation. */
assert( isSaveLeft==0 || isExact==0 );
assert( *p1!=0 && *p2!=0 );
if( *p1==POS_COLUMN ){
p1++;
p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
}
if( *p2==POS_COLUMN ){
p2++;
|
︙ | | |
109593
109594
109595
109596
109597
109598
109599
109600
109601
109602
109603
109604
109605
109606
109607
109608
109609
|
108760
108761
108762
108763
108764
108765
108766
108767
108768
108769
108770
108771
108772
108773
108774
|
-
-
+
-
|
assert( *p1!=POS_END && *p1!=POS_COLUMN );
assert( *p2!=POS_END && *p2!=POS_COLUMN );
fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
while( 1 ){
if( iPos2==iPos1+nToken
|| (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
if( iPos2>iPos1 && iPos2<=iPos1+nToken ){
){
sqlite3_int64 iSave;
if( !pp ){
fts3PoslistCopy(0, &p2);
fts3PoslistCopy(0, &p1);
*pp1 = p1;
*pp2 = p2;
return 1;
|
︙ | | |
109678
109679
109680
109681
109682
109683
109684
109685
109686
109687
109688
109689
109690
109691
109692
109693
109694
109695
109696
109697
109698
109699
109700
109701
109702
109703
109704
109705
109706
|
108843
108844
108845
108846
108847
108848
108849
108850
108851
108852
108853
108854
108855
108856
108857
108858
108859
108860
108861
108862
108863
108864
108865
108866
108867
108868
108869
108870
108871
|
-
+
-
+
-
+
-
+
|
char **pp1, /* IN/OUT: Left input list */
char **pp2 /* IN/OUT: Right input list */
){
char *p1 = *pp1;
char *p2 = *pp2;
if( !pp ){
if( fts3PoslistPhraseMerge(0, nRight, 0, 0, pp1, pp2) ) return 1;
if( fts3PoslistPhraseMerge(0, nRight, 0, pp1, pp2) ) return 1;
*pp1 = p1;
*pp2 = p2;
return fts3PoslistPhraseMerge(0, nLeft, 0, 0, pp2, pp1);
return fts3PoslistPhraseMerge(0, nLeft, 0, pp2, pp1);
}else{
char *pTmp1 = aTmp;
char *pTmp2;
char *aTmp2;
int res = 1;
fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
fts3PoslistPhraseMerge(&pTmp1, nRight, 0, pp1, pp2);
aTmp2 = pTmp2 = pTmp1;
*pp1 = p1;
*pp2 = p2;
fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, pp2, pp1);
if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
fts3PoslistMerge(pp, &aTmp, &aTmp2);
}else if( pTmp1!=aTmp ){
fts3PoslistCopy(pp, &aTmp);
}else if( pTmp2!=aTmp2 ){
fts3PoslistCopy(pp, &aTmp2);
}else{
|
︙ | | |
109738
109739
109740
109741
109742
109743
109744
109745
109746
109747
109748
109749
109750
109751
109752
109753
109754
109755
109756
109757
109758
109759
109760
109761
109762
109763
109764
|
108903
108904
108905
108906
108907
108908
108909
108910
108911
108912
108913
108914
108915
108916
108917
108918
108919
108920
108921
108922
108923
108924
108925
108926
108927
|
-
+
-
-
|
int nParam1, /* Used by MERGE_NEAR and MERGE_POS_NEAR */
int nParam2, /* Used by MERGE_NEAR and MERGE_POS_NEAR */
char *aBuffer, /* Pre-allocated output buffer */
int *pnBuffer, /* OUT: Bytes written to aBuffer */
char *a1, /* Buffer containing first doclist */
int n1, /* Size of buffer a1 */
char *a2, /* Buffer containing second doclist */
int n2, /* Size of buffer a2 */
int n2 /* Size of buffer a2 */
int *pnDoc /* OUT: Number of docids in output */
){
sqlite3_int64 i1 = 0;
sqlite3_int64 i2 = 0;
sqlite3_int64 iPrev = 0;
char *p = aBuffer;
char *p1 = a1;
char *p2 = a2;
char *pEnd1 = &a1[n1];
char *pEnd2 = &a2[n2];
int nDoc = 0;
assert( mergetype==MERGE_OR || mergetype==MERGE_POS_OR
|| mergetype==MERGE_AND || mergetype==MERGE_NOT
|| mergetype==MERGE_PHRASE || mergetype==MERGE_POS_PHRASE
|| mergetype==MERGE_NEAR || mergetype==MERGE_POS_NEAR
);
|
︙ | | |
109794
109795
109796
109797
109798
109799
109800
109801
109802
109803
109804
109805
109806
109807
109808
|
108957
108958
108959
108960
108961
108962
108963
108964
108965
108966
108967
108968
108969
108970
|
-
|
case MERGE_AND:
while( p1 && p2 ){
if( i1==i2 ){
fts3PutDeltaVarint(&p, &iPrev, i1);
fts3GetDeltaVarint2(&p1, pEnd1, &i1);
fts3GetDeltaVarint2(&p2, pEnd2, &i2);
nDoc++;
}else if( i1<i2 ){
fts3GetDeltaVarint2(&p1, pEnd1, &i1);
}else{
fts3GetDeltaVarint2(&p2, pEnd2, &i2);
}
}
break;
|
︙ | | |
109825
109826
109827
109828
109829
109830
109831
109832
109833
109834
109835
109836
109837
109838
109839
109840
109841
109842
109843
|
108987
108988
108989
108990
108991
108992
108993
108994
108995
108996
108997
108998
108999
109000
109001
109002
109003
|
-
+
-
-
|
case MERGE_PHRASE: {
char **ppPos = (mergetype==MERGE_PHRASE ? 0 : &p);
while( p1 && p2 ){
if( i1==i2 ){
char *pSave = p;
sqlite3_int64 iPrevSave = iPrev;
fts3PutDeltaVarint(&p, &iPrev, i1);
if( 0==fts3PoslistPhraseMerge(ppPos, nParam1, 0, 1, &p1, &p2) ){
if( 0==fts3PoslistPhraseMerge(ppPos, 1, 0, &p1, &p2) ){
p = pSave;
iPrev = iPrevSave;
}else{
nDoc++;
}
fts3GetDeltaVarint2(&p1, pEnd1, &i1);
fts3GetDeltaVarint2(&p2, pEnd2, &i2);
}else if( i1<i2 ){
fts3PoslistCopy(0, &p1);
fts3GetDeltaVarint2(&p1, pEnd1, &i1);
}else{
|
︙ | | |
109882
109883
109884
109885
109886
109887
109888
109889
109890
109891
109892
109893
109894
109895
109896
|
109042
109043
109044
109045
109046
109047
109048
109049
109050
109051
109052
109053
109054
109055
|
-
|
}
}
sqlite3_free(aTmp);
break;
}
}
if( pnDoc ) *pnDoc = nDoc;
*pnBuffer = (int)(p-aBuffer);
return SQLITE_OK;
}
/*
** A pointer to an instance of this structure is used as the context
** argument to sqlite3Fts3SegReaderIterate()
|
︙ | | |
109921
109922
109923
109924
109925
109926
109927
109928
109929
109930
109931
109932
109933
109934
109935
109936
109937
109938
109939
109940
109941
109942
109943
109944
|
109080
109081
109082
109083
109084
109085
109086
109087
109088
109089
109090
109091
109092
109093
109094
109095
109096
109097
109098
109099
109100
109101
109102
109103
|
-
+
-
+
|
** into a single doclist.
*/
for(i=0; i<SizeofArray(pTS->aaOutput); i++){
if( pTS->aaOutput[i] ){
if( !aOut ){
aOut = pTS->aaOutput[i];
nOut = pTS->anOutput[i];
pTS->aaOutput[i] = 0;
pTS->aaOutput[0] = 0;
}else{
int nNew = nOut + pTS->anOutput[i];
char *aNew = sqlite3_malloc(nNew);
if( !aNew ){
sqlite3_free(aOut);
return SQLITE_NOMEM;
}
fts3DoclistMerge(mergetype, 0, 0,
aNew, &nNew, pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, 0
aNew, &nNew, pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut
);
sqlite3_free(pTS->aaOutput[i]);
sqlite3_free(aOut);
pTS->aaOutput[i] = 0;
aOut = aNew;
nOut = nNew;
}
|
︙ | | |
110001
110002
110003
110004
110005
110006
110007
110008
110009
110010
110011
110012
110013
110014
110015
110016
110017
110018
110019
110020
110021
110022
110023
110024
110025
110026
110027
110028
110029
110030
110031
110032
110033
110034
110035
110036
110037
110038
110039
110040
110041
110042
110043
110044
110045
110046
110047
110048
110049
110050
110051
110052
110053
110054
110055
110056
110057
110058
110059
110060
110061
110062
110063
110064
110065
110066
110067
110068
110069
110070
110071
110072
110073
110074
110075
110076
110077
110078
110079
110080
110081
110082
110083
110084
110085
110086
110087
110088
110089
110090
110091
110092
110093
110094
110095
110096
110097
110098
110099
110100
110101
110102
110103
110104
110105
110106
110107
110108
110109
110110
110111
110112
110113
110114
110115
110116
110117
110118
110119
110120
110121
110122
110123
110124
110125
110126
110127
110128
110129
110130
110131
110132
110133
110134
110135
110136
110137
110138
110139
110140
110141
110142
110143
110144
110145
110146
110147
110148
110149
110150
110151
110152
110153
110154
110155
110156
110157
110158
110159
110160
110161
110162
110163
110164
110165
110166
110167
110168
110169
110170
110171
110172
110173
110174
110175
110176
110177
110178
110179
110180
110181
110182
110183
110184
110185
110186
110187
110188
110189
110190
110191
110192
110193
110194
110195
110196
110197
110198
110199
110200
110201
110202
110203
110204
110205
110206
110207
110208
110209
110210
110211
110212
110213
110214
110215
110216
110217
110218
110219
110220
110221
110222
110223
110224
110225
110226
110227
110228
110229
110230
110231
110232
110233
110234
110235
110236
110237
110238
110239
110240
110241
110242
110243
110244
110245
110246
110247
110248
110249
110250
110251
110252
110253
110254
110255
110256
110257
110258
110259
110260
110261
110262
110263
110264
110265
110266
110267
110268
110269
110270
110271
110272
110273
110274
110275
110276
110277
110278
110279
110280
110281
110282
110283
110284
110285
110286
110287
110288
110289
110290
110291
110292
110293
110294
110295
110296
110297
110298
110299
110300
110301
110302
110303
110304
110305
110306
110307
110308
110309
110310
110311
110312
110313
110314
110315
110316
110317
110318
110319
110320
110321
110322
110323
110324
110325
110326
110327
110328
110329
110330
110331
110332
110333
110334
110335
110336
110337
110338
110339
110340
110341
110342
110343
110344
110345
110346
110347
110348
110349
110350
110351
110352
110353
110354
110355
110356
110357
110358
110359
110360
110361
110362
110363
110364
110365
110366
110367
110368
110369
110370
110371
110372
110373
110374
110375
110376
110377
110378
110379
110380
110381
110382
110383
110384
110385
110386
110387
110388
110389
110390
110391
110392
110393
110394
110395
110396
110397
110398
110399
110400
110401
110402
110403
110404
110405
110406
110407
110408
110409
110410
110411
110412
110413
110414
110415
110416
110417
110418
110419
110420
110421
110422
110423
110424
110425
110426
110427
110428
110429
110430
110431
110432
110433
110434
110435
110436
110437
110438
110439
110440
110441
110442
110443
110444
110445
110446
110447
110448
110449
110450
110451
110452
110453
110454
110455
110456
110457
110458
110459
110460
110461
110462
110463
110464
110465
110466
110467
110468
110469
110470
110471
110472
110473
110474
110475
110476
110477
110478
110479
110480
110481
110482
110483
110484
110485
110486
110487
110488
110489
110490
110491
110492
110493
110494
110495
110496
110497
110498
110499
110500
110501
110502
110503
110504
110505
110506
110507
110508
110509
110510
110511
110512
110513
110514
110515
110516
110517
110518
110519
110520
110521
110522
110523
110524
110525
110526
110527
110528
110529
110530
110531
110532
110533
110534
110535
110536
110537
110538
110539
110540
110541
110542
110543
110544
110545
110546
110547
110548
110549
110550
110551
110552
110553
110554
110555
110556
110557
110558
|
109160
109161
109162
109163
109164
109165
109166
109167
109168
109169
109170
109171
109172
109173
109174
109175
109176
109177
109178
109179
109180
109181
109182
109183
109184
109185
109186
109187
109188
109189
109190
109191
109192
109193
109194
109195
109196
109197
109198
109199
109200
109201
109202
109203
109204
109205
109206
109207
109208
109209
109210
109211
109212
109213
109214
109215
109216
109217
109218
109219
109220
109221
109222
109223
109224
109225
109226
109227
109228
109229
109230
109231
109232
109233
109234
109235
109236
109237
109238
109239
109240
109241
109242
109243
109244
109245
109246
109247
109248
109249
109250
109251
109252
109253
109254
109255
109256
109257
109258
109259
109260
109261
109262
109263
109264
109265
109266
109267
109268
109269
109270
109271
109272
109273
109274
109275
109276
109277
109278
109279
109280
109281
109282
109283
109284
109285
109286
109287
109288
109289
109290
109291
109292
109293
109294
109295
109296
109297
109298
109299
109300
109301
109302
109303
109304
109305
109306
109307
109308
109309
109310
109311
109312
109313
109314
109315
109316
109317
109318
109319
109320
109321
109322
109323
109324
109325
109326
109327
109328
109329
109330
109331
109332
109333
109334
109335
109336
109337
109338
109339
109340
109341
109342
109343
109344
109345
109346
109347
109348
109349
109350
109351
109352
109353
109354
109355
109356
109357
109358
109359
109360
109361
109362
109363
109364
109365
109366
109367
109368
109369
109370
109371
109372
109373
109374
109375
109376
109377
109378
109379
109380
109381
109382
109383
109384
109385
109386
109387
109388
109389
109390
109391
109392
109393
109394
109395
109396
109397
109398
109399
109400
109401
109402
109403
109404
109405
109406
109407
109408
109409
109410
109411
109412
109413
109414
109415
109416
109417
109418
109419
109420
109421
109422
109423
109424
109425
109426
109427
109428
109429
109430
109431
109432
109433
109434
109435
109436
109437
109438
109439
109440
|
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
|
aNew = sqlite3_malloc(nNew);
if( !aNew ){
if( aMerge!=aDoclist ){
sqlite3_free(aMerge);
}
return SQLITE_NOMEM;
}
fts3DoclistMerge(mergetype, 0, 0, aNew, &nNew,
pTS->aaOutput[iOut], pTS->anOutput[iOut], aMerge, nMerge, 0
fts3DoclistMerge(mergetype, 0, 0,
aNew, &nNew, pTS->aaOutput[iOut], pTS->anOutput[iOut], aMerge, nMerge
);
if( iOut>0 ) sqlite3_free(aMerge);
sqlite3_free(pTS->aaOutput[iOut]);
pTS->aaOutput[iOut] = 0;
aMerge = aNew;
nMerge = nNew;
if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
pTS->aaOutput[iOut] = aMerge;
pTS->anOutput[iOut] = nMerge;
}
}
}
return SQLITE_OK;
}
static int fts3DeferredTermSelect(
Fts3DeferredToken *pToken, /* Phrase token */
int isTermPos, /* True to include positions */
int *pnOut, /* OUT: Size of list */
char **ppOut /* OUT: Body of list */
){
char *aSource;
int nSource;
aSource = sqlite3Fts3DeferredDoclist(pToken, &nSource);
if( !aSource ){
*pnOut = 0;
*ppOut = 0;
}else if( isTermPos ){
*ppOut = sqlite3_malloc(nSource);
if( !*ppOut ) return SQLITE_NOMEM;
memcpy(*ppOut, aSource, nSource);
*pnOut = nSource;
}else{
sqlite3_int64 docid;
*pnOut = sqlite3Fts3GetVarint(aSource, &docid);
*ppOut = sqlite3_malloc(*pnOut);
if( !*ppOut ) return SQLITE_NOMEM;
sqlite3Fts3PutVarint(*ppOut, docid);
}
return SQLITE_OK;
}
/*
** An Fts3SegReaderArray is used to store an array of Fts3SegReader objects.
** Elements are added to the array using fts3SegReaderArrayAdd().
*/
struct Fts3SegReaderArray {
int nSegment; /* Number of valid entries in apSegment[] */
int nAlloc; /* Allocated size of apSegment[] */
int nCost; /* The cost of executing SegReaderIterate() */
Fts3SegReader *apSegment[1]; /* Array of seg-reader objects */
};
/*
** Free an Fts3SegReaderArray object. Also free all seg-readers in the
** array (using sqlite3Fts3SegReaderFree()).
*/
static void fts3SegReaderArrayFree(Fts3SegReaderArray *pArray){
if( pArray ){
int i;
for(i=0; i<pArray->nSegment; i++){
sqlite3Fts3SegReaderFree(0, pArray->apSegment[i]);
}
sqlite3_free(pArray);
}
}
static int fts3SegReaderArrayAdd(
Fts3SegReaderArray **ppArray,
Fts3SegReader *pNew
){
Fts3SegReaderArray *pArray = *ppArray;
if( !pArray || pArray->nAlloc==pArray->nSegment ){
int nNew = (pArray ? pArray->nAlloc+16 : 16);
pArray = (Fts3SegReaderArray *)sqlite3_realloc(pArray,
sizeof(Fts3SegReaderArray) + (nNew-1) * sizeof(Fts3SegReader*)
);
if( !pArray ){
sqlite3Fts3SegReaderFree(0, pNew);
return SQLITE_NOMEM;
}
if( nNew==16 ){
pArray->nSegment = 0;
pArray->nCost = 0;
}
pArray->nAlloc = nNew;
*ppArray = pArray;
}
pArray->apSegment[pArray->nSegment++] = pNew;
return SQLITE_OK;
}
static int fts3TermSegReaderArray(
Fts3Cursor *pCsr, /* Virtual table cursor handle */
const char *zTerm, /* Term to query for */
int nTerm, /* Size of zTerm in bytes */
int isPrefix, /* True for a prefix search */
Fts3SegReaderArray **ppArray /* OUT: Allocated seg-reader array */
){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
int rc; /* Return code */
Fts3SegReaderArray *pArray = 0; /* Array object to build */
Fts3SegReader *pReader = 0; /* Seg-reader to add to pArray */
sqlite3_stmt *pStmt = 0; /* SQL statement to scan %_segdir table */
int iAge = 0; /* Used to assign ages to segments */
/* Allocate a seg-reader to scan the pending terms, if any. */
rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &pReader);
if( rc==SQLITE_OK && pReader ) {
rc = fts3SegReaderArrayAdd(&pArray, pReader);
}
/* Loop through the entire %_segdir table. For each segment, create a
** Fts3SegReader to iterate through the subset of the segment leaves
** that may contain a term that matches zTerm/nTerm. For non-prefix
** searches, this is always a single leaf. For prefix searches, this
** may be a contiguous block of leaves.
*/
if( rc==SQLITE_OK ){
rc = sqlite3Fts3AllSegdirs(p, &pStmt);
}
while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
Fts3SegReader *pNew = 0;
int nRoot = sqlite3_column_bytes(pStmt, 4);
char const *zRoot = sqlite3_column_blob(pStmt, 4);
if( sqlite3_column_int64(pStmt, 1)==0 ){
/* The entire segment is stored on the root node (which must be a
** leaf). Do not bother inspecting any data in this case, just
** create a Fts3SegReader to scan the single leaf.
*/
rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew);
}else{
sqlite3_int64 i1; /* First leaf that may contain zTerm */
sqlite3_int64 i2; /* Final leaf that may contain zTerm */
rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1, (isPrefix?&i2:0));
if( isPrefix==0 ) i2 = i1;
if( rc==SQLITE_OK ){
rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew);
}
}
assert( (pNew==0)==(rc!=SQLITE_OK) );
/* If a new Fts3SegReader was allocated, add it to the array. */
if( rc==SQLITE_OK ){
rc = fts3SegReaderArrayAdd(&pArray, pNew);
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts3SegReaderCost(pCsr, pNew, &pArray->nCost);
}
iAge++;
}
if( rc==SQLITE_DONE ){
rc = sqlite3_reset(pStmt);
}else{
sqlite3_reset(pStmt);
}
if( rc!=SQLITE_OK ){
fts3SegReaderArrayFree(pArray);
pArray = 0;
}
*ppArray = pArray;
return rc;
}
/*
** This function retreives the doclist for the specified term (or term
** prefix) from the database.
**
** The returned doclist may be in one of two formats, depending on the
** value of parameter isReqPos. If isReqPos is zero, then the doclist is
** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
** is non-zero, then the returned list is in the same format as is stored
** in the database without the found length specifier at the start of on-disk
** doclists.
*/
static int fts3TermSelect(
Fts3Table *p, /* Virtual table handle */
Fts3PhraseToken *pTok, /* Token to query for */
int iColumn, /* Column to query (or -ve for all columns) */
const char *zTerm, /* Term to query for */
int nTerm, /* Size of zTerm in bytes */
int isPrefix, /* True for a prefix search */
int isReqPos, /* True to include position lists in output */
int *pnOut, /* OUT: Size of buffer at *ppOut */
char **ppOut /* OUT: Malloced result buffer */
){
int i;
TermSelect tsc;
Fts3SegFilter filter; /* Segment term filter configuration */
Fts3SegReader **apSegment; /* Array of segments to read data from */
int nSegment = 0; /* Size of apSegment array */
int nAlloc = 16; /* Allocated size of segment array */
int rc; /* Return code */
sqlite3_stmt *pStmt = 0; /* SQL statement to scan %_segdir table */
int iAge = 0; /* Used to assign ages to segments */
apSegment = (Fts3SegReader **)sqlite3_malloc(sizeof(Fts3SegReader*)*nAlloc);
if( !apSegment ) return SQLITE_NOMEM;
rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &apSegment[0]);
if( rc!=SQLITE_OK ) goto finished;
if( apSegment[0] ){
nSegment = 1;
}
/* Loop through the entire %_segdir table. For each segment, create a
** Fts3SegReader to iterate through the subset of the segment leaves
** that may contain a term that matches zTerm/nTerm. For non-prefix
** searches, this is always a single leaf. For prefix searches, this
** may be a contiguous block of leaves.
**
** The code in this loop does not actually load any leaves into memory
** (unless the root node happens to be a leaf). It simply examines the
** b-tree structure to determine which leaves need to be inspected.
*/
rc = sqlite3Fts3AllSegdirs(p, &pStmt);
while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
Fts3SegReaderArray *pArray; /* Seg-reader array for this term */
TermSelect tsc; /* Context object for fts3TermSelectCb() */
Fts3SegFilter filter; /* Segment term filter configuration */
pArray = pTok->pArray;
Fts3SegReader *pNew = 0;
int nRoot = sqlite3_column_bytes(pStmt, 4);
char const *zRoot = sqlite3_column_blob(pStmt, 4);
if( sqlite3_column_int64(pStmt, 1)==0 ){
/* The entire segment is stored on the root node (which must be a
** leaf). Do not bother inspecting any data in this case, just
** create a Fts3SegReader to scan the single leaf.
*/
rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew);
}else{
int rc2; /* Return value of sqlite3Fts3ReadBlock() */
sqlite3_int64 i1; /* Blockid of leaf that may contain zTerm */
rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1);
if( rc==SQLITE_OK ){
sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2);
rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew);
}
/* The following call to ReadBlock() serves to reset the SQL statement
** used to retrieve blocks of data from the %_segments table. If it is
** not reset here, then it may remain classified as an active statement
** by SQLite, which may lead to "DROP TABLE" or "DETACH" commands
** failing.
*/
rc2 = sqlite3Fts3ReadBlock(p, 0, 0, 0);
if( rc==SQLITE_OK ){
rc = rc2;
}
}
iAge++;
/* If a new Fts3SegReader was allocated, add it to the apSegment array. */
assert( pNew!=0 || rc!=SQLITE_OK );
if( pNew ){
if( nSegment==nAlloc ){
Fts3SegReader **pArray;
nAlloc += 16;
pArray = (Fts3SegReader **)sqlite3_realloc(
apSegment, nAlloc*sizeof(Fts3SegReader *)
);
if( !pArray ){
sqlite3Fts3SegReaderFree(p, pNew);
rc = SQLITE_NOMEM;
goto finished;
}
apSegment = pArray;
}
apSegment[nSegment++] = pNew;
}
}
if( rc!=SQLITE_DONE ){
assert( rc!=SQLITE_OK );
goto finished;
}
memset(&tsc, 0, sizeof(TermSelect));
tsc.isReqPos = isReqPos;
filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
| (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
| (isPrefix ? FTS3_SEGMENT_PREFIX : 0)
| (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
| (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
filter.iCol = iColumn;
filter.zTerm = pTok->z;
filter.nTerm = pTok->n;
filter.zTerm = zTerm;
filter.nTerm = nTerm;
rc = sqlite3Fts3SegReaderIterate(p, pArray->apSegment, pArray->nSegment,
&filter, fts3TermSelectCb, (void *)&tsc
rc = sqlite3Fts3SegReaderIterate(p, apSegment, nSegment, &filter,
fts3TermSelectCb, (void *)&tsc
);
if( rc==SQLITE_OK ){
rc = fts3TermSelectMerge(&tsc);
}
if( rc==SQLITE_OK ){
*ppOut = tsc.aaOutput[0];
*pnOut = tsc.anOutput[0];
}else{
int i;
for(i=0; i<SizeofArray(tsc.aaOutput); i++){
sqlite3_free(tsc.aaOutput[i]);
}
}
fts3SegReaderArrayFree(pArray);
pTok->pArray = 0;
return rc;
}
finished:
/*
** This function counts the total number of docids in the doclist stored
** in buffer aList[], size nList bytes.
**
** If the isPoslist argument is true, then it is assumed that the doclist
** contains a position-list following each docid. Otherwise, it is assumed
** that the doclist is simply a list of docids stored as delta encoded
** varints.
*/
static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
int nDoc = 0; /* Return value */
if( aList ){
char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
char *p = aList; /* Cursor */
if( !isPoslist ){
/* The number of docids in the list is the same as the number of
** varints. In FTS3 a varint consists of a single byte with the 0x80
** bit cleared and zero or more bytes with the 0x80 bit set. So to
** count the varints in the buffer, just count the number of bytes
** with the 0x80 bit clear. */
while( p<aEnd ) nDoc += (((*p++)&0x80)==0);
}else{
while( p<aEnd ){
nDoc++;
while( (*p++)&0x80 ); /* Skip docid varint */
fts3PoslistCopy(0, &p); /* Skip over position list */
}
}
}
sqlite3_reset(pStmt);
return nDoc;
}
for(i=0; i<nSegment; i++){
/*
** Call sqlite3Fts3DeferToken() for each token in the expression pExpr.
sqlite3Fts3SegReaderFree(p, apSegment[i]);
*/
static int fts3DeferExpression(Fts3Cursor *pCsr, Fts3Expr *pExpr){
int rc = SQLITE_OK;
if( pExpr ){
rc = fts3DeferExpression(pCsr, pExpr->pLeft);
if( rc==SQLITE_OK ){
rc = fts3DeferExpression(pCsr, pExpr->pRight);
}
}
if( pExpr->eType==FTSQUERY_PHRASE ){
int iCol = pExpr->pPhrase->iColumn;
int i;
for(i=0; rc==SQLITE_OK && i<pExpr->pPhrase->nToken; i++){
Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
if( pToken->pDeferred==0 ){
rc = sqlite3Fts3DeferToken(pCsr, pToken, iCol);
sqlite3_free(apSegment);
}
}
}
}
return rc;
}
/*
** This function removes the position information from a doclist. When
** called, buffer aList (size *pnList bytes) contains a doclist that includes
** position information. This function removes the position information so
** that aList contains only docids, and adjusts *pnList to reflect the new
** (possibly reduced) size of the doclist.
*/
static void fts3DoclistStripPositions(
char *aList, /* IN/OUT: Buffer containing doclist */
int *pnList /* IN/OUT: Size of doclist in bytes */
){
if( aList ){
char *aEnd = &aList[*pnList]; /* Pointer to one byte after EOF */
char *p = aList; /* Input cursor */
char *pOut = aList; /* Output cursor */
while( p<aEnd ){
sqlite3_int64 delta;
p += sqlite3Fts3GetVarint(p, &delta);
fts3PoslistCopy(0, &p);
pOut += sqlite3Fts3PutVarint(pOut, delta);
}
*pnList = (pOut - aList);
}
}
/*
** Return a DocList corresponding to the phrase *pPhrase.
**
** If this function returns SQLITE_OK, but *pnOut is set to a negative value,
** then no tokens in the phrase were looked up in the full-text index. This
** is only possible when this function is called from within xFilter(). The
** caller should assume that all documents match the phrase. The actual
** filtering will take place in xNext().
*/
static int fts3PhraseSelect(
Fts3Cursor *pCsr, /* Virtual table cursor handle */
Fts3Table *p, /* Virtual table handle */
Fts3Phrase *pPhrase, /* Phrase to return a doclist for */
int isReqPos, /* True if output should contain positions */
char **paOut, /* OUT: Pointer to malloc'd result buffer */
int *pnOut /* OUT: Size of buffer at *paOut */
){
char *pOut = 0;
int nOut = 0;
int rc = SQLITE_OK;
int ii;
int iCol = pPhrase->iColumn;
int isTermPos = (pPhrase->nToken>1 || isReqPos);
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
int isFirst = 1;
int iPrevTok = 0;
int nDoc = 0;
/* If this is an xFilter() evaluation, create a segment-reader for each
** phrase token. Or, if this is an xNext() or snippet/offsets/matchinfo
** evaluation, only create segment-readers if there are no Fts3DeferredToken
** objects attached to the phrase-tokens.
*/
for(ii=0; ii<pPhrase->nToken; ii++){
Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
if( pTok->pArray==0 ){
struct PhraseToken *pTok = &pPhrase->aToken[ii];
char *z = pTok->z; /* Next token of the phrase */
if( (pCsr->eEvalmode==FTS3_EVAL_FILTER)
|| (pCsr->eEvalmode==FTS3_EVAL_NEXT && pCsr->pDeferred==0)
|| (pCsr->eEvalmode==FTS3_EVAL_MATCHINFO && pTok->bFulltext)
){
rc = fts3TermSegReaderArray(
pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pArray
int n = pTok->n; /* Size of z in bytes */
);
if( rc!=SQLITE_OK ) return rc;
}
}
}
int isPrefix = pTok->isPrefix;/* True if token is a prefix */
for(ii=0; ii<pPhrase->nToken; ii++){
Fts3PhraseToken *pTok; /* Token to find doclist for */
int iTok; /* The token being queried this iteration */
char *pList; /* Pointer to token doclist */
int nList; /* Size of buffer at pList */
/* Select a token to process. If this is an xFilter() call, then tokens
** are processed in order from least to most costly. Otherwise, tokens
** are processed in the order in which they occur in the phrase.
*/
if( pCsr->eEvalmode==FTS3_EVAL_MATCHINFO ){
assert( isReqPos );
iTok = ii;
pTok = &pPhrase->aToken[iTok];
if( pTok->bFulltext==0 ) continue;
}else if( pCsr->eEvalmode==FTS3_EVAL_NEXT || isReqPos ){
iTok = ii;
pTok = &pPhrase->aToken[iTok];
}else{
int nMinCost = 0x7FFFFFFF;
int jj;
/* Find the remaining token with the lowest cost. */
for(jj=0; jj<pPhrase->nToken; jj++){
Fts3SegReaderArray *pArray = pPhrase->aToken[jj].pArray;
if( pArray && pArray->nCost<nMinCost ){
iTok = jj;
nMinCost = pArray->nCost;
}
}
pTok = &pPhrase->aToken[iTok];
/* This branch is taken if it is determined that loading the doclist
** for the next token would require more IO than loading all documents
** currently identified by doclist pOut/nOut. No further doclists will
** be loaded from the full-text index for this phrase.
*/
if( nMinCost>nDoc && ii>0 ){
rc = fts3DeferExpression(pCsr, pCsr->pExpr);
break;
}
}
if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){
rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList);
}else{
assert( pTok->pArray );
rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList);
rc = fts3TermSelect(p, iCol, z, n, isPrefix, isTermPos, &nList, &pList);
pTok->bFulltext = 1;
}
assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pArray==0 );
if( rc!=SQLITE_OK ) break;
if( isFirst ){
if( ii==0 ){
pOut = pList;
nOut = nList;
if( pCsr->eEvalmode==FTS3_EVAL_FILTER && pPhrase->nToken>1 ){
nDoc = fts3DoclistCountDocids(1, pOut, nOut);
}
isFirst = 0;
iPrevTok = iTok;
}else{
/* Merge the new term list and the current output. */
/* Merge the new term list and the current output. If this is the
char *aLeft, *aRight;
int nLeft, nRight;
int nDist;
int mt;
/* If this is the final token of the phrase, and positions were not
** last term in the phrase, and positions are not required in the
** output of this function, the positions can be dropped as part
** requested by the caller, use MERGE_PHRASE instead of POS_PHRASE.
** This drops the position information from the output list.
** of this merge. Either way, the result of this merge will be
** smaller than nList bytes. The code in fts3DoclistMerge() is written
** so that it is safe to use pList as the output as well as an input
** in this case.
*/
mt = MERGE_POS_PHRASE;
if( ii==pPhrase->nToken-1 && !isReqPos ) mt = MERGE_PHRASE;
int mergetype = MERGE_POS_PHRASE;
if( ii==pPhrase->nToken-1 && !isReqPos ){
mergetype = MERGE_PHRASE;
assert( iPrevTok!=iTok );
if( iPrevTok<iTok ){
aLeft = pOut;
nLeft = nOut;
aRight = pList;
nRight = nList;
nDist = iTok-iPrevTok;
iPrevTok = iTok;
}else{
aRight = pOut;
nRight = nOut;
aLeft = pList;
nLeft = nList;
nDist = iPrevTok-iTok;
}
pOut = aRight;
fts3DoclistMerge(
fts3DoclistMerge(mergetype, 0, 0, pList, &nOut, pOut, nOut, pList, nList);
mt, nDist, 0, pOut, &nOut, aLeft, nLeft, aRight, nRight, &nDoc
);
sqlite3_free(aLeft);
sqlite3_free(pOut);
pOut = pList;
}
assert( nOut==0 || pOut!=0 );
}
if( rc==SQLITE_OK ){
if( ii!=pPhrase->nToken ){
assert( pCsr->eEvalmode==FTS3_EVAL_FILTER && isReqPos==0 );
fts3DoclistStripPositions(pOut, &nOut);
}
*paOut = pOut;
*pnOut = nOut;
}else{
sqlite3_free(pOut);
}
return rc;
}
/*
** This function merges two doclists according to the requirements of a
** NEAR operator.
**
** Both input doclists must include position information. The output doclist
** includes position information if the first argument to this function
** is MERGE_POS_NEAR, or does not if it is MERGE_NEAR.
*/
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; /* Buffer to write output doclist to */
int rc; /* Return code */
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, 0
aOut, pnOut, aLeft, nLeft, aRight, nRight
);
if( rc!=SQLITE_OK ){
sqlite3_free(aOut);
aOut = 0;
}
}
*paOut = aOut;
return rc;
}
/*
** This function is used as part of the processing for the snippet() and
** offsets() functions.
**
** Both pLeft and pRight are expression nodes of type FTSQUERY_PHRASE. Both
** have their respective doclists (including position information) loaded
** in Fts3Expr.aDoclist/nDoclist. This function removes all entries from
** each doclist that are not within nNear tokens of a corresponding entry
** in the other doclist.
*/
SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){
int rc; /* Return code */
int rc;
assert( pLeft->eType==FTSQUERY_PHRASE );
assert( pRight->eType==FTSQUERY_PHRASE );
assert( pLeft->isLoaded && pRight->isLoaded );
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; /* Buffer in which to assemble new doclist */
int nOut; /* Size of buffer aOut in bytes */
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;
|
︙ | | |
110568
110569
110570
110571
110572
110573
110574
110575
110576
110577
110578
110579
110580
110581
110582
110583
110584
110585
110586
110587
110588
110589
110590
110591
110592
110593
110594
110595
110596
110597
110598
110599
110600
110601
110602
110603
110604
110605
110606
110607
110608
110609
110610
110611
110612
110613
110614
110615
110616
110617
110618
110619
110620
110621
110622
110623
110624
110625
110626
110627
110628
110629
110630
110631
110632
110633
110634
110635
110636
110637
110638
110639
110640
110641
110642
110643
110644
110645
110646
110647
110648
110649
110650
110651
110652
110653
110654
110655
110656
110657
110658
110659
110660
110661
110662
110663
110664
110665
110666
110667
110668
110669
110670
110671
110672
110673
110674
110675
110676
110677
110678
110679
110680
110681
110682
110683
110684
110685
110686
110687
110688
110689
110690
110691
110692
110693
110694
110695
110696
110697
110698
110699
110700
110701
110702
110703
110704
110705
110706
110707
110708
110709
110710
110711
110712
110713
110714
110715
110716
110717
110718
110719
110720
110721
110722
110723
110724
110725
110726
110727
110728
110729
110730
110731
110732
110733
110734
110735
110736
110737
110738
110739
110740
110741
110742
110743
110744
110745
110746
110747
110748
110749
110750
110751
110752
110753
110754
110755
110756
110757
110758
110759
110760
110761
110762
110763
110764
110765
110766
110767
110768
110769
110770
110771
110772
110773
110774
110775
110776
110777
110778
110779
110780
110781
110782
110783
110784
110785
110786
110787
110788
110789
110790
110791
110792
110793
110794
110795
110796
110797
110798
110799
110800
110801
110802
110803
110804
110805
110806
110807
110808
110809
110810
110811
110812
110813
110814
110815
110816
110817
110818
110819
110820
110821
110822
110823
110824
110825
110826
110827
110828
110829
110830
110831
|
109450
109451
109452
109453
109454
109455
109456
109457
109458
109459
109460
109461
109462
109463
109464
109465
109466
109467
109468
109469
109470
109471
109472
109473
109474
109475
109476
109477
109478
109479
109480
109481
109482
109483
109484
109485
109486
109487
109488
109489
109490
109491
109492
109493
109494
109495
109496
109497
109498
109499
109500
109501
109502
109503
109504
109505
109506
109507
109508
109509
109510
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
-
-
-
+
-
-
-
-
-
+
+
|
sqlite3_free(pLeft->aDoclist);
pLeft->aDoclist = aOut;
pLeft->nDoclist = nOut;
}
return rc;
}
/*
** Allocate an Fts3SegReaderArray for each token in the expression pExpr.
** The allocated objects are stored in the Fts3PhraseToken.pArray member
** variables of each token structure.
*/
static int fts3ExprAllocateSegReaders(
Fts3Cursor *pCsr, /* FTS3 table */
Fts3Expr *pExpr, /* Expression to create seg-readers for */
int *pnExpr /* OUT: Number of AND'd expressions */
){
int rc = SQLITE_OK; /* Return code */
assert( pCsr->eEvalmode==FTS3_EVAL_FILTER );
if( pnExpr && pExpr->eType!=FTSQUERY_AND ){
(*pnExpr)++;
pnExpr = 0;
}
if( pExpr->eType==FTSQUERY_PHRASE ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
int ii;
for(ii=0; rc==SQLITE_OK && ii<pPhrase->nToken; ii++){
Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
if( pTok->pArray==0 ){
rc = fts3TermSegReaderArray(
pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pArray
);
}
}
}else{
rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pLeft, pnExpr);
if( rc==SQLITE_OK ){
rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pRight, pnExpr);
}
}
return rc;
}
/*
** Free the Fts3SegReaderArray objects associated with each token in the
** expression pExpr. In other words, this function frees the resources
** allocated by fts3ExprAllocateSegReaders().
*/
static void fts3ExprFreeSegReaders(Fts3Expr *pExpr){
if( pExpr ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase ){
int kk;
for(kk=0; kk<pPhrase->nToken; kk++){
fts3SegReaderArrayFree(pPhrase->aToken[kk].pArray);
pPhrase->aToken[kk].pArray = 0;
}
}
fts3ExprFreeSegReaders(pExpr->pLeft);
fts3ExprFreeSegReaders(pExpr->pRight);
}
}
/*
** Return the sum of the costs of all tokens in the expression pExpr. This
** function must be called after Fts3SegReaderArrays have been allocated
** for all tokens using fts3ExprAllocateSegReaders().
*/
int fts3ExprCost(Fts3Expr *pExpr){
int nCost; /* Return value */
if( pExpr->eType==FTSQUERY_PHRASE ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
int ii;
nCost = 0;
for(ii=0; ii<pPhrase->nToken; ii++){
nCost += pPhrase->aToken[ii].pArray->nCost;
}
}else{
nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight);
}
return nCost;
}
/*
** The following is a helper function (and type) for fts3EvalExpr(). It
** must be called after Fts3SegReaders have been allocated for every token
** in the expression. See the context it is called from in fts3EvalExpr()
** for further explanation.
*/
typedef struct ExprAndCost ExprAndCost;
struct ExprAndCost {
Fts3Expr *pExpr;
int nCost;
};
static void fts3ExprAssignCosts(
Fts3Expr *pExpr, /* Expression to create seg-readers for */
ExprAndCost **ppExprCost /* OUT: Write to *ppExprCost */
){
if( pExpr->eType==FTSQUERY_AND ){
fts3ExprAssignCosts(pExpr->pLeft, ppExprCost);
fts3ExprAssignCosts(pExpr->pRight, ppExprCost);
}else{
(*ppExprCost)->pExpr = pExpr;
(*ppExprCost)->nCost = fts3ExprCost(pExpr);;
(*ppExprCost)++;
}
}
/*
** Evaluate the full-text expression pExpr against FTS3 table pTab. Store
** the resulting doclist in *paOut and *pnOut. This routine mallocs for
** the space needed to store the output. The caller is responsible for
** Evaluate the full-text expression pExpr against fts3 table pTab. Store
** the resulting doclist in *paOut and *pnOut. This routine mallocs for
** the space needed to store the output. The caller is responsible for
** freeing the space when it has finished.
**
** This function is called in two distinct contexts:
**
** * From within the virtual table xFilter() method. In this case, the
** output doclist contains entries for all rows in the table, based on
** data read from the full-text index.
**
** In this case, if the query expression contains one or more tokens that
** are very common, then the returned doclist may contain a superset of
** the documents that actually match the expression.
**
** * From within the virtual table xNext() method. This call is only made
** if the call from within xFilter() found that there were very common
** tokens in the query expression and did return a superset of the
** matching documents. In this case the returned doclist contains only
** entries that correspond to the current row of the table. Instead of
** reading the data for each token from the full-text index, the data is
** already available in-memory in the Fts3PhraseToken.pDeferred structures.
** See fts3EvalDeferred() for how it gets there.
**
** In the first case above, Fts3Cursor.doDeferred==0. In the second (if it is
** required) Fts3Cursor.doDeferred==1.
**
** If the SQLite invokes the snippet(), offsets() or matchinfo() function
** as part of a SELECT on an FTS3 table, this function is called on each
** individual phrase expression in the query. If there were very common tokens
** found in the xFilter() call, then this function is called once for phrase
** for each row visited, and the returned doclist contains entries for the
** current row only. Otherwise, if there were no very common tokens, then this
** function is called once only for each phrase in the query and the returned
** doclist contains entries for all rows of the table.
**
** Fts3Cursor.doDeferred==1 when this function is called on phrases as a
** result of a snippet(), offsets() or matchinfo() invocation.
*/
static int fts3EvalExpr(
Fts3Cursor *p, /* Virtual table cursor handle */
static int evalFts3Expr(
Fts3Table *p, /* Virtual table handle */
Fts3Expr *pExpr, /* Parsed fts3 expression */
char **paOut, /* OUT: Pointer to malloc'd result buffer */
int *pnOut, /* OUT: Size of buffer at *paOut */
int isReqPos /* Require positions in output buffer */
){
int rc = SQLITE_OK; /* Return code */
/* Zero the output parameters. */
*paOut = 0;
*pnOut = 0;
if( pExpr ){
assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR
|| pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
|| pExpr->eType==FTSQUERY_PHRASE
assert( pExpr->eType==FTSQUERY_PHRASE
|| pExpr->eType==FTSQUERY_NEAR
|| isReqPos==0
);
assert( pExpr->eType==FTSQUERY_PHRASE || isReqPos==0 );
if( pExpr->eType==FTSQUERY_PHRASE ){
rc = fts3PhraseSelect(p, pExpr->pPhrase,
rc = fts3PhraseSelect(p, pExpr->pPhrase,
isReqPos || (pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR),
paOut, pnOut
);
fts3ExprFreeSegReaders(pExpr);
}else if( p->eEvalmode==FTS3_EVAL_FILTER && pExpr->eType==FTSQUERY_AND ){
ExprAndCost *aExpr = 0; /* Array of AND'd expressions and costs */
int nExpr = 0; /* Size of aExpr[] */
char *aRet = 0; /* Doclist to return to caller */
int nRet = 0; /* Length of aRet[] in bytes */
int nDoc = 0x7FFFFFFF;
assert( !isReqPos );
rc = fts3ExprAllocateSegReaders(p, pExpr, &nExpr);
if( rc==SQLITE_OK ){
assert( nExpr>1 );
aExpr = sqlite3_malloc(sizeof(ExprAndCost) * nExpr);
if( !aExpr ) rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
int ii; /* Used to iterate through expressions */
fts3ExprAssignCosts(pExpr, &aExpr);
aExpr -= nExpr;
for(ii=0; ii<nExpr; ii++){
char *aNew;
int nNew;
int jj;
ExprAndCost *pBest = 0;
for(jj=0; jj<nExpr; jj++){
ExprAndCost *pCand = &aExpr[jj];
if( pCand->pExpr && (pBest==0 || pCand->nCost<pBest->nCost) ){
pBest = pCand;
}
}
if( pBest->nCost>nDoc ){
rc = fts3DeferExpression(p, p->pExpr);
break;
}else{
rc = fts3EvalExpr(p, pBest->pExpr, &aNew, &nNew, 0);
if( rc!=SQLITE_OK ) break;
pBest->pExpr = 0;
if( ii==0 ){
aRet = aNew;
nRet = nNew;
nDoc = fts3DoclistCountDocids(0, aRet, nRet);
}else{
fts3DoclistMerge(
MERGE_AND, 0, 0, aRet, &nRet, aRet, nRet, aNew, nNew, &nDoc
);
sqlite3_free(aNew);
}
}
}
}
*paOut = aRet;
*pnOut = nRet;
sqlite3_free(aExpr);
fts3ExprFreeSegReaders(pExpr);
}else{
char *aLeft;
char *aRight;
int nLeft;
int nRight;
if( 0==(rc = evalFts3Expr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
&& 0==(rc = evalFts3Expr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
){
assert( pExpr->eType==FTSQUERY_NEAR
|| pExpr->eType==FTSQUERY_OR
assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR
|| pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
|| pExpr->eType==FTSQUERY_NOT
|| (pExpr->eType==FTSQUERY_AND && p->eEvalmode==FTS3_EVAL_NEXT)
);
);
if( 0==(rc = fts3EvalExpr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
&& 0==(rc = fts3EvalExpr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
){
switch( pExpr->eType ){
case FTSQUERY_NEAR: {
Fts3Expr *pLeft;
Fts3Expr *pRight;
int mergetype = MERGE_NEAR;
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;
}
|
︙ | | |
110846
110847
110848
110849
110850
110851
110852
110853
110854
110855
110856
110857
110858
110859
110860
110861
110862
110863
110864
110865
110866
110867
110868
110869
110870
110871
110872
110873
110874
110875
110876
110877
110878
110879
110880
110881
110882
110883
110884
110885
110886
110887
110888
110889
110890
110891
110892
110893
110894
110895
110896
110897
110898
110899
110900
110901
110902
110903
110904
110905
110906
110907
110908
110909
110910
110911
110912
110913
110914
110915
110916
110917
110918
110919
110920
110921
110922
110923
110924
110925
110926
110927
110928
110929
110930
110931
110932
110933
110934
110935
110936
110937
110938
110939
110940
110941
110942
110943
110944
110945
110946
110947
110948
110949
110950
110951
110952
110953
110954
110955
110956
110957
110958
110959
110960
110961
110962
110963
110964
110965
110966
110967
110968
110969
110970
110971
110972
110973
110974
110975
110976
110977
110978
110979
110980
|
109525
109526
109527
109528
109529
109530
109531
109532
109533
109534
109535
109536
109537
109538
109539
109540
109541
109542
109543
109544
109545
109546
109547
109548
109549
109550
109551
109552
109553
109554
109555
109556
109557
109558
109559
109560
109561
109562
109563
109564
109565
109566
109567
109568
109569
109570
109571
109572
109573
109574
109575
109576
109577
109578
109579
109580
109581
109582
|
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
|
/* Allocate a buffer for the output. The maximum size is the
** sum of the sizes of the two input buffers. The +1 term is
** so that a buffer of zero bytes is never allocated - this can
** cause fts3DoclistMerge() to incorrectly return SQLITE_NOMEM.
*/
char *aBuffer = sqlite3_malloc(nRight+nLeft+1);
rc = fts3DoclistMerge(MERGE_OR, 0, 0, aBuffer, pnOut,
aLeft, nLeft, aRight, nRight, 0
aLeft, nLeft, aRight, nRight
);
*paOut = aBuffer;
sqlite3_free(aLeft);
break;
}
default: {
assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND );
fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut,
aLeft, nLeft, aRight, nRight, 0
aLeft, nLeft, aRight, nRight
);
*paOut = aLeft;
break;
}
}
}
sqlite3_free(aRight);
}
}
return rc;
}
/*
** This function is called from within xNext() for each row visited by
** an FTS3 query. If evaluating the FTS3 query expression within xFilter()
** was able to determine the exact set of matching rows, this function sets
** *pbRes to true and returns SQLITE_IO immediately.
**
** Otherwise, if evaluating the query expression within xFilter() returned a
** superset of the matching documents instead of an exact set (this happens
** when the query includes very common tokens and it is deemed too expensive to
** load their doclists from disk), this function tests if the current row
** really does match the FTS3 query.
**
** If an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK
** is returned and *pbRes is set to true if the current row matches the
** FTS3 query (and should be included in the results returned to SQLite), or
** false otherwise.
*/
static int fts3EvalDeferred(
Fts3Cursor *pCsr, /* FTS3 cursor pointing at row to test */
int *pbRes /* OUT: Set to true if row is a match */
){
int rc = SQLITE_OK;
if( pCsr->pDeferred==0 ){
*pbRes = 1;
}else{
rc = fts3CursorSeek(0, pCsr);
if( rc==SQLITE_OK ){
sqlite3Fts3FreeDeferredDoclists(pCsr);
rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
}
if( rc==SQLITE_OK ){
char *a = 0;
int n = 0;
rc = fts3EvalExpr(pCsr, pCsr->pExpr, &a, &n, 0);
assert( n>=0 );
*pbRes = (n>0);
sqlite3_free(a);
}
}
return rc;
}
/*
** Advance the cursor to the next row in the %_content table that
** matches the search criteria. For a MATCH search, this will be
** the next row that matches. For a full-table scan, this will be
** simply the next row in the %_content table. For a docid lookup,
** this routine simply sets the EOF flag.
**
** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
** even if we reach end-of-file. The fts3EofMethod() will be called
** subsequently to determine whether or not an EOF was hit.
*/
static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
int res;
int rc = SQLITE_OK; /* Return code */
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
pCsr->eEvalmode = FTS3_EVAL_NEXT;
do {
if( pCsr->aDoclist==0 ){
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
pCsr->isEof = 1;
rc = sqlite3_reset(pCsr->pStmt);
break;
}
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
}else{
if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
pCsr->isEof = 1;
break;
}
sqlite3_reset(pCsr->pStmt);
fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
}
}while( SQLITE_OK==(rc = fts3EvalDeferred(pCsr, &res)) && res==0 );
return rc;
}
/*
** This is the xFilter interface for the virtual table. See
** the virtual table xFilter method documentation for additional
** information.
**
** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against
** the %_content table.
**
** If idxNum==FTS3_DOCID_SEARCH then do a docid lookup for a single entry
** in the %_content table.
**
** If idxNum>=FTS3_FULLTEXT_SEARCH then use the full text index. The
** column on the left-hand side of the MATCH operator is column
** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand
** side of the MATCH operator.
*/
/* TODO(shess) Upgrade the cursor initialization and destruction to
** account for fts3FilterMethod() being called multiple times on the
** same cursor. The current solution is very fragile. Apply fix to
** fts3 as appropriate.
*/
static int fts3FilterMethod(
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
int idxNum, /* Strategy index */
const char *idxStr, /* Unused */
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
︙ | | |
110990
110991
110992
110993
110994
110995
110996
110997
110998
110999
111000
111001
111002
111003
111004
111005
111006
111007
111008
111009
111010
111011
111012
|
109592
109593
109594
109595
109596
109597
109598
109599
109600
109601
109602
109603
109604
109605
109606
109607
109608
109609
109610
109611
109612
109613
109614
109615
109616
109617
109618
109619
109620
109621
109622
109623
109624
109625
109626
109627
109628
109629
109630
|
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
|
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(nVal);
assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
assert( nVal==0 || nVal==1 );
assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
assert( p->pSegments==0 );
/* In case the cursor has been used before, clear it now. */
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
/* Compile a SELECT statement for this cursor. For a full-table-scan, the
** statement loops through all rows of the %_content table. For a
** full-text query or docid lookup, the statement retrieves a single
** row by docid.
*/
zSql = sqlite3_mprintf(azSql[idxNum==FTS3_FULLSCAN_SEARCH], p->zDb, p->zName);
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc!=SQLITE_OK ) return rc;
pCsr->eSearch = (i16)idxNum;
if( idxNum==FTS3_DOCID_SEARCH ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
}else if( idxNum!=FTS3_FULLSCAN_SEARCH ){
int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
return SQLITE_NOMEM;
}
|
︙ | | |
111020
111021
111022
111023
111024
111025
111026
111027
111028
111029
111030
111031
111032
111033
111034
111035
111036
111037
111038
111039
111040
111041
111042
111043
111044
111045
111046
111047
111048
111049
111050
111051
111052
111053
111054
111055
111056
111057
|
109638
109639
109640
109641
109642
109643
109644
109645
109646
109647
109648
109649
109650
109651
109652
109653
109654
109655
109656
|
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
}
return rc;
}
rc = sqlite3Fts3ReadLock(p);
if( rc!=SQLITE_OK ) return rc;
rc = fts3EvalExpr(pCsr, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
rc = evalFts3Expr(p, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
sqlite3Fts3SegmentsClose(p);
if( rc!=SQLITE_OK ) return rc;
pCsr->pNextId = pCsr->aDoclist;
pCsr->iPrevId = 0;
}
/* Compile a SELECT statement for this cursor. For a full-table-scan, the
** statement loops through all rows of the %_content table. For a
** full-text query or docid lookup, the statement retrieves a single
** row by docid.
*/
zSql = sqlite3_mprintf(azSql[idxNum==FTS3_FULLSCAN_SEARCH], p->zDb, p->zName);
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK && idxNum==FTS3_DOCID_SEARCH ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
}
pCsr->eSearch = (i16)idxNum;
if( rc!=SQLITE_OK ) return rc;
return fts3NextMethod(pCursor);
}
/*
** This is the xEof method of the virtual table. SQLite calls this
** routine to find out if it has reached the end of a result set.
|
︙ | | |
111067
111068
111069
111070
111071
111072
111073
111074
111075
111076
111077
111078
111079
111080
111081
111082
111083
111084
111085
|
109666
109667
109668
109669
109670
109671
109672
109673
109674
109675
109676
109677
109678
109679
|
-
-
-
-
-
|
** rowid should be written to *pRowid.
*/
static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
if( pCsr->aDoclist ){
*pRowid = pCsr->iPrevId;
}else{
/* This branch runs if the query is implemented using a full-table scan
** (not using the full-text index). In this case grab the rowid from the
** SELECT statement.
*/
assert( pCsr->isRequireSeek==0 );
*pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
}
return SQLITE_OK;
}
/*
** This is the xColumn method, called by SQLite to request a value from
|
︙ | | |
111134
111135
111136
111137
111138
111139
111140
111141
111142
111143
111144
111145
111146
111147
111148
111149
111150
|
109728
109729
109730
109731
109732
109733
109734
109735
109736
109737
109738
109739
109740
109741
109742
|
-
+
-
-
|
}
/*
** Implementation of xSync() method. Flush the contents of the pending-terms
** hash-table to the database.
*/
static int fts3SyncMethod(sqlite3_vtab *pVtab){
int rc = sqlite3Fts3PendingTermsFlush((Fts3Table *)pVtab);
return sqlite3Fts3PendingTermsFlush((Fts3Table *)pVtab);
sqlite3Fts3SegmentsClose((Fts3Table *)pVtab);
return rc;
}
/*
** Implementation of xBegin() method. This is a no-op.
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
UNUSED_PARAMETER(pVtab);
|
︙ | | |
111174
111175
111176
111177
111178
111179
111180
111181
111182
111183
111184
111185
111186
111187
111188
111189
111190
111191
111192
111193
111194
111195
111196
111197
111198
111199
111200
111201
111202
111203
111204
111205
111206
111207
111208
|
109766
109767
109768
109769
109770
109771
109772
109773
109774
109775
109776
109777
109778
109779
109780
109781
|
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
/*
** Load the doclist associated with expression pExpr to pExpr->aDoclist.
** The loaded doclist contains positions as well as the document ids.
** This is used by the matchinfo(), snippet() and offsets() auxillary
** functions.
*/
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *pCsr, Fts3Expr *pExpr){
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *pTab, Fts3Expr *pExpr){
int rc;
assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
rc = fts3EvalExpr(pCsr, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
return evalFts3Expr(pTab, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
return rc;
}
SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(
Fts3Cursor *pCsr,
Fts3Expr *pExpr,
char **paDoclist,
int *pnDoclist
){
int rc;
assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
pCsr->eEvalmode = FTS3_EVAL_NEXT;
return rc;
}
/*
** 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.
*/
|
︙ | | |
111260
111261
111262
111263
111264
111265
111266
111267
111268
111269
111270
111271
111272
111273
111274
|
109833
109834
109835
109836
109837
109838
109839
109840
109841
109842
109843
109844
109845
109846
109847
|
-
+
|
** message is written to context pContext and SQLITE_ERROR returned. The
** string passed via zFunc is used as part of the error message.
*/
static int fts3FunctionArg(
sqlite3_context *pContext, /* SQL function call context */
const char *zFunc, /* Function name */
sqlite3_value *pVal, /* argv[0] passed to function */
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
){
Fts3Cursor *pRet;
if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
){
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
sqlite3_result_error(pContext, zErr, -1);
|
︙ | | |
111386
111387
111388
111389
111390
111391
111392
111393
111394
111395
111396
111397
111398
111399
111400
|
109959
109960
109961
109962
109963
109964
109965
109966
109967
109968
109969
109970
109971
109972
109973
109974
109975
109976
109977
109978
109979
|
+
-
+
+
+
+
+
+
|
*/
static void fts3MatchinfoFunc(
sqlite3_context *pContext, /* SQLite function call context */
int nVal, /* Size of argument array */
sqlite3_value **apVal /* Array of arguments */
){
Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
assert( nVal==1 );
if( nVal!=1 ){
sqlite3_result_error(pContext,
"wrong number of arguments to function matchinfo()", -1);
return;
}
if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){
sqlite3Fts3Matchinfo(pContext, pCsr);
}
}
/*
** This routine implements the xFindFunction method for the FTS3
|
︙ | | |
111449
111450
111451
111452
111453
111454
111455
111456
111457
111458
111459
111460
111461
111462
111463
111464
111465
111466
111467
111468
111469
|
110028
110029
110030
110031
110032
110033
110034
110035
110036
110037
110038
110039
110040
110041
110042
110043
110044
110045
110046
110047
|
+
-
-
|
return rc;
}
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
);
}
if( p->bHasStat ){
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';",
|
︙ | | |
111480
111481
111482
111483
111484
111485
111486
111487
111488
111489
111490
111491
111492
111493
111494
|
110058
110059
110060
110061
110062
110063
110064
110065
110066
110067
110068
110069
110070
110071
110072
|
-
+
|
/* iVersion */ 0,
/* xCreate */ fts3CreateMethod,
/* xConnect */ fts3ConnectMethod,
/* xBestIndex */ fts3BestIndexMethod,
/* xDisconnect */ fts3DisconnectMethod,
/* xDestroy */ fts3DestroyMethod,
/* xOpen */ fts3OpenMethod,
/* xClose */ fts3CloseMethod,
/* xClose */ fulltextClose,
/* xFilter */ fts3FilterMethod,
/* xNext */ fts3NextMethod,
/* xEof */ fts3EofMethod,
/* xColumn */ fts3ColumnMethod,
/* xRowid */ fts3RowidMethod,
/* xUpdate */ fts3UpdateMethod,
/* xBegin */ fts3BeginMethod,
|
︙ | | |
111507
111508
111509
111510
111511
111512
111513
111514
111515
111516
111517
111518
111519
111520
111521
111522
111523
111524
111525
111526
111527
111528
111529
111530
111531
111532
111533
111534
|
110085
110086
110087
110088
110089
110090
110091
110092
110093
110094
110095
110096
110097
110098
110099
110100
110101
110102
110103
110104
110105
110106
110107
110108
110109
110110
110111
|
-
-
-
-
+
+
+
+
+
-
+
-
-
|
static void hashDestroy(void *p){
Fts3Hash *pHash = (Fts3Hash *)p;
sqlite3Fts3HashClear(pHash);
sqlite3_free(pHash);
}
/*
** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are
** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c
** respectively. The following three forward declarations are for functions
** declared in these files used to retrieve the respective implementations.
** The fts3 built-in tokenizers - "simple" and "porter" - are implemented
** in files fts3_tokenizer1.c and fts3_porter.c respectively. The following
** two forward declarations are for functions declared in these files
** used to retrieve the respective implementations.
**
** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed
** to by the argument to point to the "simple" tokenizer implementation.
** Function ...PorterTokenizerModule() sets *pModule to point to the
** And so on.
** porter tokenizer/stemmer implementation.
*/
SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
#ifdef SQLITE_ENABLE_ICU
SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
#endif
/*
** Initialise the fts3 extension. If this extension is built as part
** of the sqlite library, then this function is called directly by
** SQLite. If fts3 is built as a dynamically loadable extension, this
** function is called by the sqlite3_extension_init() entry point.
*/
|
︙ | | |
111576
111577
111578
111579
111580
111581
111582
111583
111584
111585
111586
111587
111588
111589
111590
|
110153
110154
110155
110156
110157
110158
110159
110160
110161
110162
110163
110164
110165
110166
110167
|
-
+
|
** 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, "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(
|
︙ | | |
111718
111719
111720
111721
111722
111723
111724
111725
111726
111727
111728
111729
111730
111731
111732
111733
111734
111735
111736
111737
111738
111739
111740
111741
111742
111743
|
110295
110296
110297
110298
110299
110300
110301
110302
110303
110304
110305
110306
110307
110308
|
-
-
-
-
-
-
-
-
-
-
-
-
|
** is defined to accept an argument of type char, and always returns 0 for
** any values that fall outside of the range of the unsigned char type (i.e.
** negative values).
*/
static int fts3isspace(char c){
return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}
/*
** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
static void *fts3MallocZero(int nByte){
void *pRet = sqlite3_malloc(nByte);
if( pRet ) memset(pRet, 0, nByte);
return pRet;
}
/*
** Extract the next token from buffer z (length n) using the tokenizer
** and other information (column names etc.) in pParse. Create an Fts3Expr
** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
** single token and set *ppExpr to point to it. If the end of the buffer is
** reached before a token is found, set *ppExpr to zero. It is the
|
︙ | | |
111768
111769
111770
111771
111772
111773
111774
111775
111776
111777
111778
111779
111780
111781
111782
111783
111784
111785
|
110333
110334
110335
110336
110337
110338
110339
110340
110341
110342
110343
110344
110345
110346
110347
110348
110349
110350
110351
|
-
+
+
|
int nByte; /* total space to allocate */
pCursor->pTokenizer = pTokenizer;
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
pRet = (Fts3Expr *)fts3MallocZero(nByte);
pRet = (Fts3Expr *)sqlite3_malloc(nByte);
if( !pRet ){
rc = SQLITE_NOMEM;
}else{
memset(pRet, 0, nByte);
pRet->eType = FTSQUERY_PHRASE;
pRet->pPhrase = (Fts3Phrase *)&pRet[1];
pRet->pPhrase->nToken = 1;
pRet->pPhrase->iColumn = iCol;
pRet->pPhrase->aToken[0].n = nToken;
pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
|
︙ | | |
111847
111848
111849
111850
111851
111852
111853
111854
111855
111856
111857
111858
111859
111860
111861
111862
111863
111864
111865
111866
111867
111868
111869
111870
111871
|
110413
110414
110415
110416
110417
110418
110419
110420
110421
110422
110423
110424
110425
110426
110427
110428
110429
110430
110431
110432
110433
110434
110435
110436
|
-
+
-
|
pCursor->pTokenizer = pTokenizer;
for(ii=0; rc==SQLITE_OK; ii++){
const char *zToken;
int nToken, iBegin, iEnd, iPos;
rc = pModule->xNext(pCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
if( rc==SQLITE_OK ){
int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
p = fts3ReallocOrFree(p, nByte+ii*sizeof(Fts3PhraseToken));
p = fts3ReallocOrFree(p, nByte+ii*sizeof(struct PhraseToken));
zTemp = fts3ReallocOrFree(zTemp, nTemp + nToken);
if( !p || !zTemp ){
goto no_mem;
}
if( ii==0 ){
memset(p, 0, nByte);
p->pPhrase = (Fts3Phrase *)&p[1];
}
p->pPhrase = (Fts3Phrase *)&p[1];
memset(&p->pPhrase->aToken[ii], 0, sizeof(Fts3PhraseToken));
p->pPhrase->nToken = ii+1;
p->pPhrase->aToken[ii].n = nToken;
memcpy(&zTemp[nTemp], zToken, nToken);
nTemp += nToken;
if( iEnd<nInput && zInput[iEnd]=='*' ){
p->pPhrase->aToken[ii].isPrefix = 1;
}else{
|
︙ | | |
111879
111880
111881
111882
111883
111884
111885
111886
111887
111888
111889
111890
111891
111892
111893
|
110444
110445
110446
110447
110448
110449
110450
110451
110452
110453
110454
110455
110456
110457
110458
|
-
+
|
}
if( rc==SQLITE_DONE ){
int jj;
char *zNew = NULL;
int nNew = 0;
int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(Fts3PhraseToken);
nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(struct PhraseToken);
p = fts3ReallocOrFree(p, nByte + nTemp);
if( !p ){
goto no_mem;
}
if( zTemp ){
zNew = &(((char *)p)[nByte]);
memcpy(zNew, zTemp, nTemp);
|
︙ | | |
111997
111998
111999
112000
112001
112002
112003
112004
112005
112006
112007
112008
112009
112010
112011
112012
112013
112014
|
110562
110563
110564
110565
110566
110567
110568
110569
110570
110571
110572
110573
110574
110575
110576
110577
110578
110579
110580
|
-
+
+
|
** the next byte must contain either whitespace, an open or close
** parenthesis, a quote character, or EOF.
*/
cNext = zInput[nKey];
if( fts3isspace(cNext)
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
){
pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
pRet = (Fts3Expr *)sqlite3_malloc(sizeof(Fts3Expr));
if( !pRet ){
return SQLITE_NOMEM;
}
memset(pRet, 0, sizeof(Fts3Expr));
pRet->eType = pKey->eType;
pRet->nNear = nNear;
*ppExpr = pRet;
*pnConsumed = (int)((zInput - z) + nKey);
return SQLITE_OK;
}
|
︙ | | |
112176
112177
112178
112179
112180
112181
112182
112183
112184
112185
112186
112187
112188
112189
112190
112191
112192
112193
112194
112195
|
110742
110743
110744
110745
110746
110747
110748
110749
110750
110751
110752
110753
110754
110755
110756
110757
110758
110759
110760
110761
110762
|
-
+
+
|
if( rc==SQLITE_OK ){
int isPhrase;
if( !sqlite3_fts3_enable_parentheses
&& p->eType==FTSQUERY_PHRASE && p->pPhrase->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
Fts3Expr *pNot = sqlite3_malloc(sizeof(Fts3Expr));
if( !pNot ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
memset(pNot, 0, sizeof(Fts3Expr));
pNot->eType = FTSQUERY_NOT;
pNot->pRight = p;
if( pNotBranch ){
pNot->pLeft = pNotBranch;
}
pNotBranch = pNot;
p = pPrev;
|
︙ | | |
112209
112210
112211
112212
112213
112214
112215
112216
112217
112218
112219
112220
112221
112222
112223
112224
112225
112226
112227
112228
|
110776
110777
110778
110779
110780
110781
110782
110783
110784
110785
110786
110787
110788
110789
110790
110791
110792
110793
110794
110795
110796
|
-
+
+
|
goto exprparse_out;
}
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
pAnd = fts3MallocZero(sizeof(Fts3Expr));
pAnd = sqlite3_malloc(sizeof(Fts3Expr));
if( !pAnd ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
memset(pAnd, 0, sizeof(Fts3Expr));
pAnd->eType = FTSQUERY_AND;
insertBinaryOperator(&pRet, pPrev, pAnd);
pPrev = pAnd;
}
/* This test catches attempts to make either operand of a NEAR
** operator something other than a phrase. For example, either of
|
︙ | | |
113664
113665
113666
113667
113668
113669
113670
113671
113672
113673
113674
113675
113676
113677
113678
|
112232
112233
112234
112235
112236
112237
112238
112239
112240
112241
112242
112243
112244
112245
112246
|
-
+
|
return;
}
}
sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
}
SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){
static int fts3IsIdChar(char c){
static const char isFtsIdChar[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
|
︙ | | |
113702
113703
113704
113705
113706
113707
113708
113709
113710
113711
113712
113713
113714
113715
113716
113717
113718
113719
113720
113721
113722
113723
113724
113725
113726
113727
113728
113729
113730
113731
113732
113733
113734
113735
113736
113737
113738
113739
113740
113741
113742
113743
113744
113745
113746
113747
113748
113749
113750
|
112270
112271
112272
112273
112274
112275
112276
112277
112278
112279
112280
112281
112282
112283
112284
112285
112286
112287
112288
112289
112290
112291
112292
112293
112294
112295
112296
112297
112298
112299
112300
112301
112302
112303
112304
112305
112306
112307
112308
112309
112310
112311
112312
112313
112314
112315
112316
112317
112318
112319
112320
112321
112322
112323
112324
112325
112326
112327
112328
112329
112330
|
-
+
-
+
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
|
case '[':
z2 = &z1[1];
while( *z2 && z2[0]!=']' ) z2++;
if( *z2 ) z2++;
break;
default:
if( sqlite3Fts3IsIdChar(*z1) ){
if( fts3IsIdChar(*z1) ){
z2 = &z1[1];
while( sqlite3Fts3IsIdChar(*z2) ) z2++;
while( fts3IsIdChar(*z2) ) z2++;
}else{
z1++;
}
}
}
*pn = (int)(z2-z1);
return z1;
}
SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
Fts3Hash *pHash, /* Tokenizer hash table */
const char *zArg, /* Tokenizer name */
const char *zArg, /* Possible tokenizer specification */
sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
const char **pzTokenizer, /* OUT: Set to zArg if is tokenizer */
char **pzErr /* OUT: Set to malloced error message */
){
int rc;
char *z = (char *)zArg;
int n;
char *zCopy;
char *zEnd; /* Pointer to nul-term of zCopy */
sqlite3_tokenizer_module *m;
if( !z ){
zCopy = sqlite3_mprintf("%s", zArg);
if( !zCopy ) return SQLITE_NOMEM;
zCopy = sqlite3_mprintf("simple");
}else{
if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){
return SQLITE_OK;
}
zCopy = sqlite3_mprintf("%s", &z[8]);
*pzTokenizer = zArg;
}
if( !zCopy ){
return SQLITE_NOMEM;
}
zEnd = &zCopy[strlen(zCopy)];
z = (char *)sqlite3Fts3NextToken(zCopy, &n);
z[n] = '\0';
sqlite3Fts3Dequote(z);
m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1);
m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, (int)strlen(z)+1);
if( !m ){
*pzErr = sqlite3_mprintf("unknown tokenizer: %s", z);
rc = SQLITE_ERROR;
}else{
char const **aArg = 0;
int iArg = 0;
z = &z[n+1];
|
︙ | | |
114305
114306
114307
114308
114309
114310
114311
114312
114313
114314
114315
114316
114317
114318
114319
114320
114321
114322
114323
114324
114325
114326
114327
114328
114329
114330
114331
114332
114333
114334
114335
114336
114337
114338
114339
114340
114341
114342
114343
114344
114345
114346
114347
114348
114349
114350
114351
114352
114353
114354
114355
114356
114357
114358
114359
114360
114361
114362
114363
114364
114365
114366
114367
114368
114369
114370
114371
114372
114373
114374
114375
114376
114377
114378
114379
114380
114381
114382
114383
114384
114385
114386
114387
114388
114389
114390
114391
114392
114393
114394
114395
114396
114397
114398
114399
114400
114401
114402
114403
114404
114405
114406
114407
|
112885
112886
112887
112888
112889
112890
112891
112892
112893
112894
112895
112896
112897
112898
112899
112900
112901
112902
112903
112904
112905
112906
112907
112908
112909
112910
112911
112912
112913
112914
112915
112916
112917
112918
112919
112920
112921
112922
112923
112924
112925
112926
112927
112928
112929
112930
112931
112932
112933
112934
112935
112936
112937
112938
112939
112940
112941
112942
112943
112944
112945
112946
112947
112948
112949
112950
112951
112952
112953
112954
112955
112956
112957
112958
112959
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
+
-
-
|
** of the sub-routines used to merge segments are also used by the query
** code in fts3.c.
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/*
** When full-text index nodes are loaded from disk, the buffer that they
** are loaded into has the following number of bytes of padding at the end
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
** of 920 bytes is allocated for it.
**
** This means that if we have a pointer into a buffer containing node data,
** it is always safe to read up to two varints from it without risking an
** overread, even if the node data is corrupted.
*/
#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)
typedef struct PendingList PendingList;
typedef struct SegmentNode SegmentNode;
typedef struct SegmentWriter SegmentWriter;
/*
** Data structure used while accumulating terms in the pending-terms hash
** table. The hash table entry maps from term (a string) to a malloc'd
** instance of this structure.
*/
struct PendingList {
int nData;
char *aData;
int nSpace;
sqlite3_int64 iLastDocid;
sqlite3_int64 iLastCol;
sqlite3_int64 iLastPos;
};
/*
** Each cursor has a (possibly empty) linked list of the following objects.
*/
struct Fts3DeferredToken {
Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */
int iCol; /* Column token must occur in */
Fts3DeferredToken *pNext; /* Next in list of deferred tokens */
PendingList *pList; /* Doclist is assembled here */
};
/*
** An instance of this structure is used to iterate through the terms on
** a contiguous set of segment b-tree leaf nodes. Although the details of
** this structure are only manipulated by code in this file, opaque handles
** of type Fts3SegReader* are also used by code in fts3.c to iterate through
** terms when querying the full-text index. See functions:
**
** sqlite3Fts3SegReaderNew()
** sqlite3Fts3SegReaderFree()
** sqlite3Fts3SegReaderCost()
** sqlite3Fts3SegReaderIterate()
**
** Methods used to manipulate Fts3SegReader structures:
**
** fts3SegReaderNext()
** fts3SegReaderFirstDocid()
** fts3SegReaderNextDocid()
*/
struct Fts3SegReader {
int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */
sqlite3_int64 iStartBlock;
sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */
sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
sqlite3_int64 iEndBlock;
sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
sqlite3_stmt *pStmt; /* SQL Statement to access leaf nodes */
char *aNode; /* Pointer to node data (or NULL) */
int nNode; /* Size of buffer at aNode (or 0) */
int nTermAlloc; /* Allocated size of zTerm buffer */
Fts3HashElem **ppNextElem;
/* Variables set by fts3SegReaderNext(). These may be read directly
** by the caller. They are valid from the time SegmentReaderNew() returns
** until SegmentReaderNext() returns something other than SQLITE_OK
** (i.e. SQLITE_DONE).
*/
int nTerm; /* Number of bytes in current term */
char *zTerm; /* Pointer to current term */
int nTermAlloc; /* Allocated size of zTerm buffer */
char *aDoclist; /* Pointer to doclist of current entry */
int nDoclist; /* Size of doclist in current entry */
/* The following variables are used to iterate through the current doclist */
char *pOffsetList;
sqlite3_int64 iDocid;
};
#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
#define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])
/*
** An instance of this structure is used to create a segment b-tree in the
** database. The internal details of this type are only accessed by the
** following functions:
**
** fts3SegWriterAdd()
|
︙ | | |
114462
114463
114464
114465
114466
114467
114468
114469
114470
114471
114472
114473
114474
114475
114476
114477
114478
114479
114480
|
113014
113015
113016
113017
113018
113019
113020
113021
113022
113023
113024
113025
113026
113027
113028
113029
113030
113031
113032
113033
|
+
-
-
-
-
-
+
+
+
+
+
|
#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 19
#define SQL_REPLACE_DOCSIZE 20
#define SQL_SELECT_DOCSIZE 21
#define SQL_SELECT_DOCTOTAL 22
#define SQL_REPLACE_DOCTOTAL 23
#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.
**
|
︙ | | |
114511
114512
114513
114514
114515
114516
114517
114518
114519
114520
114521
114522
114523
114524
114525
114526
114527
114528
114529
|
113064
113065
113066
113067
113068
113069
113070
113071
113072
113073
113074
113075
113076
113077
113078
113079
113080
113081
113082
113083
|
+
-
-
-
-
-
+
+
+
+
+
|
/* 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 = ?",
/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
/* 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 );
|
︙ | | |
114589
114590
114591
114592
114593
114594
114595
114596
114597
114598
114599
114600
114601
114602
|
113143
113144
113145
113146
113147
113148
113149
113150
113151
113152
113153
113154
113155
113156
113157
113158
113159
113160
113161
113162
113163
113164
113165
113166
113167
113168
113169
113170
113171
113172
113173
113174
113175
113176
113177
113178
113179
113180
113181
113182
113183
113184
113185
113186
113187
113188
113189
113190
113191
113192
113193
113194
113195
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
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.
**
** Otherwise, if successful, set *pzBlock to point to a buffer containing
** the block read from the database, and *pnBlock to the size of the read
** block in bytes.
**
** WARNING: The returned buffer is only valid until the next call to
** sqlite3Fts3ReadBlock().
*/
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
Fts3Table *p,
sqlite3_int64 iBlock,
char const **pzBlock,
int *pnBlock
){
sqlite3_stmt *pStmt;
int rc = fts3SqlStmt(p, SQL_GET_BLOCK, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_reset(pStmt);
if( pzBlock ){
sqlite3_bind_int64(pStmt, 1, iBlock);
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ){
return (rc==SQLITE_DONE ? SQLITE_CORRUPT : rc);
}
*pnBlock = sqlite3_column_bytes(pStmt, 0);
*pzBlock = (char *)sqlite3_column_blob(pStmt, 0);
if( sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
return SQLITE_CORRUPT;
}
}
return SQLITE_OK;
}
/*
** This function ensures that the caller has obtained a shared-cache
** table-lock on the %_content table. This is required before reading
** data from the fts3 table. If this lock is not acquired first, then
** the caller may end up holding read-locks on the %_segments and %_segdir
** tables, but no read-lock on the %_content table. If this happens
|
︙ | | |
114758
114759
114760
114761
114762
114763
114764
114765
114766
114767
114768
114769
114770
114771
114772
114773
114774
114775
|
113351
113352
113353
113354
113355
113356
113357
113358
113359
113360
113361
113362
113363
113364
113365
113366
113367
113368
|
-
-
-
-
+
+
+
+
|
** 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, /* Table into which text will be inserted */
const char *zText, /* Text of document to be inserted */
int iCol, /* Column into which text is being inserted */
u32 *pnWord /* OUT: Number of tokens inserted */
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;
|
︙ | | |
114846
114847
114848
114849
114850
114851
114852
114853
114854
114855
114856
114857
114858
114859
114860
114861
114862
|
113439
113440
113441
113442
113443
113444
113445
113446
113447
113448
113449
113450
113451
113452
|
-
-
-
|
int rc = sqlite3Fts3PendingTermsFlush(p);
if( rc!=SQLITE_OK ) return rc;
}
p->iPrevDocid = iDocid;
return SQLITE_OK;
}
/*
** Discard the contents of the pending-terms hash table.
*/
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
Fts3HashElem *pElem;
for(pElem=fts3HashFirst(&p->pendingTerms); pElem; pElem=fts3HashNext(pElem)){
sqlite3_free(fts3HashData(pElem));
}
fts3HashClear(&p->pendingTerms);
p->nPendingData = 0;
|
︙ | | |
114876
114877
114878
114879
114880
114881
114882
114883
114884
114885
114886
114887
114888
114889
114890
|
113466
113467
113468
113469
113470
113471
113472
113473
113474
113475
113476
113477
113478
113479
|
-
|
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;
}
}
aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
}
return SQLITE_OK;
}
/*
** This function is called by the xUpdate() method for an INSERT operation.
** The apVal parameter is passed a copy of the apVal argument passed by
|
︙ | | |
114964
114965
114966
114967
114968
114969
114970
114971
114972
114973
114974
114975
114976
114977
114978
114979
114980
114981
114982
114983
114984
114985
114986
114987
114988
114989
114990
|
113553
113554
113555
113556
113557
113558
113559
113560
113561
113562
113563
113564
113565
113566
113567
113568
113569
113570
113571
113572
113573
113574
113575
113576
113577
|
-
-
-
+
|
/* 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);
}
if( p->bHasStat ){
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(
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;
|
︙ | | |
114998
114999
115000
115001
115002
115003
115004
115005
115006
115007
115008
115009
115010
115011
115012
|
113585
113586
113587
113588
113589
113590
113591
113592
113593
113594
113595
113596
113597
113598
|
-
|
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;
}
aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
}
}
rc = sqlite3_reset(pSelect);
}else{
sqlite3_reset(pSelect);
}
*pRC = rc;
|
︙ | | |
115061
115062
115063
115064
115065
115066
115067
115068
115069
115070
115071
115072
115073
115074
115075
115076
115077
115078
115079
115080
115081
115082
115083
115084
115085
115086
115087
115088
115089
115090
115091
115092
115093
115094
115095
115096
115097
115098
115099
115100
115101
115102
115103
115104
115105
115106
115107
115108
115109
115110
115111
115112
115113
115114
115115
115116
115117
115118
115119
115120
115121
115122
115123
115124
115125
115126
115127
115128
115129
115130
115131
115132
115133
115134
115135
115136
115137
115138
115139
115140
115141
115142
115143
115144
115145
115146
115147
115148
115149
115150
115151
115152
115153
115154
115155
115156
115157
115158
115159
115160
115161
115162
115163
115164
115165
115166
115167
115168
115169
115170
115171
115172
115173
115174
115175
115176
115177
115178
115179
115180
115181
115182
115183
115184
115185
115186
115187
115188
115189
115190
115191
115192
115193
115194
115195
115196
115197
115198
115199
115200
115201
115202
115203
115204
115205
115206
115207
115208
115209
115210
115211
115212
115213
115214
115215
115216
115217
115218
115219
115220
115221
115222
115223
115224
115225
115226
115227
115228
115229
115230
115231
115232
115233
115234
115235
115236
115237
115238
115239
115240
115241
115242
115243
115244
115245
|
113647
113648
113649
113650
113651
113652
113653
113654
113655
113656
113657
113658
113659
113660
113661
113662
113663
113664
113665
113666
113667
113668
113669
113670
113671
113672
113673
113674
113675
113676
113677
113678
113679
113680
113681
113682
113683
113684
113685
113686
113687
113688
113689
113690
113691
113692
113693
113694
113695
113696
113697
113698
113699
113700
113701
113702
113703
113704
113705
113706
113707
113708
113709
113710
113711
113712
113713
113714
113715
113716
113717
113718
113719
113720
113721
113722
113723
113724
113725
113726
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
+
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
|
*piIdx = iNext;
}
}
return rc;
}
/*
** The %_segments table is declared as follows:
**
** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB)
**
** This function reads data from a single row of the %_segments table. The
** specific row is identified by the iBlockid parameter. If paBlob is not
** NULL, then a buffer is allocated using sqlite3_malloc() and populated
** with the contents of the blob stored in the "block" column of the
** identified table row is. Whether or not paBlob is NULL, *pnBlob is set
** to the size of the blob in bytes before returning.
**
** If an error occurs, or the table does not contain the specified row,
** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If
** paBlob is non-NULL, then it is the responsibility of the caller to
** eventually free the returned buffer.
**
** This function may leave an open sqlite3_blob* handle in the
** Fts3Table.pSegments variable. This handle is reused by subsequent calls
** to this function. The handle may be closed by calling the
** sqlite3Fts3SegmentsClose() function. Reusing a blob handle is a handy
** performance improvement, but the blob handle should always be closed
** before control is returned to the user (to prevent a lock being held
** on the database file for longer than necessary). Thus, any virtual table
** method (xFilter etc.) that may directly or indirectly call this function
** must call sqlite3Fts3SegmentsClose() before returning.
*/
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
Fts3Table *p, /* FTS3 table handle */
sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */
char **paBlob, /* OUT: Blob data in malloc'd buffer */
int *pnBlob /* OUT: Size of blob data */
){
int rc; /* Return code */
/* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
assert( pnBlob);
if( p->pSegments ){
rc = sqlite3_blob_reopen(p->pSegments, iBlockid);
}else{
if( 0==p->zSegmentsTbl ){
p->zSegmentsTbl = sqlite3_mprintf("%s_segments", p->zName);
if( 0==p->zSegmentsTbl ) return SQLITE_NOMEM;
}
rc = sqlite3_blob_open(
p->db, p->zDb, p->zSegmentsTbl, "block", iBlockid, 0, &p->pSegments
);
}
if( rc==SQLITE_OK ){
int nByte = sqlite3_blob_bytes(p->pSegments);
if( paBlob ){
char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
if( !aByte ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
if( rc!=SQLITE_OK ){
sqlite3_free(aByte);
aByte = 0;
}
}
*paBlob = aByte;
}
*pnBlob = nByte;
}
return rc;
}
/*
** Close the blob handle at p->pSegments, if it is open. See comments above
** the sqlite3Fts3ReadBlock() function for details.
*/
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){
sqlite3_blob_close(p->pSegments);
p->pSegments = 0;
}
/*
** Move the iterator passed as the first argument to the next term in the
** segment. If successful, SQLITE_OK is returned. If there is no next term,
** SQLITE_DONE. Otherwise, an SQLite error code.
*/
static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
static int fts3SegReaderNext(Fts3SegReader *pReader){
char *pNext; /* Cursor variable */
int nPrefix; /* Number of bytes in term prefix */
int nSuffix; /* Number of bytes in term suffix */
if( !pReader->aDoclist ){
pNext = pReader->aNode;
}else{
pNext = &pReader->aDoclist[pReader->nDoclist];
}
if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
int rc; /* Return code from Fts3ReadBlock() */
int rc;
if( fts3SegReaderIsPending(pReader) ){
Fts3HashElem *pElem = *(pReader->ppNextElem);
if( pElem==0 ){
pReader->aNode = 0;
}else{
PendingList *pList = (PendingList *)fts3HashData(pElem);
pReader->zTerm = (char *)fts3HashKey(pElem);
pReader->nTerm = fts3HashKeysize(pElem);
pReader->nNode = pReader->nDoclist = pList->nData + 1;
pReader->aNode = pReader->aDoclist = pList->aData;
pReader->ppNextElem++;
assert( pReader->aNode );
}
return SQLITE_OK;
}
if( !fts3SegReaderIsRootOnly(pReader) ){
sqlite3_free(pReader->aNode);
if( !pReader->pStmt ){
}
pReader->aNode = 0;
pReader->aNode = 0;
/* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
** blocks have already been traversed. */
assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
return SQLITE_OK;
}
rc = sqlite3_step(pReader->pStmt);
if( rc!=SQLITE_ROW ){
pReader->aNode = 0;
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
rc = sqlite3Fts3ReadBlock(
p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode
}
pReader->nNode = sqlite3_column_bytes(pReader->pStmt, 0);
pReader->aNode = (char *)sqlite3_column_blob(pReader->pStmt, 0);
);
if( rc!=SQLITE_OK ) return rc;
pNext = pReader->aNode;
}
/* Because of the FTS3_NODE_PADDING bytes of padding, the following is
** safe (no risk of overread) even if the node data is corrupted.
*/
pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
if( nPrefix<0 || nSuffix<=0
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
){
return SQLITE_CORRUPT;
}
if( nPrefix+nSuffix>pReader->nTermAlloc ){
int nNew = (nPrefix+nSuffix)*2;
char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
if( !zNew ){
return SQLITE_NOMEM;
}
pReader->zTerm = zNew;
pReader->nTermAlloc = nNew;
}
memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
pReader->nTerm = nPrefix+nSuffix;
pNext += nSuffix;
pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
assert( pNext<&pReader->aNode[pReader->nNode] );
pReader->aDoclist = pNext;
pReader->pOffsetList = 0;
/* Check that the doclist does not appear to extend past the end of the
** b-tree node. And that the final byte of the doclist is 0x00. If either
** of these statements is untrue, then the data structure is corrupt.
*/
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
|| pReader->aDoclist[pReader->nDoclist-1]
){
return SQLITE_CORRUPT;
}
return SQLITE_OK;
}
/*
** Set the SegReader to point to the first docid in the doclist associated
** with the current term.
*/
|
︙ | | |
115294
115295
115296
115297
115298
115299
115300
115301
115302
115303
115304
115305
115306
115307
115308
115309
115310
115311
115312
115313
115314
115315
115316
115317
115318
115319
115320
115321
115322
115323
115324
115325
115326
115327
115328
115329
115330
115331
115332
115333
115334
115335
115336
115337
115338
115339
115340
115341
115342
115343
115344
115345
115346
115347
115348
115349
115350
115351
115352
115353
115354
115355
115356
115357
115358
115359
115360
115361
115362
115363
115364
115365
115366
115367
115368
115369
115370
115371
115372
115373
115374
115375
115376
115377
115378
115379
115380
115381
115382
115383
115384
115385
115386
115387
115388
115389
115390
115391
115392
115393
115394
115395
115396
115397
115398
115399
115400
115401
115402
115403
115404
115405
115406
115407
115408
115409
115410
115411
115412
115413
115414
115415
115416
115417
115418
115419
115420
115421
115422
115423
115424
115425
115426
115427
115428
115429
115430
115431
115432
115433
115434
115435
115436
115437
115438
115439
115440
115441
115442
115443
115444
115445
|
113775
113776
113777
113778
113779
113780
113781
113782
113783
113784
113785
113786
113787
113788
113789
113790
113791
113792
113793
113794
113795
113796
113797
113798
113799
113800
113801
113802
113803
113804
113805
113806
113807
113808
113809
113810
113811
113812
113813
113814
113815
113816
113817
113818
113819
113820
113821
113822
113823
113824
113825
113826
113827
113828
113829
113830
113831
113832
113833
113834
113835
113836
113837
113838
113839
113840
113841
113842
113843
113844
113845
113846
113847
113848
113849
113850
113851
113852
113853
113854
113855
113856
113857
113858
113859
113860
113861
113862
113863
113864
113865
113866
113867
113868
113869
113870
113871
113872
113873
113874
113875
113876
113877
113878
113879
113880
113881
113882
113883
113884
113885
113886
113887
113888
113889
113890
113891
113892
113893
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
}else{
sqlite3_int64 iDelta;
pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
pReader->iDocid += iDelta;
}
}
/*
** This function is called to estimate the amount of data that will be
** loaded from the disk If SegReaderIterate() is called on this seg-reader,
** in units of average document size.
**
** This can be used as follows: If the caller has a small doclist that
** contains references to N documents, and is considering merging it with
** a large doclist (size X "average documents"), it may opt not to load
** the large doclist if X>N.
*/
SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(
Fts3Cursor *pCsr, /* FTS3 cursor handle */
Fts3SegReader *pReader, /* Segment-reader handle */
int *pnCost /* IN/OUT: Number of bytes read */
){
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
int rc = SQLITE_OK; /* Return code */
int nCost = 0; /* Cost in bytes to return */
int pgsz = p->nPgsz; /* Database page size */
/* If this seg-reader is reading the pending-terms table, or if all data
** for the segment is stored on the root page of the b-tree, then the cost
** is zero. In this case all required data is already in main memory.
*/
if( p->bHasStat
&& !fts3SegReaderIsPending(pReader)
&& !fts3SegReaderIsRootOnly(pReader)
){
int nBlob = 0;
sqlite3_int64 iBlock;
if( pCsr->nRowAvg==0 ){
/* The average document size, which is required to calculate the cost
** of each doclist, has not yet been determined. Read the required
** data from the %_stat table to calculate it.
**
** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
** varints, where nCol is the number of columns in the FTS3 table.
** The first varint is the number of documents currently stored in
** the table. The following nCol varints contain the total amount of
** data stored in all rows of each column of the table, from left
** to right.
*/
sqlite3_stmt *pStmt;
rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
if( rc ) return rc;
if( sqlite3_step(pStmt)==SQLITE_ROW ){
sqlite3_int64 nDoc = 0;
sqlite3_int64 nByte = 0;
const char *a = sqlite3_column_blob(pStmt, 0);
if( a ){
const char *pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
a += sqlite3Fts3GetVarint(a, &nDoc);
while( a<pEnd ){
a += sqlite3Fts3GetVarint(a, &nByte);
}
}
pCsr->nRowAvg = (((nByte / nDoc) + pgsz - 1) / pgsz);
}
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK || pCsr->nRowAvg==0 ) return rc;
}
/* Assume that a blob flows over onto overflow pages if it is larger
** than (pgsz-35) bytes in size (the file-format documentation
** confirms this).
*/
for(iBlock=pReader->iStartBlock; iBlock<=pReader->iLeafEndBlock; iBlock++){
rc = sqlite3Fts3ReadBlock(p, iBlock, 0, &nBlob);
if( rc!=SQLITE_OK ) break;
if( (nBlob+35)>pgsz ){
int nOvfl = (nBlob + 34)/pgsz;
nCost += ((nOvfl + pCsr->nRowAvg - 1)/pCsr->nRowAvg);
}
}
}
*pnCost += nCost;
return rc;
}
/*
** Free all allocations associated with the iterator passed as the
** second argument.
*/
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){
if( pReader && !fts3SegReaderIsPending(pReader) ){
sqlite3_free(pReader->zTerm);
if( !fts3SegReaderIsRootOnly(pReader) ){
sqlite3_free(pReader->aNode);
if( pReader ){
if( pReader->pStmt ){
/* Move the leaf-range SELECT statement to the aLeavesStmt[] array,
** so that it can be reused when required by another query.
*/
assert( p->nLeavesStmt<p->nLeavesTotal );
sqlite3_reset(pReader->pStmt);
p->aLeavesStmt[p->nLeavesStmt++] = pReader->pStmt;
}
if( !fts3SegReaderIsPending(pReader) ){
sqlite3_free(pReader->zTerm);
}
sqlite3_free(pReader);
}
sqlite3_free(pReader);
}
}
/*
** Allocate a new SegReader object.
*/
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
Fts3Table *p, /* Virtual table handle */
int iAge, /* Segment "age". */
sqlite3_int64 iStartLeaf, /* First leaf to traverse */
sqlite3_int64 iEndLeaf, /* Final leaf to traverse */
sqlite3_int64 iEndBlock, /* Final block of segment */
const char *zRoot, /* Buffer containing root node */
int nRoot, /* Size of buffer containing root node */
Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */
){
int rc = SQLITE_OK; /* Return code */
Fts3SegReader *pReader; /* Newly allocated SegReader object */
int nExtra = 0; /* Bytes to allocate segment root node */
assert( iStartLeaf<=iEndLeaf );
if( iStartLeaf==0 ){
nExtra = nRoot + FTS3_NODE_PADDING;
nExtra = nRoot;
}
pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
if( !pReader ){
return SQLITE_NOMEM;
}
memset(pReader, 0, sizeof(Fts3SegReader));
pReader->iIdx = iAge;
pReader->iStartBlock = iStartLeaf;
pReader->iLeafEndBlock = iEndLeaf;
pReader->iIdx = iAge;
pReader->iEndBlock = iEndBlock;
if( nExtra ){
/* The entire segment is stored in the root node. */
pReader->aNode = (char *)&pReader[1];
pReader->nNode = nRoot;
memcpy(pReader->aNode, zRoot, nRoot);
}else{
/* If the text of the SQL statement to iterate through a contiguous
** set of entries in the %_segments table has not yet been composed,
** compose it now.
*/
if( !p->zSelectLeaves ){
p->zSelectLeaves = sqlite3_mprintf(
"SELECT block FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ? "
"ORDER BY blockid", p->zDb, p->zName
);
if( !p->zSelectLeaves ){
rc = SQLITE_NOMEM;
goto finished;
}
}
memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
}else{
pReader->iCurrentBlock = iStartLeaf-1;
/* If there are no free statements in the aLeavesStmt[] array, prepare
** a new statement now. Otherwise, reuse a prepared statement from
** aLeavesStmt[].
*/
if( p->nLeavesStmt==0 ){
if( p->nLeavesTotal==p->nLeavesAlloc ){
int nNew = p->nLeavesAlloc + 16;
sqlite3_stmt **aNew = (sqlite3_stmt **)sqlite3_realloc(
p->aLeavesStmt, nNew*sizeof(sqlite3_stmt *)
);
if( !aNew ){
rc = SQLITE_NOMEM;
goto finished;
}
p->nLeavesAlloc = nNew;
p->aLeavesStmt = aNew;
}
rc = sqlite3_prepare_v2(p->db, p->zSelectLeaves, -1, &pReader->pStmt, 0);
if( rc!=SQLITE_OK ){
goto finished;
}
p->nLeavesTotal++;
}else{
pReader->pStmt = p->aLeavesStmt[--p->nLeavesStmt];
}
/* Bind the start and end leaf blockids to the prepared SQL statement. */
sqlite3_bind_int64(pReader->pStmt, 1, iStartLeaf);
sqlite3_bind_int64(pReader->pStmt, 2, iEndLeaf);
}
rc = fts3SegReaderNext(pReader);
finished:
if( rc==SQLITE_OK ){
*ppReader = pReader;
}else{
sqlite3Fts3SegReaderFree(p, pReader);
}
return rc;
}
|
︙ | | |
115526
115527
115528
115529
115530
115531
115532
115533
115534
115535
115536
115537
115538
115539
|
113974
113975
113976
113977
113978
113979
113980
113981
113982
113983
113984
113985
113986
113987
113988
|
+
|
if( !pReader ){
rc = SQLITE_NOMEM;
}else{
memset(pReader, 0, nByte);
pReader->iIdx = 0x7FFFFFFF;
pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
fts3SegReaderNext(pReader);
}
}
if( isPrefix ){
sqlite3_free(aElem);
}
*ppReader = pReader;
|
︙ | | |
115767
115768
115769
115770
115771
115772
115773
115774
115775
115776
115777
115778
115779
115780
115781
|
114216
114217
114218
114219
114220
114221
114222
114223
114224
114225
114226
114227
114228
114229
114230
|
-
+
|
}
/*
** Add term zTerm to the SegmentNode. It is guaranteed that zTerm is larger
** (according to memcmp) than the previous term.
*/
static int fts3NodeAddTerm(
Fts3Table *p, /* Virtual table handle */
Fts3Table *p, /* Virtual table handle */
SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
int isCopyTerm, /* True if zTerm/nTerm is transient */
const char *zTerm, /* Pointer to buffer containing term */
int nTerm /* Size of term in bytes */
){
SegmentNode *pTree = *ppTree;
int rc;
|
︙ | | |
116397
116398
116399
116400
116401
116402
116403
116404
116405
116406
116407
116408
116409
116410
116411
116412
116413
116414
116415
116416
116417
116418
|
114846
114847
114848
114849
114850
114851
114852
114853
114854
114855
114856
114857
114858
114859
114860
114861
114862
114863
114864
114865
114866
114867
114868
|
-
+
+
-
+
-
-
-
+
+
+
-
+
|
/* If the Fts3SegFilter defines a specific term (or term prefix) to search
** for, then advance each segment iterator until it points to a term of
** equal or greater value than the specified term. This prevents many
** unnecessary merge/sort operations for the case where single segment
** b-tree leaf nodes contain more than one term.
*/
for(i=0; i<nSegment; i++){
if( pFilter->zTerm ){
int nTerm = pFilter->nTerm;
const char *zTerm = pFilter->zTerm;
for(i=0; i<nSegment; i++){
Fts3SegReader *pSeg = apSegment[i];
Fts3SegReader *pSeg = apSegment[i];
do {
rc = fts3SegReaderNext(p, pSeg);
if( rc!=SQLITE_OK ) goto finished;
while( fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 ){
rc = fts3SegReaderNext(pSeg);
if( rc!=SQLITE_OK ) goto finished; }
}while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
}
}
fts3SegReaderSort(apSegment, nSegment, nSegment, fts3SegReaderCmp);
while( apSegment[0]->aNode ){
int nTerm = apSegment[0]->nTerm;
char *zTerm = apSegment[0]->zTerm;
int nMerge = 1;
|
︙ | | |
116513
116514
116515
116516
116517
116518
116519
116520
116521
116522
116523
116524
116525
116526
116527
|
114963
114964
114965
114966
114967
114968
114969
114970
114971
114972
114973
114974
114975
114976
114977
|
-
+
|
** term (if such a term exists in the index) has already been made.
*/
if( pFilter->zTerm && !isPrefix ){
goto finished;
}
for(i=0; i<nMerge; i++){
rc = fts3SegReaderNext(p, apSegment[i]);
rc = fts3SegReaderNext(apSegment[i]);
if( rc!=SQLITE_OK ) goto finished;
}
fts3SegReaderSort(apSegment, nSegment, nMerge, fts3SegReaderCmp);
}
finished:
sqlite3_free(aBuffer);
|
︙ | | |
116539
116540
116541
116542
116543
116544
116545
116546
116547
116548
116549
116550
116551
116552
116553
|
114989
114990
114991
114992
114993
114994
114995
114996
114997
114998
114999
115000
115001
115002
115003
|
-
+
|
** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
** an SQLite error code is returned.
*/
static int fts3SegmentMerge(Fts3Table *p, int iLevel){
int i; /* Iterator variable */
int rc; /* Return code */
int iIdx; /* Index of new segment */
int iNewLevel = 0; /* Level to create new segment at */
int iNewLevel; /* Level to create new segment at */
sqlite3_stmt *pStmt = 0;
SegmentWriter *pWriter = 0;
int nSegment = 0; /* Number of segments being merged */
Fts3SegReader **apSegment = 0; /* Array of Segment iterators */
Fts3SegReader *pPending = 0; /* Iterator for pending-terms */
Fts3SegFilter filter; /* Segment term filter condition */
|
︙ | | |
116828
116829
116830
116831
116832
116833
116834
116835
116836
116837
116838
116839
116840
116841
116842
116843
116844
116845
116846
116847
116848
116849
116850
116851
116852
116853
116854
116855
116856
116857
116858
116859
116860
116861
116862
116863
116864
116865
116866
116867
116868
116869
116870
116871
116872
116873
116874
116875
116876
116877
116878
116879
116880
116881
116882
116883
116884
116885
116886
116887
116888
116889
116890
116891
116892
116893
116894
116895
116896
116897
116898
116899
116900
116901
116902
116903
116904
116905
116906
116907
|
115278
115279
115280
115281
115282
115283
115284
115285
115286
115287
115288
115289
115290
115291
115292
115293
115294
115295
115296
115297
115298
115299
115300
115301
115302
115303
115304
115305
115306
115307
115308
115309
115310
115311
115312
115313
115314
115315
115316
115317
115318
115319
115320
115321
115322
115323
115324
115325
115326
115327
115328
115329
115330
115331
115332
115333
115334
115335
115336
115337
115338
115339
115340
115341
115342
115343
115344
115345
|
-
+
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
-
+
-
+
-
+
-
+
-
+
|
sqlite3_bind_int64(pStmt, 1, p->iPrevDocid);
sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free);
sqlite3_step(pStmt);
*pRC = sqlite3_reset(pStmt);
}
/*
** Record 0 of the %_stat table contains a blob consisting of N varints,
** Update the 0 record of the %_stat table so that it holds a blob
** where N is the number of user defined columns in the fts3 table plus
** two. If nCol is the number of user defined columns, then values of the
** varints are set as follows:
** which contains the document count followed by the cumulative
**
** Varint 0: Total number of rows in the table.
**
** Varint 1..nCol: For each column, the total number of tokens stored in
** the column for all rows of the table.
** document sizes for all columns.
**
** Varint 1+nCol: The total size, in bytes, of all text values in all
** columns of all rows of the table.
**
*/
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 */
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 */
const int nStat = p->nColumn+2;
if( *pRC ) return;
a = sqlite3_malloc( (sizeof(u32)+10)*nStat );
a = sqlite3_malloc( (sizeof(u32)+10)*(p->nColumn+1) );
if( a==0 ){
*pRC = SQLITE_NOMEM;
return;
}
pBlob = (char*)&a[nStat];
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(nStat, a,
fts3DecodeIntArray(p->nColumn+1, a,
sqlite3_column_blob(pStmt, 0),
sqlite3_column_bytes(pStmt, 0));
}else{
memset(a, 0, sizeof(u32)*(nStat) );
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+1; i++){
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(nStat, a, pBlob, &nBlob);
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);
|
︙ | | |
116940
116941
116942
116943
116944
116945
116946
116947
116948
116949
116950
116951
116952
116953
116954
116955
116956
116957
116958
116959
116960
116961
116962
116963
116964
116965
116966
116967
116968
116969
116970
116971
116972
116973
116974
116975
116976
116977
116978
116979
116980
116981
116982
116983
116984
116985
116986
116987
116988
116989
116990
116991
116992
116993
116994
116995
116996
116997
116998
116999
117000
117001
117002
117003
117004
117005
117006
117007
117008
117009
117010
117011
117012
117013
117014
117015
117016
117017
117018
117019
117020
117021
117022
117023
117024
117025
117026
117027
117028
117029
117030
117031
117032
117033
117034
117035
117036
117037
117038
117039
117040
117041
117042
117043
117044
117045
117046
117047
117048
117049
117050
117051
117052
117053
117054
117055
117056
117057
117058
117059
117060
117061
117062
117063
117064
117065
117066
117067
117068
117069
117070
117071
117072
117073
117074
117075
117076
117077
117078
117079
117080
117081
117082
117083
117084
117085
117086
117087
117088
117089
117090
117091
117092
117093
117094
117095
117096
117097
117098
117099
117100
117101
117102
117103
117104
117105
117106
117107
117108
117109
117110
117111
117112
117113
117114
117115
117116
117117
117118
117119
117120
117121
117122
117123
117124
117125
117126
117127
117128
117129
117130
117131
117132
117133
117134
117135
117136
117137
117138
117139
117140
117141
117142
117143
117144
117145
117146
117147
117148
117149
117150
117151
117152
117153
117154
117155
117156
117157
117158
117159
117160
117161
117162
117163
117164
117165
117166
117167
117168
117169
117170
117171
117172
117173
117174
117175
117176
117177
117178
117179
117180
117181
|
115378
115379
115380
115381
115382
115383
115384
115385
115386
115387
115388
115389
115390
115391
115392
115393
115394
115395
115396
115397
115398
115399
115400
115401
115402
115403
115404
115405
115406
115407
115408
115409
115410
115411
115412
115413
115414
115415
115416
115417
115418
115419
115420
115421
115422
115423
115424
115425
115426
115427
115428
115429
115430
115431
115432
115433
115434
115435
115436
115437
115438
115439
115440
115441
115442
115443
115444
115445
115446
115447
115448
115449
115450
115451
115452
115453
115454
115455
115456
115457
115458
115459
115460
115461
115462
115463
115464
115465
115466
115467
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
+
-
-
+
+
+
-
-
+
-
|
p->nMaxPendingData = atoi(&zVal[11]);
rc = SQLITE_OK;
#endif
}else{
rc = SQLITE_ERROR;
}
sqlite3Fts3SegmentsClose(p);
return rc;
}
/*
** Return the deferred doclist associated with deferred token pDeferred.
** This function assumes that sqlite3Fts3CacheDeferredDoclists() has already
** been called to allocate and populate the doclist.
*/
SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *pDeferred, int *pnByte){
if( pDeferred->pList ){
*pnByte = pDeferred->pList->nData;
return pDeferred->pList->aData;
}
*pnByte = 0;
return 0;
}
/*
** Helper fucntion for FreeDeferredDoclists(). This function removes all
** references to deferred doclists from within the tree of Fts3Expr
** structures headed by
*/
static void fts3DeferredDoclistClear(Fts3Expr *pExpr){
if( pExpr ){
fts3DeferredDoclistClear(pExpr->pLeft);
fts3DeferredDoclistClear(pExpr->pRight);
if( pExpr->isLoaded ){
sqlite3_free(pExpr->aDoclist);
pExpr->isLoaded = 0;
pExpr->aDoclist = 0;
pExpr->nDoclist = 0;
pExpr->pCurrent = 0;
pExpr->iCurrent = 0;
}
}
}
/*
** Delete all cached deferred doclists. Deferred doclists are cached
** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
*/
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
Fts3DeferredToken *pDef;
for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
sqlite3_free(pDef->pList);
pDef->pList = 0;
}
if( pCsr->pDeferred ){
fts3DeferredDoclistClear(pCsr->pExpr);
}
}
/*
** Free all entries in the pCsr->pDeffered list. Entries are added to
** this list using sqlite3Fts3DeferToken().
*/
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
Fts3DeferredToken *pDef;
Fts3DeferredToken *pNext;
for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
pNext = pDef->pNext;
sqlite3_free(pDef->pList);
sqlite3_free(pDef);
}
pCsr->pDeferred = 0;
}
/*
** Generate deferred-doclists for all tokens in the pCsr->pDeferred list
** based on the row that pCsr currently points to.
**
** A deferred-doclist is like any other doclist with position information
** included, except that it only contains entries for a single row of the
** table, not for all rows.
*/
SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
int rc = SQLITE_OK; /* Return code */
if( pCsr->pDeferred ){
int i; /* Used to iterate through table columns */
sqlite3_int64 iDocid; /* Docid of the row pCsr points to */
Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
sqlite3_tokenizer *pT = p->pTokenizer;
sqlite3_tokenizer_module const *pModule = pT->pModule;
assert( pCsr->isRequireSeek==0 );
iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
sqlite3_tokenizer_cursor *pTC = 0;
rc = pModule->xOpen(pT, zText, -1, &pTC);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken; /* Number of bytes in token */
int iDum1, iDum2; /* Dummy variables */
int iPos; /* Position of token in zText */
pTC->pTokenizer = pT;
rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
Fts3PhraseToken *pPT = pDef->pToken;
if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
&& (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
&& (0==memcmp(zToken, pPT->z, pPT->n))
){
fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
}
}
}
if( pTC ) pModule->xClose(pTC);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
if( pDef->pList ){
rc = fts3PendingListAppendVarint(&pDef->pList, 0);
}
}
}
return rc;
}
/*
** Add an entry for token pToken to the pCsr->pDeferred list.
*/
SQLITE_PRIVATE int sqlite3Fts3DeferToken(
Fts3Cursor *pCsr, /* Fts3 table cursor */
Fts3PhraseToken *pToken, /* Token to defer */
int iCol /* Column that token must appear in (or -1) */
){
Fts3DeferredToken *pDeferred;
pDeferred = sqlite3_malloc(sizeof(*pDeferred));
if( !pDeferred ){
return SQLITE_NOMEM;
}
memset(pDeferred, 0, sizeof(*pDeferred));
pDeferred->pToken = pToken;
pDeferred->pNext = pCsr->pDeferred;
pDeferred->iCol = iCol;
pCsr->pDeferred = pDeferred;
assert( pToken->pDeferred==0 );
pToken->pDeferred = pDeferred;
return SQLITE_OK;
}
/*
** This function does the work for the xUpdate method of FTS3 virtual
** tables.
*/
SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
sqlite3_vtab *pVtab, /* FTS3 vtab object */
int nArg, /* Size of argument array */
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 */
assert( p->pSegments==0 );
/* Allocate space to hold the change in document sizes */
aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*p->nColumn*2 );
if( aSzIns==0 ) return SQLITE_NOMEM;
aSzDel = &aSzIns[p->nColumn+1];
memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
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 = 0;
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--;
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);
}
nChng++;
}
if( p->bHasStat ){
if( p->bHasDocsize ){
fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
}
sqlite3_free(aSzIns);
sqlite3Fts3SegmentsClose(p);
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.
|
︙ | | |
117191
117192
117193
117194
117195
117196
117197
117198
117199
117200
117201
117202
117203
117204
117205
|
115477
115478
115479
115480
115481
115482
115483
115484
115485
115486
115487
115488
115489
115490
|
-
|
sqlite3Fts3PendingTermsClear(p);
}
}else{
sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
}
}
sqlite3Fts3SegmentsClose(p);
return rc;
}
#endif
/************** End of fts3_write.c ******************************************/
/************** Begin file fts3_snippet.c ************************************/
|
︙ | | |
117222
117223
117224
117225
117226
117227
117228
117229
117230
117231
117232
117233
117234
117235
117236
|
115507
115508
115509
115510
115511
115512
115513
115514
115515
115516
115517
115518
115519
115520
115521
|
-
+
|
/*
** Used as an fts3ExprIterate() context when loading phrase doclists to
** Fts3Expr.aDoclist[]/nDoclist.
*/
typedef struct LoadDoclistCtx LoadDoclistCtx;
struct LoadDoclistCtx {
Fts3Cursor *pCsr; /* FTS3 Cursor */
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.
|
︙ | | |
117416
117417
117418
117419
117420
117421
117422
117423
117424
117425
117426
117427
117428
117429
117430
|
115701
115702
115703
115704
115705
115706
115707
115708
115709
115710
115711
115712
115713
115714
115715
|
-
+
|
UNUSED_PARAMETER(iPhrase);
p->nPhrase++;
p->nToken += pExpr->pPhrase->nToken;
if( pExpr->isLoaded==0 ){
rc = sqlite3Fts3ExprLoadDoclist(p->pCsr, pExpr);
rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr);
pExpr->isLoaded = 1;
if( rc==SQLITE_OK ){
rc = fts3ExprNearTrim(pExpr);
}
}
return rc;
|
︙ | | |
117459
117460
117461
117462
117463
117464
117465
117466
117467
117468
117469
117470
117471
117472
117473
|
115744
115745
115746
115747
115748
115749
115750
115751
115752
115753
115754
115755
115756
115757
115758
|
-
+
|
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.pCsr = pCsr;
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;
|
︙ | | |
117990
117991
117992
117993
117994
117995
117996
117997
117998
117999
118000
118001
118002
118003
118004
118005
118006
118007
118008
118009
118010
118011
118012
118013
118014
118015
118016
118017
118018
118019
118020
118021
118022
118023
118024
118025
118026
118027
118028
118029
118030
118031
118032
118033
118034
118035
118036
118037
118038
118039
118040
118041
118042
118043
118044
|
116275
116276
116277
116278
116279
116280
116281
116282
116283
116284
116285
116286
116287
116288
116289
116290
116291
116292
116293
116294
116295
116296
116297
116298
116299
116300
116301
116302
|
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
-
|
*/
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;
Fts3Cursor *pCsr = p->pCursor;
char *pIter;
char *pCsr;
char *pEnd;
char *pFree = 0;
const int iStart = 2 + (iPhrase * p->nCol * 3) + 1;
assert( pExpr->isLoaded );
assert( pExpr->eType==FTSQUERY_PHRASE );
if( pCsr->pDeferred ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
/* Fill in the global hit count matrix row for this phrase. */
int ii;
for(ii=0; ii<pPhrase->nToken; ii++){
if( pPhrase->aToken[ii].bFulltext ) break;
}
if( ii<pPhrase->nToken ){
int nFree = 0;
int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree);
if( rc!=SQLITE_OK ) return rc;
pIter = pFree;
pEnd = &pFree[nFree];
}else{
int nDoc = p->aMatchinfo[2 + 3*p->nCol*p->aMatchinfo[0]];
for(ii=0; ii<p->nCol; ii++){
p->aMatchinfo[iStart + ii*3] = nDoc;
p->aMatchinfo[iStart + ii*3 + 1] = nDoc;
}
return SQLITE_OK;
}
}else{
pIter = pExpr->aDoclist;
pEnd = &pExpr->aDoclist[pExpr->nDoclist];
pCsr = pExpr->aDoclist;
pEnd = &pExpr->aDoclist[pExpr->nDoclist];
}
/* Fill in the global hit count matrix row for this phrase. */
while( pIter<pEnd ){
while( *pIter++ & 0x80 ); /* Skip past docid. */
fts3LoadColumnlistCounts(&pIter, &p->aMatchinfo[iStart], 1);
while( pCsr<pEnd ){
while( *pCsr++ & 0x80 ); /* Skip past docid. */
fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 1);
}
sqlite3_free(pFree);
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.
|
︙ | | |
118098
118099
118100
118101
118102
118103
118104
118105
118106
118107
118108
118109
118110
118111
118112
118113
118114
118115
118116
118117
118118
118119
118120
|
116356
116357
116358
116359
116360
116361
116362
116363
116364
116365
116366
116367
116368
116369
116370
116371
116372
116373
116374
116375
116376
116377
116378
116379
|
+
+
-
|
}
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]);
}
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo);
pCsr->aMatchinfo = sInfo.aMatchinfo;
pCsr->isMatchinfoNeeded = 1;
}
sInfo.aMatchinfo = pCsr->aMatchinfo;
if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo);
|
︙ | | |
118216
118217
118218
118219
118220
118221
118222
118223
118224
118225
118226
118227
118228
118229
118230
|
116475
116476
116477
116478
116479
116480
116481
116482
116483
116484
116485
116486
116487
116488
|
-
|
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:
sqlite3Fts3SegmentsClose(pTab);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
sqlite3_free(res.z);
}else{
sqlite3_result_text(pCtx, res.z, -1, sqlite3_free);
}
}
|
︙ | | |
118396
118397
118398
118399
118400
118401
118402
118403
118404
118405
118406
118407
118408
118409
118410
118411
118412
118413
118414
118415
118416
118417
118418
118419
118420
118421
118422
118423
118424
118425
118426
118427
118428
118429
118430
|
116654
116655
116656
116657
116658
116659
116660
116661
116662
116663
116664
116665
116666
116667
116668
116669
116670
116671
116672
116673
116674
116675
116676
116677
116678
116679
116680
116681
116682
116683
116684
116685
116686
|
-
-
|
pMod->xClose(pC);
if( rc!=SQLITE_OK ) goto offsets_out;
}
offsets_out:
sqlite3_free(sCtx.aTerm);
assert( rc!=SQLITE_DONE );
sqlite3Fts3SegmentsClose(pTab);
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);
sqlite3Fts3SegmentsClose((Fts3Table *)pCsr->base.pVtab );
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);
|
︙ | | |